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"
25 #define CLAMP(x, y, z) ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x)))
27 #define CW (get_h()/2+2)
28 #define SW (get_h()*2/5+1)
29 #define Z1 (get_h()/7+2)
30 #define Z2 (get_h()*2/5+1)
31 #define Z3 (get_h()-Z2-1)
32 #define Z4 (get_h()-Z1-1)
33 #define ZC ((Z3+Z2)/2)
41 static int scale_color(int color, float scale){
42 int r = ((color >> 16) & 0xff)*scale;
43 int g = ((color >> 8) & 0xff)*scale;
44 int b = (color & 0xff)*scale;
49 return (r<<16)|(g<<8)|b;
52 static int mix_color(int c1, float s1, int c2, float s2){
53 int r = ((c1 >> 16) & 0xff)*s1 + ((c2 >> 16) & 0xff)*s2;
54 int g = ((c1 >> 8) & 0xff)*s1 + ((c2 >> 8) & 0xff)*s2;
55 int b = (c1 & 0xff)*s1 + (c2 & 0xff)*s2;
60 return (r<<16)|(g<<8)|b;
63 BluebananaSlider::BluebananaSlider(BluebananaMain *plugin,
64 BluebananaWindow *gui,
71 : BC_SubWindow(x, y, w, h){
73 this->plugin = plugin;
75 this->minval = minval;
76 this->maxval = maxval;
84 int bg_c = get_resources()->get_bg_color();
85 int bg_r = ((bg_c >> 16) & 0xff);
86 int bg_g = ((bg_c >> 8) & 0xff);
87 int bg_b = (bg_c & 0xff);
88 int bg_v = (bg_r * 76 + bg_g *150 + bg_b *29) >> 8;
90 int dt_c = get_resources()->default_text_color;
91 int dt_r = ((dt_c >> 16) & 0xff);
92 int dt_g = ((dt_c >> 8) & 0xff);
93 int dt_b = (dt_c & 0xff);
94 int dt_v = (dt_r * 76 + dt_g *150 + dt_b *29) >> 8;
97 /* light text, dark background */
98 int dg_c = get_resources()->default_text_color;
99 int dg_r = (((dg_c >> 16) & 0xff) + bg_r*2) /3;
100 int dg_g = (((dg_c >> 8) & 0xff) + bg_g*2) /3;
101 int dg_b = ((dg_c & 0xff) + bg_b*2) /3;
102 dg_c = (dg_r<<16) | (dg_g<<8) | dg_b;
104 active_bordercolor = get_resources()->default_text_color;
105 inactive_bordercolor = dg_c;
107 troughcolor = scale_color(dg_c,.5);
108 slidercolor = (bg_v > 0xa0 ? 0x606060 : 0xa0a0a0);
109 sliderlit = (bg_v > 0xa0 ? 0x909070 : 0xd0d0b0);
112 /* dark text, light background */
113 active_bordercolor = scale_color(bg_c,1.25);
114 inactive_bordercolor = scale_color(bg_c,1.01);
115 troughcolor = scale_color(bg_c,.8);
116 dimtextcolor = this->troughcolor;
117 sliderlit = scale_color(bg_c,1.75);
118 slidercolor = scale_color(this->sliderlit,.90);
122 needlecolor = 0xe07000;
123 needlelit = 0xff9000;
126 troughlines = Z4-Z1-1;
127 troughcols = w-CW-CW-ZR-ZL;
130 BluebananaSlider::~BluebananaSlider(){
131 if(trough) delete trough;
132 if(histval) delete[] histval;
133 if(histred) delete[] histred;
134 if(histgreen) delete[] histgreen;
135 if(histblue) delete[] histblue;
138 void BluebananaSlider::reposition(int x, int y, int w, int h){
139 BC_WindowBase::reposition_window(x,y,w,h);
140 if(trough) delete trough;
142 if(histval) delete[] histval;
144 if(histred) delete[] histred;
146 if(histgreen) delete[] histgreen;
148 if(histblue) delete[] histblue;
150 troughlines = Z4-Z1-1;
151 troughcols = w-CW-CW-ZR-ZL;
155 int BluebananaSlider::fraction_to_pixel(float input){
156 return (int)rint((input*(troughcols-1)+CW+ZL)+.001);
159 int BluebananaSlider::value_to_pixel(float input){
160 return fraction_to_pixel((input-minval)/(maxval-minval));
163 float BluebananaSlider::pixel_to_fraction(int pixel){
164 return (float)((pixel-CW-ZL)/(float)(troughcols-1));
167 float BluebananaSlider::pixel_to_value(int pixel){
168 float fraction=((pixel-CW-ZL)/(float)(troughcols-1));
169 return fraction*(maxval-minval)+minval;
172 static int inside_box(int cx, int cy, int x, int y, int w, int h){
173 return (cx>=x && cx<x+w && cy>=y && cy<y+h);
176 static int inside_vline(int cx, int cy, int x, int y0, int y1){
178 if(cy>=y0 && cy<=y1)return 1;
179 if(cy>=y1 && cy<=y0)return 1;
184 static int inside_hline(int cx, int cy, int x0, int x1, int y){
186 if(cx>=x0 && cx<=x1)return 1;
187 if(cx>=x1 && cx<=x0)return 1;
192 int BluebananaSlider::in_midslider(int x, int cx,int cy){
196 if( (cx-x)*(cx-x) + (cy-y)*(cy-y) < r*r ) return 1;
200 int BluebananaSlider::in_leftslider(int x,int cx, int cy){
204 if(inside_hline(cx,cy,x-1,x-Z1*2-1,Z4)) return 1;
206 if(inside_hline(cx,cy,x-(i*2),x-Z1*2-1,Z4-i)) return 1;
207 if(inside_hline(cx,cy,x-(i*2),x-Z1*2-1,Z4+i)) return 1;
210 if(inside_vline(cx,cy,x-Z1*2-2,Z4-Z1+1,Z4+Z1-1))return 1;
211 if(inside_vline(cx,cy,x,Z1+1,h-1))return 1;
216 int BluebananaSlider::in_rightslider(int x, int cx, int cy){
220 if(inside_hline(cx,cy,x+1,x+Z1*2+1,Z4)) return 1;
222 if(inside_hline(cx,cy,x+(i*2),x+Z1*2+1,Z4-i)) return 1;
223 if(inside_hline(cx,cy,x+(i*2),x+Z1*2+1,Z4+i)) return 1;
226 if(inside_vline(cx,cy,x+Z1*2+2,Z4-Z1+1,Z4+Z1-1))return 1;
227 if(inside_vline(cx,cy,x,Z1+1,h-1))return 1;
231 int BluebananaSlider::in_topslider(int x, int cx, int cy){
234 if(inside_vline(cx,cy,x,Z1*2,1))return 1;
236 if(inside_vline(cx,cy,x+i,1,Z1*2-i*2+1))return 1;
237 if(inside_vline(cx,cy,x-i,1,Z1*2-i*2+1))return 1;
239 if(inside_hline(cx,cy,x-Z1+1,x+Z1-1,0)) return 1;
243 int BluebananaSlider::in_overslider(int x,int cx, int cy){
248 int w2 = CW;//Z1*2-1;
249 if(cy<=Z1 && cx>=x-w2 && cx<=x+w2) return 1;
253 int BluebananaSlider::in_bottomslider(int x,int cx, int cy){
257 if(inside_vline(cx,cy,x,h-Z1*2-1,h-2))return 1;
259 if(inside_vline(cx,cy,x+i,h-2,h-Z1*2+i*2-2))return 1;
260 if(inside_vline(cx,cy,x-i,h-2,h-Z1*2+i*2-2))return 1;
262 if(inside_hline(cx,cy,x-Z1+1,x+Z1-1,h-1)) return 1;
266 int BluebananaSlider::in_leftslider2(int x,int cx){
267 if(cx<=x+2 && cx>x-CW) return 1;
271 int BluebananaSlider::in_rightslider2(int x,int cx){
272 if(cx<x+CW && cx>=x-2) return 1;
276 int BluebananaSlider::in_midslider2(int x,int cx){
277 if(cx>x-CW/2 && cx<x+CW/2) return 1;
281 int BluebananaSlider::in_overslider2(int x,int cx, int cy){
282 if(cx>x-CW/2 && cx<x+CW/2 && cy<=(Z1+Z4)/2) return 1;
286 void BluebananaSlider::draw_midslider(int x,int lit){
292 set_color(lit?sliderlit:slidercolor);
293 draw_disc(x-Z1+2,y0,Z1*2-3,y1-y0+1);
296 draw_circle(x-Z1+2,y0,Z1*2-3,y1-y0+1);
299 void BluebananaSlider::draw_leftslider(int x, int lit){
303 set_color(lit?sliderlit:slidercolor);
304 draw_line(x-1,Z4,x-Z1*2-1,Z4);
306 draw_line(x-(i*2),Z4-i,x-Z1*2-1,Z4-i);
307 draw_line(x-(i*2),Z4+i,x-Z1*2-1,Z4+i);
311 draw_line(x-1,Z4,x-1,Z4);
312 draw_line(x-Z1*2-2,Z4-Z1+1,x-Z1*2-2,Z4+Z1-1);
314 draw_line(x-(i*2),Z4-i,x-(i*2)-1,Z4-i);
315 draw_line(x-(i*2),Z4+i,x-(i*2)-1,Z4+i);
318 set_color(lit?needlelit:needlecolor);
319 draw_line(x,Z4-Z1,x,Z4+Z1);
322 void BluebananaSlider::draw_rightslider(int x, int lit){
326 set_color(lit?sliderlit:slidercolor);
327 draw_line(x+1,Z4,x+Z1*2+1,Z4);
329 draw_line(x+(i*2),Z4-i,x+Z1*2+1,Z4-i);
330 draw_line(x+(i*2),Z4+i,x+Z1*2+1,Z4+i);
334 draw_line(x+1,Z4,x+1,Z4);
335 draw_line(x+Z1*2+2,Z4-Z1+1,x+Z1*2+2,Z4+Z1-1);
337 draw_line(x+(i*2),Z4-i,x+(i*2)+1,Z4-i);
338 draw_line(x+(i*2),Z4+i,x+(i*2)+1,Z4+i);
341 set_color(lit?needlelit:needlecolor);
342 draw_line(x,Z4-Z1,x,Z4+Z1);
345 void BluebananaSlider::draw_topslider(int x, int lit){
349 set_color(lit?sliderlit:slidercolor);
350 draw_line(x,Z1*2,x,1);
352 draw_line(x+i,1,x+i,Z1*2-i*2+1);
353 draw_line(x-i,1,x-i,Z1*2-i*2+1);
357 draw_line(x-Z1+1,0,x+Z1-1,0);
358 draw_line(x,Z1*2+1,x,Z1*2+1);
360 draw_line(x+i, Z1*2-i*2+1, x+i, Z1*2-i*2+2);
361 draw_line(x-i, Z1*2-i*2+1, x-i, Z1*2-i*2+2);
365 void BluebananaSlider::draw_bottomslider(int x, int lit){
369 set_color(lit?sliderlit:slidercolor);
370 draw_line(x,h-Z1*2-1,x,h-2);
372 draw_line(x+i,h-2,x+i,h-Z1*2+i*2-2);
373 draw_line(x-i,h-2,x-i,h-Z1*2+i*2-2);
377 draw_line(x-Z1+1,h-1,x+Z1-1,h-1);
378 draw_line(x,h-Z1*2-2,x,h-Z1*2-2);
380 draw_line(x+i,h-Z1*2+i*2-2,x+i,h-Z1*2+i*2-3);
381 draw_line(x-i,h-Z1*2+i*2-2,x-i,h-Z1*2+i*2-3);
385 void BluebananaSlider::draw_overslider(int x, int lit){
392 int bg_c = get_resources()->get_bg_color();
393 int bg_r = ((bg_c >> 16) & 0xff);
394 int bg_g = ((bg_c >> 8) & 0xff);
395 int bg_b = (bg_c & 0xff);
396 float del = lit ? 1. : .9;
397 set_color(((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del)));
398 draw_box(x-w2+1,0,w2*2-2,Z1);
399 draw_box(x-w2,1,w2*2+1,Z1-2);
401 set_color(lit?sliderlit:slidercolor);
402 draw_box(x-w2+2,1,w2*2-3,Z1-2);
403 draw_box(x-w2+1,2,w2*2-1,Z1-4);
405 set_color(((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del)));
406 draw_line(x,2,x,Z1-3);
409 int BluebananaSlider::button_release_event(){
414 cursor_motion_event();
421 void BluebananaSlider::update(){
424 int bg_c = get_resources()->get_bg_color();
425 int bg_r = ((bg_c >> 16) & 0xff);
426 int bg_g = ((bg_c >> 8) & 0xff);
427 int bg_b = (bg_c & 0xff);
428 int b_c = highlight ? active_bordercolor : inactive_bordercolor;
429 int b_r = ((b_c >> 16) & 0xff);
430 int b_g = ((b_c >> 8) & 0xff);
431 int b_b = (b_c & 0xff);
432 int tb_c = troughcolor;
433 int tb_r = ((tb_c >> 16) & 0xff);
434 int tb_g = ((tb_c >> 8) & 0xff);
435 int tb_b = (tb_c & 0xff);
442 clear_box(0, 0, w, h);
446 int shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
448 draw_box (0,Z1,w,ZH+2);
449 draw_box (1,Z1-1,w-2,ZH+4);
452 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
454 draw_box (1,Z1+1,w-2,ZH);
455 draw_box (2,Z1,w-4,ZH+2);
458 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
460 draw_box (2,Z1+2,w-4,ZH-2);
461 draw_box (3,Z1+1,w-6,ZH);
465 draw_box (1,Z1+1,w-4,ZH-2);
466 draw_box (2,Z1,w-6,ZH);
469 int ntw = troughcols;
470 int nth = troughlines;
475 trough = new VFrame(ntw,nth,BC_RGBA8888);
479 fprintf(stderr,_("Bluebanana: Unable to create Frame for slider\n"));
481 unsigned char *data = trough->get_data();
482 long bpr = trough->get_bytes_per_line();
491 if(histval){ // trough is a histogram and has data
492 long bpp = trough->get_bytes_per_pixel();
497 unsigned char *row = data;
498 float y = nth-histval[i];
499 float y0 = i>0?nth-histval[i-1]:y;
500 float y1 = i+1<ntw?nth-histval[i+1]:y;
501 float yp = MIN(y,MIN(y0+1,y1+1));
502 float y3 = (y0+y+y1)*.333f;
505 trough_color((i+.5f)/ntw,0.f,rr,gg,bb,aa);
509 rr = CLAMP((rr+b_r*3)/4,0,255);
510 gg = CLAMP((gg+b_g*3)/4,0,255);
511 bb = CLAMP((bb+b_b*3)/4,0,255);
518 trough_color((i+.5)/ntw,0,r,g,b,a);
524 for(j=0;j<yp-1 && j<nth;j++){
533 for(;j<y && j<nth;j++){
534 row[0] = rint(rr*a + tb_r*(1-a));
535 row[1] = rint(gg*a + tb_g*(1-a));
536 row[2] = rint(bb*a + tb_b*(1-a));
543 float a = CLAMP(1. - .3*(float)(j-y3)/(nth-y3+1),0.f,1.f)*ha;
544 row[0] = rint(r*a*255.f + tb_r*(1-a));
545 row[1] = rint(g*a*255.f + tb_g*(1-a));
546 row[2] = rint(b*a*255.f + tb_b*(1-a));
555 unsigned char *row = data + i*trough->get_bytes_per_pixel();
558 trough_color((i+.5f)/ntw,(j+.5)/nth,r,g,b,a);
564 row[0] = rint(r*a*255 + tb_r*(1-a));
565 row[1] = rint(g*a*255 + tb_g*(1-a));
566 row[2] = rint(b*a*255 + tb_b*(1-a));
572 draw_vframe(trough,ntx,nty);
576 // quick/dirty unnormalized linear resample from native -> display size
577 static void resample_histogram(float *raw, float *raw_red, float *raw_green, float *raw_blue,
578 float *out, float *out_red, float *out_green, float *out_blue,
579 int raw_n, int raw_off, int out_n, int out_start, int out_end){
580 float coverage = (float)raw_n/out_n;
581 float scale = coverage;
582 if(coverage<1.)coverage=1.;
583 float icoverage = 1./coverage;
585 float raw_center = out_start*scale+raw_off;
586 float raw_start = raw_center-coverage;
587 float raw_end = raw_center+coverage;
589 for(int i=out_start; i<out_end; i++){
593 if(e>HISTSIZE)e=HISTSIZE;
595 float k = (j-raw_start)*icoverage-1.f;
599 float ik = 1.-fabs(k);
609 coverage = (float)raw_n/out_n;
611 if(coverage<(1<<HRGBSHIFT))coverage=(1<<HRGBSHIFT);
612 icoverage = 1./coverage;
614 raw_center = out_start*scale+raw_off;
615 raw_start = raw_center-coverage;
616 raw_end = raw_center+coverage;
618 for(int i=out_start; i<out_end; i++){
622 if(e>HISTSIZE)e=HISTSIZE;
624 float k = (j-raw_start)*icoverage-1.f;
625 float r=0.f, g=0.f, b=0.f, a=0.f;
627 float ik = 1.-fabs(k);
628 int sj = (j>>HRGBSHIFT);
629 int sjs = sj<<HRGBSHIFT;
655 g += raw_green[sj]*ik;
656 b += raw_blue[sj]*ik;
661 out_red[i] = CLAMP(r*a,0.f,1.f);
662 out_green[i] = CLAMP(g*a,0.f,1.f);
663 out_blue[i] = CLAMP(b*a,0.f,1.f);
670 void BluebananaSlider::update_histogram(float *raw, float *red, float *green, float *blue, int n){
674 float il2n = 1./log2(n);
677 histval = new float[w];
680 histred = new float[w];
681 histgreen = new float[w];
682 histblue = new float[w];
685 /* resample center */
686 resample_histogram(raw, red, green, blue, histval, histred, histgreen, histblue,
687 HISTSIZE, 0, w, 0, w);
689 /* select value normalization */
691 if(histval[i]<=.0001f){
694 float val = log2(histval[i])*il2n;
695 val = pow(val<0?0:val,.75)*h;
704 // ---------------------------- Single ----------------------------------
706 BluebananaSliderSingle::BluebananaSliderSingle(BluebananaMain *plugin,
707 BluebananaWindow *gui,
714 : BluebananaSlider(plugin,gui,x,y,w,h,minval,maxval){
715 val = (minval+maxval)/2;
719 int BluebananaSliderSingle::button_press_event(){
720 if(is_event_win() && cursor_inside()){
723 int cx = get_cursor_x();
727 if(get_buttonpress() == 4){
728 set_val(val - increment);
730 }else if(get_buttonpress() == 5){
731 set_val(val + increment);
737 xoff = cx-value_to_pixel(val);
750 int BluebananaSliderSingle::cursor_motion_event(){
751 int cx = get_cursor_x();
752 //int cy = get_cursor_y();
757 set_val(pixel_to_value(cx - xoff));
767 if(is_event_win() && cursor_inside()){
769 if(in_midslider2(value_to_pixel(val),cx)){
791 void BluebananaSliderSingle::set_val(float v){
793 if(val<minval)val=minval;
794 if(val>maxval)val=maxval;
799 void BluebananaSliderSingle::update(){
800 BluebananaSlider::update();
801 draw_bottomslider(value_to_pixel(val),light==0);
806 // ---------------------------- Bracket ----------------------------------
808 BluebananaSliderBracket::BluebananaSliderBracket(BluebananaMain *plugin,
809 BluebananaWindow *gui,
816 : BluebananaSlider(plugin,gui,x,y,w,h,minval,maxval){
818 midval = (minval+maxval)/2;
824 int BluebananaSliderBracket::button_press_event(){
825 if(is_event_win() && cursor_inside()){
828 int cx = get_cursor_x();
833 /* narrow/widen range */
834 if(get_buttonpress() == 4){
835 set_delta(increment*2);
837 }else if(get_buttonpress() == 5){
838 set_delta(-increment*2);
841 }else if (ctrl_down()){
842 /* shift all vals up/down */
843 if(get_buttonpress() == 4){
844 set_mid(midval-increment);
846 }else if(get_buttonpress() == 5){
847 set_mid(midval+increment);
851 /* increase/decrease overlap */
852 if(get_buttonpress() == 4){
855 }else if(get_buttonpress() == 5){
863 xoff = cx-value_to_pixel(loval);
866 xoff = cx-value_to_pixel(midval);
869 xoff = cx-value_to_pixel(hival);
872 xoff = cx-value_to_pixel(overval);
885 int BluebananaSliderBracket::cursor_motion_event(){
886 int cx = get_cursor_x();
887 int cy = get_cursor_y();
892 set_lo(pixel_to_value(cx - xoff));
895 set_mid(pixel_to_value(cx - xoff));
898 set_hi(pixel_to_value(cx - xoff));
901 set_over(pixel_to_value(cx - xoff));
911 if(is_event_win() && cursor_inside()){
912 if(in_overslider(value_to_pixel(overval),cx,cy)){
917 }else if(in_midslider(value_to_pixel(midval),cx,cy)){
922 }else if(in_leftslider(value_to_pixel(loval),cx,cy)){
927 }else if(in_rightslider(value_to_pixel(hival),cx,cy)){
932 }else if(in_midslider2(value_to_pixel(midval),cx)){
937 }else if(in_rightslider2(value_to_pixel(hival),cx)){
942 }else if(in_leftslider2(value_to_pixel(loval),cx)){
947 }else if(in_overslider2(value_to_pixel(overval),cx,cy)){
969 void BluebananaSliderBracket::set_lo(float val){
970 if(val<minval)val=minval;
971 if(val>maxval)val=maxval;
972 if(val > hival) val=hival;
975 if(hival<loval)hival+=(maxval-minval);
976 if(midval<loval)midval+=(maxval-minval);
977 midval = (hival+loval)/2.;
978 if(hival>maxval)hival-=(maxval-minval);
979 if(midval>maxval)midval-=(maxval-minval);
980 if(loval>maxval)loval-=(maxval-minval);
981 if(hival<minval)hival+=(maxval-minval);
982 if(midval<minval)midval+=(maxval-minval);
983 if(loval<minval)loval+=(maxval-minval);
988 void BluebananaSliderBracket::set_mid(float val){
989 //float oldmid=midval;
990 if(val<minval)val=minval;
991 if(val>maxval)val=maxval;
994 float delta = (hival+loval)/2.;
998 loval += maxval-hival;
999 midval += maxval-hival;
1011 void BluebananaSliderBracket::set_hi(float val){
1012 if(val<minval)val=minval;
1013 if(val>maxval)val=maxval;
1014 if(val<loval)val=loval;
1017 if(loval>hival)loval-=(maxval-minval);
1018 if(midval>hival)midval-=(maxval-minval);
1019 midval=(hival+loval)/2.;
1020 if(hival>maxval)hival-=(maxval-minval);
1021 if(midval>maxval)midval-=(maxval-minval);
1022 if(loval>maxval)loval-=(maxval-minval);
1023 if(hival<minval)hival+=(maxval-minval);
1024 if(midval<minval)midval+=(maxval-minval);
1025 if(loval<minval)loval+=(maxval-minval);
1031 void BluebananaSliderBracket::set_delta(float incr){
1032 float delta = (hival-loval)+incr;
1033 if(delta<minval)delta=minval;
1034 if(delta>maxval)delta=maxval;
1035 loval = midval-delta/2;
1036 hival = loval+delta;
1044 loval-=(hival-maxval);
1045 midval-=(hival-maxval);
1052 void BluebananaSliderBracket::set_over(float val){
1053 if(val<minval)val=minval;
1054 if(val>maxval)val=maxval;
1061 void BluebananaSliderBracket::update(){
1062 BluebananaSlider::update();
1063 draw_overslider(value_to_pixel(overval),light==3);
1064 draw_leftslider(value_to_pixel(loval),light==0);
1065 draw_rightslider(value_to_pixel(hival),light==2);
1066 draw_midslider(value_to_pixel(midval),light==1);
1071 // ----------------------- Circular Bracket -----------------------------
1073 BluebananaSliderCircular::BluebananaSliderCircular(BluebananaMain *plugin,
1074 BluebananaWindow *gui,
1081 : BluebananaSliderBracket(plugin,gui,x,y,w,h,minval,maxval){}
1083 void BluebananaSliderCircular::set_lo(float val){
1084 if(val<minval)val=minval;
1085 if(val>maxval)val=maxval;
1088 if(hival<loval)hival+=(maxval-minval);
1089 if(midval<loval)midval+=(maxval-minval);
1090 midval = (hival+loval)/2.;
1091 if(hival>maxval)hival-=(maxval-minval);
1092 if(midval>maxval)midval-=(maxval-minval);
1093 if(loval>maxval)loval-=(maxval-minval);
1094 if(hival<minval)hival+=(maxval-minval);
1095 if(midval<minval)midval+=(maxval-minval);
1096 if(loval<minval)loval+=(maxval-minval);
1102 void BluebananaSliderCircular::set_mid(float val){
1103 float oldmid=midval;
1104 if(val<minval)val=minval;
1105 if(val>maxval)val=maxval;
1107 if(hival<oldmid)hival+=(maxval-minval);
1108 if(loval>oldmid)loval-=(maxval-minval);
1109 float delta = hival-loval;
1110 loval = midval-delta/2;
1111 hival = loval+delta;
1112 if(hival>maxval)hival-=(maxval-minval);
1113 if(loval>maxval)loval-=(maxval-minval);
1114 if(hival<minval)hival+=(maxval-minval);
1115 if(loval<minval)loval+=(maxval-minval);
1120 void BluebananaSliderCircular::set_hi(float val){
1121 if(val<minval)val=minval;
1122 if(val>maxval)val=maxval;
1124 if(loval>hival)loval-=(maxval-minval);
1125 if(midval>hival)midval-=(maxval-minval);
1126 midval = (hival+loval)/2.;
1127 if(hival>maxval)hival-=(maxval-minval);
1128 if(midval>maxval)midval-=(maxval-minval);
1129 if(loval>maxval)loval-=(maxval-minval);
1130 if(hival<minval)hival+=(maxval-minval);
1131 if(midval<minval)midval+=(maxval-minval);
1132 if(loval<minval)loval+=(maxval-minval);
1137 void BluebananaSliderCircular::set_delta(float incr){
1138 if(hival<midval)hival+=(maxval-minval);
1139 if(loval>midval)loval-=(maxval-minval);
1141 float delta = (hival-loval)+incr;
1142 if(delta<minval)delta=minval;
1143 if(delta>maxval)delta=maxval;
1144 loval = midval-delta/2;
1145 hival = loval+delta;
1147 if(hival>maxval)hival-=(maxval-minval);
1148 if(loval>maxval)loval-=(maxval-minval);
1149 if(hival<minval)hival+=(maxval-minval);
1150 if(loval<minval)loval+=(maxval-minval);
1155 void BluebananaSliderCircular::update(){
1156 BluebananaSliderBracket::update();
1161 // -------------------------- In + Out + Gamma --------------------------------
1163 #define mG2 (2.f-2.f*MIN_GAMMA)
1164 #define MG2 (2.f*MAX_GAMMA-2.f)
1166 float BluebananaSliderChannel::pixel_to_gamma(float pixel){
1167 float unit = (1.-pixel_to_fraction(pixel)-FRAC0)/(FRAC100-FRAC0);
1168 return (unit > .5f ?
1169 (1.f-unit) * mG2 + MIN_GAMMA :
1170 (.5f-unit) * MG2 + 1.f );
1173 float BluebananaSliderChannel::gamma_to_pixel(float gamma){
1175 gamma<1 ? 1.f - (gamma-MIN_GAMMA) / mG2 :
1176 .5f - (gamma-1.f) / MG2 ;
1177 return fraction_to_pixel((1.-fraction) * (FRAC100-FRAC0) + FRAC0);
1180 float BluebananaSliderChannel::pixel_to_value(float pixel){
1182 return (t_x0-pixel)/t_w01*MIN_HISTBRACKET+MIN_HISTBRACKET;
1183 }else if (pixel<t_x2){
1184 return (pixel-t_x1)/t_w12*100;
1186 return (pixel-t_x2)/t_w23*(MAX_HISTBRACKET-100)+100;
1190 float BluebananaSliderChannel::value_to_pixel(float val){
1192 return rint(MIN_HISTBRACKET-val)/MIN_HISTBRACKET*t_w01+t_x0;
1194 return rint(val/100.*t_w12+t_x1+.01);
1196 return rint((val-100)/(MAX_HISTBRACKET-100.)*t_w23+t_x2);
1200 BluebananaSliderChannel::BluebananaSliderChannel(BluebananaMain *plugin,
1201 BluebananaWindow *gui,
1206 : BluebananaSlider(plugin,gui,x,y,w,h,0,100){
1212 BluebananaSliderChannel::~BluebananaSliderChannel(){}
1214 int BluebananaSliderChannel::button_press_event(){
1215 if(is_event_win() && cursor_inside()){
1218 int cx = get_cursor_x();
1219 //int cy = get_cursor_y();
1224 /* narrow/widen range */
1225 if(get_buttonpress() == 4){
1226 set_range(hival-loval-2);
1228 }else if(get_buttonpress() == 5){
1230 set_range(hival-loval+2);
1234 }else if (ctrl_down()){
1235 /* shift all vals up/down */
1236 if(get_buttonpress() == 4){
1237 set_mid((loval+hival)/2+1);
1239 }else if(get_buttonpress() == 5){
1240 set_mid((loval+hival)/2-1);
1244 /* increase/decrease gamma */
1245 if(get_buttonpress() == 4){
1246 set_gamma(gamma-.01);
1248 }else if(get_buttonpress() == 5){
1249 set_gamma(gamma+.01);
1256 xoff = cx-value_to_pixel(loval);
1259 xoff = cx-value_to_pixel((loval+hival)/2);
1262 xoff = cx-value_to_pixel(hival);
1265 xoff = cx-gamma_to_pixel(gamma);
1278 int BluebananaSliderChannel::cursor_motion_event(){
1279 int cx = get_cursor_x();
1280 int cy = get_cursor_y();
1285 set_lo(pixel_to_value(cx - xoff));
1288 set_mid(pixel_to_value(cx - xoff));
1291 set_hi(pixel_to_value(cx - xoff));
1294 set_gamma(pixel_to_gamma(cx - xoff));
1304 if(is_event_win() && cursor_inside()){
1305 if(in_topslider(gamma_to_pixel(gamma),cx,cy)){
1310 }else if(in_midslider(value_to_pixel((loval+hival)/2),cx,cy)){
1315 }else if(in_leftslider(value_to_pixel(loval),cx,cy)){
1320 }else if(in_rightslider(value_to_pixel(hival),cx,cy)){
1325 }else if(in_bottomslider(value_to_pixel(hival),cx,cy)){
1330 }else if(in_bottomslider(value_to_pixel(loval),cx,cy)){
1335 }else if(in_midslider2(value_to_pixel((loval+hival)/2),cx)){
1340 }else if(in_overslider2(gamma_to_pixel(gamma),cx,cy)){
1362 void BluebananaSliderChannel::set_lo(float v){
1371 void BluebananaSliderChannel::set_hi(float v){
1380 void BluebananaSliderChannel::set_mid(float v){
1381 float mid = (hival+loval)*.5;
1382 float range = hival-loval;
1385 if(hival+del>200)del=200-hival;
1386 if(hival+del<0)del=0-hival;
1387 if(loval+del>100)del=100-loval;
1388 if(loval+del<-100)del=-100-loval;
1391 hival=loval+rint(range);
1396 void BluebananaSliderChannel::set_range(float v){
1397 //float mid = (hival+loval)*.5;
1398 float range = hival-loval;
1403 float del = (v-range)/2;
1405 if(hival+del>200)del=200-hival;
1406 if(hival+del<0)del=0-hival;
1408 if(loval-del>100)del=loval-100;
1409 if(loval-del<-100)del=loval+100;
1412 hival=rint(loval+v);
1417 void BluebananaSliderChannel::set_gamma(float v){
1418 if(v>MAX_GAMMA)v=MAX_GAMMA;
1419 if(v<MIN_GAMMA)v=MIN_GAMMA;
1425 void BluebananaSliderChannel::update(){
1428 int bg_c = get_resources()->get_bg_color();
1429 int bg_r = ((bg_c >> 16) & 0xff);
1430 int bg_g = ((bg_c >> 8) & 0xff);
1431 int bg_b = (bg_c & 0xff);
1432 int b_c = highlight ? active_bordercolor : inactive_bordercolor;
1433 int b_r = ((b_c >> 16) & 0xff);
1434 int b_g = ((b_c >> 8) & 0xff);
1435 int b_b = (b_c & 0xff);
1436 int tb_c = troughcolor;
1437 int tb_r = ((tb_c >> 16) & 0xff);
1438 int tb_g = ((tb_c >> 8) & 0xff);
1439 int tb_b = (tb_c & 0xff);
1442 //int ZHC = Z4-ZC+1;
1446 t_x0 = fraction_to_pixel(0);
1447 t_x1 = fraction_to_pixel(FRAC0);
1448 t_x2 = fraction_to_pixel(FRAC100);
1449 t_x3 = fraction_to_pixel(1.);
1455 int ntw = troughcols-6;
1456 int nth = troughlines;
1460 clear_box(0, 0, w, h);
1464 /* w+4 h+4 x-1 y-1 */
1466 int shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1467 set_color(shadow_c);
1468 draw_box (0,Z1,t_x1+3,ZH+2);
1469 draw_box (1,Z1-1,t_x1+1,ZH+4);
1470 draw_box (t_x1,Z1,t_w12+3,ZH+2);
1471 draw_box (t_x1+1,Z1-1,t_w12+1,ZH+4);
1472 draw_box (t_x2,Z1,w-t_x2,ZH-2+2);
1473 draw_box (t_x2+1,Z1-1,w-t_x2-2,ZH+4);
1477 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1478 set_color(shadow_c);
1479 draw_box (1,Z1+1,t_x1+1,ZH);
1480 draw_box (2,Z1,t_x1-1,ZH+2);
1481 draw_box (t_x1+1,Z1+1,t_w12+1,ZH);
1482 draw_box (t_x1+2,Z1,t_w12-1,ZH+2);
1483 draw_box (t_x2+1,Z1+1,w-t_x2-2,ZH);
1484 draw_box (t_x2+2,Z1,w-t_x2-4,ZH+2);
1488 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1489 set_color(shadow_c);
1490 draw_box (2,Z1+2,t_x1-1,ZH-2);
1491 draw_box (3,Z1+1,t_x1-3,ZH);
1492 draw_box (t_x1+2,Z1+2,t_w12-1,ZH-2);
1493 draw_box (t_x1+3,Z1+1,t_w12-3,ZH);
1494 draw_box (t_x2+2,Z1+2,w-t_x2-4,ZH-2);
1495 draw_box (t_x2+3,Z1+1,w-t_x2-6,ZH);
1499 draw_box (1,Z1+1,t_x1-1,ZH-2);
1500 draw_box (2,Z1,t_x1-3,ZH);
1501 draw_box (t_x1+1,Z1+1,t_w12-1,ZH-2);
1502 draw_box (t_x1+2,Z1,t_w12-3,ZH);
1503 draw_box (t_x2+1,Z1+1,w-t_x2-4,ZH-2);
1504 draw_box (t_x2+2,Z1,w-t_x2-6,ZH);
1507 /* the trough in the three-part hist slider is slightly smaller than
1508 the full slider range, and cut into three sections */
1510 trough = new VFrame(ntw,nth,BC_RGBA8888);
1514 fprintf(stderr,_("Bluebanana: Unable to create Frame for slider\n"));
1516 unsigned char *data = trough->get_data();
1518 long bpp = trough->get_bytes_per_pixel();
1519 long bpr = trough->get_bytes_per_line();
1520 float r,g,b,a,rr,gg,bb;
1531 unsigned char *row = data;
1533 unsigned char *rp = row;
1546 trough_color(1.,rr,gg,bb);
1550 rr = CLAMP((rr+b_r*3)/4,0,255);
1551 gg = CLAMP((gg+b_g*3)/4,0,255);
1552 bb = CLAMP((bb+b_b*3)/4,0,255);
1555 unsigned char *row = data;
1556 float y = nth-histval[i];
1557 float y0 = i>0?nth-histval[i-1]:y;
1558 float y1 = i+1<ntw?nth-histval[i+1]:y;
1559 float yp = MIN(y,MIN(y0+1,y1+1));
1560 float y3 = (y0+y+y1)*.333f;
1567 float val = (i < t_w01-1 ?
1568 ((MIN_HISTBRACKET/100.f) - i/(t_w01-1.f)*(MIN_HISTBRACKET/100.f)) :
1570 ((i - t_w01 + 1) / (t_w12-4.f)) :
1571 ((i - t_w01 - t_w12 + 5) / (t_w23-1.f)*((MAX_HISTBRACKET/100.f)-1.f)+1.f)));
1573 trough_color(val,r,g,b);
1580 for(j=0;j<yp-1 && j<nth;j++){
1589 for(;j<y && j<nth;j++){
1590 row[0] = rint(rr*a + tb_r*(1-a));
1591 row[1] = rint(gg*a + tb_g*(1-a));
1592 row[2] = rint(bb*a + tb_b*(1-a));
1599 float a = CLAMP(1. - .3*(float)(j-y3)/(nth-y3+1),0.f,1.f)*ha;
1600 row[0] = rint(r*a*255.f + tb_r*(1-a));
1601 row[1] = rint(g*a*255.f + tb_g*(1-a));
1602 row[2] = rint(b*a*255.f + tb_b*(1-a));
1611 draw_vframe(trough, ntx, nty, t_w01-2, 1, 0, 0, t_w01-2, 1);
1612 draw_vframe(trough, ntx, nty+1, t_w01-1, nth-2, 0, 1, t_w01-1, nth-2);
1613 draw_vframe(trough, ntx, nty+nth-1, t_w01-2, 1, 0, nth-1, t_w01-2, 1);
1615 draw_vframe(trough, t_x1+3, nty, t_w12-5, 1, t_w01, 0, t_w12-5, 1);
1616 draw_vframe(trough, t_x1+2, nty+1, t_w12-3, nth-2, t_w01-1, 1, t_w12-3, nth-2);
1617 draw_vframe(trough, t_x1+3, nty+nth-1, t_w12-5, 1, t_w01, nth-1, t_w12-5, 1);
1619 draw_vframe(trough, t_x2+3, nty, t_w23-2, 1, t_w01+t_w12-3, 0, t_w23-2, 1);
1620 draw_vframe(trough, t_x2+2, nty+1, t_w23-1, nth-2, t_w01+t_w12-4, 1, t_w23-1, nth-2);
1621 draw_vframe(trough, t_x2+3, nty+nth-1, t_w23-2, 1, t_w01+t_w12-3, nth-1, t_w23-2, 1);
1624 draw_topslider(rint(gamma_to_pixel(gamma)),light==3);
1626 draw_bottomslider(rint(value_to_pixel(loval)),light==0);
1627 draw_bottomslider(rint(value_to_pixel(hival)),light==2);
1628 draw_midslider(rint(value_to_pixel((loval+hival)/2.)),light==1);
1634 void BluebananaSliderChannel::update_histogram(float *raw, float *red, float *green, float *blue, int n){
1636 //int h = troughlines;
1637 int w = troughcols-6;
1638 float il2n = 1./log2(n);
1644 histval = new float[w];
1646 if(!histred && red){
1647 histred = new float[w];
1648 histgreen = new float[w];
1649 histblue = new float[w];
1653 int span0 = rint((0.f-MIN_HISTBRACKET) / (MAX_HISTBRACKET-MIN_HISTBRACKET) * HISTSIZE);
1654 resample_histogram(raw, red, green, blue, histval, histred, histgreen, histblue,
1655 span0, 0, w0, 0, w0);
1657 /* resample center */
1658 int span1 = rint(100.f/(MAX_HISTBRACKET-MIN_HISTBRACKET) * HISTSIZE);
1659 resample_histogram(raw, red, green, blue, histval+w0, histred+w0, histgreen+w0, histblue+w0,
1660 span1, span0, w1, 0, w1+1);
1662 /* resample right */
1663 int span2 = rint((MAX_HISTBRACKET-100.f) / (MAX_HISTBRACKET-MIN_HISTBRACKET) * HISTSIZE);
1664 resample_histogram(raw, red, green, blue, histval+w0+w1, histred+w0+w1, histgreen+w0+w1, histblue+w0+w1,
1665 span2, span0+span1, w2, 1, w2+1);
1667 /* select value normalization */
1669 if(histval[i]<=.0001f){
1672 float val = log2(histval[i])*il2n;
1673 val = pow(val<0?0:val,.75)*troughlines;
1675 if(val>troughlines)val=troughlines;
1682 // ---------------------------- Fill ----------------------------------
1684 int BluebananaSliderFill::over_to_pixel(float input){
1685 return fraction_to_pixel(input/maxover);
1688 float BluebananaSliderFill::pixel_to_over(int pixel){
1689 return pixel_to_fraction(pixel)*maxover;
1692 BluebananaSliderFill::BluebananaSliderFill(BluebananaMain *plugin,
1693 BluebananaWindow *gui,
1701 : BluebananaSlider(plugin,gui,x,y,w,h,minval,maxval){
1706 this->maxover = maxover;
1709 int BluebananaSliderFill::button_press_event(){
1710 if(is_event_win() && cursor_inside()){
1713 int cx = get_cursor_x();
1718 /* narrow/widen range */
1719 if(get_buttonpress() == 4){
1722 }else if(get_buttonpress() == 5){
1726 }else if (ctrl_down()){
1727 /* shift all vals up/down */
1728 if(get_buttonpress() == 4){
1729 if(loval-increment>minval)
1730 set_fill(loval-1,midval-1,hival-1);
1732 }else if(get_buttonpress() == 5){
1733 if(hival+increment<maxval)
1734 set_fill(loval+1,midval+1,hival+1);
1738 /* increase/decrease feather */
1739 if(get_buttonpress() == 4){
1740 set_over(overval-1);
1742 }else if(get_buttonpress() == 5){
1743 set_over(overval+1);
1750 xoff = cx-value_to_pixel(loval);
1753 xoff = cx-value_to_pixel(midval);
1756 xoff = cx-value_to_pixel(hival);
1759 xoff = cx-over_to_pixel(overval);
1772 int BluebananaSliderFill::cursor_motion_event(){
1773 int cx = get_cursor_x();
1774 int cy = get_cursor_y();
1779 set_fill(pixel_to_value(cx - xoff),midval,hival);
1782 set_fill(loval,pixel_to_value(cx - xoff),hival);
1785 set_fill(loval,midval,pixel_to_value(cx - xoff));
1788 set_over(pixel_to_over(cx - xoff));
1798 if(is_event_win() && cursor_inside()){
1799 if(in_overslider(over_to_pixel(overval),cx,cy)){
1804 }else if(in_bottomslider(value_to_pixel(midval),cx,cy)){
1809 }else if(in_leftslider(value_to_pixel(loval),cx,cy)){
1814 }else if(in_rightslider(value_to_pixel(hival),cx,cy)){
1819 }else if(in_midslider2(value_to_pixel(midval),cx)){
1824 }else if(in_rightslider2(value_to_pixel(hival),cx)){
1829 }else if(in_leftslider2(value_to_pixel(loval),cx)){
1834 }else if(in_overslider2(over_to_pixel(overval),cx,cy)){
1856 void BluebananaSliderFill::set_fill(float lo, float mid, float hi){
1857 if(lo<minval)lo=minval;
1858 if(mid<minval)mid=minval;
1861 if(mid>maxval)mid=maxval;
1862 if(hi>maxval)hi=maxval;
1864 if(lo>midval)mid=lo;
1865 if(mid<loval)lo=mid;
1866 if(mid>hival)hi=mid;
1867 if(hi<midval)mid=hi;
1877 void BluebananaSliderFill::set_delta(float del){
1878 if(loval+del>=minval && hival+del<=maxval){
1882 loval=hival=rint((loval+hival)/2);
1883 if(midval<loval)midval=loval;
1884 if(midval>hival)midval=hival;
1890 void BluebananaSliderFill::set_over(float over){
1891 if(over>=0 && over<=maxover){
1898 void BluebananaSliderFill::update(){
1901 int bg_c = get_resources()->get_bg_color();
1902 int bg_r = ((bg_c >> 16) & 0xff);
1903 int bg_g = ((bg_c >> 8) & 0xff);
1904 int bg_b = (bg_c & 0xff);
1905 int b_c = highlight ? active_bordercolor : inactive_bordercolor;
1906 //int b_r = ((b_c >> 16) & 0xff);
1907 //int b_g = ((b_c >> 8) & 0xff);
1908 //int b_b = (b_c & 0xff);
1909 int tb_c = troughcolor;
1910 int tb_r = ((tb_c >> 16) & 0xff);
1911 int tb_g = ((tb_c >> 8) & 0xff);
1912 int tb_b = (tb_c & 0xff);
1915 //int ZHC = Z4-ZC+1;
1919 int xC = value_to_pixel(0);
1920 int ntw = troughcols;
1921 int nth = troughlines;
1925 clear_box(0, 0, w, h);
1929 /* w+4 h+4 x-1 y-1 */
1931 int shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1932 set_color(shadow_c);
1933 draw_box (0,Z1,xC+3,ZH+2);
1934 draw_box (1,Z1-1,xC+1,ZH+4);
1935 draw_box (xC,Z1,w-xC,ZH+2);
1936 draw_box (xC+1,Z1-1,w-xC-2,ZH+4);
1940 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1941 set_color(shadow_c);
1942 draw_box (1,Z1+1,xC+1,ZH);
1943 draw_box (2,Z1,xC-1,ZH+2);
1944 draw_box (xC+1,Z1+1,w-xC-2,ZH);
1945 draw_box (xC+2,Z1,w-xC-4,ZH+2);
1949 shadow_c = ((int)(bg_r*del) << 16) | ((int)(bg_g*del) << 8) | ((int)(bg_b*del));
1950 set_color(shadow_c);
1951 draw_box (2,Z1+2,xC-1,ZH-2);
1952 draw_box (3,Z1+1,xC-3,ZH);
1953 draw_box (xC+2,Z1+2,w-xC-4,ZH-2);
1954 draw_box (xC+3,Z1+1,w-xC-6,ZH);
1958 draw_box (1,Z1+1,xC-1,ZH-2);
1959 draw_box (2,Z1,xC-3,ZH);
1960 draw_box (xC+1,Z1+1,w-xC-4,ZH-2);
1961 draw_box (xC+2,Z1,w-xC-6,ZH);
1964 /* the trough in the two-part contour slider is slightly smaller than
1965 the full slider range, and cut into two sections */
1967 trough = new VFrame(ntw,nth,BC_RGBA8888);
1970 /* Unlike the hist slider, we just drop the three pixel columns in the center */
1972 fprintf(stderr,_("Bluebanana: Unable to create Frame for slider\n"));
1974 unsigned char *data = trough->get_data();
1975 long bpr = trough->get_bytes_per_line();
1985 unsigned char *row = data + i*trough->get_bytes_per_pixel();
1988 trough_color((i+.5f)/ntw,(j+.5)/nth,r,g,b,a);
1993 row[0] = rint(r*a*255 + tb_r*(1-a));
1994 row[1] = rint(g*a*255 + tb_g*(1-a));
1995 row[2] = rint(b*a*255 + tb_b*(1-a));
2001 draw_vframe(trough, ntx, nty, xC-ntx-2, 1, 0, 0, xC-ntx-2, 1);
2002 draw_vframe(trough, ntx, nty+1, xC-ntx-1, nth-2, 0, 1, xC-ntx-1, nth-2);
2003 draw_vframe(trough, ntx, nty+nth-1, xC-ntx-2, 1, 0, nth-1, xC-ntx-2, 1);
2005 draw_vframe(trough, xC+3, nty, ntw-xC+ntx-3, 1, xC-ntx+2, 0, ntw-xC+ntx-3, 1);
2006 draw_vframe(trough, xC+2, nty+1, ntw-xC+ntx-2, nth-2, xC-ntx+1, 1, ntx-xC+ntx-2, nth-2);
2007 draw_vframe(trough, xC+3, nty+nth-1, ntw-xC+ntx-3, 1, xC-ntx+2, nth-1, ntw-xC+ntx-3, 1);
2010 draw_overslider(over_to_pixel(overval),light==3);
2011 draw_leftslider(value_to_pixel(loval),light==0);
2012 draw_rightslider(value_to_pixel(hival),light==2);
2013 draw_bottomslider(value_to_pixel(midval),light==1);