]> git.lyx.org Git - lyx.git/blob - src/frontends/qt2/QLImage.C
Joao latest bits
[lyx.git] / src / frontends / qt2 / QLImage.C
1 /**
2  * \file QLImage.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  * \author John Levon
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "debug.h"
15 #include "QLImage.h"
16 #include "graphics/GraphicsParams.h"
17 #include "format.h"
18 #include "support/lstrings.h"       // lowercase
19 #include "support/lyxfunctional.h"  // compare_memfun
20 #include "qt_helpers.h"
21
22 #include <qimage.h>
23 #include <qpainter.h>
24
25 #include <boost/tuple/tuple.hpp>
26
27 using lyx::support::lowercase;
28
29 using std::endl;
30 using std::find_if;
31 using std::string;
32
33
34 namespace lyx {
35 namespace graphics {
36
37 /// Access to this class is through this static method.
38 Image::ImagePtr QLImage::newImage()
39 {
40         ImagePtr ptr;
41         ptr.reset(new QLImage);
42         return ptr;
43 }
44
45
46 /// Return the list of loadable formats.
47 Image::FormatList QLImage::loadableFormats()
48 {
49         static FormatList fmts;
50
51         if (!fmts.empty())
52                 return fmts;
53
54         // The formats recognised by LyX
55         Formats::const_iterator begin = formats.begin();
56         Formats::const_iterator end   = formats.end();
57
58         lyxerr[Debug::GRAPHICS]
59                 << "\nThe image loader can load the following directly:\n";
60
61         QStrList qt_formats = QImageIO::inputFormats();
62
63         QStrListIterator it(qt_formats);
64
65         for (; it.current(); ++it) {
66                 lyxerr[Debug::GRAPHICS] << it.current() << endl;
67
68                 string ext = lowercase(it.current());
69
70                 // special case
71                 if (ext == "jpeg")
72                         ext = "jpg";
73
74                 Formats::const_iterator fit =
75                         find_if(begin, end, lyx::compare_memfun(&Format::extension, ext));
76                 if (fit != end)
77                         fmts.push_back(fit->name());
78         }
79
80         if (lyxerr.debugging()) {
81                 lyxerr[Debug::GRAPHICS]
82                         << "\nOf these, LyX recognises the following formats:\n";
83
84                 FormatList::const_iterator fbegin = fmts.begin();
85                 FormatList::const_iterator fend   = fmts.end();
86                 for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
87                         if (fit != fbegin)
88                                 lyxerr[Debug::GRAPHICS] << ", ";
89                         lyxerr[Debug::GRAPHICS] << *fit;
90                 }
91                 lyxerr[Debug::GRAPHICS] << '\n' << endl;
92         }
93
94         return fmts;
95 }
96
97
98 QLImage::QLImage()
99         : Image()
100 {
101 }
102
103
104 QLImage::QLImage(QLImage const & other)
105         : Image(other), pixmap_(other.pixmap_),
106           xformed_pixmap_(other.xformed_pixmap_)
107 {
108 }
109
110
111 QLImage::~QLImage()
112 {
113 }
114
115
116 Image * QLImage::clone_impl() const
117 {
118         return new QLImage(*this);
119 }
120
121
122 unsigned int QLImage::getWidth_impl() const
123 {
124         return xformed_pixmap_.width();
125 }
126
127
128 unsigned int QLImage::getHeight_impl() const
129 {
130         return xformed_pixmap_.height();
131 }
132
133
134 void QLImage::load_impl(string const & filename)
135 {
136         if (!pixmap_.isNull()) {
137                 lyxerr[Debug::GRAPHICS]
138                         << "Image is loaded already!" << endl;
139                 finishedLoading(false);
140                 return;
141         }
142
143         if (!pixmap_.load(toqstr(filename))) {
144                 lyxerr[Debug::GRAPHICS]
145                         << "Unable to open image" << endl;
146                 finishedLoading(false);
147                 return;
148         }
149         xformed_pixmap_ = pixmap_;
150         finishedLoading(true);
151 }
152
153
154 bool QLImage::setPixmap_impl(Params const & params)
155 {
156         if (pixmap_.isNull() || params.display == NoDisplay)
157                 return false;
158
159         // FIXME: it's a fake kind of grayscale !
160
161         switch (params.display) {
162                 case GrayscaleDisplay:
163                 case MonochromeDisplay: {
164                         QImage i(xformed_pixmap_.convertToImage());
165                         xformed_pixmap_.convertFromImage(i, QPixmap::Mono);
166                         break;
167                 }
168
169                 default:
170                         break;
171         }
172 // FIXME
173 #if 0
174         unsigned int fill = packedcolor(LColor::graphicsbg);
175         if (fill != image_->fill_color) {
176                 // the background color has changed.
177                 // Note that in grayscale/monochrome images the background is
178                 // grayed also, so this call will have no visible effect. Sorry!
179                 flimage_replace_pixel(image_, image_->fill_color, fill);
180                 image_->fill_color = fill;
181         }
182 #endif
183
184         return true;
185 }
186
187
188 void QLImage::clip_impl(Params const & params)
189 {
190         if (xformed_pixmap_.isNull())
191                 return;
192
193         if (params.bb.empty())
194                 // No clipping is necessary.
195                 return;
196
197         int const new_width  = params.bb.xr - params.bb.xl;
198         int const new_height = params.bb.yt - params.bb.yb;
199
200         // No need to check if the width, height are > 0 because the
201         // Bounding Box would be empty() in this case.
202         if (new_width > pixmap_.width() || new_height > pixmap_.height()) {
203                 // Bounds are invalid.
204                 return;
205         }
206
207         if (new_width == pixmap_.width() && new_height == pixmap_.height())
208                 return;
209
210         int const xoffset_l = params.bb.xl;
211         int const yoffset_t = (pixmap_.height() > params.bb.yt ?
212                                 pixmap_.height() - params.bb.yt : 0);
213
214         xformed_pixmap_.resize(new_width, new_height);
215         QPainter p;
216         p.begin(&xformed_pixmap_);
217         p.drawPixmap(0, 0, pixmap_, xoffset_l, yoffset_t, new_width, new_height);
218         p.end();
219 }
220
221
222 void QLImage::rotate_impl(Params const & params)
223 {
224         if (xformed_pixmap_.isNull())
225                 return;
226
227         if (!params.angle)
228                 return;
229
230         // The angle passed to flimage_rotate is the angle in one-tenth of a
231         // degree units.
232
233         QWMatrix m;
234         m.rotate(-params.angle);
235         xformed_pixmap_ = xformed_pixmap_.xForm(m);
236 }
237
238
239 void QLImage::scale_impl(Params const & params)
240 {
241         if (xformed_pixmap_.isNull())
242                 return;
243
244         unsigned int width;
245         unsigned int height;
246         boost::tie(width, height) = getScaledDimensions(params);
247
248         if (width == getWidth() && height == getHeight())
249                 return;
250
251         QWMatrix m;
252         m.scale(double(width) / getWidth(), double(height) / getHeight());
253         xformed_pixmap_ = xformed_pixmap_.xForm(m);
254 }
255
256 } // namespace graphics
257 } // lyx