/** -*- C++ -*- * * This file is part of RawTherapee. * * Copyright (c) 2017 Alberto Griggio * * Copyright (c) 2021 Jacques Desmis for CIE xy graph * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ // adapted from the "color correction" module of Darktable. Original copyright follows /* copyright (c) 2009--2010 johannes hanika. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. darktable is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with darktable. If not, see . */ #include "labgrid.h" #include "../rtengine/color.h" #include "options.h" #include "rtimage.h" #include "rtscalable.h" using rtengine::Color; //----------------------------------------------------------------------------- // LabGridArea //----------------------------------------------------------------------------- bool LabGridArea::notifyListener() { if (listener) { const auto round = [](float v) -> float { return int(v * 1000) / 1000.f; }; if (! ciexy_enabled && !ghs_enabled){ listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(high_a), round(high_b), round(low_a), round(low_b))); } else if (ciexy_enabled) { float high_a1 = 0.55f * (high_a + 1.f) - 0.1f; float high_b1 = 0.55f * (high_b + 1.f) - 0.1f; float low_a1 = 0.55f * (low_a + 1.f) - 0.1f; float low_b1 = 0.55f * (low_b + 1.f) - 0.1f; float gre_x1 = 0.55f * (gre_x + 1.f) - 0.1f; float gre_y1 = 0.55f * (gre_y + 1.f) - 0.1f; listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(low_a1), round(low_b1), round(gre_x1), round(gre_y1), round(high_a1), round(high_b1))); } } return false; } LabGridArea::LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low, bool ciexy, bool ghs, bool mous): Gtk::DrawingArea(), evt(evt), evtMsg(msg), litPoint(NONE), low_a(0.f), high_a(0.f), low_b(0.f), high_b(0.f), gre_x(0.f), gre_y(0.f), whi_x(0.f), whi_y(0.f), me_x(0.f), me_y(0.f),ghs_x6(0.f), ghs_y6(0.f), ghs_x7(0.f), ghs_y7(0.f), ghs_x8(0.f), ghs_y8(0.f), ghs_x9(0.f), ghs_y9(0.f), ghs_x10(0.f), ghs_y10(0.f), ghs_x11(0.f), ghs_y11(0.f), //these variables are used as xy in Ciexy - no change labels +4 12 11 defaultLow_a(0.f), defaultHigh_a(0.f), defaultLow_b(0.f), defaultHigh_b(0.f), defaultgre_x(0.f), defaultgre_y(0.f), defaultwhi_x(0.f), defaultwhi_y(0.f), defaultme_x(0.f), defaultme_y(0.f), default_gsx6(0.f), default_gsy6(0.f), default_gsx7(0.f), default_gsy7(0.f), default_gsx8(0.f), default_gsy8(0.f), default_gsx9(0.f), default_gsy9(0.f), default_gsx10(0.f), default_gsy10(0.f), default_gsx11(0.f), default_gsy11(0.f),//+4 12 11 listener(nullptr), edited(false), isDragged(false), low_enabled(enable_low), ciexy_enabled(ciexy), ghs_enabled(ghs), mous_enabled(mous) { set_can_focus(false); // prevent moving the grid while you're moving a point add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK); set_name("LabGrid"); get_style_context()->add_class("drawingarea"); } void LabGridArea::getParams(double &la, double &lb, double &ha, double &hb, double &gx, double &gy, double &wx, double &wy, double &mx, double &my, double &gx6, double &gy6, double &gx7, double &gy7, double &gx8, double &gy8, double &gx9, double &gy9, double &gx10, double &gy10, double &gx11, double &gy11) const { la = low_a; ha = high_a; lb = low_b; hb = high_b; gx = gre_x; gy = gre_y; wx = whi_x; wy = whi_y; mx = me_x; my = me_y; gx6 = ghs_x6; gy6 = ghs_y6; gx7 = ghs_x7; gy7 = ghs_y7; gx8 = ghs_x8; gy8 = ghs_y8; gx9 = ghs_x9; gy9 = ghs_y9; gx10 = ghs_x10;//+4 12 11 gy10 = ghs_y10; gx11 = ghs_x11; gy11 = ghs_y11; // printf("la=%f ha=%f lb=%f hb=%f gx=%f gy=%f\n", la, ha, lb, hb, gx, gy); } void LabGridArea::setParams(double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy, double mx, double my, double gx6, double gy6, double gx7, double gy7, double gx8, double gy8, double gx9, double gy9, double gx10, double gy10, double gx11, double gy11, bool notify) { const double lo = -1.0; const double hi = 1.0; low_a = rtengine::LIM(la, lo, hi); low_b = rtengine::LIM(lb, lo, hi); high_a = rtengine::LIM(ha, lo, hi); high_b = rtengine::LIM(hb, lo, hi); gre_x = rtengine::LIM(gx, lo, hi); gre_y = rtengine::LIM(gy, lo, hi); whi_x = rtengine::LIM(wx, lo, hi); whi_y = rtengine::LIM(wy, lo, hi); me_x = rtengine::LIM(mx, lo, hi); me_y = rtengine::LIM(my, lo, hi); ghs_x6 = rtengine::LIM(gx6, lo, hi); ghs_y6 = rtengine::LIM(gy6, lo, hi); ghs_x7 = rtengine::LIM(gx7, lo, hi); ghs_y7 = rtengine::LIM(gy7, lo, hi); ghs_x8 = rtengine::LIM(gx8, lo, hi); ghs_y8 = rtengine::LIM(gy8, lo, hi); ghs_x9 = rtengine::LIM(gx9, lo, hi); ghs_y9 = rtengine::LIM(gy9, lo, hi); ghs_x10 = rtengine::LIM(gx10, lo, hi);//+4 12 11 ghs_y10 = rtengine::LIM(gy10, lo, hi); ghs_x11 = rtengine::LIM(gx11, lo, hi); ghs_y11 = rtengine::LIM(gy11, lo, hi); queue_draw(); if (notify) { notifyListener(); } } void LabGridArea::setDefault (double la, double lb, double ha, double hb, double gx, double gy, double wx, double wy, double mx, double my, double gx6, double gy6, double gx7, double gy7, double gx8, double gy8, double gx9, double gy9, double gx10, double gy10, double gx11, double gy11) { defaultLow_a = la; defaultLow_b = lb; defaultHigh_a = ha; defaultHigh_b = hb; defaultgre_x = gx; defaultgre_y = gy; defaultwhi_x = wx; defaultwhi_y = wy; defaultme_x = mx; defaultme_y = my; default_gsx6 = gx6; default_gsy6= gy6; default_gsx7 = gx7; default_gsy7= gy7; default_gsx8 = gx8; default_gsy8= gy8; default_gsx9 = gx9; default_gsy9= gy9; default_gsx10 = gx10; default_gsy10= gy10; default_gsx11 = gx11; default_gsy11= gy11; } void LabGridArea::reset(bool toInitial) { if (toInitial) { setParams(defaultLow_a, defaultLow_b, defaultHigh_a, defaultHigh_b, defaultgre_x, defaultgre_y, defaultwhi_x, defaultwhi_y, defaultme_x, defaultme_y, default_gsx6, default_gsy6, default_gsx7, default_gsy7, default_gsx8, default_gsy8, default_gsx9, default_gsy9, default_gsx10, default_gsy10, default_gsx11, default_gsy11, true);//+4 12 11 } else { // printf("RESET \n"); setParams(0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., true);//+4 12 11 } } void LabGridArea::setEdited(bool yes) { edited = yes; } bool LabGridArea::getEdited() const { return edited; } void LabGridArea::setListener(ToolPanelListener *l) { listener = l; } void LabGridArea::on_style_updated () { queue_draw (); } bool LabGridArea::on_draw(const ::Cairo::RefPtr &cr) { // Do not update drawing area if widget is not realized if (!get_realized()) { return true; } Glib::RefPtr style = get_style_context(); Gtk::Border padding = getPadding(style); // Retrieve drawing area size Gtk::Allocation allocation = get_allocation(); allocation.set_x(0); allocation.set_y(0); int width = allocation.get_width(); int height = allocation.get_height(); // Setup drawing cr->set_line_cap(Cairo::LINE_CAP_SQUARE); cr->set_operator (Cairo::OPERATOR_OVER); // Render background style->render_background(cr, static_cast(inset + padding.get_left()) - 1., static_cast(inset + padding.get_top()) - 1., static_cast(width - 2 * inset - padding.get_right() - padding.get_left()) + 2., static_cast(height - 2 * inset - padding.get_top() - padding.get_bottom()) + 2. ); // Drawing the cells cr->translate(static_cast(inset + padding.get_left()), static_cast(inset + padding.get_top())); cr->set_antialias(Cairo::ANTIALIAS_NONE); width -= 2 * inset + padding.get_right() + padding.get_left(); height -= 2 * inset + padding.get_top() + padding.get_bottom(); // flip y: cr->translate(0., static_cast(height)); cr->scale(1., -1.); if (! ciexy_enabled && !ghs_enabled) {//draw cells for general Labgrid const int cells = 8; const float step = 12000.f / static_cast(cells/2); const double cellW = static_cast(width) / static_cast(cells); const double cellH = static_cast(height) / static_cast(cells); double cellYMin = 0.; double cellYMax = std::floor(cellH); for (int j = 0; j < cells; j++) { double cellXMin = 0.; double cellXMax = std::floor(cellW); for (int i = 0; i < cells; i++) { float R, G, B; float x, y, z; const int ii = i - cells/2; const int jj = j - cells/2; const float a = step * static_cast(ii + 0.5f); const float b = step * static_cast(jj + 0.5f); Color::Lab2XYZ(25000.f, a, b, x, y, z); Color::xyz2srgb(x, y, z, R, G, B); cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); cr->rectangle( cellXMin, cellYMin, cellXMax - cellXMin - (i == cells-1 ? 0. : 1.), cellYMax - cellYMin - (j == cells-1 ? 0. : 1.) ); cellXMin = cellXMax; cellXMax = std::floor(cellW * static_cast(i+2) + 0.01); cr->fill(); } cellYMin = cellYMax; cellYMax = std::floor(cellH * static_cast(j+2) + 0.01); } } else if (ciexy_enabled) {//cells for CIE xy in SE and Abstract profile const int cells = 600; const float step = 1.f / static_cast(cells); const double cellW = static_cast(width) / static_cast(cells); const double cellH = static_cast(height) / static_cast(cells); double cellYMin = 0.; double cellYMax = std::floor(cellH); //various approximations to simulate Ciexy curves graph // this graph is not accurate...I replace curve by polygon or parabolic const float xa = 0.2653f / (0.7347f - 0.17f); const float xb = -0.17f * xa; //linear values const float axs = (0.2653f - 0.65f) / (0.7347f - 0.35f); const float bxs = 0.65f - axs * 0.35f; const float ay = 0.4f; const float by = 0.4f; for (int j = 0; j < cells; j++) { double cellXMin = 0.; double cellXMax = std::floor(cellW); for (int i = 0; i < cells; i++) { float R, G, B; float XX, YY, ZZ; const float x = 1.1f * step * static_cast(i) - 0.1f;//Graph CIExy with -0.1 to 1 - must be enough const float y = 1.1f * step * static_cast(j) - 0.1;//Graph CIExy with -0.1 to 1 - must be enough if(y > 0.5f) { YY = 0.6f; } else { YY = ay * y + by; } XX = (x * YY) / y; ZZ = ((1.f - x - y)* YY) / y; const float yr = xa * x + xb; const float y2 = axs * x + bxs; const float y6 = 22.52f * x * x - 7.652f * x + 0.65f;//parabolic passing in x=0.17 y=0 - x=0.1 y =0.11 - x=0 y= 0.65 const float y3 = -1.266666f * x * x -0.170002f * x + 0.859686f;//other parabolic for green passing in x=0.35 y=0.65 - x=0.20 y=0.775 - x=0.1 y=0.83 const float y4 = -60.71428f * x * x + 6.821428f * x + 0.65f;//other parabolic x=0 y=0.65 - x=0.03 y=0.8 - x=0.07 y=0.83 //small difference in the connection of the 2 last parabolic Color::xyz2srgb(XX, YY, ZZ, R, G, B); //replace color by gray if(y < yr && x > 0.17f) { R = 0.7f; G = 0.7f; B = 0.7f; } if(y < y6 && y < 0.65f && x < 0.17f) { R = 0.7f; G = 0.7f; B = 0.7f; } if(y > y2 && x > 0.35f) {//0.35 R = 0.7f; G = 0.7f; B = 0.7f; } if(y > y3 && x <= 0.35f && x > 0.06f) {//0.35 R = 0.7f; G = 0.7f; B = 0.7f; } if(y > y4 && x <= 0.06f) { R = 0.7f; G = 0.7f; B = 0.7f; } cr->set_source_rgb(R , G , B); cr->rectangle( cellXMin, cellYMin, cellXMax - cellXMin, cellYMax - cellYMin); cellXMin = cellXMax; cellXMax = std::floor(cellW * static_cast(i+2) + 0.001); cr->fill(); } cellYMin = cellYMax; cellYMax = std::floor(cellH * static_cast(j+2) + 0.001); } } else if (ghs_enabled) {//cells for GHS and simulation GHS const int cells = 600; const double cellW = static_cast(width) / static_cast(cells); const double cellH = static_cast(height) / static_cast(cells); double cellYMin = 0.; double cellYMax = std::floor(cellH); for (int j = 0; j < cells; j++) { double cellXMin = 0.; double cellXMax = std::floor(cellW); for (int i = 0; i < cells; i++) { float R, G, B; R = 0.7f; G = 0.7f; B = 0.7f; cr->set_source_rgb(R , G , B); cr->rectangle( cellXMin, cellYMin, cellXMax - cellXMin, cellYMax - cellYMin); cellXMin = cellXMax; cellXMax = std::floor(cellW * static_cast(i+2) + 0.001); cr->fill(); } cellYMin = cellYMax; cellYMax = std::floor(cellH * static_cast(j+2) + 0.001); } } // Drawing the connection line cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); // float loa, hia, lob, hib, grx, gry, whx, why, mex, mey; double loa = .5 * (static_cast(width) + static_cast(width) * low_a); double hia = .5 * (static_cast(width) + static_cast(width) * high_a); double lob = .5 * (static_cast(height) + static_cast(height) * low_b); double hib = .5 * (static_cast(height) + static_cast(height) * high_b); double grx = .5 * (static_cast(width) + static_cast(width) * gre_x); double gry = .5 * (static_cast(height) + static_cast(height) * gre_y); double whx = .5 * (static_cast(width) + static_cast(width) * whi_x); double why = .5 * (static_cast(height) + static_cast(height) * whi_y); double mex = .5 * (static_cast(width) + static_cast(width) * me_x); double mey = .5 * (static_cast(height) + static_cast(height) * me_y); cr->set_line_width(1.5); if (ciexy_enabled) { mex = .5 * (width + width * me_x); mey = .5 * (height + height * me_y); } cr->set_source_rgb(0.6, 0.6, 0.6); if (!ghs_enabled) { cr->move_to(loa, lob); cr->line_to(hia, hib); } if (ciexy_enabled) { cr->move_to(loa, lob); cr->line_to(grx, gry); cr->move_to(grx, gry); cr->line_to(hia, hib); } else if (ghs_enabled) { cr->set_line_width(3.); cr->set_source_rgb(0.2, 0.2, 0.2); loa = (static_cast(width) * low_a); hia = (static_cast(width) * high_a); lob = (static_cast(height) * low_b); hib = (static_cast(height) * high_b); grx = (static_cast(width) * gre_x); gry = (static_cast(height) * gre_y); whx = (static_cast(width) * whi_x); why = (static_cast(height) * whi_y); mex = (static_cast(width) * me_x); mey = (static_cast(height) * me_y); double gx6 = (static_cast(width) * ghs_x6); double gy6 = (static_cast(height) * ghs_y6); double gx7 = (static_cast(width) * ghs_x7); double gy7 = (static_cast(height) * ghs_y7); double gx8 = (static_cast(width) * ghs_x8); double gy8 = (static_cast(height) * ghs_y8); double gx9 = (static_cast(width) * ghs_x9); double gy9 = (static_cast(height) * ghs_y9); double gx10 = (static_cast(width) * ghs_x10); double gy10 = (static_cast(height) * ghs_y10); double gx11 = (static_cast(width) * ghs_x11); double gy11 = (static_cast(height) * ghs_y11); double onex = (static_cast(width) * 1.); double oney = (static_cast(height) * 1.); cr->move_to(0., 0.); cr->line_to(loa, lob); cr->move_to(loa, lob); cr->line_to(hia, hib); cr->move_to(hia, hib); cr->line_to(grx, gry); cr->move_to(grx, gry); cr->line_to(whx, why); cr->move_to(whx, why); cr->line_to(mex, mey); cr->move_to(mex, mey); cr->line_to(gx6, gy6); cr->move_to(gx6, gy6); cr->line_to(gx7, gy7); cr->move_to(gx7, gy7); cr->line_to(gx8, gy8); cr->move_to(gx8, gy8); cr->line_to(gx9, gy9); cr->move_to(gx9, gy9); cr->line_to(gx10, gy10); cr->move_to(gx10, gy10); cr->line_to(gx11, gy11); cr->move_to(gx11, gy11); cr->line_to(onex, oney); } cr->stroke(); if(ghs_enabled) {//only 10 * 10 squares cr->set_line_width(0.2); cr->set_source_rgb(0.1, 0.1, 0.1); //draw horiz and vertical lines for(int i = 0; i < 10; i++) { cr->move_to(0.1 * static_cast(i * width), 0.); cr->line_to(0.1 * static_cast(i * width), static_cast(height)); } for(int i = 0; i < 10; i++) { cr->move_to(0., 0.1 * static_cast(i * height)); cr->line_to(static_cast(width), 0.1 * static_cast(i * height)); } cr->stroke(); } else if (ciexy_enabled) {//for CIExy cr->set_line_width(0.2); cr->set_source_rgb(0.1, 0.1, 0.1); //draw horiz and vertical lines for(int i = 0; i < 22; i++) { cr->move_to(0.04545 * static_cast(i * width), 0.); cr->line_to(0.04545 * static_cast(i * width), static_cast(height)); } for(int i = 0; i < 22; i++) { cr->move_to(0., 0.04545 * static_cast(i * height)); cr->line_to(static_cast(width), 0.04545 * static_cast(i * height)); } cr->stroke(); //draw abciss and ordonate cr->set_line_width(1.); cr->set_source_rgb(0.4, 0., 0.); cr->move_to(0.04545 * static_cast(2 * width), 0.); cr->line_to(0.04545 * static_cast(2 * width), static_cast(height)); cr->move_to(0., 0.04545 * static_cast(2 * height)); cr->line_to(static_cast(width), 0.04545 * static_cast(2 * height)); cr->stroke(); //draw 0 and 1 with circle and lines cr->set_line_width(1.2); cr->set_source_rgb(0.4, 0., 0.); cr->arc(0.06 * static_cast(width), 0.06 * static_cast(height), 0.016 * static_cast(width), 0., 2. * rtengine::RT_PI); cr->stroke(); cr->set_line_width(1.5); cr->set_source_rgb(0.4, 0., 0.); cr->move_to(0.985 * static_cast(width), 0.08 * static_cast(height)); cr->line_to(0.985 * static_cast(width), 0.055 * static_cast(height)); cr->move_to(0.07 * static_cast(width), 0.99 * static_cast(height)); cr->line_to(0.07 * static_cast(width), 0.965 * static_cast(height)); cr->stroke(); } if(!ghs_enabled) {//no points with GHS // Drawing points if (low_enabled) { cr->set_source_rgb(0.1, 0.1, 0.1);//black for red in Ciexy if (litPoint == LOW) { cr->arc(loa, lob, 5., 0., 2. * rtengine::RT_PI); } else { cr->arc(loa, lob, 3., 0., 2. * rtengine::RT_PI); } cr->fill(); } if (ciexy_enabled) { cr->set_source_rgb(0.5, 0.5, 0.5);//gray for green if (litPoint == GRE) { cr->arc(grx, gry, 5., 0., 2. * rtengine::RT_PI); } else { cr->arc(grx, gry, 3., 0., 2. * rtengine::RT_PI); } cr->fill(); } if (ciexy_enabled) {//White Point cr->set_source_rgb(1., 1., 1.);//White cr->arc(whx, why, 3., 0., 2. * rtengine::RT_PI); cr->fill(); } if (ciexy_enabled) {//Dominant cr->set_source_rgb(0.3, 0.4, 0.3); cr->arc(mex, mey, 3., 0, 2. * rtengine::RT_PI); cr->fill(); } cr->set_source_rgb(0.9, 0.9, 0.9);//white for blue en Ciexy if (litPoint == HIGH) { cr->arc(hia, hib, 5., 0., 2. * rtengine::RT_PI); } else { cr->arc(hia, hib, 3., 0., 2. * rtengine::RT_PI); } cr->fill(); } return false; } bool LabGridArea::on_button_press_event(GdkEventButton *event) { if (event->button == 1 && mous_enabled) { if (!ciexy_enabled && !ghs_enabled) { if (event->type == GDK_2BUTTON_PRESS) { switch (litPoint) { case NONE: low_a = low_b = high_a = high_b = gre_x = gre_y = 0.f; break; case LOW: low_a = low_b = 0.f; break; case HIGH: high_a = high_b = 0.f; break; case GRE: gre_x = gre_y = 0.f; break; } edited = true; notifyListener(); queue_draw(); } else if (event->type == GDK_BUTTON_PRESS && litPoint != NONE) { isDragged = true; } } else { if(mous_enabled) { if (event->type == GDK_2BUTTON_PRESS) { edited = true; notifyListener(); queue_draw(); } else if (event->type == GDK_BUTTON_PRESS && litPoint != NONE) { isDragged = true; } } } return false; } return true; } bool LabGridArea::on_button_release_event(GdkEventButton *event) { if (event->button == 1 && mous_enabled) { isDragged = false; return false; } return true; } bool LabGridArea::on_motion_notify_event(GdkEventMotion *event) { if (isDragged && delayconn.connected()) { delayconn.disconnect(); } Glib::RefPtr style = get_style_context(); Gtk::Border padding = getPadding(style); // already scaled State oldLitPoint = litPoint; const int width = get_allocated_width() - 2 * inset - padding.get_right() - padding.get_left(); const int height = get_allocated_height() - 2 * inset - padding.get_top() - padding.get_bottom(); const float mouse_x = std::min(double(std::max(event->x - inset - padding.get_right(), 0.)), double(width)); const float mouse_y = std::min(double(std::max(get_allocated_height() - 1 - event->y - inset - padding.get_bottom(), 0.)), double(height)); const float ma = (2.f * mouse_x - width) / width; const float mb = (2.f * mouse_y - height) / height; if (isDragged) { if (litPoint == LOW) { low_a = ma; low_b = mb; } else if (litPoint == HIGH) { high_a = ma; high_b = mb; } else if (litPoint == GRE) { gre_x = ma; gre_y = mb; } edited = true; grab_focus(); if (options.adjusterMinDelay == 0) { notifyListener(); } else { delayconn = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LabGridArea::notifyListener), options.adjusterMinDelay); } queue_draw(); } else { litPoint = NONE; const float la = low_a; const float lb = low_b; const float ha = high_a; const float hb = high_b; const float gx = gre_x; const float gy = gre_y; const float thrs = 0.05f; const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb); const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb); const float distgxy = (gx - ma) * (gx - ma) + (gy - mb) * (gy - mb); if (low_enabled && distlo < thrs * thrs && distlo < disthi) { litPoint = LOW; } else if (disthi < thrs * thrs && disthi <= distlo) { litPoint = HIGH; } else if (ciexy_enabled && !ghs_enabled && distgxy < thrs * thrs && distgxy <= distlo) { litPoint = GRE; } if ((oldLitPoint == NONE && litPoint != NONE) || (oldLitPoint != NONE && litPoint == NONE)) { queue_draw(); } } return true; } Gtk::SizeRequestMode LabGridArea::get_request_mode_vfunc() const { return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH; } void LabGridArea::get_preferred_width_vfunc(int &minimum_width, int &natural_width) const { Glib::RefPtr style = get_style_context(); Gtk::Border padding = getPadding(style); // already scaled const int s = RTScalable::scalePixelSize(1); const int p = padding.get_left() + padding.get_right(); minimum_width = 50 * s + p; natural_width = 150 * s + p; // same as GRAPH_SIZE from mycurve.h } void LabGridArea::get_preferred_height_for_width_vfunc(int width, int &minimum_height, int &natural_height) const { Glib::RefPtr style = get_style_context(); Gtk::Border padding = getPadding(style); // already scaled minimum_height = natural_height = width - padding.get_left() - padding.get_right() + padding.get_top() + padding.get_bottom(); } bool LabGridArea::lowEnabled() const { return low_enabled; } bool LabGridArea::ciexyEnabled() const { return ciexy_enabled; } bool LabGridArea::ghsEnabled() const { return ghs_enabled; } void LabGridArea::setLowEnabled(bool yes) { if (low_enabled != yes) { low_enabled = yes; queue_draw(); } } void LabGridArea::setciexyEnabled(bool yes) { if (ciexy_enabled != yes) { ciexy_enabled = yes; queue_draw(); } } void LabGridArea::setghsEnabled(bool yes) { if (ghs_enabled != yes) { ghs_enabled = yes; queue_draw(); } } void LabGridArea::setmousEnabled(bool yes) { if (mous_enabled != yes) { mous_enabled = yes; queue_draw(); } } //----------------------------------------------------------------------------- // LabGrid //----------------------------------------------------------------------------- LabGrid::LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low, bool ciexy, bool ghs, bool mous): grid(evt, msg, enable_low, ciexy, ghs, mous) { Gtk::Button *reset = Gtk::manage(new Gtk::Button()); reset->set_tooltip_markup(M("ADJUSTER_RESET_TO_DEFAULT")); if(!ciexy || !ghs) {//disabled for Cie xy and GHS reset->add(*Gtk::manage(new RTImage("undo-small", Gtk::ICON_SIZE_BUTTON))); } reset->signal_button_release_event().connect(sigc::mem_fun(*this, &LabGrid::resetPressed)); setExpandAlignProperties(reset, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); reset->set_relief(Gtk::RELIEF_NONE); reset->get_style_context()->add_class(GTK_STYLE_CLASS_FLAT); reset->set_can_focus(false); reset->set_size_request(-1, 20); pack_start(grid, true, true, true); if(!ghs) {//disable reset when GHS pack_start(*reset, false, false); } show_all_children(); } bool LabGrid::resetPressed(GdkEventButton *event) { grid.reset(event->state & GDK_CONTROL_MASK); return false; }