Cleanup: strip trailing space from interface files
[blender.git] / source / blender / editors / interface / interface_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/interface/interface_draw.c
27  *  \ingroup edinterface
28  */
29
30
31 #include <math.h>
32 #include <string.h>
33
34 #include "DNA_color_types.h"
35 #include "DNA_screen_types.h"
36 #include "DNA_movieclip_types.h"
37
38 #include "BLI_math.h"
39 #include "BLI_rect.h"
40 #include "BLI_string.h"
41 #include "BLI_utildefines.h"
42
43 #include "BKE_colorband.h"
44 #include "BKE_colortools.h"
45 #include "BKE_node.h"
46 #include "BKE_tracking.h"
47
48
49 #include "IMB_imbuf.h"
50 #include "IMB_imbuf_types.h"
51 #include "IMB_colormanagement.h"
52
53 #include "BIF_gl.h"
54 #include "BIF_glutil.h"
55
56 #include "BLF_api.h"
57
58 #include "GPU_draw.h"
59 #include "GPU_basic_shader.h"
60
61 #include "UI_interface.h"
62
63 /* own include */
64 #include "interface_intern.h"
65
66 static int roundboxtype = UI_CNR_ALL;
67
68 void UI_draw_roundbox_corner_set(int type)
69 {
70         /* Not sure the roundbox function is the best place to change this
71          * if this is undone, it's not that big a deal, only makes curves edges
72          * square for the  */
73         roundboxtype = type;
74
75 }
76
77 int UI_draw_roundbox_corner_get(void)
78 {
79         return roundboxtype;
80 }
81
82 void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad)
83 {
84         float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
85                            {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
86         int a;
87
88         /* mult */
89         for (a = 0; a < 7; a++) {
90                 mul_v2_fl(vec[a], rad);
91         }
92
93         glBegin(mode);
94
95         /* start with corner right-bottom */
96         if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
97                 glVertex2f(maxx - rad, miny);
98                 for (a = 0; a < 7; a++) {
99                         glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
100                 }
101                 glVertex2f(maxx, miny + rad);
102         }
103         else {
104                 glVertex2f(maxx, miny);
105         }
106
107         /* corner right-top */
108         if (roundboxtype & UI_CNR_TOP_RIGHT) {
109                 glVertex2f(maxx, maxy - rad);
110                 for (a = 0; a < 7; a++) {
111                         glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
112                 }
113                 glVertex2f(maxx - rad, maxy);
114         }
115         else {
116                 glVertex2f(maxx, maxy);
117         }
118
119         /* corner left-top */
120         if (roundboxtype & UI_CNR_TOP_LEFT) {
121                 glVertex2f(minx + rad, maxy);
122                 for (a = 0; a < 7; a++) {
123                         glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
124                 }
125                 glVertex2f(minx, maxy - rad);
126         }
127         else {
128                 glVertex2f(minx, maxy);
129         }
130
131         /* corner left-bottom */
132         if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
133                 glVertex2f(minx, miny + rad);
134                 for (a = 0; a < 7; a++) {
135                         glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
136                 }
137                 glVertex2f(minx + rad, miny);
138         }
139         else {
140                 glVertex2f(minx, miny);
141         }
142
143         glEnd();
144 }
145
146 static void round_box_shade_col(const float col1[3], float const col2[3], const float fac)
147 {
148         float col[3] = {
149                 fac * col1[0] + (1.0f - fac) * col2[0],
150                 fac * col1[1] + (1.0f - fac) * col2[1],
151                 fac * col1[2] + (1.0f - fac) * col2[2]
152         };
153         glColor3fv(col);
154 }
155
156 /* linear horizontal shade within button or in outline */
157 /* view2d scrollers use it */
158 void UI_draw_roundbox_shade_x(
159         int mode, float minx, float miny, float maxx, float maxy,
160         float rad, float shadetop, float shadedown)
161 {
162         float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
163                            {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
164         const float div = maxy - miny;
165         const float idiv = 1.0f / div;
166         float coltop[3], coldown[3], color[4];
167         int a;
168
169         /* mult */
170         for (a = 0; a < 7; a++) {
171                 mul_v2_fl(vec[a], rad);
172         }
173         /* get current color, needs to be outside of glBegin/End */
174         glGetFloatv(GL_CURRENT_COLOR, color);
175
176         /* 'shade' defines strength of shading */
177         coltop[0]  = min_ff(1.0f, color[0] + shadetop);
178         coltop[1]  = min_ff(1.0f, color[1] + shadetop);
179         coltop[2]  = min_ff(1.0f, color[2] + shadetop);
180         coldown[0] = max_ff(0.0f, color[0] + shadedown);
181         coldown[1] = max_ff(0.0f, color[1] + shadedown);
182         coldown[2] = max_ff(0.0f, color[2] + shadedown);
183
184         glBegin(mode);
185
186         /* start with corner right-bottom */
187         if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
188
189                 round_box_shade_col(coltop, coldown, 0.0);
190                 glVertex2f(maxx - rad, miny);
191
192                 for (a = 0; a < 7; a++) {
193                         round_box_shade_col(coltop, coldown, vec[a][1] * idiv);
194                         glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
195                 }
196
197                 round_box_shade_col(coltop, coldown, rad * idiv);
198                 glVertex2f(maxx, miny + rad);
199         }
200         else {
201                 round_box_shade_col(coltop, coldown, 0.0);
202                 glVertex2f(maxx, miny);
203         }
204
205         /* corner right-top */
206         if (roundboxtype & UI_CNR_TOP_RIGHT) {
207
208                 round_box_shade_col(coltop, coldown, (div - rad) * idiv);
209                 glVertex2f(maxx, maxy - rad);
210
211                 for (a = 0; a < 7; a++) {
212                         round_box_shade_col(coltop, coldown, (div - rad + vec[a][1]) * idiv);
213                         glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
214                 }
215                 round_box_shade_col(coltop, coldown, 1.0);
216                 glVertex2f(maxx - rad, maxy);
217         }
218         else {
219                 round_box_shade_col(coltop, coldown, 1.0);
220                 glVertex2f(maxx, maxy);
221         }
222
223         /* corner left-top */
224         if (roundboxtype & UI_CNR_TOP_LEFT) {
225
226                 round_box_shade_col(coltop, coldown, 1.0);
227                 glVertex2f(minx + rad, maxy);
228
229                 for (a = 0; a < 7; a++) {
230                         round_box_shade_col(coltop, coldown, (div - vec[a][1]) * idiv);
231                         glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
232                 }
233
234                 round_box_shade_col(coltop, coldown, (div - rad) * idiv);
235                 glVertex2f(minx, maxy - rad);
236         }
237         else {
238                 round_box_shade_col(coltop, coldown, 1.0);
239                 glVertex2f(minx, maxy);
240         }
241
242         /* corner left-bottom */
243         if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
244
245                 round_box_shade_col(coltop, coldown, rad * idiv);
246                 glVertex2f(minx, miny + rad);
247
248                 for (a = 0; a < 7; a++) {
249                         round_box_shade_col(coltop, coldown, (rad - vec[a][1]) * idiv);
250                         glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
251                 }
252
253                 round_box_shade_col(coltop, coldown, 0.0);
254                 glVertex2f(minx + rad, miny);
255         }
256         else {
257                 round_box_shade_col(coltop, coldown, 0.0);
258                 glVertex2f(minx, miny);
259         }
260
261         glEnd();
262 }
263
264 /* linear vertical shade within button or in outline */
265 /* view2d scrollers use it */
266 void UI_draw_roundbox_shade_y(
267         int mode, float minx, float miny, float maxx, float maxy,
268         float rad, float shadeLeft, float shadeRight)
269 {
270         float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
271                            {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
272         const float div = maxx - minx;
273         const float idiv = 1.0f / div;
274         float colLeft[3], colRight[3], color[4];
275         int a;
276
277         /* mult */
278         for (a = 0; a < 7; a++) {
279                 mul_v2_fl(vec[a], rad);
280         }
281         /* get current color, needs to be outside of glBegin/End */
282         glGetFloatv(GL_CURRENT_COLOR, color);
283
284         /* 'shade' defines strength of shading */
285         colLeft[0]  = min_ff(1.0f, color[0] + shadeLeft);
286         colLeft[1]  = min_ff(1.0f, color[1] + shadeLeft);
287         colLeft[2]  = min_ff(1.0f, color[2] + shadeLeft);
288         colRight[0] = max_ff(0.0f, color[0] + shadeRight);
289         colRight[1] = max_ff(0.0f, color[1] + shadeRight);
290         colRight[2] = max_ff(0.0f, color[2] + shadeRight);
291
292         glBegin(mode);
293
294         /* start with corner right-bottom */
295         if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
296                 round_box_shade_col(colLeft, colRight, 0.0);
297                 glVertex2f(maxx - rad, miny);
298
299                 for (a = 0; a < 7; a++) {
300                         round_box_shade_col(colLeft, colRight, vec[a][0] * idiv);
301                         glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
302                 }
303
304                 round_box_shade_col(colLeft, colRight, rad * idiv);
305                 glVertex2f(maxx, miny + rad);
306         }
307         else {
308                 round_box_shade_col(colLeft, colRight, 0.0);
309                 glVertex2f(maxx, miny);
310         }
311
312         /* corner right-top */
313         if (roundboxtype & UI_CNR_TOP_RIGHT) {
314                 round_box_shade_col(colLeft, colRight, 0.0);
315                 glVertex2f(maxx, maxy - rad);
316
317                 for (a = 0; a < 7; a++) {
318
319                         round_box_shade_col(colLeft, colRight, (div - rad - vec[a][0]) * idiv);
320                         glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
321                 }
322                 round_box_shade_col(colLeft, colRight, (div - rad) * idiv);
323                 glVertex2f(maxx - rad, maxy);
324         }
325         else {
326                 round_box_shade_col(colLeft, colRight, 0.0);
327                 glVertex2f(maxx, maxy);
328         }
329
330         /* corner left-top */
331         if (roundboxtype & UI_CNR_TOP_LEFT) {
332                 round_box_shade_col(colLeft, colRight, (div - rad) * idiv);
333                 glVertex2f(minx + rad, maxy);
334
335                 for (a = 0; a < 7; a++) {
336                         round_box_shade_col(colLeft, colRight, (div - rad + vec[a][0]) * idiv);
337                         glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
338                 }
339
340                 round_box_shade_col(colLeft, colRight, 1.0);
341                 glVertex2f(minx, maxy - rad);
342         }
343         else {
344                 round_box_shade_col(colLeft, colRight, 1.0);
345                 glVertex2f(minx, maxy);
346         }
347
348         /* corner left-bottom */
349         if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
350                 round_box_shade_col(colLeft, colRight, 1.0);
351                 glVertex2f(minx, miny + rad);
352
353                 for (a = 0; a < 7; a++) {
354                         round_box_shade_col(colLeft, colRight, (vec[a][0]) * idiv);
355                         glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
356                 }
357
358                 round_box_shade_col(colLeft, colRight, 1.0);
359                 glVertex2f(minx + rad, miny);
360         }
361         else {
362                 round_box_shade_col(colLeft, colRight, 1.0);
363                 glVertex2f(minx, miny);
364         }
365
366         glEnd();
367 }
368
369 /* plain antialiased unfilled rectangle */
370 void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad)
371 {
372         float color[4];
373
374         if (roundboxtype & UI_RB_ALPHA) {
375                 glGetFloatv(GL_CURRENT_COLOR, color);
376                 color[3] = 0.5;
377                 glColor4fv(color);
378                 glEnable(GL_BLEND);
379         }
380
381         /* set antialias line */
382         glEnable(GL_LINE_SMOOTH);
383         glEnable(GL_BLEND);
384
385         UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
386
387         glDisable(GL_BLEND);
388         glDisable(GL_LINE_SMOOTH);
389 }
390
391 /* (old, used in outliner) plain antialiased filled box */
392 void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad)
393 {
394         ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA);
395 }
396
397 void UI_draw_text_underline(int pos_x, int pos_y, int len, int height)
398 {
399         int ofs_y = 4 * U.pixelsize;
400         glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
401 }
402
403 /* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
404
405 void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
406 {
407 #ifdef WITH_HEADLESS
408         (void)rect;
409         (void)but;
410 #else
411         ImBuf *ibuf = (ImBuf *)but->poin;
412
413         if (!ibuf) return;
414
415         int w = BLI_rcti_size_x(rect);
416         int h = BLI_rcti_size_y(rect);
417
418         /* scissor doesn't seem to be doing the right thing...? */
419 #if 0
420         //glColor4f(1.0, 0.f, 0.f, 1.f);
421         //fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax)
422
423         /* prevent drawing outside widget area */
424         GLint scissor[4];
425         glGetIntegerv(GL_SCISSOR_BOX, scissor);
426         glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin + rect->ymin, w, h);
427 #endif
428
429         glEnable(GL_BLEND);
430         glColor4f(0.0, 0.0, 0.0, 0.0);
431
432         if (w != ibuf->x || h != ibuf->y) {
433                 float facx = (float)w / (float)ibuf->x;
434                 float facy = (float)h / (float)ibuf->y;
435                 glPixelZoom(facx, facy);
436         }
437         glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect);
438
439         glPixelZoom(1.0f, 1.0f);
440
441         glDisable(GL_BLEND);
442
443 #if 0
444         // restore scissortest
445         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
446 #endif
447
448 #endif
449 }
450
451 /**
452  * Draw title and text safe areas.
453  *
454  * The first 4 parameters are the offsets for the view, not the zones.
455  */
456 void UI_draw_safe_areas(
457         float x1, float x2, float y1, float y2,
458         const float title_aspect[2], const float action_aspect[2])
459 {
460         const float size_x_half = (x2 - x1) * 0.5f;
461         const float size_y_half = (y2 - y1) * 0.5f;
462
463         const float *safe_areas[] = {title_aspect, action_aspect};
464         int safe_len = ARRAY_SIZE(safe_areas);
465         bool is_first = true;
466
467         for (int i = 0; i < safe_len; i++) {
468                 if (safe_areas[i][0] || safe_areas[i][1]) {
469                         float margin_x, margin_y;
470                         float minx, miny, maxx, maxy;
471
472                         if (is_first) {
473                                 UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
474                                 is_first = false;
475                         }
476
477                         margin_x = safe_areas[i][0] * size_x_half;
478                         margin_y = safe_areas[i][1] * size_y_half;
479
480                         minx = x1 + margin_x;
481                         miny = y1 + margin_y;
482                         maxx = x2 - margin_x;
483                         maxy = y2 - margin_y;
484
485                         glBegin(GL_LINE_LOOP);
486                         glVertex2f(maxx, miny);
487                         glVertex2f(maxx, maxy);
488                         glVertex2f(minx, maxy);
489                         glVertex2f(minx, miny);
490                         glEnd();
491                 }
492         }
493 }
494
495
496 static void draw_scope_end(const rctf *rect, GLint *scissor)
497 {
498         /* restore scissortest */
499         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
500
501         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
502
503         /* outline */
504         glColor4f(0.f, 0.f, 0.f, 0.5f);
505         UI_draw_roundbox_corner_set(UI_CNR_ALL);
506         UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f);
507 }
508
509 static void histogram_draw_one(
510         float r, float g, float b, float alpha,
511         float x, float y, float w, float h, const float *data, int res, const bool is_line)
512 {
513         glEnable(GL_LINE_SMOOTH);
514         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
515         glColor4f(r, g, b, alpha);
516
517         if (is_line) {
518                 /* curve outline */
519                 glLineWidth(1.5);
520
521                 glBegin(GL_LINE_STRIP);
522                 for (int i = 0; i < res; i++) {
523                         float x2 = x + i * (w / (float)res);
524                         glVertex2f(x2, y + (data[i] * h));
525                 }
526                 glEnd();
527         }
528         else {
529                 /* under the curve */
530                 glBegin(GL_TRIANGLE_STRIP);
531                 glVertex2f(x, y);
532                 glVertex2f(x, y + (data[0] * h));
533                 for (int i = 1; i < res; i++) {
534                         float x2 = x + i * (w / (float)res);
535                         glVertex2f(x2, y + (data[i] * h));
536                         glVertex2f(x2, y);
537                 }
538                 glEnd();
539
540                 /* curve outline */
541                 glColor4f(0.f, 0.f, 0.f, 0.25f);
542
543                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
544                 glBegin(GL_LINE_STRIP);
545                 for (int i = 0; i < res; i++) {
546                         float x2 = x + i * (w / (float)res);
547                         glVertex2f(x2, y + (data[i] * h));
548                 }
549                 glEnd();
550         }
551
552         glDisable(GL_LINE_SMOOTH);
553 }
554
555 #define HISTOGRAM_TOT_GRID_LINES 4
556
557 void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
558 {
559         Histogram *hist = (Histogram *)but->poin;
560         int res = hist->x_resolution;
561         const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0;
562
563         rctf rect = {
564                 .xmin = (float)recti->xmin + 1,
565                 .xmax = (float)recti->xmax - 1,
566                 .ymin = (float)recti->ymin + 1,
567                 .ymax = (float)recti->ymax - 1
568         };
569
570         float w = BLI_rctf_size_x(&rect);
571         float h = BLI_rctf_size_y(&rect) * hist->ymax;
572
573         glEnable(GL_BLEND);
574         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
575
576         UI_ThemeColor4(TH_PREVIEW_BACK);
577         UI_draw_roundbox_corner_set(UI_CNR_ALL);
578         UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
579
580         /* need scissor test, histogram can draw outside of boundary */
581         GLint scissor[4];
582         glGetIntegerv(GL_VIEWPORT, scissor);
583         glScissor(ar->winrct.xmin + (rect.xmin - 1),
584                   ar->winrct.ymin + (rect.ymin - 1),
585                   (rect.xmax + 1) - (rect.xmin - 1),
586                   (rect.ymax + 1) - (rect.ymin - 1));
587
588         glColor4f(1.f, 1.f, 1.f, 0.08f);
589         /* draw grid lines here */
590         for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) {
591                 const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES;
592
593                 /* so we can tell the 1.0 color point */
594                 if (i == HISTOGRAM_TOT_GRID_LINES) {
595                         glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
596                 }
597
598                 fdrawline(rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h);
599                 fdrawline(rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax);
600         }
601
602         if (hist->mode == HISTO_MODE_LUMA) {
603                 histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line);
604         }
605         else if (hist->mode == HISTO_MODE_ALPHA) {
606                 histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line);
607         }
608         else {
609                 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R)
610                         histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line);
611                 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G)
612                         histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line);
613                 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B)
614                         histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line);
615         }
616
617         /* outline */
618         draw_scope_end(&rect, scissor);
619 }
620
621 #undef HISTOGRAM_TOT_GRID_LINES
622
623 void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
624 {
625         Scopes *scopes = (Scopes *)but->poin;
626         GLint scissor[4];
627         float colors[3][3];
628         float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}};
629         float colors_alpha[3][3], colorsycc_alpha[3][3]; /* colors  pre multiplied by alpha for speed up */
630         float min, max;
631
632         if (scopes == NULL) return;
633
634         rctf rect = {
635                 .xmin = (float)recti->xmin + 1,
636                 .xmax = (float)recti->xmax - 1,
637                 .ymin = (float)recti->ymin + 1,
638                 .ymax = (float)recti->ymax - 1
639         };
640
641         if (scopes->wavefrm_yfac < 0.5f)
642                 scopes->wavefrm_yfac = 0.98f;
643         float w = BLI_rctf_size_x(&rect) - 7;
644         float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
645         float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f;
646         float w3 = w / 3.0f;
647
648         /* log scale for alpha */
649         float alpha = scopes->wavefrm_alpha * scopes->wavefrm_alpha;
650
651         unit_m3(colors);
652
653         for (int c = 0; c < 3; c++) {
654                 for (int i = 0; i < 3; i++) {
655                         colors_alpha[c][i] = colors[c][i] * alpha;
656                         colorsycc_alpha[c][i] = colorsycc[c][i] * alpha;
657                 }
658         }
659
660         glEnable(GL_BLEND);
661         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
662
663         UI_ThemeColor4(TH_PREVIEW_BACK);
664         UI_draw_roundbox_corner_set(UI_CNR_ALL);
665         UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
666
667         /* need scissor test, waveform can draw outside of boundary */
668         glGetIntegerv(GL_VIEWPORT, scissor);
669         glScissor(ar->winrct.xmin + (rect.xmin - 1),
670                   ar->winrct.ymin + (rect.ymin - 1),
671                   (rect.xmax + 1) - (rect.xmin - 1),
672                   (rect.ymax + 1) - (rect.ymin - 1));
673
674         glColor4f(1.f, 1.f, 1.f, 0.08f);
675         /* draw grid lines here */
676         for (int i = 0; i < 6; i++) {
677                 char str[4];
678                 BLI_snprintf(str, sizeof(str), "%-3d", i * 20);
679                 str[3] = '\0';
680                 fdrawline(rect.xmin + 22, yofs + (i / 5.f) * h, rect.xmax + 1, yofs + (i / 5.f) * h);
681                 BLF_draw_default(rect.xmin + 1, yofs - 5 + (i / 5.f) * h, 0, str, sizeof(str) - 1);
682                 /* in the loop because blf_draw reset it */
683                 glEnable(GL_BLEND);
684                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
685         }
686         /* 3 vertical separation */
687         if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
688                 for (int i = 1; i < 3; i++) {
689                         fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax);
690                 }
691         }
692
693         /* separate min max zone on the right */
694         fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax);
695         /* 16-235-240 level in case of ITU-R BT601/709 */
696         glColor4f(1.f, 0.4f, 0.f, 0.2f);
697         if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
698                 fdrawline(rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
699                 fdrawline(rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
700                 fdrawline(rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
701                 fdrawline(rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
702         }
703         /* 7.5 IRE black point level for NTSC */
704         if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA)
705                 fdrawline(rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f);
706
707         if (scopes->ok && scopes->waveform_1 != NULL) {
708
709                 /* LUMA (1 channel) */
710                 glBlendFunc(GL_ONE, GL_ONE);
711                 glColor3f(alpha, alpha, alpha);
712                 glPointSize(1.0);
713
714                 if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
715
716                         glBlendFunc(GL_ONE, GL_ONE);
717
718                         glPushMatrix();
719                         glEnableClientState(GL_VERTEX_ARRAY);
720
721                         glTranslatef(rect.xmin, yofs, 0.f);
722                         glScalef(w, h, 0.f);
723                         glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
724                         glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
725
726                         glDisableClientState(GL_VERTEX_ARRAY);
727                         glPopMatrix();
728
729                         /* min max */
730                         glColor3f(0.5f, 0.5f, 0.5f);
731                         min = yofs + scopes->minmax[0][0] * h;
732                         max = yofs + scopes->minmax[0][1] * h;
733                         CLAMP(min, rect.ymin, rect.ymax);
734                         CLAMP(max, rect.ymin, rect.ymax);
735                         fdrawline(rect.xmax - 3, min, rect.xmax - 3, max);
736                 }
737                 /* RGB (3 channel) */
738                 else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
739                         glBlendFunc(GL_ONE, GL_ONE);
740
741                         glEnableClientState(GL_VERTEX_ARRAY);
742
743                         glPushMatrix();
744
745                         glTranslatef(rect.xmin, yofs, 0.f);
746                         glScalef(w, h, 0.f);
747
748                         glColor3fv( colors_alpha[0] );
749                         glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
750                         glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
751
752                         glColor3fv( colors_alpha[1] );
753                         glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2);
754                         glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
755
756                         glColor3fv( colors_alpha[2] );
757                         glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3);
758                         glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
759
760                         glDisableClientState(GL_VERTEX_ARRAY);
761                         glPopMatrix();
762                 }
763                 /* PARADE / YCC (3 channels) */
764                 else if (ELEM(scopes->wavefrm_mode,
765                               SCOPES_WAVEFRM_RGB_PARADE,
766                               SCOPES_WAVEFRM_YCC_601,
767                               SCOPES_WAVEFRM_YCC_709,
768                               SCOPES_WAVEFRM_YCC_JPEG
769                               ))
770                 {
771                         int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
772
773                         glBlendFunc(GL_ONE, GL_ONE);
774
775                         glPushMatrix();
776                         glEnableClientState(GL_VERTEX_ARRAY);
777
778                         glTranslatef(rect.xmin, yofs, 0.f);
779                         glScalef(w3, h, 0.f);
780
781                         glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
782                         glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
783                         glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
784
785                         glTranslatef(1.f, 0.f, 0.f);
786                         glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
787                         glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2);
788                         glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
789
790                         glTranslatef(1.f, 0.f, 0.f);
791                         glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
792                         glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3);
793                         glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
794
795                         glDisableClientState(GL_VERTEX_ARRAY);
796                         glPopMatrix();
797                 }
798                 /* min max */
799                 if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) {
800                         for (int c = 0; c < 3; c++) {
801                                 if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB))
802                                         glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
803                                 else
804                                         glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
805                                 min = yofs + scopes->minmax[c][0] * h;
806                                 max = yofs + scopes->minmax[c][1] * h;
807                                 CLAMP(min, rect.ymin, rect.ymax);
808                                 CLAMP(max, rect.ymin, rect.ymax);
809                                 fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max);
810                         }
811                 }
812         }
813
814         /* outline */
815         draw_scope_end(&rect, scissor);
816 }
817
818 static float polar_to_x(float center, float diam, float ampli, float angle)
819 {
820         return center + diam * ampli * cosf(angle);
821 }
822
823 static float polar_to_y(float center, float diam, float ampli, float angle)
824 {
825         return center + diam * ampli * sinf(angle);
826 }
827
828 static void vectorscope_draw_target(float centerx, float centery, float diam, const float colf[3])
829 {
830         float y, u, v;
831         float tangle = 0.f, tampli;
832         float dangle, dampli, dangle2, dampli2;
833
834         rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v, BLI_YUV_ITU_BT709);
835         if (u > 0 && v >= 0) tangle = atanf(v / u);
836         else if (u > 0 && v < 0) tangle = atanf(v / u) + 2.0f * (float)M_PI;
837         else if (u < 0) tangle = atanf(v / u) + (float)M_PI;
838         else if (u == 0 && v > 0.0f) tangle = M_PI_2;
839         else if (u == 0 && v < 0.0f) tangle = -M_PI_2;
840         tampli = sqrtf(u * u + v * v);
841
842         /* small target vary by 2.5 degree and 2.5 IRE unit */
843         glColor4f(1.0f, 1.0f, 1.0, 0.12f);
844         dangle = DEG2RADF(2.5f);
845         dampli = 2.5f / 200.0f;
846         glBegin(GL_LINE_LOOP);
847         glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
848         glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
849         glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
850         glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
851         glEnd();
852         /* big target vary by 10 degree and 20% amplitude */
853         glColor4f(1.0f, 1.0f, 1.0, 0.12f);
854         dangle = DEG2RADF(10.0f);
855         dampli = 0.2f * tampli;
856         dangle2 = DEG2RADF(5.0f);
857         dampli2 = 0.5f * dampli;
858         glBegin(GL_LINE_STRIP);
859         glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
860         glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
861         glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
862         glEnd();
863         glBegin(GL_LINE_STRIP);
864         glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
865         glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
866         glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
867         glEnd();
868         glBegin(GL_LINE_STRIP);
869         glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
870         glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
871         glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
872         glEnd();
873         glBegin(GL_LINE_STRIP);
874         glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
875         glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
876         glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
877         glEnd();
878 }
879
880 void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
881 {
882         const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
883         Scopes *scopes = (Scopes *)but->poin;
884
885         const float colors[6][3] = {
886             {0.75, 0.0, 0.0},  {0.75, 0.75, 0.0}, {0.0, 0.75, 0.0},
887             {0.0, 0.75, 0.75}, {0.0, 0.0, 0.75},  {0.75, 0.0, 0.75}};
888
889         rctf rect = {
890                 .xmin = (float)recti->xmin + 1,
891                 .xmax = (float)recti->xmax - 1,
892                 .ymin = (float)recti->ymin + 1,
893                 .ymax = (float)recti->ymax - 1
894         };
895
896         float w = BLI_rctf_size_x(&rect);
897         float h = BLI_rctf_size_y(&rect);
898         float centerx = rect.xmin + w / 2;
899         float centery = rect.ymin + h / 2;
900         float diam = (w < h) ? w : h;
901
902         float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
903
904         glEnable(GL_BLEND);
905         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
906
907         UI_ThemeColor4(TH_PREVIEW_BACK);
908         UI_draw_roundbox_corner_set(UI_CNR_ALL);
909         UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
910
911         /* need scissor test, hvectorscope can draw outside of boundary */
912         GLint scissor[4];
913         glGetIntegerv(GL_VIEWPORT, scissor);
914         glScissor(ar->winrct.xmin + (rect.xmin - 1),
915                   ar->winrct.ymin + (rect.ymin - 1),
916                   (rect.xmax + 1) - (rect.xmin - 1),
917                   (rect.ymax + 1) - (rect.ymin - 1));
918
919         glColor4f(1.f, 1.f, 1.f, 0.08f);
920         /* draw grid elements */
921         /* cross */
922         fdrawline(centerx - (diam / 2) - 5, centery, centerx + (diam / 2) + 5, centery);
923         fdrawline(centerx, centery - (diam / 2) - 5, centerx, centery + (diam / 2) + 5);
924         /* circles */
925         for (int j = 0; j < 5; j++) {
926                 glBegin(GL_LINE_LOOP);
927                 const int increment = 15;
928                 for (int i = 0; i <= 360 - increment; i += increment) {
929                         const float a = DEG2RADF((float)i);
930                         const float r = (j + 1) / 10.0f;
931                         glVertex2f(polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
932                 }
933                 glEnd();
934         }
935         /* skin tone line */
936         glColor4f(1.f, 0.4f, 0.f, 0.2f);
937         fdrawline(polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5, skin_rad),
938                   polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1, skin_rad));
939         /* saturation points */
940         for (int i = 0; i < 6; i++)
941                 vectorscope_draw_target(centerx, centery, diam, colors[i]);
942
943         if (scopes->ok && scopes->vecscope != NULL) {
944                 /* pixel point cloud */
945                 glBlendFunc(GL_ONE, GL_ONE);
946                 glColor3f(alpha, alpha, alpha);
947
948                 glPushMatrix();
949                 glEnableClientState(GL_VERTEX_ARRAY);
950
951                 glTranslatef(centerx, centery, 0.f);
952                 glScalef(diam, diam, 0.f);
953
954                 glVertexPointer(2, GL_FLOAT, 0, scopes->vecscope);
955                 glPointSize(1.0);
956                 glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
957
958                 glDisableClientState(GL_VERTEX_ARRAY);
959                 glPopMatrix();
960         }
961
962         /* outline */
963         draw_scope_end(&rect, scissor);
964
965         glDisable(GL_BLEND);
966 }
967
968 static void ui_draw_colorband_handle_tri_hlight(float x1, float y1, float halfwidth, float height)
969 {
970         glEnable(GL_LINE_SMOOTH);
971
972         glBegin(GL_LINE_STRIP);
973         glVertex2f(x1 + halfwidth, y1);
974         glVertex2f(x1, y1 + height);
975         glVertex2f(x1 - halfwidth, y1);
976         glEnd();
977
978         glDisable(GL_LINE_SMOOTH);
979 }
980
981 static void ui_draw_colorband_handle_tri(float x1, float y1, float halfwidth, float height, bool fill)
982 {
983         glEnable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
984
985         glBegin(fill ? GL_TRIANGLES : GL_LINE_LOOP);
986         glVertex2f(x1 + halfwidth, y1);
987         glVertex2f(x1, y1 + height);
988         glVertex2f(x1 - halfwidth, y1);
989         glEnd();
990
991         glDisable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
992 }
993
994 static void ui_draw_colorband_handle_box(float x1, float y1, float x2, float y2, bool fill)
995 {
996         glBegin(fill ? GL_QUADS : GL_LINE_LOOP);
997         glVertex2f(x1, y1);
998         glVertex2f(x1, y2);
999         glVertex2f(x2, y2);
1000         glVertex2f(x2, y1);
1001         glEnd();
1002 }
1003
1004 static void ui_draw_colorband_handle(
1005         const rcti *rect, float x,
1006         const float rgb[3], struct ColorManagedDisplay *display,
1007         bool active)
1008 {
1009         const float sizey = BLI_rcti_size_y(rect);
1010         const float min_width = 3.0f;
1011         float colf[3] = {UNPACK3(rgb)};
1012
1013         float half_width = floorf(sizey / 3.5f);
1014         float height = half_width * 1.4f;
1015
1016         float y1 = rect->ymin + (sizey * 0.16f);
1017         float y2 = rect->ymax;
1018
1019         /* align to pixels */
1020         x  = floorf(x  + 0.5f);
1021         y1 = floorf(y1 + 0.5f);
1022
1023         if (active || half_width < min_width) {
1024                 glBegin(GL_LINES);
1025                 glColor3ub(0, 0, 0);
1026                 glVertex2f(x, y1);
1027                 glVertex2f(x, y2);
1028                 glEnd();
1029                 setlinestyle(active ? 2 : 1);
1030                 glBegin(GL_LINES);
1031                 glColor3ub(200, 200, 200);
1032                 glVertex2f(x, y1);
1033                 glVertex2f(x, y2);
1034                 glEnd();
1035                 setlinestyle(0);
1036
1037                 /* hide handles when zoomed out too far */
1038                 if (half_width < min_width) {
1039                         return;
1040                 }
1041         }
1042
1043         /* shift handle down */
1044         y1 -= half_width;
1045
1046         glColor3ub(0, 0, 0);
1047         ui_draw_colorband_handle_box(x - half_width, y1 - 1, x + half_width, y1 + height, false);
1048
1049         /* draw all triangles blended */
1050         glEnable(GL_BLEND);
1051
1052         ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
1053
1054         if (active)
1055                 glColor3ub(196, 196, 196);
1056         else
1057                 glColor3ub(96, 96, 96);
1058         ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
1059
1060         if (active)
1061                 glColor3ub(255, 255, 255);
1062         else
1063                 glColor3ub(128, 128, 128);
1064         ui_draw_colorband_handle_tri_hlight(x, y1 + height - 1, (half_width - 1), (half_width - 1));
1065
1066         glColor3ub(0, 0, 0);
1067         ui_draw_colorband_handle_tri_hlight(x, y1 + height, half_width, half_width);
1068
1069         glDisable(GL_BLEND);
1070
1071         glColor3ub(128, 128, 128);
1072         ui_draw_colorband_handle_box(x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
1073
1074         if (display) {
1075                 IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1076         }
1077
1078         glColor3fv(colf);
1079         ui_draw_colorband_handle_box(x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
1080 }
1081
1082 void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
1083 {
1084         struct ColorManagedDisplay *display = NULL;
1085
1086         ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin);
1087         if (coba == NULL) return;
1088
1089         if (but->block->color_profile)
1090                 display = ui_block_cm_display_get(but->block);
1091
1092         float x1 = rect->xmin;
1093         float sizex = rect->xmax - x1;
1094         float sizey = BLI_rcti_size_y(rect);
1095         float sizey_solid = sizey / 4;
1096         float y1 = rect->ymin;
1097
1098         /* Drawing the checkerboard.
1099          * This could be optimized with a single checkerboard shader,
1100          * instead of drawing twice and using stippling the second time. */
1101         /* layer: background, to show tranparency */
1102         glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
1103         glRectf(x1, y1, x1 + sizex, rect->ymax);
1104         GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
1105         glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
1106         GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX);
1107         glRectf(x1, y1, x1 + sizex, rect->ymax);
1108         GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1109
1110         /* layer: color ramp */
1111         glEnable(GL_BLEND);
1112
1113         CBData *cbd = coba->data;
1114
1115         float v1[2], v2[2];
1116         float colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */
1117
1118         v1[1] = y1 + sizey_solid;
1119         v2[1] = rect->ymax;
1120
1121         glBegin(GL_TRIANGLE_STRIP);
1122         for (int a = 0; a <= sizex; a++) {
1123                 float pos = ((float)a) / sizex;
1124                 BKE_colorband_evaluate(coba, pos, colf);
1125                 if (display)
1126                         IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1127
1128                 v1[0] = v2[0] = x1 + a;
1129
1130                 glColor4fv(colf);
1131                 glVertex2fv(v1);
1132                 glVertex2fv(v2);
1133         }
1134         glEnd();
1135
1136         /* layer: color ramp without alpha for reference when manipulating ramp properties */
1137         v1[1] = y1;
1138         v2[1] = y1 + sizey_solid;
1139
1140         glBegin(GL_TRIANGLE_STRIP);
1141         for (int a = 0; a <= sizex; a++) {
1142                 float pos = ((float)a) / sizex;
1143                 BKE_colorband_evaluate(coba, pos, colf);
1144                 if (display)
1145                         IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1146
1147                 v1[0] = v2[0] = x1 + a;
1148
1149                 glColor4f(colf[0], colf[1], colf[2], 1.0f);
1150                 glVertex2fv(v1);
1151                 glVertex2fv(v2);
1152         }
1153         glEnd();
1154
1155         glDisable(GL_BLEND);
1156
1157         /* layer: box outline */
1158         glColor4f(0.0, 0.0, 0.0, 1.0);
1159         fdrawbox(x1, y1, x1 + sizex, rect->ymax);
1160
1161         /* layer: box outline */
1162         glEnable(GL_BLEND);
1163         glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
1164         fdrawline(x1, y1, x1 + sizex, y1);
1165         glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
1166         fdrawline(x1, y1 - 1, x1 + sizex, y1 - 1);
1167         glDisable(GL_BLEND);
1168
1169         /* layer: draw handles */
1170         for (int a = 0; a < coba->tot; a++, cbd++) {
1171                 if (a != coba->cur) {
1172                         float pos = x1 + cbd->pos * (sizex - 1) + 1;
1173                         ui_draw_colorband_handle(rect, pos, &cbd->r, display, false);
1174                 }
1175         }
1176
1177         /* layer: active handle */
1178         if (coba->tot != 0) {
1179                 cbd = &coba->data[coba->cur];
1180                 float pos = x1 + cbd->pos * (sizex - 1) + 1;
1181                 ui_draw_colorband_handle(rect, pos, &cbd->r, display, true);
1182         }
1183 }
1184
1185 void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
1186 {
1187         static GLuint displist = 0;
1188         float diffuse[3] = {1.0f, 1.0f, 1.0f};
1189         float size;
1190
1191         /* backdrop */
1192         glColor3ubv((unsigned char *)wcol->inner);
1193         UI_draw_roundbox_corner_set(UI_CNR_ALL);
1194         UI_draw_roundbox_gl_mode(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
1195
1196         /* sphere color */
1197         glCullFace(GL_BACK);
1198         glEnable(GL_CULL_FACE);
1199
1200         /* setup lights */
1201         GPULightData light = {0};
1202         light.type = GPU_LIGHT_SUN;
1203         copy_v3_v3(light.diffuse, diffuse);
1204         zero_v3(light.specular);
1205         ui_but_v3_get(but, light.direction);
1206
1207         GPU_basic_shader_light_set(0, &light);
1208         for (int a = 1; a < 8; a++)
1209                 GPU_basic_shader_light_set(a, NULL);
1210
1211         /* setup shader */
1212         GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f);
1213         GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
1214
1215         /* transform to button */
1216         glPushMatrix();
1217         glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f);
1218
1219         if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect))
1220                 size = BLI_rcti_size_x(rect) / 200.f;
1221         else
1222                 size = BLI_rcti_size_y(rect) / 200.f;
1223
1224         glScalef(size, size, MIN2(size, 1.0f));
1225
1226         if (displist == 0) {
1227                 GLUquadricObj *qobj;
1228
1229                 displist = glGenLists(1);
1230                 glNewList(displist, GL_COMPILE);
1231
1232                 qobj = gluNewQuadric();
1233                 gluQuadricDrawStyle(qobj, GLU_FILL);
1234                 GPU_basic_shader_bind(GPU_basic_shader_bound_options());
1235                 gluSphere(qobj, 100.0, 32, 24);
1236                 gluDeleteQuadric(qobj);
1237
1238                 glEndList();
1239         }
1240
1241         glCallList(displist);
1242
1243         /* restore */
1244         GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1245         GPU_default_lights();
1246         glDisable(GL_CULL_FACE);
1247
1248         /* AA circle */
1249         glEnable(GL_BLEND);
1250         glEnable(GL_LINE_SMOOTH);
1251         glColor3ubv((unsigned char *)wcol->inner);
1252         glutil_draw_lined_arc(0.0f, M_PI * 2.0, 100.0f, 32);
1253         glDisable(GL_BLEND);
1254         glDisable(GL_LINE_SMOOTH);
1255
1256         /* matrix after circle */
1257         glPopMatrix();
1258
1259         /* We disabled all blender lights above, so restore them here. */
1260         GPU_default_lights();
1261 }
1262
1263 static void ui_draw_but_curve_grid(const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
1264 {
1265         glBegin(GL_LINES);
1266         float dx = step * zoomx;
1267         float fx = rect->xmin + zoomx * (-offsx);
1268         if (fx > rect->xmin) fx -= dx * (floorf(fx - rect->xmin));
1269         while (fx < rect->xmax) {
1270                 glVertex2f(fx, rect->ymin);
1271                 glVertex2f(fx, rect->ymax);
1272                 fx += dx;
1273         }
1274
1275         float dy = step * zoomy;
1276         float fy = rect->ymin + zoomy * (-offsy);
1277         if (fy > rect->ymin) fy -= dy * (floorf(fy - rect->ymin));
1278         while (fy < rect->ymax) {
1279                 glVertex2f(rect->xmin, fy);
1280                 glVertex2f(rect->xmax, fy);
1281                 fy += dy;
1282         }
1283         glEnd();
1284
1285 }
1286
1287 static void gl_shaded_color(unsigned char *col, int shade)
1288 {
1289         glColor3ub(col[0] - shade > 0 ? col[0] - shade : 0,
1290                    col[1] - shade > 0 ? col[1] - shade : 0,
1291                    col[2] - shade > 0 ? col[2] - shade : 0);
1292 }
1293
1294 void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti *rect)
1295 {
1296         CurveMapping *cumap;
1297
1298         if (but->editcumap) {
1299                 cumap = but->editcumap;
1300         }
1301         else {
1302                 cumap = (CurveMapping *)but->poin;
1303         }
1304
1305         CurveMap *cuma = &cumap->cm[cumap->cur];
1306
1307         /* need scissor test, curve can draw outside of boundary */
1308         GLint scissor[4];
1309         glGetIntegerv(GL_VIEWPORT, scissor);
1310         rcti scissor_new = {
1311                 .xmin = ar->winrct.xmin + rect->xmin,
1312                 .ymin = ar->winrct.ymin + rect->ymin,
1313                 .xmax = ar->winrct.xmin + rect->xmax,
1314                 .ymax = ar->winrct.ymin + rect->ymax
1315         };
1316         BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
1317         glScissor(scissor_new.xmin,
1318                   scissor_new.ymin,
1319                   BLI_rcti_size_x(&scissor_new),
1320                   BLI_rcti_size_y(&scissor_new));
1321
1322         /* calculate offset and zoom */
1323         float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&cumap->curr);
1324         float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&cumap->curr);
1325         float offsx = cumap->curr.xmin - (1.0f / zoomx);
1326         float offsy = cumap->curr.ymin - (1.0f / zoomy);
1327
1328         glLineWidth(1.0f);
1329
1330         /* backdrop */
1331         if (but->a1 == UI_GRAD_H) {
1332                 /* magic trigger for curve backgrounds */
1333                 float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */
1334
1335                 rcti grid = {
1336                         .xmin = rect->xmin + zoomx * (-offsx),
1337                         .xmax = grid.xmin + zoomx,
1338                         .ymin = rect->ymin + zoomy * (-offsy),
1339                         .ymax = grid.ymin + zoomy
1340                 };
1341
1342                 ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);
1343
1344                 /* grid, hsv uses different grid */
1345                 glEnable(GL_BLEND);
1346                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1347                 glColor4ub(0, 0, 0, 48);
1348                 ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
1349                 glDisable(GL_BLEND);
1350         }
1351         else {
1352                 if (cumap->flag & CUMA_DO_CLIP) {
1353                         gl_shaded_color((unsigned char *)wcol->inner, -20);
1354                         glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1355                         glColor3ubv((unsigned char *)wcol->inner);
1356                         glRectf(rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
1357                                 rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
1358                                 rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
1359                                 rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
1360                 }
1361                 else {
1362                         glColor3ubv((unsigned char *)wcol->inner);
1363                         glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1364                 }
1365
1366                 /* grid, every 0.25 step */
1367                 gl_shaded_color((unsigned char *)wcol->inner, -16);
1368                 ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f);
1369                 /* grid, every 1.0 step */
1370                 gl_shaded_color((unsigned char *)wcol->inner, -24);
1371                 ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f);
1372                 /* axes */
1373                 gl_shaded_color((unsigned char *)wcol->inner, -50);
1374                 glBegin(GL_LINES);
1375                 glVertex2f(rect->xmin, rect->ymin + zoomy * (-offsy));
1376                 glVertex2f(rect->xmax, rect->ymin + zoomy * (-offsy));
1377                 glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymin);
1378                 glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymax);
1379                 glEnd();
1380         }
1381
1382         /* cfra option */
1383         /* XXX 2.48 */
1384 #if 0
1385         if (cumap->flag & CUMA_DRAW_CFRA) {
1386                 glColor3ub(0x60, 0xc0, 0x40);
1387                 glBegin(GL_LINES);
1388                 glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
1389                 glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
1390                 glEnd();
1391         }
1392 #endif
1393         /* sample option */
1394
1395         if (cumap->flag & CUMA_DRAW_SAMPLE) {
1396                 glBegin(GL_LINES); /* will draw one of the following 3 lines */
1397                 if (but->a1 == UI_GRAD_H) {
1398                         float tsample[3];
1399                         float hsv[3];
1400                         linearrgb_to_srgb_v3_v3(tsample, cumap->sample);
1401                         rgb_to_hsv_v(tsample, hsv);
1402                         glColor3ub(240, 240, 240);
1403
1404                         glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
1405                         glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
1406                 }
1407                 else if (cumap->cur == 3) {
1408                         float lum = IMB_colormanagement_get_luminance(cumap->sample);
1409                         glColor3ub(240, 240, 240);
1410
1411                         glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymin);
1412                         glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymax);
1413                 }
1414                 else {
1415                         if (cumap->cur == 0)
1416                                 glColor3ub(240, 100, 100);
1417                         else if (cumap->cur == 1)
1418                                 glColor3ub(100, 240, 100);
1419                         else
1420                                 glColor3ub(100, 100, 240);
1421
1422                         glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
1423                         glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
1424                 }
1425                 glEnd();
1426         }
1427
1428         /* the curve */
1429         glColor3ubv((unsigned char *)wcol->item);
1430         glEnable(GL_LINE_SMOOTH);
1431         glEnable(GL_BLEND);
1432         glBegin(GL_LINE_STRIP);
1433
1434         if (cuma->table == NULL)
1435                 curvemapping_changed(cumap, false);
1436
1437         CurveMapPoint *cmp = cuma->table;
1438
1439         /* first point */
1440         if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
1441                 glVertex2f(rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy));
1442         }
1443         else {
1444                 float fx = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]);
1445                 float fy = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]);
1446                 glVertex2f(fx, fy);
1447         }
1448         for (int a = 0; a <= CM_TABLE; a++) {
1449                 float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
1450                 float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
1451                 glVertex2f(fx, fy);
1452         }
1453         /* last point */
1454         if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
1455                 glVertex2f(rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy));
1456         }
1457         else {
1458                 float fx = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]);
1459                 float fy = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]);
1460                 glVertex2f(fx, fy);
1461         }
1462         glEnd();
1463         glDisable(GL_LINE_SMOOTH);
1464         glDisable(GL_BLEND);
1465
1466         /* the points, use aspect to make them visible on edges */
1467         cmp = cuma->curve;
1468         glPointSize(3.0f);
1469         glBegin(GL_POINTS);
1470         for (int a = 0; a < cuma->totpoint; a++) {
1471                 if (cmp[a].flag & CUMA_SELECT)
1472                         UI_ThemeColor(TH_TEXT_HI);
1473                 else
1474                         UI_ThemeColor(TH_TEXT);
1475                 float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
1476                 float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
1477                 glVertex2f(fx, fy);
1478         }
1479         glEnd();
1480
1481         /* restore scissortest */
1482         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
1483
1484         /* outline */
1485         glColor3ubv((unsigned char *)wcol->outline);
1486         fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1487 }
1488
1489 void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
1490 {
1491         bool ok = false;
1492         MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
1493
1494         rctf rect = {
1495                 .xmin = (float)recti->xmin + 1,
1496                 .xmax = (float)recti->xmax - 1,
1497                 .ymin = (float)recti->ymin + 1,
1498                 .ymax = (float)recti->ymax - 1
1499         };
1500
1501         int width  = BLI_rctf_size_x(&rect) + 1;
1502         int height = BLI_rctf_size_y(&rect);
1503
1504         glEnable(GL_BLEND);
1505         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1506
1507         /* need scissor test, preview image can draw outside of boundary */
1508         GLint scissor[4];
1509         glGetIntegerv(GL_VIEWPORT, scissor);
1510         glScissor(ar->winrct.xmin + (rect.xmin - 1),
1511                   ar->winrct.ymin + (rect.ymin - 1),
1512                   (rect.xmax + 1) - (rect.xmin - 1),
1513                   (rect.ymax + 1) - (rect.ymin - 1));
1514
1515         if (scopes->track_disabled) {
1516                 glColor4f(0.7f, 0.3f, 0.3f, 0.3f);
1517                 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1518                 UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
1519
1520                 ok = true;
1521         }
1522         else if ((scopes->track_search) &&
1523                  ((!scopes->track_preview) ||
1524                   (scopes->track_preview->x != width || scopes->track_preview->y != height)))
1525         {
1526                 if (scopes->track_preview)
1527                         IMB_freeImBuf(scopes->track_preview);
1528
1529                 ImBuf *tmpibuf = BKE_tracking_sample_pattern(scopes->frame_width, scopes->frame_height,
1530                                                              scopes->track_search, scopes->track,
1531                                                              &scopes->undist_marker, true, scopes->use_track_mask,
1532                                                              width, height, scopes->track_pos);
1533                 if (tmpibuf) {
1534                         if (tmpibuf->rect_float)
1535                                 IMB_rect_from_float(tmpibuf);
1536
1537                         if (tmpibuf->rect)
1538                                 scopes->track_preview = tmpibuf;
1539                         else
1540                                 IMB_freeImBuf(tmpibuf);
1541                 }
1542         }
1543
1544         if (!ok && scopes->track_preview) {
1545                 glPushMatrix();
1546
1547                 /* draw content of pattern area */
1548                 glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]);
1549
1550                 if (width > 0 && height > 0) {
1551                         ImBuf *drawibuf = scopes->track_preview;
1552
1553                         if (scopes->use_track_mask) {
1554                                 glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
1555                                 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1556                                 UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
1557                         }
1558
1559                         glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y,
1560                                           drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect);
1561
1562                         /* draw cross for pixel position */
1563                         glTranslatef(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.f);
1564                         glScissor(ar->winrct.xmin + rect.xmin,
1565                                   ar->winrct.ymin + rect.ymin,
1566                                   BLI_rctf_size_x(&rect),
1567                                   BLI_rctf_size_y(&rect));
1568
1569                         GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
1570
1571                         for (int a = 0; a < 2; a++) {
1572                                 if (a == 1) {
1573                                         GPU_basic_shader_bind_enable(GPU_SHADER_STIPPLE);
1574                                         GPU_basic_shader_line_stipple(3, 0xAAAA);
1575                                         UI_ThemeColor(TH_SEL_MARKER);
1576                                 }
1577                                 else {
1578                                         UI_ThemeColor(TH_MARKER_OUTLINE);
1579                                 }
1580
1581                                 glBegin(GL_LINES);
1582                                 glVertex2f(-10.0f, 0.0f);
1583                                 glVertex2f(10.0f, 0.0f);
1584                                 glVertex2f(0.0f, -10.0f);
1585                                 glVertex2f(0.0f, 10.0f);
1586                                 glEnd();
1587                         }
1588
1589                         GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
1590                 }
1591
1592                 glPopMatrix();
1593
1594                 ok = true;
1595         }
1596
1597         if (!ok) {
1598                 glColor4f(0.f, 0.f, 0.f, 0.3f);
1599                 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1600                 UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
1601         }
1602
1603         /* outline */
1604         draw_scope_end(&rect, scissor);
1605
1606         glDisable(GL_BLEND);
1607 }
1608
1609 void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
1610 {
1611         static const float size = 5.0f;
1612
1613         /* 16 values of sin function */
1614         const float si[16] = {
1615             0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
1616             0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
1617             -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
1618             -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
1619         };
1620         /* 16 values of cos function */
1621         const float co[16] = {
1622             1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
1623             -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
1624             -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
1625             0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
1626         };
1627
1628         GLint scissor[4];
1629
1630         /* need scissor test, can draw outside of boundary */
1631         glGetIntegerv(GL_VIEWPORT, scissor);
1632
1633         rcti scissor_new = {
1634                 .xmin = ar->winrct.xmin + recti->xmin,
1635                 .ymin = ar->winrct.ymin + recti->ymin,
1636                 .xmax = ar->winrct.xmin + recti->xmax,
1637                 .ymax = ar->winrct.ymin + recti->ymax
1638         };
1639
1640         BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
1641         glScissor(scissor_new.xmin,
1642                   scissor_new.ymin,
1643                   BLI_rcti_size_x(&scissor_new),
1644                   BLI_rcti_size_y(&scissor_new));
1645
1646         glColor4ubv(but->col);
1647
1648         float x = 0.5f * (recti->xmin + recti->xmax);
1649         float y = 0.5f * (recti->ymin + recti->ymax);
1650
1651         glEnable(GL_BLEND);
1652         glBegin(GL_POLYGON);
1653         for (int a = 0; a < 16; a++)
1654                 glVertex2f(x + size * si[a], y + size * co[a]);
1655         glEnd();
1656
1657         glColor4ub(0, 0, 0, 150);
1658         glLineWidth(1);
1659         glEnable(GL_LINE_SMOOTH);
1660         glBegin(GL_LINE_LOOP);
1661         for (int a = 0; a < 16; a++)
1662                 glVertex2f(x + size * si[a], y + size * co[a]);
1663         glEnd();
1664         glDisable(GL_LINE_SMOOTH);
1665         glDisable(GL_BLEND);
1666
1667         /* restore scissortest */
1668         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
1669 }
1670
1671 /* ****************************************************** */
1672
1673
1674 static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
1675 {
1676         /* right quad */
1677         glColor4ub(0, 0, 0, alpha);
1678         glVertex2f(maxx, miny);
1679         glVertex2f(maxx, maxy - 0.3f * shadsize);
1680         glColor4ub(0, 0, 0, 0);
1681         glVertex2f(maxx + shadsize, maxy - 0.75f * shadsize);
1682         glVertex2f(maxx + shadsize, miny);
1683
1684         /* corner shape */
1685         glColor4ub(0, 0, 0, alpha);
1686         glVertex2f(maxx, miny);
1687         glColor4ub(0, 0, 0, 0);
1688         glVertex2f(maxx + shadsize, miny);
1689         glVertex2f(maxx + 0.7f * shadsize, miny - 0.7f * shadsize);
1690         glVertex2f(maxx, miny - shadsize);
1691
1692         /* bottom quad */
1693         glColor4ub(0, 0, 0, alpha);
1694         glVertex2f(minx + 0.3f * shadsize, miny);
1695         glVertex2f(maxx, miny);
1696         glColor4ub(0, 0, 0, 0);
1697         glVertex2f(maxx, miny - shadsize);
1698         glVertex2f(minx + 0.5f * shadsize, miny - shadsize);
1699 }
1700
1701 void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
1702 {
1703         glEnable(GL_BLEND);
1704
1705         glBegin(GL_QUADS);
1706
1707         /* accumulated outline boxes to make shade not linear, is more pleasant */
1708         ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
1709         ui_shadowbox(minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
1710         ui_shadowbox(minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
1711
1712         glEnd();
1713
1714         glDisable(GL_BLEND);
1715 }
1716
1717
1718 void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
1719 {
1720         float rad;
1721
1722         if (radius > (BLI_rctf_size_y(rct) - 10.0f) / 2.0f)
1723                 rad = (BLI_rctf_size_y(rct) - 10.0f) / 2.0f;
1724         else
1725                 rad = radius;
1726
1727         int a, i = 12;
1728 #if 0
1729         if (select) {
1730                 a = i * aspect; /* same as below */
1731         }
1732         else
1733 #endif
1734         {
1735                 a = i * aspect;
1736         }
1737
1738         glEnable(GL_BLEND);
1739
1740         const float dalpha = alpha * 2.0f / 255.0f;
1741         float calpha = dalpha;
1742         for (; i--; a -= aspect) {
1743                 /* alpha ranges from 2 to 20 or so */
1744                 glColor4f(0.0f, 0.0f, 0.0f, calpha);
1745                 calpha += dalpha;
1746
1747                 UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a);
1748         }
1749
1750         /* outline emphasis */
1751         glEnable(GL_LINE_SMOOTH);
1752         glColor4ub(0, 0, 0, 100);
1753         UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f);
1754         glDisable(GL_LINE_SMOOTH);
1755
1756         glDisable(GL_BLEND);
1757 }
1758
1759 /**
1760  * Reset GL state (keep minimal).
1761  *
1762  * \note Blender's internal code doesn't assume these are reset,
1763  * but external callbacks may depend on their state.
1764  */
1765 void UI_reinit_gl_state(void)
1766 {
1767         glLineWidth(1.0f);
1768         glPointSize(1.0f);
1769 }