]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QLImage.C
get rid of QT3_SUPPORT
[lyx.git] / src / frontends / qt4 / 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 #ifndef QT3_SUPPORT
13 // #define QT3_SUPPORT
14 #endif
15
16 #include <config.h>
17
18 #include "QLImage.h"
19 #include "qt_helpers.h"
20
21 #include "debug.h"
22 #include "format.h"
23
24 #include "graphics/GraphicsParams.h"
25
26 #include "support/lstrings.h"       // lowercase
27
28 #include <QPainter>
29 #include <QPictureIO>
30 #include <QPicture>
31 #include <QImage>
32 #include <QImageReader>
33
34 #include <boost/bind.hpp>
35 #include <boost/tuple/tuple.hpp>
36
37 using lyx::support::lowercase;
38
39 using boost::bind;
40
41 using std::endl;
42 using std::equal_to;
43 using std::find_if;
44 using std::string;
45
46 QPictureIO StaticPicture;
47
48 namespace lyx {
49 namespace graphics {
50
51 /// Access to this class is through this static method.
52 Image::ImagePtr QLImage::newImage()
53 {
54         ImagePtr ptr;
55         ptr.reset(new QLImage);
56         return ptr;
57 }
58
59
60 /// Return the list of loadable formats.
61 Image::FormatList QLImage::loadableFormats()
62 {
63         static FormatList fmts;
64
65         if (!fmts.empty())
66                 return fmts;
67
68         // The formats recognised by LyX
69         Formats::const_iterator begin = formats.begin();
70         Formats::const_iterator end   = formats.end();
71
72
73 //      lyxerr[Debug::GRAPHICS]
74 //              << "D:/msys/home/yns/src/lyx-devel/lib/images/banner.ppm is of format: "
75 //              << fromqstr(Pic.pictureFormat("D:/msys/home/yns/src/lyx-devel/lib/images/banner.ppm"))
76 //              << endl;
77 //      if (Pic.pictureFormat("D:/msys/home/yns/src/lyx-devel/lib/images/banner.ppm"))
78 //              lyxerr[Debug::GRAPHICS]
79 //                      << "pictureFormat not returned NULL\n" << endl;
80 //                      << "Supported formats are: " << Pic.inputFormats() << endl;
81
82         QList<QByteArray> qt_formats = QImageReader::supportedImageFormats ();
83
84         lyxerr[Debug::GRAPHICS]
85                 << "\nThe image loader can load the following directly:\n";
86
87         if (qt_formats.empty())
88                 lyxerr[Debug::GRAPHICS]
89                         << "\nQt4 Problem: No Format available!" << endl;
90
91         for (QList<QByteArray>::const_iterator it =qt_formats.begin(); it != qt_formats.end(); ++it) {
92
93                 lyxerr[Debug::GRAPHICS] << (const char *) *it << ", ";
94
95                 string ext = lowercase((const char *) *it);
96
97                 // special case
98                 if (ext == "jpeg")
99                         ext = "jpg";
100
101                 Formats::const_iterator fit =
102                         find_if(begin, end,
103                                 bind(equal_to<string>(),
104                                      bind(&Format::extension, _1),
105                                      ext));
106                 if (fit != end)
107                         fmts.push_back(fit->name());
108         }
109
110         if (lyxerr.debugging()) {
111                 lyxerr[Debug::GRAPHICS]
112                         << "\nOf these, LyX recognises the following formats:\n";
113
114                 FormatList::const_iterator fbegin = fmts.begin();
115                 FormatList::const_iterator fend   = fmts.end();
116                 for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
117                         if (fit != fbegin)
118                                 lyxerr[Debug::GRAPHICS] << ", ";
119                         lyxerr[Debug::GRAPHICS] << *fit;
120                 }
121                 lyxerr[Debug::GRAPHICS] << '\n' << endl;
122         }
123
124         return fmts;
125 }
126
127
128 QLImage::QLImage()
129         : Image()
130 {
131 }
132
133
134 QLImage::QLImage(QLImage const & other)
135         : Image(other), original_(other.original_),
136           transformed_(other.transformed_),
137           transformed_pixmap_(other.transformed_pixmap_)
138 {}
139
140
141 Image * QLImage::clone_impl() const
142 {
143         return new QLImage(*this);
144 }
145
146
147 unsigned int QLImage::getWidth_impl() const
148 {
149         return transformed_.width();
150 }
151
152
153 unsigned int QLImage::getHeight_impl() const
154 {
155         return transformed_.height();
156 }
157
158
159 void QLImage::load_impl(string const & filename)
160 {
161         if (!original_.isNull()) {
162                 lyxerr[Debug::GRAPHICS]
163                         << "Image is loaded already!" << endl;
164                 finishedLoading(false);
165                 return;
166         }
167
168         if (!original_.load(toqstr(filename))) {
169                 lyxerr[Debug::GRAPHICS]
170                         << "Unable to open image" << endl;
171                 finishedLoading(false);
172                 return;
173         }
174         transformed_ = original_;
175         finishedLoading(true);
176 }
177
178
179 namespace {
180
181 // This code is taken from KImageEffect::toGray
182 QImage & toGray(QImage & img)
183 {
184         if (img.width() == 0 || img.height() == 0)
185                 return img;
186
187         int const pixels = img.depth() > 8 ?
188                 img.width() * img.height() : img.numColors();
189
190         // FIXME this code used to be like this:
191         //
192         //unsigned int * const data = img.depth() > 8 ?
193         //      (unsigned int *)img.bits() :
194         //      (unsigned int *)img.jumpTable();
195         // 
196         // But Qt doc just say use bits...
197         unsigned int * const data = (unsigned int *)img.bits();
198
199         for(int i = 0; i < pixels; ++i){
200                 int const val = qGray(data[i]);
201                 data[i] = qRgba(val, val, val, qAlpha(data[i]));
202         }
203         return img;
204 }
205
206 } // namespace anon
207
208
209 bool QLImage::setPixmap_impl(Params const & params)
210 {
211         if (original_.isNull() || params.display == NoDisplay)
212                 return false;
213
214         switch (params.display) {
215         case GrayscaleDisplay: {
216                 toGray(transformed_);
217                 break;
218         }
219
220         case MonochromeDisplay: {
221                 transformed_.convertToFormat(transformed_.format(), Qt::MonoOnly);
222                 break;
223         }
224
225         default:
226                 break;
227         }
228
229         transformed_pixmap_ = QPixmap::fromImage(transformed_);
230         return true;
231 }
232
233
234 void QLImage::clip_impl(Params const & params)
235 {
236         if (transformed_.isNull())
237                 return;
238
239         if (params.bb.empty())
240                 // No clipping is necessary.
241                 return;
242
243         int const new_width  = params.bb.xr - params.bb.xl;
244         int const new_height = params.bb.yt - params.bb.yb;
245
246         // No need to check if the width, height are > 0 because the
247         // Bounding Box would be empty() in this case.
248         if (new_width > original_.width() || new_height > original_.height()) {
249                 // Bounds are invalid.
250                 return;
251         }
252
253         if (new_width == original_.width() && new_height == original_.height())
254                 return;
255
256         int const xoffset_l = params.bb.xl;
257         int const yoffset_t = (original_.height() > int(params.bb.yt) ?
258                                original_.height() - params.bb.yt : 0);
259
260         transformed_ = original_.copy(xoffset_l, yoffset_t,
261                                       new_width, new_height);
262 }
263
264
265 void QLImage::rotate_impl(Params const & params)
266 {
267         if (transformed_.isNull())
268                 return;
269
270         if (!params.angle)
271                 return;
272
273         QMatrix m;
274         m.rotate(-params.angle);
275
276         // FIXME: alpha chanel detection is automautic for monochrome
277         // and 8-bit images. For 32 bit, is something like still necessary?
278         //transformed_.setAlphaBuffer(true);
279         transformed_ = transformed_.transformed(m);
280 }
281
282
283 void QLImage::scale_impl(Params const & params)
284 {
285         if (transformed_.isNull())
286                 return;
287
288         unsigned int width;
289         unsigned int height;
290         boost::tie(width, height) = getScaledDimensions(params);
291
292         if (width == getWidth() && height == getHeight())
293                 return;
294
295         QMatrix m;
296         m.scale(double(width) / getWidth(), double(height) / getHeight());
297         transformed_ = transformed_.transformed(m);
298 }
299
300 } // namespace graphics
301 } // lyx