rework keyframe hide popup, keyframe auto render, textbox set_selection wide text
[goodguy/history.git] / cinelerra-5.1 / cinelerra / colorpicker.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "colorpicker.h"
24 #include "condition.h"
25 #include "language.h"
26 #include "mutex.h"
27 #include "mwindow.inc"
28 #include "cicolors.h"
29 #include "vframe.h"
30
31 #include <string.h>
32 #include <unistd.h>
33
34
35 ColorThread::ColorThread(int do_alpha, char *title)
36  : Thread()
37 {
38         window = 0;
39         this->title = title;
40         this->do_alpha = do_alpha;
41         set_synchronous(0);
42         mutex = new Mutex("ColorThread::mutex");
43         completion = new Condition(1, "ColorThread::completion");
44 }
45
46 ColorThread::~ColorThread()
47 {
48         if(running())
49         {
50                 window->set_done(0);
51                 completion->lock("ColorThread::~ColorThread");
52                 completion->unlock();
53         }
54         delete mutex;
55         delete completion;
56 }
57
58 void ColorThread::start_window(int output, int alpha)
59 {
60         mutex->lock("ColorThread::start_window 1");
61         this->output = output;
62         this->alpha = alpha;
63         mutex->unlock();
64
65         if(!running())
66         {
67                 completion->lock("ColorThread::start_window");
68                 Thread::start();
69         }
70         else
71         {
72                 window->raise_window();
73                 window->flush();
74         }
75 }
76
77 void ColorThread::run()
78 {
79         BC_DisplayInfo info;
80 //printf("ColorThread::run 1\n");
81         char window_title[BCTEXTLEN];
82
83         strcpy(window_title, _(PROGRAM_NAME ": "));
84         if(title)
85                 strcat(window_title, title);
86         else
87                 strcat(window_title, _("Color Picker"));
88
89
90         mutex->lock("ColorThread::run 1");
91         window = new ColorWindow(this, 
92                 info.get_abs_cursor_x() - 200, 
93                 info.get_abs_cursor_y() - 200,
94                 window_title);
95         window->create_objects();
96         mutex->unlock();
97         window->run_window();
98         mutex->lock("lorThread::run 2");
99         delete window;
100         window = 0;
101         mutex->unlock();
102         completion->unlock();
103 }
104
105 void ColorThread::update_gui(int output, int alpha)
106 {
107         mutex->lock("ColorThread::update_gui");
108         if (window)
109         {
110                 this->output = output;
111                 this->alpha = alpha;
112                 window->change_values();
113                 window->lock_window();
114                 window->update_display();
115                 window->unlock_window();
116         }
117         mutex->unlock();
118 }
119
120 int ColorThread::handle_new_color(int output, int alpha)
121 {
122         printf("ColorThread::handle_new_color undefined.\n");
123         return 0;
124 }
125
126 ColorWindow* ColorThread::get_gui()
127 {
128         return window;
129 }
130
131
132
133 ColorWindow::ColorWindow(ColorThread *thread, int x, int y, char *title)
134  : BC_Window(title, 
135         x,
136         y,
137         410, 
138         320, 
139         410, 
140         320, 
141         0, 
142         0,
143         1)
144 {
145         this->thread = thread;
146 }
147
148 void ColorWindow::create_objects()
149 {
150         int x = 10, init_x = 10, y = 10, init_y = 10;
151         
152         lock_window("ColorWindow::create_objects");
153         change_values();
154         
155         
156         
157 //printf("ColorWindow::create_objects 1 %p\n", this);
158         add_tool(wheel = new PaletteWheel(this, x, y));
159 //printf("ColorWindow::create_objects 1\n");
160         wheel->create_objects();
161 //printf("ColorWindow::create_objects 1\n");
162
163         x += 180;
164         add_tool(wheel_value = new PaletteWheelValue(this, x, y));
165 //printf("ColorWindow::create_objects 1\n");
166         wheel_value->create_objects();
167
168
169         y += 180;
170         x = init_x; 
171 //printf("ColorWindow::create_objects 1\n");
172         add_tool(output = new PaletteOutput(this, x, y));
173 //printf("ColorWindow::create_objects 1\n");
174         output->create_objects();
175 //printf("ColorWindow::create_objects 1\n");
176         
177         x += 240; y = init_y;
178         add_tool(new BC_Title(x, y, _("Hue"), SMALLFONT));
179         y += 15;
180 //printf("ColorWindow::create_objects 1 %p\n", this);
181         add_tool(hue = new PaletteHue(this, x, y));
182         y += 30;
183 //printf("ColorWindow::create_objects 1\n");
184         add_tool(new BC_Title(x, y, _("Saturation"), SMALLFONT));
185         y += 15;
186 //printf("ColorWindow::create_objects 1\n");
187         add_tool(saturation = new PaletteSaturation(this, x, y));
188         y += 30;
189 //printf("ColorWindow::create_objects 1\n");
190         add_tool(new BC_Title(x, y, _("Value"), SMALLFONT));
191         y += 15;
192 //printf("ColorWindow::create_objects 1\n");
193         add_tool(value = new PaletteValue(this, x, y));
194         y += 30;
195 //printf("ColorWindow::create_objects 1\n");
196         add_tool(new BC_Title(x, y, _("Red"), SMALLFONT));
197         y += 15;
198 //printf("ColorWindow::create_objects 1\n");
199         add_tool(red = new PaletteRed(this, x, y));
200         y += 30;
201 //printf("ColorWindow::create_objects 1\n");
202         add_tool(new BC_Title(x, y, _("Green"), SMALLFONT));
203         y += 15;
204 //printf("ColorWindow::create_objects 1\n");
205         add_tool(green = new PaletteGreen(this, x, y));
206         y += 30;
207 //printf("ColorWindow::create_objects 1\n");
208         add_tool(new BC_Title(x, y, _("Blue"), SMALLFONT));
209         y += 15;
210 //printf("ColorWindow::create_objects 1\n");
211         add_tool(blue = new PaletteBlue(this, x, y));
212
213         if(thread->do_alpha)
214         {
215                 y += 30;
216                 add_tool(new BC_Title(x, y, _("Alpha"), SMALLFONT));
217                 y += 15;
218                 add_tool(alpha = new PaletteAlpha(this, x, y));
219         }
220
221         update_display();
222         show_window();
223         flush();
224         unlock_window();
225         return;
226 }
227
228
229 void ColorWindow::change_values()
230  {
231         r = (float)((thread->output & 0xff0000) >> 16) / 255;
232         g = (float)((thread->output & 0xff00) >> 8) / 255;
233         b = (float)((thread->output & 0xff)) / 255;
234         HSV::rgb_to_hsv(r, g, b, h, s, v);
235         a = (float)thread->alpha / 255;
236 }
237
238
239 int ColorWindow::close_event()
240 {
241         set_done(0);
242         return 1;
243 }
244
245
246 void ColorWindow::update_rgb()
247 {
248         HSV::rgb_to_hsv(red->get_value(), 
249                                 green->get_value(), 
250                                 blue->get_value(), 
251                                 h, 
252                                 s, 
253                                 v);
254         update_display();
255 }
256
257 void ColorWindow::update_display()
258 {
259         float r, g, b;
260         if(h < 0) h = 0;
261         if(h > 360) h = 360;
262         if(s < 0) s = 0;
263         if(s > 1) s = 1;
264         if(v < 0) v = 0;
265         if(v > 1) v = 1;
266         if(a < 0) a = 0;
267         if(a > 1) a = 1;
268
269         wheel->draw(wheel->oldhue, 
270                                 wheel->oldsaturation);
271         wheel->oldhue = h;
272         wheel->oldsaturation = s;
273         wheel->draw(h, s);
274         wheel->flash();
275         wheel_value->draw(h, s, v);
276         wheel_value->flash();
277         output->draw();
278         output->flash();
279         hue->update((int)h);
280         saturation->update(s);
281         value->update(v);
282
283         HSV::hsv_to_rgb(r, g, b, h, s, v);
284         red->update(r);
285         green->update(g);
286         blue->update(b);
287         if(thread->do_alpha)
288         {
289                 alpha->update(a);
290         }
291 }
292
293 int ColorWindow::handle_event()
294 {
295         float r, g, b;
296         HSV::hsv_to_rgb(r, g, b, h, s, v);
297         int result = (((int)(r * 255)) << 16) | (((int)(g * 255)) << 8) | ((int)(b * 255));
298         thread->handle_new_color(result, (int)(a * 255));
299         return 1;
300 }
301
302
303
304
305
306
307
308 PaletteWheel::PaletteWheel(ColorWindow *window, int x, int y)
309  : BC_SubWindow(x, y, 170, 170)
310 {
311         this->window = window;
312         oldhue = 0;
313         oldsaturation = 0;
314         button_down = 0;
315 }
316 PaletteWheel::~PaletteWheel()
317 {
318 }
319
320 int PaletteWheel::button_press_event()
321 {
322         if(get_cursor_x() >= 0 && get_cursor_x() < get_w() &&
323                 get_cursor_y() >= 0 && get_cursor_y() < get_h() && 
324                 is_event_win())
325         {
326                 button_down = 1;
327                 cursor_motion_event();
328                 return 1;
329         }
330         return 0;
331 }
332
333 int PaletteWheel::cursor_motion_event()
334 {
335         int x1, y1, distance;
336         if(button_down && is_event_win())
337         {
338                 window->h = get_angle(get_w() / 2, 
339                         get_h() / 2, 
340                         get_cursor_x(), 
341                         get_cursor_y());
342                 x1 = get_w() / 2 - get_cursor_x();
343                 y1 = get_h() / 2 - get_cursor_y();
344                 distance = (int)sqrt(x1 * x1 + y1 * y1);
345                 if(distance > get_w() / 2) distance = get_w() / 2;
346                 window->s = (float)distance / (get_w() / 2);
347                 window->update_display();
348                 window->handle_event();
349                 return 1;
350         }
351         return 0;
352 }
353
354 int PaletteWheel::button_release_event()
355 {
356         if(button_down)
357         {
358                 button_down = 0;
359                 return 1;
360         }
361         return 0;
362 }
363
364 void PaletteWheel::create_objects()
365 {
366 // Upper right
367 //printf("PaletteWheel::create_objects 1\n");
368         float h;
369         float s;
370         float v = 1;
371         float r, g, b;
372         float x1, y1, x2, y2;
373         float distance;
374         int default_r, default_g, default_b;
375         VFrame frame(0, -1, get_w(), get_h(), BC_RGBA8888, -1);
376         x1 = get_w() / 2;
377         y1 = get_h() / 2;
378         default_r = (get_resources()->get_bg_color() & 0xff0000) >> 16;
379         default_g = (get_resources()->get_bg_color() & 0xff00) >> 8;
380         default_b = (get_resources()->get_bg_color() & 0xff);
381 //printf("PaletteWheel::create_objects 1\n");
382
383         int highlight_r = (get_resources()->button_light & 0xff0000) >> 16;
384         int highlight_g = (get_resources()->button_light & 0xff00) >> 8;
385         int highlight_b = (get_resources()->button_light & 0xff);
386
387         for(y2 = 0; y2 < get_h(); y2++)
388         {
389                 unsigned char *row = (unsigned char*)frame.get_rows()[(int)y2];
390                 for(x2 = 0; x2 < get_w(); x2++)
391                 {
392                         distance = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
393                         if(distance > x1)
394                         {
395                                 row[(int)x2 * 4] = default_r;
396                                 row[(int)x2 * 4 + 1] = default_g;
397                                 row[(int)x2 * 4 + 2] = default_b;
398                                 row[(int)x2 * 4 + 3] = 0;
399                         }
400                         else
401                         if(distance > x1 - 1)
402                         {
403                                 int r_i, g_i, b_i;
404                                 if(get_h() - y2 < x2)
405                                 {
406                                         r_i = highlight_r;
407                                         g_i = highlight_g;
408                                         b_i = highlight_b;
409                                 }
410                                 else
411                                 {
412                                         r_i = 0;
413                                         g_i = 0;
414                                         b_i = 0;
415                                 }
416
417                                 row[(int)x2 * 4] = r_i;
418                                 row[(int)x2 * 4 + 1] = g_i;
419                                 row[(int)x2 * 4 + 2] = b_i;
420                                 row[(int)x2 * 4 + 3] = 255;
421                         }
422                         else
423                         {
424                                 h = get_angle(x1, y1, x2, y2);
425                                 s = distance / x1;
426                                 HSV::hsv_to_rgb(r, g, b, h, s, v);
427                                 row[(int)x2 * 4] = (int)(r * 255);
428                                 row[(int)x2 * 4 + 1] = (int)(g * 255);
429                                 row[(int)x2 * 4 + 2] = (int)(b * 255);
430                                 row[(int)x2 * 4 + 3] = 255;
431                         }
432                 }
433         }
434 //printf("PaletteWheel::create_objects 1\n");
435
436         draw_vframe(&frame, 
437                 0, 
438                 0, 
439                 get_w(), 
440                 get_h(), 
441                 0, 
442                 0, 
443                 get_w(), 
444                 get_h(), 
445                 0);
446 //printf("PaletteWheel::create_objects 1\n");
447
448         oldhue = window->h;
449         oldsaturation = window->s;
450 //printf("PaletteWheel::create_objects 1\n");
451         draw(oldhue, oldsaturation);
452 //printf("PaletteWheel::create_objects 1\n");
453         flash();
454 //printf("PaletteWheel::create_objects 2\n");
455 }
456
457 float PaletteWheel::torads(float angle)
458 {
459         return (float)angle / 360 * 2 * M_PI;
460 }
461
462
463 int PaletteWheel::draw(float hue, float saturation)
464 {
465         int x, y, w, h;
466         x = w = get_w() / 2;
467         y = h = get_h() / 2;
468
469         if(hue > 0 && hue < 90)
470         {
471                 x = (int)(w - w * cos(torads(90 - hue)) * saturation);
472                 y = (int)(h - h * sin(torads(90 - hue)) * saturation);
473         }
474         else
475         if(hue > 90 && hue < 180)
476         {
477                 x = (int)(w - w * cos(torads(hue - 90)) * saturation);
478                 y = (int)(h + h * sin(torads(hue - 90)) * saturation);
479         }
480         else
481         if(hue > 180 && hue < 270)
482         {
483                 x = (int)(w + w * cos(torads(270 - hue)) * saturation);
484                 y = (int)(h + h * sin(torads(270 - hue)) * saturation);
485         }
486         else
487         if(hue > 270 && hue < 360)
488         {
489                 x = (int)(w + w * cos(torads(hue - 270)) * saturation);
490                 y = (int)(h - w * sin(torads(hue - 270)) * saturation);
491         }
492         else
493         if(hue == 0) 
494         {
495                 x = w;
496                 y = (int)(h - h * saturation);
497         }
498         else
499         if(hue == 90)
500         {
501                 x = (int)(w - w * saturation);
502                 y = h;
503         }
504         else
505         if(hue == 180)
506         {
507                 x = w;
508                 y = (int)(h + h * saturation);
509         }
510         else
511         if(hue == 270)
512         {
513                 x = (int)(w + w * saturation);
514                 y = h;
515         }
516
517         set_inverse();
518         set_color(WHITE);
519         draw_circle(x - 5, y - 5, 10, 10);
520         set_opaque();
521         return 0;
522 }
523
524 int PaletteWheel::get_angle(float x1, float y1, float x2, float y2)
525 {
526         float result = -atan2(x2 - x1, y1 - y2) * (360 / M_PI / 2);
527         if (result < 0)
528                 result += 360;
529         return (int)result;
530 }
531
532 PaletteWheelValue::PaletteWheelValue(ColorWindow *window, int x, int y)
533  : BC_SubWindow(x, y, 40, 170, BLACK)
534 {
535         this->window = window;
536         button_down = 0;
537 }
538 PaletteWheelValue::~PaletteWheelValue()
539 {
540         delete frame;
541 }
542
543 void PaletteWheelValue::create_objects()
544 {
545         frame = new VFrame(0, -1, get_w(), get_h(), BC_RGB888, -1);
546         draw(window->h, window->s, window->v);
547         flash();
548 }
549
550 int PaletteWheelValue::button_press_event()
551 {
552 //printf("PaletteWheelValue::button_press 1 %d\n", is_event_win());
553         if(get_cursor_x() >= 0 && get_cursor_x() < get_w() &&
554                 get_cursor_y() >= 0 && get_cursor_y() < get_h() && 
555                 is_event_win())
556         {
557 //printf("PaletteWheelValue::button_press 2\n");
558                 button_down = 1;
559                 cursor_motion_event();
560                 return 1;
561         }
562         return 0;
563 }
564
565 int PaletteWheelValue::cursor_motion_event()
566 {
567         if(button_down && is_event_win())
568         {
569 //printf("PaletteWheelValue::cursor_motion 1\n");
570                 window->v = 1.0 - (float)(get_cursor_y() - 2) / (get_h() - 4);
571                 window->update_display();
572                 window->handle_event();
573                 return 1;
574         }
575         return 0;
576 }
577
578 int PaletteWheelValue::button_release_event()
579 {
580         if(button_down)
581         {
582 //printf("PaletteWheelValue::button_release 1\n");
583                 button_down = 0;
584                 return 1;
585         }
586         return 0;
587 }
588
589 int PaletteWheelValue::draw(float hue, float saturation, float value)
590 {
591         float r_f, g_f, b_f;
592         int i, j, r, g, b;
593
594         for(i = get_h() - 3; i >= 2; i--)
595         {
596                 unsigned char *row = (unsigned char*)frame->get_rows()[i];
597                 HSV::hsv_to_rgb(r_f, 
598                         g_f, 
599                         b_f, 
600                         hue, 
601                         saturation, 
602                         1.0 - (float)(i - 2) / (get_h() - 4));
603                 r = (int)(r_f * 255);
604                 g = (int)(g_f * 255);
605                 b = (int)(b_f * 255);
606                 for(j = 0; j < get_w(); j++)
607                 {
608                         row[j * 3] = r;
609                         row[j * 3 + 1] = g;
610                         row[j * 3 + 2] = b;
611                 }
612         }
613
614         draw_3d_border(0, 
615                 0, 
616                 get_w(), 
617                 get_h(), 
618                 1);
619         draw_vframe(frame, 
620                 2, 
621                 2, 
622                 get_w() - 4, 
623                 get_h() - 4, 
624                 2, 
625                 2, 
626                 get_w() - 4, 
627                 get_h() - 4, 
628                 0);
629         set_color(BLACK);
630         draw_line(2, 
631                 get_h() - 3 - (int)(value * (get_h() - 5)), 
632                 get_w() - 3, 
633                 get_h() - 3 - (int)(value * (get_h() - 5)));
634 //printf("PaletteWheelValue::draw %d %f\n", __LINE__, value);
635
636         return 0;
637 }
638
639 PaletteOutput::PaletteOutput(ColorWindow *window, int x, int y)
640  : BC_SubWindow(x, y, 180, 30, BLACK)
641 {
642         this->window = window;
643 }
644 PaletteOutput::~PaletteOutput()
645 {
646 }
647
648
649 void PaletteOutput::create_objects()
650 {
651         draw();
652         flash();
653 }
654
655 int PaletteOutput::handle_event()
656 {
657         return 1;
658 }
659
660 int PaletteOutput::draw()
661 {
662         float r_f, g_f, b_f;
663         
664         HSV::hsv_to_rgb(r_f, g_f, b_f, window->h, window->s, window->v);
665         set_color(((int)(r_f * 255) << 16) | ((int)(g_f * 255) << 8) | ((int)(b_f * 255)));
666         draw_box(2, 2, get_w() - 4, get_h() - 4);
667         draw_3d_border(0, 
668                 0, 
669                 get_w(), 
670                 get_h(), 
671                 1);
672
673
674         return 0;
675 }
676
677 PaletteHue::PaletteHue(ColorWindow *window, int x, int y)
678  : BC_ISlider(x, y, 0, 150, 200, 0, 359, (int)(window->h), 0)
679 {
680         this->window = window;
681 }
682 PaletteHue::~PaletteHue()
683 {
684 }
685
686 int PaletteHue::handle_event()
687 {
688         window->h = get_value();
689         window->update_display();
690         window->handle_event();
691         return 1;
692 }
693
694 PaletteSaturation::PaletteSaturation(ColorWindow *window, int x, int y)
695  : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, window->s, 0)
696 {
697         this->window = window;
698         set_precision(0.01);
699 }
700 PaletteSaturation::~PaletteSaturation()
701 {
702 }
703
704 int PaletteSaturation::handle_event()
705 {
706 //printf("PaletteSaturation::handle_event 1 %f\n", get_value());
707         window->s = get_value();
708         window->update_display();
709 //printf("PaletteSaturation::handle_event 2 %f\n", get_value());
710         window->handle_event();
711         return 1;
712 }
713
714 PaletteValue::PaletteValue(ColorWindow *window, int x, int y)
715  : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, window->v, 0)
716 {
717         this->window = window;
718         set_precision(0.01);
719 }
720 PaletteValue::~PaletteValue()
721 {
722 }
723
724 int PaletteValue::handle_event()
725 {
726         window->v = get_value();
727         window->update_display();
728         window->handle_event();
729         return 1;
730 }
731
732
733 PaletteRed::PaletteRed(ColorWindow *window, int x, int y)
734  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->r, 0)
735 {
736         this->window = window;
737         set_precision(0.01);
738 }
739 PaletteRed::~PaletteRed()
740 {
741 }
742
743 int PaletteRed::handle_event()
744 {
745         window->update_rgb();
746         window->handle_event();
747         return 1;
748 }
749
750 PaletteGreen::PaletteGreen(ColorWindow *window, int x, int y)
751  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->g, 0)
752 {
753         this->window = window;
754         set_precision(0.01);
755 }
756 PaletteGreen::~PaletteGreen()
757 {
758 }
759
760 int PaletteGreen::handle_event()
761 {
762         window->update_rgb();
763         window->handle_event();
764         return 1;
765 }
766
767 PaletteBlue::PaletteBlue(ColorWindow *window, int x, int y)
768  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->b, 0)
769 {
770         this->window = window;
771         set_precision(0.01);
772 }
773 PaletteBlue::~PaletteBlue()
774 {
775 }
776
777 int PaletteBlue::handle_event()
778 {
779         window->update_rgb();
780         window->handle_event();
781         return 1;
782 }
783
784 PaletteAlpha::PaletteAlpha(ColorWindow *window, int x, int y)
785  : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->a, 0)
786 {
787         this->window = window;
788         set_precision(0.01);
789 }
790 PaletteAlpha::~PaletteAlpha()
791 {
792 }
793
794 int PaletteAlpha::handle_event()
795 {
796         window->a = get_value();
797         window->handle_event();
798         return 1;
799 }
800
801