2 * Cinelerra :: Blue Banana - color modification plugin for Cinelerra-CV
3 * Copyright (C) 2012-2013 Monty <monty@xiph.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "bluebananaslider.h"
24 #define CLAMP(x, y, z) ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x)))
26 #define CW (get_h()/2+2)
27 #define SW (get_h()*2/5+1)
28 #define Z1 (get_h()/7+2)
29 #define Z2 (get_h()*2/5+1)
30 #define Z3 (get_h()-Z2-1)
31 #define Z4 (get_h()-Z1-1)
32 #define ZC ((Z3+Z2)/2)
40 static int scale_color(int color, float scale){
41 int r = ((color >> 16) & 0xff)*scale;
42 int g = ((color >> 8) & 0xff)*scale;
43 int b = (color & 0xff)*scale;
48 return (r<<16)|(g<<8)|b;
51 static int mix_color(int c1, float s1, int c2, float s2){
52 int r = ((c1 >> 16) & 0xff)*s1 + ((c2 >> 16) & 0xff)*s2;
53 int g = ((c1 >> 8) & 0xff)*s1 + ((c2 >> 8) & 0xff)*s2;
54 int b = (c1 & 0xff)*s1 + (c2 & 0xff)*s2;
59 return (r<<16)|(g<<8)|b;
62 BluebananaSlider::BluebananaSlider(BluebananaMain *plugin,
63 BluebananaWindow *gui,
70 : BC_SubWindow(x, y, w, h){
72 this->plugin = plugin;
74 this->minval = minval;
75 this->maxval = maxval;
83 int bg_c = get_resources()->get_bg_color();
84 int bg_r = ((bg_c >> 16) & 0xff);
85 int bg_g = ((bg_c >> 8) & 0xff);
86 int bg_b = (bg_c & 0xff);
87 int bg_v = (bg_r * 76 + bg_g *150 + bg_b *29) >> 8;
89 int dt_c = get_resources()->default_text_color;
90 int dt_r = ((dt_c >> 16) & 0xff);
91 int dt_g = ((dt_c >> 8) & 0xff);
92 int dt_b = (dt_c & 0xff);
93 int dt_v = (dt_r * 76 + dt_g *150 + dt_b *29) >> 8;
96 /* light text, dark background */
97 int dg_c = get_resources()->default_text_color;
98 int dg_r = (((dg_c >> 16) & 0xff) + bg_r*2) /3;
99 int dg_g = (((dg_c >> 8) & 0xff) + bg_g*2) /3;
100 int dg_b = ((dg_c & 0xff) + bg_b*2) /3;
101 dg_c = (dg_r<<16) | (dg_g<<8) | dg_b;
103 active_bordercolor = get_resources()->default_text_color;
104 inactive_bordercolor = dg_c;
106 troughcolor = scale_color(dg_c,.5);
107 slidercolor = (bg_v > 0xa0 ? 0x606060 : 0xa0a0a0);
108 sliderlit = (bg_v > 0xa0 ? 0x909070 : 0xd0d0b0);
111 /* dark text, light background */
112 active_bordercolor = scale_color(bg_c,1.25);
113 inactive_bordercolor = scale_color(bg_c,1.01);
114 troughcolor = scale_color(bg_c,.8);
115 dimtextcolor = this->troughcolor;
116 sliderlit = scale_color(bg_c,1.75);
117 slidercolor = scale_color(this->sliderlit,.90);
121 needlecolor = 0xe07000;
122 needlelit = 0xff9000;
125 troughlines = Z4-Z1-1;
126 troughcols = w-CW-CW-ZR-ZL;
129 BluebananaSlider::~BluebananaSlider(){
130 if(trough) delete trough;
131 if(histval) delete[] histval;
132 if(histred) delete[] histred;
133 if(histgreen) delete[] histgreen;
134 if(histblue) delete[] histblue;
137 void BluebananaSlider::reposition(int x, int y, int w, int h){
138 BC_WindowBase::reposition_window(x,y,w,h);
139 if(trough) delete trough;
141 if(histval) delete[] histval;
143 if(histred) delete[] histred;
145 if(histgreen) delete[] histgreen;
147 if(histblue) delete[] histblue;
149 troughlines = Z4-Z1-1;
150 troughcols = w-CW-CW-ZR-ZL;
154 int BluebananaSlider::fraction_to_pixel(float input){
155 return (int)rint((input*(troughcols-1)+CW+ZL)+.001);
158 int BluebananaSlider::value_to_pixel(float input){
159 return fraction_to_pixel((input-minval)/(maxval-minval));
162 float BluebananaSlider::pixel_to_fraction(int pixel){
163 return (float)((pixel-CW-ZL)/(float)(troughcols-1));
166 float BluebananaSlider::pixel_to_value(int pixel){
167 float fraction=((pixel-CW-ZL)/(float)(troughcols-1));
168 return fraction*(maxval-minval)+minval;
171 static int inside_box(int cx, int cy, int x, int y, int w, int h){
172 return (cx>=x && cx<x+w && cy>=y && cy<y+h);
175 static int inside_vline(int cx, int cy, int x, int y0, int y1){
177 if(cy>=y0 && cy<=y1)return 1;
178 if(cy>=y1 && cy<=y0)return 1;
183 static int inside_hline(int cx, int cy, int x0, int x1, int y){
185 if(cx>=x0 && cx<=x1)return 1;
186 if(cx>=x1 && cx<=x0)return 1;
191 int BluebananaSlider::in_midslider(int x, int cx,int cy){
195 if( (cx-x)*(cx-x) + (cy-y)*(cy-y) < r*r ) return 1;
199 int BluebananaSlider::in_leftslider(int x,int cx, int cy){
203 if(inside_hline(cx,cy,x-1,x-Z1*2-1,Z4)) return 1;
205 if(inside_hline(cx,cy,x-(i*2),x-Z1*2-1,Z4-i)) return 1;
206 if(inside_hline(cx,cy,x-(i*2),x-Z1*2-1,Z4+i)) return 1;
209 if(inside_vline(cx,cy,x-Z1*2-2,Z4-Z1+1,Z4+Z1-1))return 1;
210 if(inside_vline(cx,cy,x,Z1+1,h-1))return 1;
215 int BluebananaSlider::in_rightslider(int x, int cx, int cy){
219 if(inside_hline(cx,cy,x+1,x+Z1*2+1,Z4)) return 1;
221 if(inside_hline(cx,cy,x+(i*2),x+Z1*2+1,Z4-i)) return 1;
222 if(inside_hline(cx,cy,x+(i*2),x+Z1*2+1,Z4+i)) return 1;
225 if(inside_vline(cx,cy,x+Z1*2+2,Z4-Z1+1,Z4+Z1-1))return 1;
226 if(inside_vline(cx,cy,x,Z1+1,h-1))return 1;
230 int BluebananaSlider::in_topslider(int x, int cx, int cy){
233 if(inside_vline(cx,cy,x,Z1*2,1))return 1;
235 if(inside_vline(cx,cy,x+i,1,Z1*2-i*2+1))return 1;
236 if(inside_vline(cx,cy,x-i,1,Z1*2-i*2+1))return 1;
238 if(inside_hline(cx,cy,x-Z1+1,x+Z1-1,0)) return 1;
242 int BluebananaSlider::in_overslider(int x,int cx, int cy){
247 int w2 = CW;//Z1*2-1;
248 if(cy<=Z1 && cx>=x-w2 && cx<=x+w2) return 1;
252 int BluebananaSlider::in_bottomslider(int x,int cx, int cy){
256 if(inside_vline(cx,cy,x,h-Z1*2-1,h-2))return 1;
258 if(inside_vline(cx,cy,x+i,h-2,h-Z1*2+i*2-2))return 1;
259 if(inside_vline(cx,cy,x-i,h-2,h-Z1*2+i*2-2))return 1;
261 if(inside_hline(cx,cy,x-Z1+1,x+Z1-1,h-1)) return 1;
265 int BluebananaSlider::in_leftslider2(int x,int cx){
266 if(cx<=x+2 && cx>x-CW) return 1;
270 int BluebananaSlider::in_rightslider2(int x,int cx){
271 if(cx<x+CW && cx>=x-2) return 1;
275 int BluebananaSlider::in_midslider2(int x,int cx){
276 if(cx>x-CW/2 && cx<x+CW/2) return 1;
280 int BluebananaSlider::in_overslider2(int x,int cx, int cy){
281 if(cx>x-CW/2 && cx<x+CW/2 && cy<=(Z1+Z4)/2) return 1;
285 void BluebananaSlider::draw_midslider(int x,int lit){
291 set_color(lit?sliderlit:slidercolor);
292 draw_disc(x-Z1+2,y0,Z1*2-3,y1-y0+1);
295 draw_circle(x-Z1+2,y0,Z1*2-3,y1-y0+1);
298 void BluebananaSlider::draw_leftslider(int x, int lit){
302 set_color(lit?sliderlit:slidercolor);
303 draw_line(x-1,Z4,x-Z1*2-1,Z4);
305 draw_line(x-(i*2),Z4-i,x-Z1*2-1,Z4-i);
306 draw_line(x-(i*2),Z4+i,x-Z1*2-1,Z4+i);
310 draw_line(x-1,Z4,x-1,Z4);
311 draw_line(x-Z1*2-2,Z4-Z1+1,x-Z1*2-2,Z4+Z1-1);
313 draw_line(x-(i*2),Z4-i,x-(i*2)-1,Z4-i);
314 draw_line(x-(i*2),Z4+i,x-(i*2)-1,Z4+i);
317 set_color(lit?needlelit:needlecolor);
318 draw_line(x,Z4-Z1,x,Z4+Z1);
321 void BluebananaSlider::draw_rightslider(int x, int lit){
325 set_color(lit?sliderlit:slidercolor);
326 draw_line(x+1,Z4,x+Z1*2+1,Z4);
328 draw_line(x+(i*2),Z4-i,x+Z1*2+1,Z4-i);
329 draw_line(x+(i*2),Z4+i,x+Z1*2+1,Z4+i);
333 draw_line(x+1,Z4,x+1,Z4);
334 draw_line(x+Z1*2+2,Z4-Z1+1,x+Z1*2+2,Z4+Z1-1);
336 draw_line(x+(i*2),Z4-i,x+(i*2)+1,Z4-i);
337 draw_line(x+(i*2),Z4+i,x+(i*2)+1,Z4+i);
340 set_color(lit?needlelit:needlecolor);
341 draw_line(x,Z4-Z1,x,Z4+Z1);
344 void BluebananaSlider::draw_topslider(int x, int lit){
348 set_color(lit?sliderlit:slidercolor);
349 draw_line(x,Z1*2,x,1);
351 draw_line(x+i,1,x+i,Z1*2-i*2+1);
352 draw_line(x-i,1,x-i,Z1*2-i*2+1);
356 draw_line(x-Z1+1,0,x+Z1-1,0);
357 draw_line(x,Z1*2+1,x,Z1*2+1);
359 draw_line(x+i, Z1*2-i*2+1, x+i, Z1*2-i*2+2);
360 draw_line(x-i, Z1*2-i*2+1, x-i, Z1*2-i*2+2);
364 void BluebananaSlider::draw_bottomslider(int x, int lit){
368 set_color(lit?sliderlit:slidercolor);
369 draw_line(x,h-Z1*2-1,x,h-2);
371 draw_line(x+i,h-2,x+i,h-Z1*2+i*2-2);
372 draw_line(x-i,h-2,x-i,h-Z1*2+i*2-2);
376 draw_line(x-Z1+1,h-1,x+Z1-1,h-1);
377 draw_line(x,h-Z1*2-2,x,h-Z1*2-2);
379 draw_line(x+i,h-Z1*2+i*2-2,x+i,h-Z1*2+i*2-3);
380 draw_line(x-i,h-Z1*2+i*2-2,x-i,h-Z1*2+i*2-3);
384 void BluebananaSlider::draw_overslider(int x, int lit){
391 int bg_c = get_resources()->get_bg_color();
392 int bg_r = ((bg_c >> 16) & 0xff);
393 int bg_g = ((bg_c >> 8) & 0xff);
394 int bg_b = (bg_c & 0xff);
395 float del = lit ? 1. : .9;
396 set_color(((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del)));
397 draw_box(x-w2+1,0,w2*2-2,Z1);
398 draw_box(x-w2,1,w2*2+1,Z1-2);
400 set_color(lit?sliderlit:slidercolor);
401 draw_box(x-w2+2,1,w2*2-3,Z1-2);
402 draw_box(x-w2+1,2,w2*2-1,Z1-4);
404 set_color(((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del)));
405 draw_line(x,2,x,Z1-3);
408 int BluebananaSlider::button_release_event(){
413 cursor_motion_event();
420 void BluebananaSlider::update(){
423 int bg_c = get_resources()->get_bg_color();
424 int bg_r = ((bg_c >> 16) & 0xff);
425 int bg_g = ((bg_c >> 8) & 0xff);
426 int bg_b = (bg_c & 0xff);
427 int b_c = highlight ? active_bordercolor : inactive_bordercolor;
428 int b_r = ((b_c >> 16) & 0xff);
429 int b_g = ((b_c >> 8) & 0xff);
430 int b_b = (b_c & 0xff);
431 int tb_c = troughcolor;
432 int tb_r = ((tb_c >> 16) & 0xff);
433 int tb_g = ((tb_c >> 8) & 0xff);
434 int tb_b = (tb_c & 0xff);
441 clear_box(0, 0, w, h);
445 int shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
447 draw_box (0,Z1,w,ZH+2);
448 draw_box (1,Z1-1,w-2,ZH+4);
451 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
453 draw_box (1,Z1+1,w-2,ZH);
454 draw_box (2,Z1,w-4,ZH+2);
457 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
459 draw_box (2,Z1+2,w-4,ZH-2);
460 draw_box (3,Z1+1,w-6,ZH);
464 draw_box (1,Z1+1,w-4,ZH-2);
465 draw_box (2,Z1,w-6,ZH);
468 int ntw = troughcols;
469 int nth = troughlines;
474 trough = new VFrame(ntw,nth,BC_RGBA8888);
478 fprintf(stderr,"Bluebanana: Unable to create Frame for slider\n");
480 unsigned char *data = trough->get_data();
481 long bpr = trough->get_bytes_per_line();
490 if(histval){ // trough is a histogram and has data
491 long bpp = trough->get_bytes_per_pixel();
496 unsigned char *row = data;
497 float y = nth-histval[i];
498 float y0 = i>0?nth-histval[i-1]:y;
499 float y1 = i+1<ntw?nth-histval[i+1]:y;
500 float yp = MIN(y,MIN(y0+1,y1+1));
501 float y3 = (y0+y+y1)*.333f;
504 trough_color((i+.5f)/ntw,0.f,rr,gg,bb,aa);
508 rr = CLAMP((rr+b_r*3)/4,0,255);
509 gg = CLAMP((gg+b_g*3)/4,0,255);
510 bb = CLAMP((bb+b_b*3)/4,0,255);
517 trough_color((i+.5)/ntw,0,r,g,b,a);
523 for(j=0;j<yp-1 && j<nth;j++){
532 for(;j<y && j<nth;j++){
533 row[0] = rint(rr*a + tb_r*(1-a));
534 row[1] = rint(gg*a + tb_g*(1-a));
535 row[2] = rint(bb*a + tb_b*(1-a));
542 float a = CLAMP(1. - .3*(float)(j-y3)/(nth-y3+1),0.f,1.f)*ha;
543 row[0] = rint(r*a*255.f + tb_r*(1-a));
544 row[1] = rint(g*a*255.f + tb_g*(1-a));
545 row[2] = rint(b*a*255.f + tb_b*(1-a));
554 unsigned char *row = data + i*trough->get_bytes_per_pixel();
557 trough_color((i+.5f)/ntw,(j+.5)/nth,r,g,b,a);
563 row[0] = rint(r*a*255 + tb_r*(1-a));
564 row[1] = rint(g*a*255 + tb_g*(1-a));
565 row[2] = rint(b*a*255 + tb_b*(1-a));
571 draw_vframe(trough,ntx,nty);
575 // quick/dirty unnormalized linear resample from native -> display size
576 static void resample_histogram(float *raw, float *raw_red, float *raw_green, float *raw_blue,
577 float *out, float *out_red, float *out_green, float *out_blue,
578 int raw_n, int raw_off, int out_n, int out_start, int out_end){
579 float coverage = (float)raw_n/out_n;
580 float scale = coverage;
581 if(coverage<1.)coverage=1.;
582 float icoverage = 1./coverage;
584 float raw_center = out_start*scale+raw_off;
585 float raw_start = raw_center-coverage;
586 float raw_end = raw_center+coverage;
588 for(int i=out_start; i<out_end; i++){
592 if(e>HISTSIZE)e=HISTSIZE;
594 float k = (j-raw_start)*icoverage-1.f;
598 float ik = 1.-fabs(k);
608 coverage = (float)raw_n/out_n;
610 if(coverage<(1<<HRGBSHIFT))coverage=(1<<HRGBSHIFT);
611 icoverage = 1./coverage;
613 raw_center = out_start*scale+raw_off;
614 raw_start = raw_center-coverage;
615 raw_end = raw_center+coverage;
617 for(int i=out_start; i<out_end; i++){
621 if(e>HISTSIZE)e=HISTSIZE;
623 float k = (j-raw_start)*icoverage-1.f;
624 float r=0.f, g=0.f, b=0.f, a=0.f;
626 float ik = 1.-fabs(k);
627 int sj = (j>>HRGBSHIFT);
628 int sjs = sj<<HRGBSHIFT;
654 g += raw_green[sj]*ik;
655 b += raw_blue[sj]*ik;
660 out_red[i] = CLAMP(r*a,0.f,1.f);
661 out_green[i] = CLAMP(g*a,0.f,1.f);
662 out_blue[i] = CLAMP(b*a,0.f,1.f);
669 void BluebananaSlider::update_histogram(float *raw, float *red, float *green, float *blue, int n){
673 float il2n = 1./log2(n);
676 histval = new float[w];
679 histred = new float[w];
680 histgreen = new float[w];
681 histblue = new float[w];
684 /* resample center */
685 resample_histogram(raw, red, green, blue, histval, histred, histgreen, histblue,
686 HISTSIZE, 0, w, 0, w);
688 /* select value normalization */
690 if(histval[i]<=.0001f){
693 float val = log2(histval[i])*il2n;
694 val = pow(val<0?0:val,.75)*h;
703 // ---------------------------- Single ----------------------------------
705 BluebananaSliderSingle::BluebananaSliderSingle(BluebananaMain *plugin,
706 BluebananaWindow *gui,
713 : BluebananaSlider(plugin,gui,x,y,w,h,minval,maxval){
714 val = (minval+maxval)/2;
718 int BluebananaSliderSingle::button_press_event(){
719 if(is_event_win() && cursor_inside()){
722 int cx = get_cursor_x();
726 if(get_buttonpress() == 4){
727 set_val(val - increment);
729 }else if(get_buttonpress() == 5){
730 set_val(val + increment);
736 xoff = cx-value_to_pixel(val);
749 int BluebananaSliderSingle::cursor_motion_event(){
750 int cx = get_cursor_x();
751 //int cy = get_cursor_y();
756 set_val(pixel_to_value(cx - xoff));
766 if(is_event_win() && cursor_inside()){
768 if(in_midslider2(value_to_pixel(val),cx)){
790 void BluebananaSliderSingle::set_val(float v){
792 if(val<minval)val=minval;
793 if(val>maxval)val=maxval;
798 void BluebananaSliderSingle::update(){
799 BluebananaSlider::update();
800 draw_bottomslider(value_to_pixel(val),light==0);
805 // ---------------------------- Bracket ----------------------------------
807 BluebananaSliderBracket::BluebananaSliderBracket(BluebananaMain *plugin,
808 BluebananaWindow *gui,
815 : BluebananaSlider(plugin,gui,x,y,w,h,minval,maxval){
817 midval = (minval+maxval)/2;
823 int BluebananaSliderBracket::button_press_event(){
824 if(is_event_win() && cursor_inside()){
827 int cx = get_cursor_x();
832 /* narrow/widen range */
833 if(get_buttonpress() == 4){
834 set_delta(increment*2);
836 }else if(get_buttonpress() == 5){
837 set_delta(-increment*2);
840 }else if (ctrl_down()){
841 /* shift all vals up/down */
842 if(get_buttonpress() == 4){
843 set_mid(midval-increment);
845 }else if(get_buttonpress() == 5){
846 set_mid(midval+increment);
850 /* increase/decrease overlap */
851 if(get_buttonpress() == 4){
854 }else if(get_buttonpress() == 5){
862 xoff = cx-value_to_pixel(loval);
865 xoff = cx-value_to_pixel(midval);
868 xoff = cx-value_to_pixel(hival);
871 xoff = cx-value_to_pixel(overval);
884 int BluebananaSliderBracket::cursor_motion_event(){
885 int cx = get_cursor_x();
886 int cy = get_cursor_y();
891 set_lo(pixel_to_value(cx - xoff));
894 set_mid(pixel_to_value(cx - xoff));
897 set_hi(pixel_to_value(cx - xoff));
900 set_over(pixel_to_value(cx - xoff));
910 if(is_event_win() && cursor_inside()){
911 if(in_overslider(value_to_pixel(overval),cx,cy)){
916 }else if(in_midslider(value_to_pixel(midval),cx,cy)){
921 }else if(in_leftslider(value_to_pixel(loval),cx,cy)){
926 }else if(in_rightslider(value_to_pixel(hival),cx,cy)){
931 }else if(in_midslider2(value_to_pixel(midval),cx)){
936 }else if(in_rightslider2(value_to_pixel(hival),cx)){
941 }else if(in_leftslider2(value_to_pixel(loval),cx)){
946 }else if(in_overslider2(value_to_pixel(overval),cx,cy)){
968 void BluebananaSliderBracket::set_lo(float val){
969 if(val<minval)val=minval;
970 if(val>maxval)val=maxval;
971 if(val > hival) val=hival;
974 if(hival<loval)hival+=(maxval-minval);
975 if(midval<loval)midval+=(maxval-minval);
976 midval = (hival+loval)/2.;
977 if(hival>maxval)hival-=(maxval-minval);
978 if(midval>maxval)midval-=(maxval-minval);
979 if(loval>maxval)loval-=(maxval-minval);
980 if(hival<minval)hival+=(maxval-minval);
981 if(midval<minval)midval+=(maxval-minval);
982 if(loval<minval)loval+=(maxval-minval);
987 void BluebananaSliderBracket::set_mid(float val){
988 //float oldmid=midval;
989 if(val<minval)val=minval;
990 if(val>maxval)val=maxval;
993 float delta = (hival+loval)/2.;
997 loval += maxval-hival;
998 midval += maxval-hival;
1010 void BluebananaSliderBracket::set_hi(float val){
1011 if(val<minval)val=minval;
1012 if(val>maxval)val=maxval;
1013 if(val<loval)val=loval;
1016 if(loval>hival)loval-=(maxval-minval);
1017 if(midval>hival)midval-=(maxval-minval);
1018 midval=(hival+loval)/2.;
1019 if(hival>maxval)hival-=(maxval-minval);
1020 if(midval>maxval)midval-=(maxval-minval);
1021 if(loval>maxval)loval-=(maxval-minval);
1022 if(hival<minval)hival+=(maxval-minval);
1023 if(midval<minval)midval+=(maxval-minval);
1024 if(loval<minval)loval+=(maxval-minval);
1030 void BluebananaSliderBracket::set_delta(float incr){
1031 float delta = (hival-loval)+incr;
1032 if(delta<minval)delta=minval;
1033 if(delta>maxval)delta=maxval;
1034 loval = midval-delta/2;
1035 hival = loval+delta;
1043 loval-=(hival-maxval);
1044 midval-=(hival-maxval);
1051 void BluebananaSliderBracket::set_over(float val){
1052 if(val<minval)val=minval;
1053 if(val>maxval)val=maxval;
1060 void BluebananaSliderBracket::update(){
1061 BluebananaSlider::update();
1062 draw_overslider(value_to_pixel(overval),light==3);
1063 draw_leftslider(value_to_pixel(loval),light==0);
1064 draw_rightslider(value_to_pixel(hival),light==2);
1065 draw_midslider(value_to_pixel(midval),light==1);
1070 // ----------------------- Circular Bracket -----------------------------
1072 BluebananaSliderCircular::BluebananaSliderCircular(BluebananaMain *plugin,
1073 BluebananaWindow *gui,
1080 : BluebananaSliderBracket(plugin,gui,x,y,w,h,minval,maxval){}
1082 void BluebananaSliderCircular::set_lo(float val){
1083 if(val<minval)val=minval;
1084 if(val>maxval)val=maxval;
1087 if(hival<loval)hival+=(maxval-minval);
1088 if(midval<loval)midval+=(maxval-minval);
1089 midval = (hival+loval)/2.;
1090 if(hival>maxval)hival-=(maxval-minval);
1091 if(midval>maxval)midval-=(maxval-minval);
1092 if(loval>maxval)loval-=(maxval-minval);
1093 if(hival<minval)hival+=(maxval-minval);
1094 if(midval<minval)midval+=(maxval-minval);
1095 if(loval<minval)loval+=(maxval-minval);
1101 void BluebananaSliderCircular::set_mid(float val){
1102 float oldmid=midval;
1103 if(val<minval)val=minval;
1104 if(val>maxval)val=maxval;
1106 if(hival<oldmid)hival+=(maxval-minval);
1107 if(loval>oldmid)loval-=(maxval-minval);
1108 float delta = hival-loval;
1109 loval = midval-delta/2;
1110 hival = loval+delta;
1111 if(hival>maxval)hival-=(maxval-minval);
1112 if(loval>maxval)loval-=(maxval-minval);
1113 if(hival<minval)hival+=(maxval-minval);
1114 if(loval<minval)loval+=(maxval-minval);
1119 void BluebananaSliderCircular::set_hi(float val){
1120 if(val<minval)val=minval;
1121 if(val>maxval)val=maxval;
1123 if(loval>hival)loval-=(maxval-minval);
1124 if(midval>hival)midval-=(maxval-minval);
1125 midval = (hival+loval)/2.;
1126 if(hival>maxval)hival-=(maxval-minval);
1127 if(midval>maxval)midval-=(maxval-minval);
1128 if(loval>maxval)loval-=(maxval-minval);
1129 if(hival<minval)hival+=(maxval-minval);
1130 if(midval<minval)midval+=(maxval-minval);
1131 if(loval<minval)loval+=(maxval-minval);
1136 void BluebananaSliderCircular::set_delta(float incr){
1137 if(hival<midval)hival+=(maxval-minval);
1138 if(loval>midval)loval-=(maxval-minval);
1140 float delta = (hival-loval)+incr;
1141 if(delta<minval)delta=minval;
1142 if(delta>maxval)delta=maxval;
1143 loval = midval-delta/2;
1144 hival = loval+delta;
1146 if(hival>maxval)hival-=(maxval-minval);
1147 if(loval>maxval)loval-=(maxval-minval);
1148 if(hival<minval)hival+=(maxval-minval);
1149 if(loval<minval)loval+=(maxval-minval);
1154 void BluebananaSliderCircular::update(){
1155 BluebananaSliderBracket::update();
1160 // -------------------------- In + Out + Gamma --------------------------------
1162 #define mG2 (2.f-2.f*MIN_GAMMA)
1163 #define MG2 (2.f*MAX_GAMMA-2.f)
1165 float BluebananaSliderChannel::pixel_to_gamma(float pixel){
1166 float unit = (1.-pixel_to_fraction(pixel)-FRAC0)/(FRAC100-FRAC0);
1167 return (unit > .5f ?
1168 (1.f-unit) * mG2 + MIN_GAMMA :
1169 (.5f-unit) * MG2 + 1.f );
1172 float BluebananaSliderChannel::gamma_to_pixel(float gamma){
1174 gamma<1 ? 1.f - (gamma-MIN_GAMMA) / mG2 :
1175 .5f - (gamma-1.f) / MG2 ;
1176 return fraction_to_pixel((1.-fraction) * (FRAC100-FRAC0) + FRAC0);
1179 float BluebananaSliderChannel::pixel_to_value(float pixel){
1181 return (t_x0-pixel)/t_w01*MIN_HISTBRACKET+MIN_HISTBRACKET;
1182 }else if (pixel<t_x2){
1183 return (pixel-t_x1)/t_w12*100;
1185 return (pixel-t_x2)/t_w23*(MAX_HISTBRACKET-100)+100;
1189 float BluebananaSliderChannel::value_to_pixel(float val){
1191 return rint(MIN_HISTBRACKET-val)/MIN_HISTBRACKET*t_w01+t_x0;
1193 return rint(val/100.*t_w12+t_x1+.01);
1195 return rint((val-100)/(MAX_HISTBRACKET-100.)*t_w23+t_x2);
1199 BluebananaSliderChannel::BluebananaSliderChannel(BluebananaMain *plugin,
1200 BluebananaWindow *gui,
1205 : BluebananaSlider(plugin,gui,x,y,w,h,0,100){
1211 BluebananaSliderChannel::~BluebananaSliderChannel(){}
1213 int BluebananaSliderChannel::button_press_event(){
1214 if(is_event_win() && cursor_inside()){
1217 int cx = get_cursor_x();
1218 //int cy = get_cursor_y();
1223 /* narrow/widen range */
1224 if(get_buttonpress() == 4){
1225 set_range(hival-loval-2);
1227 }else if(get_buttonpress() == 5){
1229 set_range(hival-loval+2);
1233 }else if (ctrl_down()){
1234 /* shift all vals up/down */
1235 if(get_buttonpress() == 4){
1236 set_mid((loval+hival)/2+1);
1238 }else if(get_buttonpress() == 5){
1239 set_mid((loval+hival)/2-1);
1243 /* increase/decrease gamma */
1244 if(get_buttonpress() == 4){
1245 set_gamma(gamma-.01);
1247 }else if(get_buttonpress() == 5){
1248 set_gamma(gamma+.01);
1255 xoff = cx-value_to_pixel(loval);
1258 xoff = cx-value_to_pixel((loval+hival)/2);
1261 xoff = cx-value_to_pixel(hival);
1264 xoff = cx-gamma_to_pixel(gamma);
1277 int BluebananaSliderChannel::cursor_motion_event(){
1278 int cx = get_cursor_x();
1279 int cy = get_cursor_y();
1284 set_lo(pixel_to_value(cx - xoff));
1287 set_mid(pixel_to_value(cx - xoff));
1290 set_hi(pixel_to_value(cx - xoff));
1293 set_gamma(pixel_to_gamma(cx - xoff));
1303 if(is_event_win() && cursor_inside()){
1304 if(in_topslider(gamma_to_pixel(gamma),cx,cy)){
1309 }else if(in_midslider(value_to_pixel((loval+hival)/2),cx,cy)){
1314 }else if(in_leftslider(value_to_pixel(loval),cx,cy)){
1319 }else if(in_rightslider(value_to_pixel(hival),cx,cy)){
1324 }else if(in_bottomslider(value_to_pixel(hival),cx,cy)){
1329 }else if(in_bottomslider(value_to_pixel(loval),cx,cy)){
1334 }else if(in_midslider2(value_to_pixel((loval+hival)/2),cx)){
1339 }else if(in_overslider2(gamma_to_pixel(gamma),cx,cy)){
1361 void BluebananaSliderChannel::set_lo(float v){
1370 void BluebananaSliderChannel::set_hi(float v){
1379 void BluebananaSliderChannel::set_mid(float v){
1380 float mid = (hival+loval)*.5;
1381 float range = hival-loval;
1384 if(hival+del>200)del=200-hival;
1385 if(hival+del<0)del=0-hival;
1386 if(loval+del>100)del=100-loval;
1387 if(loval+del<-100)del=-100-loval;
1390 hival=loval+rint(range);
1395 void BluebananaSliderChannel::set_range(float v){
1396 //float mid = (hival+loval)*.5;
1397 float range = hival-loval;
1402 float del = (v-range)/2;
1404 if(hival+del>200)del=200-hival;
1405 if(hival+del<0)del=0-hival;
1407 if(loval-del>100)del=loval-100;
1408 if(loval-del<-100)del=loval+100;
1411 hival=rint(loval+v);
1416 void BluebananaSliderChannel::set_gamma(float v){
1417 if(v>MAX_GAMMA)v=MAX_GAMMA;
1418 if(v<MIN_GAMMA)v=MIN_GAMMA;
1424 void BluebananaSliderChannel::update(){
1427 int bg_c = get_resources()->get_bg_color();
1428 int bg_r = ((bg_c >> 16) & 0xff);
1429 int bg_g = ((bg_c >> 8) & 0xff);
1430 int bg_b = (bg_c & 0xff);
1431 int b_c = highlight ? active_bordercolor : inactive_bordercolor;
1432 int b_r = ((b_c >> 16) & 0xff);
1433 int b_g = ((b_c >> 8) & 0xff);
1434 int b_b = (b_c & 0xff);
1435 int tb_c = troughcolor;
1436 int tb_r = ((tb_c >> 16) & 0xff);
1437 int tb_g = ((tb_c >> 8) & 0xff);
1438 int tb_b = (tb_c & 0xff);
1441 //int ZHC = Z4-ZC+1;
1445 t_x0 = fraction_to_pixel(0);
1446 t_x1 = fraction_to_pixel(FRAC0);
1447 t_x2 = fraction_to_pixel(FRAC100);
1448 t_x3 = fraction_to_pixel(1.);
1454 int ntw = troughcols-6;
1455 int nth = troughlines;
1459 clear_box(0, 0, w, h);
1463 /* w+4 h+4 x-1 y-1 */
1465 int shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1466 set_color(shadow_c);
1467 draw_box (0,Z1,t_x1+3,ZH+2);
1468 draw_box (1,Z1-1,t_x1+1,ZH+4);
1469 draw_box (t_x1,Z1,t_w12+3,ZH+2);
1470 draw_box (t_x1+1,Z1-1,t_w12+1,ZH+4);
1471 draw_box (t_x2,Z1,w-t_x2,ZH-2+2);
1472 draw_box (t_x2+1,Z1-1,w-t_x2-2,ZH+4);
1476 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1477 set_color(shadow_c);
1478 draw_box (1,Z1+1,t_x1+1,ZH);
1479 draw_box (2,Z1,t_x1-1,ZH+2);
1480 draw_box (t_x1+1,Z1+1,t_w12+1,ZH);
1481 draw_box (t_x1+2,Z1,t_w12-1,ZH+2);
1482 draw_box (t_x2+1,Z1+1,w-t_x2-2,ZH);
1483 draw_box (t_x2+2,Z1,w-t_x2-4,ZH+2);
1487 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1488 set_color(shadow_c);
1489 draw_box (2,Z1+2,t_x1-1,ZH-2);
1490 draw_box (3,Z1+1,t_x1-3,ZH);
1491 draw_box (t_x1+2,Z1+2,t_w12-1,ZH-2);
1492 draw_box (t_x1+3,Z1+1,t_w12-3,ZH);
1493 draw_box (t_x2+2,Z1+2,w-t_x2-4,ZH-2);
1494 draw_box (t_x2+3,Z1+1,w-t_x2-6,ZH);
1498 draw_box (1,Z1+1,t_x1-1,ZH-2);
1499 draw_box (2,Z1,t_x1-3,ZH);
1500 draw_box (t_x1+1,Z1+1,t_w12-1,ZH-2);
1501 draw_box (t_x1+2,Z1,t_w12-3,ZH);
1502 draw_box (t_x2+1,Z1+1,w-t_x2-4,ZH-2);
1503 draw_box (t_x2+2,Z1,w-t_x2-6,ZH);
1506 /* the trough in the three-part hist slider is slightly smaller than
1507 the full slider range, and cut into three sections */
1509 trough = new VFrame(ntw,nth,BC_RGBA8888);
1513 fprintf(stderr,"Bluebanana: Unable to create Frame for slider\n");
1515 unsigned char *data = trough->get_data();
1517 long bpp = trough->get_bytes_per_pixel();
1518 long bpr = trough->get_bytes_per_line();
1519 float r,g,b,a,rr,gg,bb;
1531 unsigned char *row = data;
1543 trough_color(1.,rr,gg,bb);
1547 rr = CLAMP((rr+b_r*3)/4,0,255);
1548 gg = CLAMP((gg+b_g*3)/4,0,255);
1549 bb = CLAMP((bb+b_b*3)/4,0,255);
1552 unsigned char *row = data;
1553 float y = nth-histval[i];
1554 float y0 = i>0?nth-histval[i-1]:y;
1555 float y1 = i+1<ntw?nth-histval[i+1]:y;
1556 float yp = MIN(y,MIN(y0+1,y1+1));
1557 float y3 = (y0+y+y1)*.333f;
1564 float val = (i < t_w01-1 ?
1565 ((MIN_HISTBRACKET/100.f) - i/(t_w01-1.f)*(MIN_HISTBRACKET/100.f)) :
1567 ((i - t_w01 + 1) / (t_w12-4.f)) :
1568 ((i - t_w01 - t_w12 + 5) / (t_w23-1.f)*((MAX_HISTBRACKET/100.f)-1.f)+1.f)));
1570 trough_color(val,r,g,b);
1577 for(j=0;j<yp-1 && j<nth;j++){
1586 for(;j<y && j<nth;j++){
1587 row[0] = rint(rr*a + tb_r*(1-a));
1588 row[1] = rint(gg*a + tb_g*(1-a));
1589 row[2] = rint(bb*a + tb_b*(1-a));
1596 float a = CLAMP(1. - .3*(float)(j-y3)/(nth-y3+1),0.f,1.f)*ha;
1597 row[0] = rint(r*a*255.f + tb_r*(1-a));
1598 row[1] = rint(g*a*255.f + tb_g*(1-a));
1599 row[2] = rint(b*a*255.f + tb_b*(1-a));
1608 draw_vframe(trough, ntx, nty, t_w01-2, 1, 0, 0, t_w01-2, 1);
1609 draw_vframe(trough, ntx, nty+1, t_w01-1, nth-2, 0, 1, t_w01-1, nth-2);
1610 draw_vframe(trough, ntx, nty+nth-1, t_w01-2, 1, 0, nth-1, t_w01-2, 1);
1612 draw_vframe(trough, t_x1+3, nty, t_w12-5, 1, t_w01, 0, t_w12-5, 1);
1613 draw_vframe(trough, t_x1+2, nty+1, t_w12-3, nth-2, t_w01-1, 1, t_w12-3, nth-2);
1614 draw_vframe(trough, t_x1+3, nty+nth-1, t_w12-5, 1, t_w01, nth-1, t_w12-5, 1);
1616 draw_vframe(trough, t_x2+3, nty, t_w23-2, 1, t_w01+t_w12-3, 0, t_w23-2, 1);
1617 draw_vframe(trough, t_x2+2, nty+1, t_w23-1, nth-2, t_w01+t_w12-4, 1, t_w23-1, nth-2);
1618 draw_vframe(trough, t_x2+3, nty+nth-1, t_w23-2, 1, t_w01+t_w12-3, nth-1, t_w23-2, 1);
1621 draw_topslider(rint(gamma_to_pixel(gamma)),light==3);
1623 draw_bottomslider(rint(value_to_pixel(loval)),light==0);
1624 draw_bottomslider(rint(value_to_pixel(hival)),light==2);
1625 draw_midslider(rint(value_to_pixel((loval+hival)/2.)),light==1);
1631 void BluebananaSliderChannel::update_histogram(float *raw, float *red, float *green, float *blue, int n){
1633 //int h = troughlines;
1634 int w = troughcols-6;
1635 float il2n = 1./log2(n);
1641 histval = new float[w];
1643 if(!histred && red){
1644 histred = new float[w];
1645 histgreen = new float[w];
1646 histblue = new float[w];
1650 int span0 = rint((0.f-MIN_HISTBRACKET) / (MAX_HISTBRACKET-MIN_HISTBRACKET) * HISTSIZE);
1651 resample_histogram(raw, red, green, blue, histval, histred, histgreen, histblue,
1652 span0, 0, w0, 0, w0);
1654 /* resample center */
1655 int span1 = rint(100.f/(MAX_HISTBRACKET-MIN_HISTBRACKET) * HISTSIZE);
1656 resample_histogram(raw, red, green, blue, histval+w0, histred+w0, histgreen+w0, histblue+w0,
1657 span1, span0, w1, 0, w1+1);
1659 /* resample right */
1660 int span2 = rint((MAX_HISTBRACKET-100.f) / (MAX_HISTBRACKET-MIN_HISTBRACKET) * HISTSIZE);
1661 resample_histogram(raw, red, green, blue, histval+w0+w1, histred+w0+w1, histgreen+w0+w1, histblue+w0+w1,
1662 span2, span0+span1, w2, 1, w2+1);
1664 /* select value normalization */
1666 if(histval[i]<=.0001f){
1669 float val = log2(histval[i])*il2n;
1670 val = pow(val<0?0:val,.75)*troughlines;
1672 if(val>troughlines)val=troughlines;
1679 // ---------------------------- Fill ----------------------------------
1681 int BluebananaSliderFill::over_to_pixel(float input){
1682 return fraction_to_pixel(input/maxover);
1685 float BluebananaSliderFill::pixel_to_over(int pixel){
1686 return pixel_to_fraction(pixel)*maxover;
1689 BluebananaSliderFill::BluebananaSliderFill(BluebananaMain *plugin,
1690 BluebananaWindow *gui,
1698 : BluebananaSlider(plugin,gui,x,y,w,h,minval,maxval){
1703 this->maxover = maxover;
1706 int BluebananaSliderFill::button_press_event(){
1707 if(is_event_win() && cursor_inside()){
1710 int cx = get_cursor_x();
1715 /* narrow/widen range */
1716 if(get_buttonpress() == 4){
1719 }else if(get_buttonpress() == 5){
1723 }else if (ctrl_down()){
1724 /* shift all vals up/down */
1725 if(get_buttonpress() == 4){
1726 if(loval-increment>minval)
1727 set_fill(loval-1,midval-1,hival-1);
1729 }else if(get_buttonpress() == 5){
1730 if(hival+increment<maxval)
1731 set_fill(loval+1,midval+1,hival+1);
1735 /* increase/decrease feather */
1736 if(get_buttonpress() == 4){
1737 set_over(overval-1);
1739 }else if(get_buttonpress() == 5){
1740 set_over(overval+1);
1747 xoff = cx-value_to_pixel(loval);
1750 xoff = cx-value_to_pixel(midval);
1753 xoff = cx-value_to_pixel(hival);
1756 xoff = cx-over_to_pixel(overval);
1769 int BluebananaSliderFill::cursor_motion_event(){
1770 int cx = get_cursor_x();
1771 int cy = get_cursor_y();
1776 set_fill(pixel_to_value(cx - xoff),midval,hival);
1779 set_fill(loval,pixel_to_value(cx - xoff),hival);
1782 set_fill(loval,midval,pixel_to_value(cx - xoff));
1785 set_over(pixel_to_over(cx - xoff));
1795 if(is_event_win() && cursor_inside()){
1796 if(in_overslider(over_to_pixel(overval),cx,cy)){
1801 }else if(in_bottomslider(value_to_pixel(midval),cx,cy)){
1806 }else if(in_leftslider(value_to_pixel(loval),cx,cy)){
1811 }else if(in_rightslider(value_to_pixel(hival),cx,cy)){
1816 }else if(in_midslider2(value_to_pixel(midval),cx)){
1821 }else if(in_rightslider2(value_to_pixel(hival),cx)){
1826 }else if(in_leftslider2(value_to_pixel(loval),cx)){
1831 }else if(in_overslider2(over_to_pixel(overval),cx,cy)){
1853 void BluebananaSliderFill::set_fill(float lo, float mid, float hi){
1854 if(lo<minval)lo=minval;
1855 if(mid<minval)mid=minval;
1858 if(mid>maxval)mid=maxval;
1859 if(hi>maxval)hi=maxval;
1861 if(lo>midval)mid=lo;
1862 if(mid<loval)lo=mid;
1863 if(mid>hival)hi=mid;
1864 if(hi<midval)mid=hi;
1874 void BluebananaSliderFill::set_delta(float del){
1875 if(loval+del>=minval && hival+del<=maxval){
1879 loval=hival=rint((loval+hival)/2);
1880 if(midval<loval)midval=loval;
1881 if(midval>hival)midval=hival;
1887 void BluebananaSliderFill::set_over(float over){
1888 if(over>=0 && over<=maxover){
1895 void BluebananaSliderFill::update(){
1898 int bg_c = get_resources()->get_bg_color();
1899 int bg_r = ((bg_c >> 16) & 0xff);
1900 int bg_g = ((bg_c >> 8) & 0xff);
1901 int bg_b = (bg_c & 0xff);
1902 int b_c = highlight ? active_bordercolor : inactive_bordercolor;
1903 //int b_r = ((b_c >> 16) & 0xff);
1904 //int b_g = ((b_c >> 8) & 0xff);
1905 //int b_b = (b_c & 0xff);
1906 int tb_c = troughcolor;
1907 int tb_r = ((tb_c >> 16) & 0xff);
1908 int tb_g = ((tb_c >> 8) & 0xff);
1909 int tb_b = (tb_c & 0xff);
1912 //int ZHC = Z4-ZC+1;
1916 int xC = value_to_pixel(0);
1917 int ntw = troughcols;
1918 int nth = troughlines;
1922 clear_box(0, 0, w, h);
1926 /* w+4 h+4 x-1 y-1 */
1928 int shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1929 set_color(shadow_c);
1930 draw_box (0,Z1,xC+3,ZH+2);
1931 draw_box (1,Z1-1,xC+1,ZH+4);
1932 draw_box (xC,Z1,w-xC,ZH+2);
1933 draw_box (xC+1,Z1-1,w-xC-2,ZH+4);
1937 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1938 set_color(shadow_c);
1939 draw_box (1,Z1+1,xC+1,ZH);
1940 draw_box (2,Z1,xC-1,ZH+2);
1941 draw_box (xC+1,Z1+1,w-xC-2,ZH);
1942 draw_box (xC+2,Z1,w-xC-4,ZH+2);
1946 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1947 set_color(shadow_c);
1948 draw_box (2,Z1+2,xC-1,ZH-2);
1949 draw_box (3,Z1+1,xC-3,ZH);
1950 draw_box (xC+2,Z1+2,w-xC-4,ZH-2);
1951 draw_box (xC+3,Z1+1,w-xC-6,ZH);
1955 draw_box (1,Z1+1,xC-1,ZH-2);
1956 draw_box (2,Z1,xC-3,ZH);
1957 draw_box (xC+1,Z1+1,w-xC-4,ZH-2);
1958 draw_box (xC+2,Z1,w-xC-6,ZH);
1961 /* the trough in the two-part contour slider is slightly smaller than
1962 the full slider range, and cut into two sections */
1964 trough = new VFrame(ntw,nth,BC_RGBA8888);
1967 /* Unlike the hist slider, we just drop the three pixel columns in the center */
1969 fprintf(stderr,"Bluebanana: Unable to create Frame for slider\n");
1971 unsigned char *data = trough->get_data();
1972 long bpr = trough->get_bytes_per_line();
1982 unsigned char *row = data + i*trough->get_bytes_per_pixel();
1985 trough_color((i+.5f)/ntw,(j+.5)/nth,r,g,b,a);
1990 row[0] = rint(r*a*255 + tb_r*(1-a));
1991 row[1] = rint(g*a*255 + tb_g*(1-a));
1992 row[2] = rint(b*a*255 + tb_b*(1-a));
1998 draw_vframe(trough, ntx, nty, xC-ntx-2, 1, 0, 0, xC-ntx-2, 1);
1999 draw_vframe(trough, ntx, nty+1, xC-ntx-1, nth-2, 0, 1, xC-ntx-1, nth-2);
2000 draw_vframe(trough, ntx, nty+nth-1, xC-ntx-2, 1, 0, nth-1, xC-ntx-2, 1);
2002 draw_vframe(trough, xC+3, nty, ntw-xC+ntx-3, 1, xC-ntx+2, 0, ntw-xC+ntx-3, 1);
2003 draw_vframe(trough, xC+2, nty+1, ntw-xC+ntx-2, nth-2, xC-ntx+1, 1, ntx-xC+ntx-2, nth-2);
2004 draw_vframe(trough, xC+3, nty+nth-1, ntw-xC+ntx-3, 1, xC-ntx+2, nth-1, ntw-xC+ntx-3, 1);
2007 draw_overslider(over_to_pixel(overval),light==3);
2008 draw_leftslider(value_to_pixel(loval),light==0);
2009 draw_rightslider(value_to_pixel(hival),light==2);
2010 draw_bottomslider(value_to_pixel(midval),light==1);