35889e3c22070bc32fb7accd959ad7165191e36e
[blender.git] / source / blender / src / interface_icons.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <math.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40 #ifndef WIN32
41 #include <unistd.h>
42 #else
43 #include <io.h>
44 #endif   
45 #include "MEM_guardedalloc.h"
46
47 #include "BLI_arithb.h"
48
49 #include "DNA_material_types.h"
50 #include "DNA_texture_types.h"
51 #include "DNA_world_types.h"
52 #include "DNA_object_types.h"
53 #include "DNA_lamp_types.h"
54 #include "DNA_image_types.h"
55 #include "DNA_texture_types.h"
56 #include "DNA_world_types.h"
57 #include "DNA_camera_types.h"
58 #include "DNA_image_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_space_types.h"
62
63 #include "BKE_global.h"
64 #include "BKE_material.h"
65 #include "BKE_texture.h"
66 #include "BKE_world.h"
67 #include "BKE_image.h"
68 #include "BKE_object.h"
69 #include "BKE_utildefines.h"
70 #include "BKE_icons.h"
71
72 #include "IMB_imbuf.h"
73 #include "IMB_imbuf_types.h"
74
75 #include "BIF_gl.h"
76 #include "BIF_glutil.h"
77 #include "BIF_interface.h"
78 #include "BIF_interface_icons.h"
79 #include "BIF_previewrender.h"
80 #include "BIF_resources.h" /* elubie: should be removed once the enum for the ICONS is in BIF_preview_icons.h */
81
82 #include "interface.h"
83
84 #include "PIL_time.h"
85
86 #include "blendef.h"    // CLAMP
87 #include "datatoc.h"
88 #include "mydevice.h"
89
90 /* OpenGL textures have to be size 2n+2 x 2m+2 for some n,m */
91 /* choose ICON_RENDERSIZE accordingly */
92 #define ICON_RENDERSIZE 32      
93 #define ICON_MIPMAPS 8
94
95 typedef struct DrawInfo {
96         int w;
97         int h;
98         int rw;
99         int rh;
100         VectorDrawFunc drawFunc; /* If drawFunc is defined then it is a vector icon, otherwise use rect */
101         float aspect;
102         unsigned int* rect; 
103 } DrawInfo;
104
105 static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs)
106 {
107         Icon* new_icon = 0;
108         DrawInfo* di;
109         int y = 0;
110
111         new_icon = MEM_callocN(sizeof(Icon), "texicon");
112
113         new_icon->obj = 0; /* icon is not for library object */
114         new_icon->type = 0;
115         new_icon->changed = 0; 
116         
117
118         di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
119         di->drawFunc = 0;
120         di->w = ICON_DEFAULT_HEIGHT;
121         di->h = ICON_DEFAULT_HEIGHT;
122         di->rw = ICON_DEFAULT_HEIGHT;
123         di->rh = ICON_DEFAULT_HEIGHT;
124         di->aspect = 1.0f;
125         di->rect = MEM_mallocN(ICON_DEFAULT_HEIGHT*ICON_DEFAULT_HEIGHT*sizeof(unsigned int), "icon_rect");
126         
127         /* Here we store the rect in the icon - same as before */
128         for (y=0; y<ICON_DEFAULT_HEIGHT; y++) {
129                 memcpy(&di->rect[y*ICON_DEFAULT_HEIGHT], &bbuf->rect[(y+yofs)*512+xofs], ICON_DEFAULT_HEIGHT*sizeof(int));
130         }
131
132         new_icon->drawinfo_free = BIF_icons_free_drawinfo;
133         new_icon->drawinfo = di;
134
135         BKE_icon_set(icon_id, new_icon);
136 }
137
138 static void def_internal_vicon( int icon_id, VectorDrawFunc drawFunc)
139 {
140         Icon* new_icon = 0;
141         DrawInfo* di;
142
143         new_icon = MEM_callocN(sizeof(Icon), "texicon");
144
145         new_icon->obj = 0; /* icon is not for library object */
146         new_icon->type = 0;
147         new_icon->changed = 0; 
148         
149         di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
150         di->drawFunc =drawFunc;
151         di->w = ICON_DEFAULT_HEIGHT;
152         di->h = ICON_DEFAULT_HEIGHT;
153         di->rw = ICON_DEFAULT_HEIGHT;
154         di->rh = ICON_DEFAULT_HEIGHT;
155         di->aspect = 1.0f;
156         di->rect = 0;
157         
158         new_icon->drawinfo_free = 0;
159         new_icon->drawinfo = di;
160
161         BKE_icon_set(icon_id, new_icon);
162 }
163
164 /* Vector Icon Drawing Routines */
165
166         /* Utilities */
167
168 static void viconutil_set_point(GLint pt[2], int x, int y)
169 {
170         pt[0] = x;
171         pt[1] = y;
172 }
173
174 static void viconutil_draw_tri(GLint (*pts)[2])
175 {
176         glBegin(GL_TRIANGLES);
177         glVertex2iv(pts[0]);
178         glVertex2iv(pts[1]);
179         glVertex2iv(pts[2]);
180         glEnd();
181 }
182
183 #if 0
184 static void viconutil_draw_quad(GLint (*pts)[2])
185 {
186         glBegin(GL_QUADS);
187         glVertex2iv(pts[0]);
188         glVertex2iv(pts[1]);
189         glVertex2iv(pts[2]);
190         glVertex2iv(pts[3]);
191         glEnd();
192 }
193 #endif
194
195 static void viconutil_draw_lineloop(GLint (*pts)[2], int numPoints)
196 {
197         int i;
198
199         glBegin(GL_LINE_LOOP);
200         for (i=0; i<numPoints; i++) {
201                 glVertex2iv(pts[i]);
202         }
203         glEnd();
204 }
205
206 static void viconutil_draw_lineloop_smooth(GLint (*pts)[2], int numPoints)
207 {
208         glEnable(GL_LINE_SMOOTH);
209         viconutil_draw_lineloop(pts, numPoints);
210         glDisable(GL_LINE_SMOOTH);
211 }
212
213 static void viconutil_draw_points(GLint (*pts)[2], int numPoints, int pointSize)
214 {
215         int i;
216
217         glBegin(GL_QUADS);
218         for (i=0; i<numPoints; i++) {
219                 int x = pts[i][0], y = pts[i][1];
220
221                 glVertex2i(x-pointSize,y-pointSize);
222                 glVertex2i(x+pointSize,y-pointSize);
223                 glVertex2i(x+pointSize,y+pointSize);
224                 glVertex2i(x-pointSize,y+pointSize);
225         }
226         glEnd();
227 }
228
229         /* Drawing functions */
230
231 static void vicon_x_draw(int x, int y, int w, int h, float alpha)
232 {
233         x += 3;
234         y += 3;
235         w -= 6;
236         h -= 6;
237
238         glEnable( GL_LINE_SMOOTH );
239
240         glLineWidth(2.5);
241         
242         glColor4f(0.0, 0.0, 0.0, alpha);
243         glBegin(GL_LINES);
244         glVertex2i(x  ,y  );
245         glVertex2i(x+w,y+h);
246         glVertex2i(x+w,y  );
247         glVertex2i(x  ,y+h);
248         glEnd();
249
250         glLineWidth(1.0);
251         
252         glDisable( GL_LINE_SMOOTH );
253 }
254
255 static void vicon_view3d_draw(int x, int y, int w, int h, float alpha)
256 {
257         int cx = x + w/2;
258         int cy = y + h/2;
259         int d = MAX2(2, h/3);
260
261         glColor4f(0.5, 0.5, 0.5, alpha);
262         glBegin(GL_LINES);
263         glVertex2i(x  , cy-d);
264         glVertex2i(x+w, cy-d);
265         glVertex2i(x  , cy+d);
266         glVertex2i(x+w, cy+d);
267
268         glVertex2i(cx-d, y  );
269         glVertex2i(cx-d, y+h);
270         glVertex2i(cx+d, y  );
271         glVertex2i(cx+d, y+h);
272         glEnd();
273         
274         glColor4f(0.0, 0.0, 0.0, alpha);
275         glBegin(GL_LINES);
276         glVertex2i(x  , cy);
277         glVertex2i(x+w, cy);
278         glVertex2i(cx, y  );
279         glVertex2i(cx, y+h);
280         glEnd();
281 }
282
283 static void vicon_edit_draw(int x, int y, int w, int h, float alpha)
284 {
285         GLint pts[4][2];
286
287         viconutil_set_point(pts[0], x+3  , y+3  );
288         viconutil_set_point(pts[1], x+w-3, y+3  );
289         viconutil_set_point(pts[2], x+w-3, y+h-3);
290         viconutil_set_point(pts[3], x+3  , y+h-3);
291
292         glColor4f(0.0, 0.0, 0.0, alpha);
293         viconutil_draw_lineloop(pts, 4);
294
295         glColor3f(1, 1, 0.0);
296         viconutil_draw_points(pts, 4, 1);
297 }
298
299 static void vicon_editmode_hlt_draw(int x, int y, int w, int h, float alpha)
300 {
301         GLint pts[3][2];
302
303         viconutil_set_point(pts[0], x+w/2, y+h-2);
304         viconutil_set_point(pts[1], x+3, y+4);
305         viconutil_set_point(pts[2], x+w-3, y+4);
306
307         glColor4f(0.5, 0.5, 0.5, alpha);
308         viconutil_draw_tri(pts);
309
310         glColor4f(0.0, 0.0, 0.0, 1);
311         viconutil_draw_lineloop_smooth(pts, 3);
312
313         glColor3f(1, 1, 0.0);
314         viconutil_draw_points(pts, 3, 1);
315 }
316
317 static void vicon_editmode_dehlt_draw(int x, int y, int w, int h, float alpha)
318 {
319         GLint pts[3][2];
320
321         viconutil_set_point(pts[0], x+w/2, y+h-2);
322         viconutil_set_point(pts[1], x+3, y+4);
323         viconutil_set_point(pts[2], x+w-3, y+4);
324
325         glColor4f(0.0, 0.0, 0.0, 1);
326         viconutil_draw_lineloop_smooth(pts, 3);
327
328         glColor3f(.9, .9, .9);
329         viconutil_draw_points(pts, 3, 1);
330 }
331
332 static void vicon_disclosure_tri_right_draw(int x, int y, int w, int h, float alpha)
333 {
334         GLint pts[3][2];
335         int cx = x+w/2;
336         int cy = y+w/2;
337         int d = w/3, d2 = w/5;
338
339         viconutil_set_point(pts[0], cx-d2, cy+d);
340         viconutil_set_point(pts[1], cx-d2, cy-d);
341         viconutil_set_point(pts[2], cx+d2, cy);
342
343         glShadeModel(GL_SMOOTH);
344         glBegin(GL_TRIANGLES);
345         glColor4f(0.8, 0.8, 0.8, alpha);
346         glVertex2iv(pts[0]);
347         glVertex2iv(pts[1]);
348         glColor4f(0.3, 0.3, 0.3, alpha);
349         glVertex2iv(pts[2]);
350         glEnd();
351         glShadeModel(GL_FLAT);
352
353         glColor4f(0.0, 0.0, 0.0, 1);
354         viconutil_draw_lineloop_smooth(pts, 3);
355 }
356
357 static void vicon_disclosure_tri_down_draw(int x, int y, int w, int h, float alpha)
358 {
359         GLint pts[3][2];
360         int cx = x+w/2;
361         int cy = y+w/2;
362         int d = w/3, d2 = w/5;
363
364         viconutil_set_point(pts[0], cx+d, cy+d2);
365         viconutil_set_point(pts[1], cx-d, cy+d2);
366         viconutil_set_point(pts[2], cx, cy-d2);
367
368         glShadeModel(GL_SMOOTH);
369         glBegin(GL_TRIANGLES);
370         glColor4f(0.8, 0.8, 0.8, alpha);
371         glVertex2iv(pts[0]);
372         glVertex2iv(pts[1]);
373         glColor4f(0.3, 0.3, 0.3, alpha);
374         glVertex2iv(pts[2]);
375         glEnd();
376         glShadeModel(GL_FLAT);
377
378         glColor4f(0.0, 0.0, 0.0, 1);
379         viconutil_draw_lineloop_smooth(pts, 3);
380 }
381
382 static void vicon_move_up_draw(int x, int y, int w, int h, float alpha)
383 {
384         int d=-2;
385
386         glEnable(GL_LINE_SMOOTH);
387         glLineWidth(1);
388         glColor3f(0.0, 0.0, 0.0);
389
390         glBegin(GL_LINE_STRIP);
391         glVertex2i(x+w/2-d*2, y+h/2+d);
392         glVertex2i(x+w/2, y+h/2-d + 1);
393         glVertex2i(x+w/2+d*2, y+h/2+d);
394         glEnd();
395
396         glLineWidth(1.0);
397         glDisable(GL_LINE_SMOOTH);
398 }
399
400 static void vicon_move_down_draw(int x, int y, int w, int h, float alpha)
401 {
402         int d=2;
403
404         glEnable(GL_LINE_SMOOTH);
405         glLineWidth(1);
406         glColor3f(0.0, 0.0, 0.0);
407
408         glBegin(GL_LINE_STRIP);
409         glVertex2i(x+w/2-d*2, y+h/2+d);
410         glVertex2i(x+w/2, y+h/2-d - 1);
411         glVertex2i(x+w/2+d*2, y+h/2+d);
412         glEnd();
413
414         glLineWidth(1.0);
415         glDisable(GL_LINE_SMOOTH);
416 }
417
418 /***/
419
420
421 /* this only works for the hardcoded buttons image, turning the grey AA pixels to alpha, and slight off-grey to half alpha */
422
423 static void clear_transp_rect_soft(unsigned char *transp, unsigned char *rect, int w, int h, int rowstride)
424 {
425         int x, y, val;
426         
427         for (y=1; y<h-1; y++) {
428                 unsigned char *row0= &rect[(y-1)*rowstride];
429                 unsigned char *row= &rect[y*rowstride];
430                 unsigned char *row1= &rect[(y+1)*rowstride];
431                 for (x=1; x<w-1; x++) {
432                         unsigned char *pxl0= &row0[x*4];
433                         unsigned char *pxl= &row[x*4];
434                         unsigned char *pxl1= &row1[x*4];
435                         
436                         if(pxl[3]!=0) {
437                                 val= (abs(pxl[0]-transp[0]) + abs(pxl[1]-transp[1]) + abs(pxl[2]-transp[2]))/3;
438                                 if(val<20) {
439                                         pxl[3]= 128;
440                                 }
441                                 else if(val<50) {
442                                         // one of pixels surrounding has alpha null?
443                                         if(pxl[3-4]==0 || pxl[3+4]==0 || pxl0[3]==0 || pxl1[3]==0) {
444                                 
445                                                 if(pxl[0]>val) pxl[0]-= val; else pxl[0]= 0;
446                                                 if(pxl[1]>val) pxl[1]-= val; else pxl[1]= 0;
447                                                 if(pxl[2]>val) pxl[2]-= val; else pxl[2]= 0;
448                                                 
449                                                 pxl[3]= 128;
450                                         }
451                                 }
452                         }
453                 }
454         }
455 }
456
457 static void clear_transp_rect(unsigned char *transp, unsigned char *rect, int w, int h, int rowstride)
458 {
459         int x,y;
460         for (y=0; y<h; y++) {
461                 unsigned char *row= &rect[y*rowstride];
462                 for (x=0; x<w; x++) {
463                         unsigned char *pxl= &row[x*4];
464                         if (*((unsigned int*) pxl)==*((unsigned int*) transp)) {
465                                 pxl[3]= 0;
466                         }
467                 }
468         }
469 }
470
471 static void prepare_internal_icons(ImBuf* bbuf)
472 {
473         int x, y;
474         int rowstride= bbuf->x*4;
475         char *back= (char *)bbuf->rect;
476         unsigned char transp[4];
477         
478         /* this sets blueish outside of icon to zero alpha */
479         QUATCOPY(transp, back);
480         clear_transp_rect(transp, back, bbuf->x, bbuf->y, rowstride);
481         
482         /* hack! */
483 #if 0   
484         for (y=0; y<12; y++) {
485                 for (x=0; x<21; x++) {
486                         unsigned char *start= ((unsigned char*) bbuf->rect) + (y*21 + 3)*rowstride + (x*20 + 3)*4;
487                         /* this sets backdrop of icon to zero alpha */
488                         transp[0]= start[0];
489                         transp[1]= start[1];
490                         transp[2]= start[2];
491                         transp[3]= start[3];
492                         clear_transp_rect(transp, start, 20, 21, rowstride);
493                         clear_transp_rect_soft(transp, start, 20, 21, rowstride);
494                                 
495                 }
496         } 
497 #endif
498 }
499
500
501 static void init_internal_icons()
502 {
503         ImBuf *bbuf= IMB_ibImageFromMemory((int *)datatoc_blenderbuttons, datatoc_blenderbuttons_size, IB_rect);
504         int x, y;
505
506         prepare_internal_icons(bbuf);
507
508         for (y=0; y<12; y++) {
509                 for (x=0; x<21; x++) {
510                         def_internal_icon(bbuf, BIFICONID_FIRST + y*21 + x, x*20+3, y*21+3);
511                 }
512         }
513
514         def_internal_vicon(VICON_VIEW3D, vicon_view3d_draw);
515         def_internal_vicon(VICON_EDIT, vicon_edit_draw);
516         def_internal_vicon(VICON_EDITMODE_DEHLT, vicon_editmode_dehlt_draw);
517         def_internal_vicon(VICON_EDITMODE_HLT, vicon_editmode_hlt_draw);
518         def_internal_vicon(VICON_DISCLOSURE_TRI_RIGHT, vicon_disclosure_tri_right_draw);
519         def_internal_vicon(VICON_DISCLOSURE_TRI_DOWN, vicon_disclosure_tri_down_draw);
520         def_internal_vicon(VICON_MOVE_UP, vicon_move_up_draw);
521         def_internal_vicon(VICON_MOVE_DOWN, vicon_move_down_draw);
522         def_internal_vicon(VICON_X, vicon_x_draw);
523
524         IMB_freeImBuf(bbuf);
525 }
526
527
528
529 void BIF_icons_free()
530 {
531         BKE_icons_free();
532 }
533
534 void BIF_icons_free_drawinfo(void *drawinfo)
535 {
536         DrawInfo* di = drawinfo;
537
538         if (di)
539         {
540                 MEM_freeN(di->rect);
541                 MEM_freeN(di);
542         }
543 }
544
545 static DrawInfo* icon_create_drawinfo()
546 {
547         DrawInfo* di = 0;
548
549         di = MEM_callocN(sizeof(DrawInfo), "di_icon");
550         
551         di->drawFunc = 0;
552         di->w = 16;
553         di->h = 16;
554         di->rw = ICON_RENDERSIZE;
555         di->rh = ICON_RENDERSIZE;
556         di->rect = 0;
557         di->aspect = 1.0f;
558
559         return di;
560 }
561
562 int BIF_icon_get_width(int icon_id)
563 {
564         Icon* icon = 0;
565         DrawInfo* di = 0;
566
567         icon = BKE_icon_get(icon_id);
568         
569         if (!icon) {
570                 printf("BIF_icon_get_width: Internal error, no icon for icon ID: %d\n", icon_id);
571                 return 0;
572         }
573         
574         di = (DrawInfo*)icon->drawinfo;
575         if (!di) {
576                 di = icon_create_drawinfo();
577                 icon->drawinfo = di;
578         }
579
580         if (di)
581                 return di->w;
582
583         return 0;
584 }
585
586 int BIF_icon_get_height(int icon_id)
587 {
588         Icon* icon = 0;
589         DrawInfo* di = 0;
590
591         icon = BKE_icon_get(icon_id);
592         
593         if (!icon) {
594                 printf("BIF_icon_get_width: Internal error, no icon for icon ID: %d\n", icon_id);
595                 return 0;
596         }
597         
598         di = (DrawInfo*)icon->drawinfo;
599
600         if (!di) {
601                 di = icon_create_drawinfo();
602                 icon->drawinfo = di;
603         }
604         
605         if (di)
606                 return di->h;
607
608         return 0;
609 }
610
611 void BIF_icons_init(int first_dyn_id)
612 {
613
614         BKE_icons_init(first_dyn_id);
615         init_internal_icons();
616 }
617
618 /* create single icon from jpg, png etc. */
619 static void icon_from_image(Image* img, RenderInfo* ri, unsigned int w, unsigned int h)
620 {
621         struct ImBuf *ima;
622         struct ImBuf *imb;
623         float scaledx, scaledy;
624         int pr_size = w*h*sizeof(unsigned int);
625         short ex, ey, dx, dy;
626         
627         if (!img)
628                 return;
629         
630         if (!ri->rect) {
631                 ri->rect= MEM_callocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "butsrect");
632                 memset(ri->rect, 0xFF, w*h*sizeof(unsigned int));
633         }
634         
635         /* bail out now... loading and reducing images is too expensive */
636         if(img->ibuf==NULL || img->ibuf->rect==NULL) {
637                 return;
638 //              load_image(img, IB_rect, G.sce, G.scene->r.cfra);
639         }
640         
641         ima = IMB_dupImBuf(img->ibuf);
642         
643         if (!ima) 
644                 return;
645         
646         if (ima->x > ima->y) {
647                 scaledx = (float)w;
648                 scaledy =  ( (float)ima->y/(float)ima->x )*(float)w;
649         }
650         else {                  
651                 scaledx =  ( (float)ima->x/(float)ima->y )*(float)h;
652                 scaledy = (float)h;
653         }
654         
655         ex = (short)scaledx;
656         ey = (short)scaledy;
657         
658         dx = (w - ex) / 2;
659         dy = (h - ey) / 2;
660         
661         IMB_scalefastImBuf(ima, ex, ey);
662
663         /* sigh, need to copy the float buffer too */
664         imb = IMB_allocImBuf(w, h, 32, IB_rect | IB_rectfloat, 0);
665
666         IMB_rectcpy(imb, ima, dx, dy, 0, 0, ex, ey);    
667
668         IMB_freeImBuf(ima);
669
670         memcpy(ri->rect, imb->rect,pr_size);
671
672         IMB_freeImBuf(imb);
673 }
674
675
676 /* only called when icon has changed */
677 /* only call with valid pointer from BIF_icon_draw */
678 static void icon_set_image(ID* id, DrawInfo* di)
679 {
680         RenderInfo ri;  
681
682         if (!di) return;                        
683
684         if (!di->rect)
685                 di->rect = MEM_callocN(di->rw*di->rh*sizeof(unsigned int), "laprevrect");               
686         
687         ri.cury = 0;
688         ri.rect = 0;
689         ri.pr_rectx = di->rw;
690         ri.pr_recty = di->rh;
691
692         /* no drawing (see last parameter doDraw, just calculate preview image 
693                 - hopefully small enough to be fast */
694         if (GS(id->name) == ID_IM)
695                 icon_from_image((struct Image*)id, &ri, ri.pr_rectx, ri.pr_recty);
696         else {
697                 BIF_previewrender(id, &ri, NULL, PR_ICON_RENDER);
698         }
699
700         /* and copy the image into the icon */
701         memcpy(di->rect, ri.rect,di->rw*di->rh*sizeof(unsigned int));           
702
703         /* and clean up */
704         MEM_freeN(ri.rect);
705         ri.rect = 0;
706
707 }
708
709 void BIF_icon_draw(float x, float y, int icon_id)
710 {
711         Icon* icon = 0;
712         DrawInfo* di = 0;
713
714         icon = BKE_icon_get(icon_id);
715         
716         if (!icon) {
717                 printf("BIF_icon_draw: Internal error, no icon for icon ID: %d\n", icon_id);
718                 return;
719         }
720
721         di = (DrawInfo*)icon->drawinfo;
722
723         if (!di) {
724                 
725                 di = icon_create_drawinfo();
726                                 
727                 icon->changed = 1; 
728                 icon->drawinfo = di;            
729                 icon->drawinfo_free = BIF_icons_free_drawinfo;
730         }
731
732         if (di->drawFunc) {
733                 /* vector icons use the uiBlock transformation, they are not drawn
734                    with untransformed coordinates like the other icons */
735                 di->drawFunc(x, y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f); 
736         }
737         else {
738                 if (icon->changed) /* changed only ever set by dynamic icons */
739                 {
740                         icon_set_image((ID*)icon->obj, icon->drawinfo); 
741                         icon->changed = 0;
742                 }
743
744                 if (!di->rect) return; /* something has gone wrong! */
745                 
746                 ui_rasterpos_safe(x, y, di->aspect);
747                 
748                 if(di->w<1 || di->h<1) {
749                         printf("what the heck!\n");
750                 }
751                 /* di->rect contains image in 'rendersize', we only scale if needed */
752                 else if(di->rw!=di->w && di->rh!=di->h) {
753                         ImBuf *ima;
754                         /* first allocate imbuf for scaling and copy preview into it */
755                         ima = IMB_allocImBuf(di->rw, di->rh, 32, IB_rect, 0);
756                         memcpy(ima->rect, di->rect, di->rw*di->rh*sizeof(unsigned int));        
757
758                         /* scale it */
759                         IMB_scaleImBuf(ima, di->w, di->h);
760                         glDrawPixels(di->w, di->h, GL_RGBA, GL_UNSIGNED_BYTE, ima->rect);
761
762                         IMB_freeImBuf(ima);
763                 }
764                 else
765                         glDrawPixels(di->w, di->h, GL_RGBA, GL_UNSIGNED_BYTE, di->rect);
766         }
767 }
768
769
770 void BIF_icon_draw_blended(float x, float y, int icon_id, int colorid, int shade)
771 {
772         
773         if(shade < 0) {
774                 float r= (128+shade)/128.0;
775                 glPixelTransferf(GL_ALPHA_SCALE, r);
776         }
777
778         BIF_icon_draw(x, y, icon_id);
779
780         glPixelTransferf(GL_ALPHA_SCALE, 1.0);
781 }
782
783 void BIF_icon_set_aspect(int icon_id, float aspect) 
784 {
785         Icon* icon = 0;
786         DrawInfo* di =  0;
787
788         icon = BKE_icon_get(icon_id);
789         
790         if (!icon) {
791                 printf("BIF_icon_set_aspect: Internal error, no icon for icon ID: %d\n", icon_id);
792                 return;
793         }
794
795         di = (DrawInfo*)icon->drawinfo;
796
797         if (!di) {
798                 di = icon_create_drawinfo();
799                                 
800                 icon->changed = 1; 
801                 icon->drawinfo = di;            
802                 icon->drawinfo_free = BIF_icons_free_drawinfo;          
803         } 
804         di->aspect = aspect;
805         /* scale width and height according to aspect */
806         di->w = (int)(ICON_DEFAULT_HEIGHT/di->aspect + 0.5f);
807         di->h = (int)(ICON_DEFAULT_HEIGHT/di->aspect + 0.5f);
808         
809 }
810