]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiImage.cpp
do what the FIXME suggested
[lyx.git] / src / frontends / qt4 / GuiImage.cpp
1 /**
2  * \file GuiImage.cpp
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 "GuiImage.h"
15 #include "qt_helpers.h"
16
17 #include "Format.h"
18
19 #include "graphics/GraphicsParams.h"
20
21 #include "support/debug.h"
22 #include "support/FileName.h"
23 #include "support/lstrings.h"       // ascii_lowercase
24
25 #include <QPainter>
26 #include <QImage>
27 #include <QImageReader>
28
29 using namespace std;
30 using namespace lyx::support;
31
32 namespace lyx {
33 namespace graphics {
34
35 /// Access to this class is through this static method.
36 Image * GuiImage::newImage()
37 {
38         return new GuiImage;
39 }
40
41
42 /// Return the list of loadable formats.
43 Image::FormatList GuiImage::loadableFormats()
44 {
45         static FormatList fmts;
46
47         if (!fmts.empty())
48                 return fmts;
49
50         // The formats recognised by LyX
51         Formats::const_iterator begin = formats.begin();
52         Formats::const_iterator end   = formats.end();
53
54         //LYXERR(Debug::GRAPHICS,
55         //      "D:/msys/home/yns/src/lyx-devel/lib/images/banner.png mis of format: "
56         //      << fromqstr(Pic.pictureFormat("D:/msys/.../banner.png")))
57         //if (Pic.pictureFormat("D:/msys/.../banner.png"))
58         //      LYXERR(Debug::GRAPHICS, "pictureFormat not returned NULL\n"
59         //              << "Supported formats are: " << Pic.inputFormats());
60
61         QList<QByteArray> qt_formats = QImageReader::supportedImageFormats();
62
63         LYXERR(Debug::GRAPHICS,
64                 "\nThe image loader can load the following directly:\n");
65
66         if (qt_formats.empty())
67                 LYXERR(Debug::GRAPHICS, "\nQt4 Problem: No Format available!");
68
69         for (QList<QByteArray>::const_iterator it = qt_formats.begin(); it != qt_formats.end(); ++it) {
70
71                 LYXERR(Debug::GRAPHICS, (const char *) *it << ", ");
72
73                 string ext = ascii_lowercase((const char *) *it);
74
75                 // special case
76                 if (ext == "jpeg")
77                         ext = "jpg";
78
79                 for (Formats::const_iterator fit = begin; fit != end; ++fit) 
80                         if (fit->extension() == ext) {
81                                 fmts.push_back(fit->name());
82                                 break;
83                         }
84         }
85
86         if (lyxerr.debugging()) {
87                 LYXERR(Debug::GRAPHICS, "Of these, LyX recognises the following formats:");
88
89                 FormatList::const_iterator fbegin = fmts.begin();
90                 FormatList::const_iterator fend   = fmts.end();
91                 for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
92                         if (fit != fbegin)
93                                 LYXERR(Debug::GRAPHICS, ", ");
94                         LYXERR(Debug::GRAPHICS, *fit);
95                 }
96                 LYXERR(Debug::GRAPHICS, '\n');
97         }
98
99         return fmts;
100 }
101
102
103 GuiImage::GuiImage(GuiImage const & other)
104         : Image(other), original_(other.original_),
105           transformed_(other.transformed_),
106           transformed_pixmap_(other.transformed_pixmap_)
107 {}
108
109
110 Image * GuiImage::clone() const
111 {
112         return new GuiImage(*this);
113 }
114
115
116 unsigned int GuiImage::width() const
117 {
118         return transformed_.width();
119 }
120
121
122 unsigned int GuiImage::height() const
123 {
124         return transformed_.height();
125 }
126
127
128 void GuiImage::load(FileName const & filename)
129 {
130         if (!original_.isNull()) {
131                 LYXERR(Debug::GRAPHICS, "Image is loaded already!");
132                 finishedLoading(false);
133                 return;
134         }
135
136         if (!original_.load(toqstr(filename.absFilename()))) {
137                 LYXERR(Debug::GRAPHICS, "Unable to open image");
138                 finishedLoading(false);
139                 return;
140         }
141         transformed_ = original_;
142         finishedLoading(true);
143 }
144
145
146 // This code is taken from KImageEffect::toGray
147 static QImage & toGray(QImage & img)
148 {
149         if (img.width() == 0 || img.height() == 0)
150                 return img;
151
152         int const pixels = img.depth() > 8 ?
153                 img.width() * img.height() : img.numColors();
154
155         unsigned int *data = img.depth() > 8 ?
156                 reinterpret_cast<unsigned int *>(img.bits()) :
157                 reinterpret_cast<unsigned int *>(&img.colorTable()[0]);
158
159         for(int i = 0; i < pixels; ++i){
160                 int const val = qGray(data[i]);
161                 data[i] = qRgba(val, val, val, qAlpha(data[i]));
162         }
163         return img;
164 }
165
166
167 bool GuiImage::setPixmap(Params const & params)
168 {
169         if (original_.isNull() || params.display == NoDisplay)
170                 return false;
171
172         switch (params.display) {
173         case GrayscaleDisplay: {
174                 toGray(transformed_);
175                 break;
176         }
177
178         case MonochromeDisplay: {
179                 transformed_.convertToFormat(transformed_.format(), Qt::MonoOnly);
180                 break;
181         }
182
183         default:
184                 break;
185         }
186
187         transformed_pixmap_ = QPixmap::fromImage(transformed_);
188         return true;
189 }
190
191
192 void GuiImage::clip(Params const & params)
193 {
194         if (transformed_.isNull())
195                 return;
196
197         if (params.bb.empty())
198                 // No clipping is necessary.
199                 return;
200
201         int const new_width  = params.bb.xr - params.bb.xl;
202         int const new_height = params.bb.yt - params.bb.yb;
203
204         // No need to check if the width, height are > 0 because the
205         // Bounding Box would be empty() in this case.
206         if (new_width > original_.width() || new_height > original_.height()) {
207                 // Bounds are invalid.
208                 return;
209         }
210
211         if (new_width == original_.width() && new_height == original_.height())
212                 return;
213
214         int const xoffset_l = params.bb.xl;
215         int const yoffset_t = (original_.height() > int(params.bb.yt) ?
216                                original_.height() - params.bb.yt : 0);
217
218         transformed_ = original_.copy(xoffset_l, yoffset_t,
219                                       new_width, new_height);
220 }
221
222
223 void GuiImage::rotate(Params const & params)
224 {
225         if (transformed_.isNull())
226                 return;
227
228         if (!params.angle)
229                 return;
230
231         QMatrix m;
232         m.rotate(-params.angle);
233
234         transformed_ = transformed_.transformed(m);
235 }
236
237
238 void GuiImage::scale(Params const & params)
239 {
240         if (transformed_.isNull())
241                 return;
242
243         Dimension dim = scaledDimension(params);
244
245         if (dim.width() == width() && dim.height() == height())
246                 return;
247
248         QMatrix m;
249         m.scale(double(dim.width()) / width(), double(dim.height()) / height());
250         transformed_ = transformed_.transformed(m);
251 }
252
253 } // namespace graphics
254 } // lyx