00001 #include "bcdisplayinfo.h"
00002 #include "colorpicker.h"
00003 #include "condition.h"
00004 #include "language.h"
00005 #include "mutex.h"
00006 #include "mwindow.inc"
00007 #include "plugincolors.h"
00008 #include "vframe.h"
00009
00010 #include <string.h>
00011 #include <unistd.h>
00012
00013
00014 ColorThread::ColorThread(int do_alpha, char *title)
00015 : Thread()
00016 {
00017 window = 0;
00018 this->title = title;
00019 this->do_alpha = do_alpha;
00020 set_synchronous(0);
00021 mutex = new Mutex("ColorThread::mutex");
00022 completion = new Condition(1, "ColorThread::completion");
00023 }
00024
00025 ColorThread::~ColorThread()
00026 {
00027 if(running())
00028 {
00029 window->set_done(0);
00030 completion->lock("ColorThread::~ColorThread");
00031 completion->unlock();
00032 }
00033 delete mutex;
00034 delete completion;
00035 }
00036
00037 void ColorThread::start_window(int output, int alpha)
00038 {
00039 mutex->lock("ColorThread::start_window 1");
00040 this->output = output;
00041 this->alpha = alpha;
00042 mutex->unlock();
00043
00044 if(!running())
00045 {
00046 completion->lock("ColorThread::start_window");
00047 Thread::start();
00048 }
00049 else
00050 {
00051 window->raise_window();
00052 window->flush();
00053 }
00054 }
00055
00056 void ColorThread::run()
00057 {
00058 BC_DisplayInfo info;
00059
00060 char window_title[BCTEXTLEN];
00061
00062 strcpy(window_title, PROGRAM_NAME ": ");
00063 if(title)
00064 strcat(window_title, title);
00065 else
00066 strcat(window_title, _("Color Picker"));
00067
00068
00069 mutex->lock("ColorThread::run 1");
00070 window = new ColorWindow(this,
00071 info.get_abs_cursor_x() - 200,
00072 info.get_abs_cursor_y() - 200,
00073 window_title);
00074 window->create_objects();
00075 mutex->unlock();
00076 window->run_window();
00077 mutex->lock("lorThread::run 2");
00078 delete window;
00079 window = 0;
00080 mutex->unlock();
00081 completion->unlock();
00082 }
00083
00084 void ColorThread::update_gui(int output, int alpha)
00085 {
00086 mutex->lock("ColorThread::update_gui");
00087 if (window)
00088 {
00089 this->output = output;
00090 this->alpha = alpha;
00091 window->change_values();
00092 window->lock_window();
00093 window->update_display();
00094 window->unlock_window();
00095 }
00096 mutex->unlock();
00097 }
00098
00099 int ColorThread::handle_new_color(int output, int alpha)
00100 {
00101 printf("ColorThread::handle_new_color undefined.\n");
00102 return 0;
00103 }
00104
00105
00106
00107
00108
00109 ColorWindow::ColorWindow(ColorThread *thread, int x, int y, char *title)
00110 : BC_Window(title,
00111 x,
00112 y,
00113 410,
00114 320,
00115 410,
00116 320,
00117 0,
00118 0,
00119 1)
00120 {
00121 this->thread = thread;
00122 }
00123
00124 void ColorWindow::create_objects()
00125 {
00126 int x = 10, init_x = 10, y = 10, init_y = 10;
00127 change_values();
00128
00129
00130
00131
00132 add_tool(wheel = new PaletteWheel(this, x, y));
00133
00134 wheel->create_objects();
00135
00136
00137 x += 180;
00138 add_tool(wheel_value = new PaletteWheelValue(this, x, y));
00139
00140 wheel_value->create_objects();
00141
00142
00143 y += 180;
00144 x = init_x;
00145
00146 add_tool(output = new PaletteOutput(this, x, y));
00147
00148 output->create_objects();
00149
00150
00151 x += 240; y = init_y;
00152 add_tool(new BC_Title(x, y, _("Hue"), SMALLFONT));
00153 y += 15;
00154
00155 add_tool(hue = new PaletteHue(this, x, y));
00156 y += 30;
00157
00158 add_tool(new BC_Title(x, y, _("Saturation"), SMALLFONT));
00159 y += 15;
00160
00161 add_tool(saturation = new PaletteSaturation(this, x, y));
00162 y += 30;
00163
00164 add_tool(new BC_Title(x, y, _("Value"), SMALLFONT));
00165 y += 15;
00166
00167 add_tool(value = new PaletteValue(this, x, y));
00168 y += 30;
00169
00170 add_tool(new BC_Title(x, y, _("Red"), SMALLFONT));
00171 y += 15;
00172
00173 add_tool(red = new PaletteRed(this, x, y));
00174 y += 30;
00175
00176 add_tool(new BC_Title(x, y, _("Green"), SMALLFONT));
00177 y += 15;
00178
00179 add_tool(green = new PaletteGreen(this, x, y));
00180 y += 30;
00181
00182 add_tool(new BC_Title(x, y, _("Blue"), SMALLFONT));
00183 y += 15;
00184
00185 add_tool(blue = new PaletteBlue(this, x, y));
00186
00187 if(thread->do_alpha)
00188 {
00189 y += 30;
00190 add_tool(new BC_Title(x, y, _("Alpha"), SMALLFONT));
00191 y += 15;
00192 add_tool(alpha = new PaletteAlpha(this, x, y));
00193 }
00194
00195 show_window();
00196 flush();
00197 return;
00198 }
00199
00200
00201 void ColorWindow::change_values()
00202 {
00203 r = (float)((thread->output & 0xff0000) >> 16) / 255;
00204 g = (float)((thread->output & 0xff00) >> 8) / 255;
00205 b = (float)((thread->output & 0xff)) / 255;
00206 HSV::rgb_to_hsv(r, g, b, h, s, v);
00207 a = (float)thread->alpha / 255;
00208 }
00209
00210
00211 int ColorWindow::close_event()
00212 {
00213 set_done(0);
00214 return 1;
00215 }
00216
00217
00218 void ColorWindow::update_rgb()
00219 {
00220 HSV::rgb_to_hsv(red->get_value(),
00221 green->get_value(),
00222 blue->get_value(),
00223 h,
00224 s,
00225 v);
00226 update_display();
00227 }
00228
00229 void ColorWindow::update_display()
00230 {
00231 float r, g, b;
00232 if(h < 0) h = 0;
00233 if(h > 360) h = 360;
00234 if(s < 0) s = 0;
00235 if(s > 1) s = 1;
00236 if(v < 0) v = 0;
00237 if(v > 1) v = 1;
00238 if(a < 0) a = 0;
00239 if(a > 1) a = 1;
00240
00241 wheel->draw(wheel->oldhue,
00242 wheel->oldsaturation);
00243 wheel->oldhue = h;
00244 wheel->oldsaturation = s;
00245 wheel->draw(h, s);
00246 wheel->flash();
00247 wheel_value->draw(h, s, v);
00248 wheel_value->flash();
00249 output->draw();
00250 output->flash();
00251 hue->update((int)h);
00252 saturation->update(s);
00253 value->update(v);
00254
00255 HSV::hsv_to_rgb(r, g, b, h, s, v);
00256 red->update(r);
00257 green->update(g);
00258 blue->update(b);
00259 if(thread->do_alpha)
00260 {
00261 alpha->update(a);
00262 }
00263 }
00264
00265 int ColorWindow::handle_event()
00266 {
00267 float r, g, b;
00268 HSV::hsv_to_rgb(r, g, b, h, s, v);
00269 int result = (((int)(r * 255)) << 16) | (((int)(g * 255)) << 8) | ((int)(b * 255));
00270 thread->handle_new_color(result, (int)(a * 255));
00271 return 1;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280 PaletteWheel::PaletteWheel(ColorWindow *window, int x, int y)
00281 : BC_SubWindow(x, y, 170, 170)
00282 {
00283 this->window = window;
00284 oldhue = 0;
00285 oldsaturation = 0;
00286 button_down = 0;
00287 }
00288 PaletteWheel::~PaletteWheel()
00289 {
00290 }
00291
00292 int PaletteWheel::button_press_event()
00293 {
00294 if(get_cursor_x() >= 0 && get_cursor_x() < get_w() &&
00295 get_cursor_y() >= 0 && get_cursor_y() < get_h() &&
00296 is_event_win())
00297 {
00298 button_down = 1;
00299 cursor_motion_event();
00300 return 1;
00301 }
00302 return 0;
00303 }
00304
00305 int PaletteWheel::cursor_motion_event()
00306 {
00307 int x1, y1, distance;
00308 if(button_down && is_event_win())
00309 {
00310 window->h = get_angle(get_w() / 2,
00311 get_h() / 2,
00312 get_cursor_x(),
00313 get_cursor_y());
00314 x1 = get_w() / 2 - get_cursor_x();
00315 y1 = get_h() / 2 - get_cursor_y();
00316 distance = (int)sqrt(x1 * x1 + y1 * y1);
00317 if(distance > get_w() / 2) distance = get_w() / 2;
00318 window->s = (float)distance / (get_w() / 2);
00319 window->update_display();
00320 window->handle_event();
00321 return 1;
00322 }
00323 return 0;
00324 }
00325
00326 int PaletteWheel::button_release_event()
00327 {
00328 if(button_down)
00329 {
00330 button_down = 0;
00331 return 1;
00332 }
00333 return 0;
00334 }
00335
00336 int PaletteWheel::create_objects()
00337 {
00338
00339
00340 float h;
00341 float s;
00342 float v = 1;
00343 float r, g, b;
00344 float x1, y1, x2, y2;
00345 float distance;
00346 int default_r, default_g, default_b;
00347 VFrame frame(0, get_w(), get_h(), BC_RGBA8888);
00348 x1 = get_w() / 2;
00349 y1 = get_h() / 2;
00350 default_r = (get_resources()->get_bg_color() & 0xff0000) >> 16;
00351 default_g = (get_resources()->get_bg_color() & 0xff00) >> 8;
00352 default_b = (get_resources()->get_bg_color() & 0xff);
00353
00354
00355 for(y2 = 0; y2 < get_h(); y2++)
00356 {
00357 for(x2 = 0; x2 < get_w(); x2++)
00358 {
00359 distance = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
00360 if(distance > x1)
00361 {
00362 ((unsigned char*)frame.get_rows()[(int)y2])[(int)x2 * 4] = default_r;
00363 ((unsigned char*)frame.get_rows()[(int)y2])[(int)x2 * 4 + 1] = default_g;
00364 ((unsigned char*)frame.get_rows()[(int)y2])[(int)x2 * 4 + 2] = default_b;
00365 ((unsigned char*)frame.get_rows()[(int)y2])[(int)x2 * 4 + 3] = 0;
00366 }
00367 else
00368 {
00369 h = get_angle(x1, y1, x2, y2);
00370 s = distance / x1;
00371 HSV::hsv_to_rgb(r, g, b, h, s, v);
00372 ((unsigned char*)frame.get_rows()[(int)y2])[(int)x2 * 4] = (int)(r * 255);
00373 ((unsigned char*)frame.get_rows()[(int)y2])[(int)x2 * 4 + 1] = (int)(g * 255);
00374 ((unsigned char*)frame.get_rows()[(int)y2])[(int)x2 * 4 + 2] = (int)(b * 255);
00375 ((unsigned char*)frame.get_rows()[(int)y2])[(int)x2 * 4 + 3] = 255;
00376 }
00377 }
00378 }
00379
00380
00381 draw_vframe(&frame,
00382 0,
00383 0,
00384 get_w(),
00385 get_h(),
00386 0,
00387 0,
00388 get_w(),
00389 get_h(),
00390 0);
00391
00392
00393 oldhue = window->h;
00394 oldsaturation = window->s;
00395
00396 draw(oldhue, oldsaturation);
00397
00398 flash();
00399
00400 return 0;
00401 }
00402
00403 float PaletteWheel::torads(float angle)
00404 {
00405 return (float)angle / 360 * 2 * M_PI;
00406 }
00407
00408
00409 int PaletteWheel::draw(float hue, float saturation)
00410 {
00411 int x, y, w, h;
00412 w = get_w() / 2;
00413 h = get_h() / 2;
00414
00415 if(hue > 0 && hue < 90)
00416 {
00417 x = (int)(w + w * cos(torads(90 - hue)) * saturation);
00418 y = (int)(h - h * sin(torads(90 - hue)) * saturation);
00419 }
00420 else
00421 if(hue > 90 && hue < 180)
00422 {
00423 x = (int)(w + w * cos(torads(hue - 90)) * saturation);
00424 y = (int)(h + h * sin(torads(hue - 90)) * saturation);
00425 }
00426 else
00427 if(hue > 180 && hue < 270)
00428 {
00429 x = (int)(w - w * cos(torads(270 - hue)) * saturation);
00430 y = (int)(h + h * sin(torads(270 - hue)) * saturation);
00431 }
00432 else
00433 if(hue > 270 && hue < 360)
00434 {
00435 x = (int)(w - w * cos(torads(hue - 270)) * saturation);
00436 y = (int)(h - w * sin(torads(hue - 270)) * saturation);
00437 }
00438 else
00439 if(hue == 0)
00440 {
00441 x = w;
00442 y = (int)(h - h * saturation);
00443 }
00444 else
00445 if(hue == 90)
00446 {
00447 x = (int)(w + w * saturation);
00448 y = h;
00449 }
00450 else
00451 if(hue == 180)
00452 {
00453 x = w;
00454 y = (int)(h + h * saturation);
00455 }
00456 else
00457 if(hue == 270)
00458 {
00459 x = (int)(w - w * saturation);
00460 y = h;
00461 }
00462
00463 set_inverse();
00464 set_color(WHITE);
00465 draw_circle(x - 5, y - 5, 10, 10);
00466 set_opaque();
00467 return 0;
00468 }
00469
00470 int PaletteWheel::get_angle(float x1, float y1, float x2, float y2)
00471 {
00472 float result = atan2(x2 - x1, y1 - y2) * (360 / M_PI / 2);
00473 if (result < 0)
00474 result += 360;
00475 return (int)result;
00476 }
00477
00478 PaletteWheelValue::PaletteWheelValue(ColorWindow *window, int x, int y)
00479 : BC_SubWindow(x, y, 40, 170, BLACK)
00480 {
00481 this->window = window;
00482 button_down = 0;
00483 }
00484 PaletteWheelValue::~PaletteWheelValue()
00485 {
00486 delete frame;
00487 }
00488
00489 int PaletteWheelValue::create_objects()
00490 {
00491 frame = new VFrame(0, get_w(), get_h(), BC_RGB888);
00492 draw(window->h, window->s, window->v);
00493 flash();
00494 return 0;
00495 }
00496
00497 int PaletteWheelValue::button_press_event()
00498 {
00499
00500 if(get_cursor_x() >= 0 && get_cursor_x() < get_w() &&
00501 get_cursor_y() >= 0 && get_cursor_y() < get_h() &&
00502 is_event_win())
00503 {
00504
00505 button_down = 1;
00506 cursor_motion_event();
00507 return 1;
00508 }
00509 return 0;
00510 }
00511
00512 int PaletteWheelValue::cursor_motion_event()
00513 {
00514 int x1, y1, distance;
00515 if(button_down && is_event_win())
00516 {
00517
00518 window->v = (float)(get_h() - get_cursor_y()) / get_h();
00519 window->update_display();
00520 window->handle_event();
00521 return 1;
00522 }
00523 return 0;
00524 }
00525
00526 int PaletteWheelValue::button_release_event()
00527 {
00528 if(button_down)
00529 {
00530
00531 button_down = 0;
00532 return 1;
00533 }
00534 return 0;
00535 }
00536
00537 int PaletteWheelValue::draw(float hue, float saturation, float value)
00538 {
00539 float r_f, g_f, b_f;
00540 int i, j, r, g, b;
00541 for(i = get_h() - 1; i >= 0; i--)
00542 {
00543 HSV::hsv_to_rgb(r_f, g_f, b_f, hue, saturation, (float)(get_h() - 1 - i) / get_h());
00544 r = (int)(r_f * 255);
00545 g = (int)(g_f * 255);
00546 b = (int)(b_f * 255);
00547 for(j = 0; j < get_w(); j++)
00548 {
00549 ((unsigned char*)frame->get_rows()[i])[j * 3] = r;
00550 ((unsigned char*)frame->get_rows()[i])[j * 3 + 1] = g;
00551 ((unsigned char*)frame->get_rows()[i])[j * 3 + 2] = b;
00552 }
00553 }
00554 draw_vframe(frame,
00555 0,
00556 0,
00557 get_w(),
00558 get_h(),
00559 0,
00560 0,
00561 get_w(),
00562 get_h(),
00563 0);
00564 set_color(BLACK);
00565 draw_line(0,
00566 get_h() - (int)(value * get_h()),
00567 get_w(),
00568 get_h() - (int)(value * get_h()));
00569 return 0;
00570 }
00571
00572 PaletteOutput::PaletteOutput(ColorWindow *window, int x, int y)
00573 : BC_SubWindow(x, y, 180, 30, BLACK)
00574 {
00575 this->window = window;
00576 }
00577 PaletteOutput::~PaletteOutput()
00578 {
00579 }
00580
00581
00582 int PaletteOutput::create_objects()
00583 {
00584 draw();
00585 flash();
00586 return 0;
00587 }
00588
00589 int PaletteOutput::handle_event()
00590 {
00591 return 1;
00592 }
00593
00594 int PaletteOutput::draw()
00595 {
00596 float r_f, g_f, b_f;
00597
00598 HSV::hsv_to_rgb(r_f, g_f, b_f, window->h, window->s, window->v);
00599 set_color(((int)(r_f * 255) << 16) | ((int)(g_f * 255) << 8) | ((int)(b_f * 255)));
00600 draw_box(0, 0, get_w(), get_h());
00601 return 0;
00602 }
00603
00604 PaletteHue::PaletteHue(ColorWindow *window, int x, int y)
00605 : BC_ISlider(x, y, 0, 150, 200, 0, 359, (int)(window->h), 0)
00606 {
00607 this->window = window;
00608 }
00609 PaletteHue::~PaletteHue()
00610 {
00611 }
00612
00613 int PaletteHue::handle_event()
00614 {
00615 window->h = get_value();
00616 window->update_display();
00617 window->handle_event();
00618 return 1;
00619 }
00620
00621 PaletteSaturation::PaletteSaturation(ColorWindow *window, int x, int y)
00622 : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, window->s, 0)
00623 {
00624 this->window = window;
00625 set_precision(0.01);
00626 }
00627 PaletteSaturation::~PaletteSaturation()
00628 {
00629 }
00630
00631 int PaletteSaturation::handle_event()
00632 {
00633
00634 window->s = get_value();
00635 window->update_display();
00636
00637 window->handle_event();
00638 return 1;
00639 }
00640
00641 PaletteValue::PaletteValue(ColorWindow *window, int x, int y)
00642 : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, window->v, 0)
00643 {
00644 this->window = window;
00645 set_precision(0.01);
00646 }
00647 PaletteValue::~PaletteValue()
00648 {
00649 }
00650
00651 int PaletteValue::handle_event()
00652 {
00653 window->v = get_value();
00654 window->update_display();
00655 window->handle_event();
00656 return 1;
00657 }
00658
00659
00660 PaletteRed::PaletteRed(ColorWindow *window, int x, int y)
00661 : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->r, 0)
00662 {
00663 this->window = window;
00664 set_precision(0.01);
00665 }
00666 PaletteRed::~PaletteRed()
00667 {
00668 }
00669
00670 int PaletteRed::handle_event()
00671 {
00672 window->update_rgb();
00673 window->handle_event();
00674 return 1;
00675 }
00676
00677 PaletteGreen::PaletteGreen(ColorWindow *window, int x, int y)
00678 : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->g, 0)
00679 {
00680 this->window = window;
00681 set_precision(0.01);
00682 }
00683 PaletteGreen::~PaletteGreen()
00684 {
00685 }
00686
00687 int PaletteGreen::handle_event()
00688 {
00689 window->update_rgb();
00690 window->handle_event();
00691 return 1;
00692 }
00693
00694 PaletteBlue::PaletteBlue(ColorWindow *window, int x, int y)
00695 : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->b, 0)
00696 {
00697 this->window = window;
00698 set_precision(0.01);
00699 }
00700 PaletteBlue::~PaletteBlue()
00701 {
00702 }
00703
00704 int PaletteBlue::handle_event()
00705 {
00706 window->update_rgb();
00707 window->handle_event();
00708 return 1;
00709 }
00710
00711 PaletteAlpha::PaletteAlpha(ColorWindow *window, int x, int y)
00712 : BC_FSlider(x, y, 0, 150, 200, 0, 1, window->a, 0)
00713 {
00714 this->window = window;
00715 set_precision(0.01);
00716 }
00717 PaletteAlpha::~PaletteAlpha()
00718 {
00719 }
00720
00721 int PaletteAlpha::handle_event()
00722 {
00723 window->a = get_value();
00724 window->handle_event();
00725 return 1;
00726 }
00727
00728