1 /*
2  *  This file is part of RawTherapee.
3  *
4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5  *
6  *  RawTherapee 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 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  RawTherapee 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 RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 #pragma once
20 
21 #include <gtkmm.h>
22 
23 #include <glibmm/ustring.h>
24 
25 #include <cairomm/cairomm.h>
26 
27 #include "guiutils.h"
28 #include "pointermotionlistener.h"
29 
30 #include "../rtengine/LUT.h"
31 #include "../rtengine/noncopyable.h"
32 
33 class HistogramArea;
34 
35 struct HistogramAreaIdleHelper {
36     HistogramArea* harea;
37     bool destroyed;
38     int pending;
39 };
40 
41 class HistogramRGBArea;
42 struct HistogramRGBAreaIdleHelper {
43     HistogramRGBArea* harea;
44     bool destroyed;
45     int pending;
46 };
47 
48 class HistogramScaling
49 {
50 public:
51     double factor;
HistogramScaling()52     HistogramScaling() : factor(10.0) {}
53     double log (double vsize, double val);
54 };
55 
56 class HistogramRGBArea : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling, public rtengine::NonCopyable
57 {
58 private:
59     typedef const double (*TMatrix)[3];
60 
61     IdleRegister idle_register;
62 
63 protected:
64     int val;
65     int r;
66     int g;
67     int b;
68 
69     bool valid;
70 
71     bool needRed;
72     bool needGreen;
73     bool needBlue;
74     bool needLuma;
75     bool needChroma;
76     bool rawMode;
77     bool showMode;
78     bool barDisplayed;
79 
80     Gtk::Grid* parent;
81 
82     HistogramRGBAreaIdleHelper* harih;
83 
84 public:
85     HistogramRGBArea();
86     ~HistogramRGBArea() override;
87 
88     void updateBackBuffer (int r, int g, int b, const Glib::ustring &profile = "", const Glib::ustring &profileW = "");
89     bool getShow ();
setParent(Gtk::Grid * p)90     void setParent (Gtk::Grid* p)
91     {
92         parent = p;
93     };
94 
95     void update (int val, int rh, int gh, int bh);
96     void updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, bool show);
97 
98     void on_realize() override;
99     bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override;
100     bool on_button_press_event (GdkEventButton* event) override;
101     void factorChanged (double newFactor);
102 
103 private:
104     Gtk::SizeRequestMode get_request_mode_vfunc () const override;
105     void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override;
106     void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override;
107     void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const override;
108     void get_preferred_width_for_height_vfunc (int h, int &minimum_width, int &natural_width) const override;
109 
110 };
111 
112 class DrawModeListener
113 {
114 public:
115     virtual ~DrawModeListener() = default;
116     virtual void toggleButtonMode() = 0;
117 };
118 
119 class HistogramArea : public Gtk::DrawingArea, public BackBuffer, private HistogramScaling, public rtengine::NonCopyable
120 {
121 public:
122     typedef sigc::signal<void, double> type_signal_factor_changed;
123 
124 private:
125     IdleRegister idle_register;
126     type_signal_factor_changed sigFactorChanged;
127 
128 protected:
129     LUTu rhist, ghist, bhist, lhist, chist;
130     LUTu rhistRaw, ghistRaw, bhistRaw, lhistRaw; //lhistRaw is unused?
131 
132     bool valid;
133     int drawMode;
134     DrawModeListener *myDrawModeListener;
135     int oldwidth, oldheight;
136 
137     bool needRed, needGreen, needBlue, needLuma, needChroma;
138     bool rawMode;
139     bool isPressed;
140     double movingPosition;
141 
142     HistogramAreaIdleHelper* haih;
143 
144 public:
145     explicit HistogramArea(DrawModeListener *fml = nullptr);
146     ~HistogramArea() override;
147 
148     void updateBackBuffer ();
149     void update(
150         const LUTu& histRed,
151         const LUTu& histGreen,
152         const LUTu& histBlue,
153         const LUTu& histLuma,
154         const LUTu& histChroma,
155         const LUTu& histRedRaw,
156         const LUTu& histGreenRaw,
157         const LUTu& histBlueRaw
158     );
159     void updateOptions (bool r, bool g, bool b, bool l, bool c, bool raw, int mode);
160     void on_realize() override;
161     bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override;
162     bool on_button_press_event (GdkEventButton* event) override;
163     bool on_button_release_event (GdkEventButton* event) override;
164     bool on_motion_notify_event (GdkEventMotion* event) override;
165     type_signal_factor_changed signal_factor_changed();
166 
167 private:
168     void drawCurve(Cairo::RefPtr<Cairo::Context> &cr, const LUTu & data, double scale, int hsize, int vsize);
169     void drawMarks(Cairo::RefPtr<Cairo::Context> &cr, const LUTu & data, double scale, int hsize, int & ui, int & oi);
170     Gtk::SizeRequestMode get_request_mode_vfunc () const override;
171     void get_preferred_height_vfunc (int& minimum_height, int& natural_height) const override;
172     void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override;
173     void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const override;
174     void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override;
175 };
176 
177 class HistogramPanel : public Gtk::Grid, public PointerMotionListener, public DrawModeListener, public rtengine::NonCopyable
178 {
179 
180 protected:
181 
182     Gtk::Grid* gfxGrid;
183     Gtk::Grid* buttonGrid;
184     HistogramArea* histogramArea;
185     HistogramRGBArea* histogramRGBArea;
186     Gtk::ToggleButton* showRed;
187     Gtk::ToggleButton* showGreen;
188     Gtk::ToggleButton* showBlue;
189     Gtk::ToggleButton* showValue;
190     Gtk::ToggleButton* showRAW;
191     Gtk::ToggleButton* showBAR;
192     Gtk::ToggleButton* showChro;
193     Gtk::Button* showMode;
194 
195     Gtk::Image *redImage;
196     Gtk::Image *greenImage;
197     Gtk::Image *blueImage;
198     Gtk::Image *valueImage;
199     Gtk::Image *rawImage;
200     Gtk::Image *barImage;
201     Gtk::Image *chroImage;
202 
203     Gtk::Image *redImage_g;
204     Gtk::Image *greenImage_g;
205     Gtk::Image *blueImage_g;
206     Gtk::Image *valueImage_g;
207     Gtk::Image *rawImage_g;
208     Gtk::Image *barImage_g;
209     Gtk::Image *chroImage_g;
210 
211     Gtk::Image *mode0Image;
212     Gtk::Image *mode1Image;
213     Gtk::Image *mode2Image;
214 
215     sigc::connection rconn;
216     void setHistInvalid ();
217 
218 public:
219 
220     HistogramPanel ();
221     ~HistogramPanel () override;
222 
histogramChanged(const LUTu & histRed,const LUTu & histGreen,const LUTu & histBlue,const LUTu & histLuma,const LUTu & histChroma,const LUTu & histRedRaw,const LUTu & histGreenRaw,const LUTu & histBlueRaw)223     void histogramChanged(
224         const LUTu& histRed,
225         const LUTu& histGreen,
226         const LUTu& histBlue,
227         const LUTu& histLuma,
228         const LUTu& histChroma,
229         const LUTu& histRedRaw,
230         const LUTu& histGreenRaw,
231         const LUTu& histBlueRaw)
232     {
233         histogramArea->update(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw);
234     }
235     // pointermotionlistener interface
236     void pointerMoved (bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int x, int y, int r, int g, int b, bool isRaw = false) override;
237 
238     // TODO should be protected
239     void setHistRGBInvalid ();
240 
241     void reorder (Gtk::PositionType position);
242     void red_toggled ();
243     void green_toggled ();
244     void blue_toggled ();
245     void value_toggled ();
246     void raw_toggled ();
247     void chro_toggled ();
248     void bar_toggled ();
249     void mode_released ();
250     void rgbv_toggled ();
251     void resized (Gtk::Allocation& req);
252 
253     // drawModeListener interface
254     void toggleButtonMode () override;
255 };
256