1 /*
2 * This file is part of RawTherapee.
3 *
4 * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5 * Copyright (c) 2018 Jean-Christophe FRISCH <natureh.510@gmail.com>
6 *
7 * RawTherapee is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * RawTherapee is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "rtimage.h"
22
23 #include <iostream>
24
25 #include "options.h"
26
27 namespace
28 {
29
30 std::map<std::string, Glib::RefPtr<Gdk::Pixbuf> > pixbufCache;
31 std::map<std::string, Cairo::RefPtr<Cairo::ImageSurface> > surfaceCache;
32
33 }
34
35 double RTImage::dpiBack = 0.;
36 int RTImage::scaleBack = 0;
37
RTImage()38 RTImage::RTImage () {}
39
RTImage(RTImage & other)40 RTImage::RTImage (RTImage &other)
41 {
42 dpiBack = other.dpiBack;
43 scaleBack = other.scaleBack;
44 pixbuf = other.pixbuf;
45 surface = other.surface;
46 if (pixbuf) {
47 set(pixbuf);
48 } else if (surface) {
49 set(surface);
50 }
51 }
52
RTImage(const Glib::ustring & fileName,const Glib::ustring & rtlFileName)53 RTImage::RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName) : Gtk::Image()
54 {
55 setImage (fileName, rtlFileName);
56 }
57
RTImage(Glib::RefPtr<Gdk::Pixbuf> & pbuf)58 RTImage::RTImage (Glib::RefPtr<Gdk::Pixbuf> &pbuf)
59 {
60 if (surface) {
61 surface.clear();
62 }
63 if (pbuf) {
64 set(pbuf);
65 this->pixbuf = pbuf;
66 }
67 }
68
RTImage(Cairo::RefPtr<Cairo::ImageSurface> & surf)69 RTImage::RTImage (Cairo::RefPtr<Cairo::ImageSurface> &surf)
70 {
71 if (pixbuf) {
72 pixbuf.clear();
73 }
74 if (surf) {
75 set(surf);
76 surface = surf;
77 }
78 }
79
RTImage(Glib::RefPtr<RTImage> & other)80 RTImage::RTImage (Glib::RefPtr<RTImage> &other)
81 {
82 if (other) {
83 if (other->get_surface()) {
84 surface = other->get_surface();
85 set(surface);
86 } else {
87 pixbuf = other->get_pixbuf();
88 set(pixbuf);
89 }
90 }
91 }
92
setImage(const Glib::ustring & fileName,const Glib::ustring & rtlFileName)93 void RTImage::setImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName)
94 {
95 Glib::ustring imageName;
96
97 if (!rtlFileName.empty() && getDirection() == Gtk::TEXT_DIR_RTL) {
98 imageName = rtlFileName;
99 } else {
100 imageName = fileName;
101 }
102
103 changeImage (imageName);
104 }
105
106 /*
107 * On windows, if scale = 2, the dpi is non significant, i.e. should be considered = 192
108 */
setDPInScale(const double newDPI,const int newScale)109 void RTImage::setDPInScale (const double newDPI, const int newScale)
110 {
111 if (scaleBack != newScale || (scaleBack == 1 && dpiBack != newDPI)) {
112 RTScalable::setDPInScale(newDPI, newScale);
113 dpiBack = getDPI();
114 scaleBack = getScale();
115 updateImages();
116 }
117 }
118
changeImage(const Glib::ustring & imageName)119 void RTImage::changeImage (const Glib::ustring& imageName)
120 {
121 clear ();
122
123 if (imageName.empty()) {
124 return;
125 }
126
127 if (pixbuf) {
128 auto iterator = pixbufCache.find (imageName);
129 assert(iterator != pixbufCache.end ());
130 pixbuf = iterator->second;
131 set(iterator->second);
132 } else { // if no Pixbuf is set, we update or create a Cairo::ImageSurface
133 auto iterator = surfaceCache.find (imageName);
134 if (iterator == surfaceCache.end ()) {
135 auto surf = createImgSurfFromFile(imageName);
136 iterator = surfaceCache.emplace (imageName, surf).first;
137 }
138 surface = iterator->second;
139 set(iterator->second);
140 }
141 }
142
get_surface()143 Cairo::RefPtr<Cairo::ImageSurface> RTImage::get_surface()
144 {
145 return surface;
146 }
147
get_width()148 int RTImage::get_width()
149 {
150 if (surface) {
151 return surface->get_width();
152 }
153 if (pixbuf) {
154 return pixbuf->get_width();
155 }
156 return -1;
157 }
158
get_height()159 int RTImage::get_height()
160 {
161 if (surface) {
162 return surface->get_height();
163 }
164 if (pixbuf) {
165 return pixbuf->get_height();
166 }
167 return -1;
168 }
169
init()170 void RTImage::init()
171 {
172 dpiBack = RTScalable::getDPI();
173 scaleBack = RTScalable::getScale();
174 }
175
cleanup(bool all)176 void RTImage::cleanup(bool all)
177 {
178 for (auto& entry : pixbufCache) {
179 entry.second.reset();
180 }
181 for (auto& entry : surfaceCache) {
182 entry.second.clear();
183 }
184 RTScalable::cleanup(all);
185 }
186
updateImages()187 void RTImage::updateImages()
188 {
189 for (auto& entry : pixbufCache) {
190 entry.second = createPixbufFromFile(entry.first);
191 }
192 for (auto& entry : surfaceCache) {
193 entry.second = createImgSurfFromFile(entry.first);
194 }
195 }
196
createPixbufFromFile(const Glib::ustring & fileName)197 Glib::RefPtr<Gdk::Pixbuf> RTImage::createPixbufFromFile (const Glib::ustring& fileName)
198 {
199 Cairo::RefPtr<Cairo::ImageSurface> imgSurf = createImgSurfFromFile(fileName);
200 return Gdk::Pixbuf::create(imgSurf, 0, 0, imgSurf->get_width(), imgSurf->get_height());
201 }
202
createImgSurfFromFile(const Glib::ustring & fileName)203 Cairo::RefPtr<Cairo::ImageSurface> RTImage::createImgSurfFromFile (const Glib::ustring& fileName)
204 {
205 Cairo::RefPtr<Cairo::ImageSurface> surf;
206
207 try {
208 surf = loadImage(fileName, getTweakedDPI());
209
210 // HOMBRE: As of now, GDK_SCALE is forced to 1, so setting the Cairo::ImageSurface scale is not required
211 /*
212 double x=0., y=0.;
213 cairo_surface_get_device_scale(surf->cobj(), &x, &y);
214 if (getScale() == 2) {
215 cairo_surface_set_device_scale(surf->cobj(), 0.5, 0.5);
216 cairo_surface_get_device_scale(surf->cobj(), &x, &y);
217 surf->flush();
218 }
219 */
220 } catch (const Glib::Exception& exception) {
221 if (options.rtSettings.verbose) {
222 std::cerr << "Failed to load image \"" << fileName << "\": " << exception.what() << std::endl;
223 }
224 }
225
226 return surf;
227 }
228