Line | Source | Count |
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | | - |
8 | | - |
9 | | - |
10 | | - |
11 | | - |
12 | | - |
13 | | - |
14 | | - |
15 | | - |
16 | | - |
17 | | - |
18 | | - |
19 | | - |
20 | | - |
21 | | - |
22 | | - |
23 | | - |
24 | | - |
25 | | - |
26 | | - |
27 | | - |
28 | | - |
29 | | - |
30 | | - |
31 | | - |
32 | | - |
33 | | - |
34 | #include <qplatformdefs.h> | - |
35 | #include "private/qxbmhandler_p.h" | - |
36 | | - |
37 | #ifndef QT_NO_IMAGEFORMAT_XBM | - |
38 | | - |
39 | #include <qimage.h> | - |
40 | #include <qiodevice.h> | - |
41 | #include <qvariant.h> | - |
42 | | - |
43 | #include <stdio.h> | - |
44 | #include <ctype.h> | - |
45 | | - |
46 | QT_BEGIN_NAMESPACE | - |
47 | | - |
48 | | - |
49 | | - |
50 | | - |
51 | | - |
52 | static inline int hex2byte(char *p) | - |
53 | { | - |
54 | return ((isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4) | never executed: return ((isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4) | (isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10); TRUE | never evaluated | FALSE | never evaluated |
| 0 |
55 | (isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10); never executed: return ((isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4) | (isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10); | 0 |
56 | } | - |
57 | | - |
58 | static bool read_xbm_header(QIODevice *device, int& w, int& h) | - |
59 | { | - |
60 | const int buflen = 300; | - |
61 | const int maxlen = 4096; | - |
62 | char buf[buflen + 1]; | - |
63 | QRegExp r1(QLatin1String("^#define[ \t]+[a-zA-Z0-9._]+[ \t]+")); | - |
64 | QRegExp r2(QLatin1String("[0-9]+")); | - |
65 | | - |
66 | qint64 readBytes = 0; | - |
67 | qint64 totalReadBytes = 0; | - |
68 | | - |
69 | buf[0] = '\0'; | - |
70 | | - |
71 | | - |
72 | while (buf[0] != '#') {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
73 | readBytes = device->readLine(buf, buflen); | - |
74 | | - |
75 | | - |
76 | if (readBytes <= 0 || readBytes >= buflen -1)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
77 | return false; never executed: return false; | 0 |
78 | | - |
79 | | - |
80 | | - |
81 | totalReadBytes += readBytes; | - |
82 | if (totalReadBytes >= maxlen)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
83 | return false; never executed: return false; | 0 |
84 | } never executed: end of block | 0 |
85 | | - |
86 | buf[readBytes - 1] = '\0'; | - |
87 | QString sbuf; | - |
88 | sbuf = QString::fromLatin1(buf); | - |
89 | | - |
90 | | - |
91 | if (r1.indexIn(sbuf) == 0 &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
92 | r2.indexIn(sbuf, r1.matchedLength()) == r1.matchedLength())TRUE | never evaluated | FALSE | never evaluated |
| 0 |
93 | w = QByteArray(&buf[r1.matchedLength()]).trimmed().toInt(); never executed: w = QByteArray(&buf[r1.matchedLength()]).trimmed().toInt(); | 0 |
94 | | - |
95 | | - |
96 | readBytes = device->readLine(buf, buflen); | - |
97 | if (readBytes <= 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
98 | return false; never executed: return false; | 0 |
99 | buf[readBytes - 1] = '\0'; | - |
100 | | - |
101 | sbuf = QString::fromLatin1(buf); | - |
102 | | - |
103 | if (r1.indexIn(sbuf) == 0 &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
104 | r2.indexIn(sbuf, r1.matchedLength()) == r1.matchedLength())TRUE | never evaluated | FALSE | never evaluated |
| 0 |
105 | h = QByteArray(&buf[r1.matchedLength()]).trimmed().toInt(); never executed: h = QByteArray(&buf[r1.matchedLength()]).trimmed().toInt(); | 0 |
106 | | - |
107 | | - |
108 | if (w <= 0 || w > 32767 || h <= 0 || h > 32767)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
109 | return false; never executed: return false; | 0 |
110 | | - |
111 | return true; never executed: return true; | 0 |
112 | } | - |
113 | | - |
114 | static bool read_xbm_body(QIODevice *device, int w, int h, QImage *outImage) | - |
115 | { | - |
116 | const int buflen = 300; | - |
117 | char buf[buflen + 1]; | - |
118 | | - |
119 | qint64 readBytes = 0; | - |
120 | | - |
121 | char *p; | - |
122 | | - |
123 | | - |
124 | do { | - |
125 | if ((readBytes = device->readLine(buf, buflen)) <= 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
126 | | - |
127 | return false; never executed: return false; | 0 |
128 | } | - |
129 | | - |
130 | buf[readBytes] = '\0'; | - |
131 | p = strstr(buf, "0x"); | - |
132 | } while (!p); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
133 | | - |
134 | if (outImage->size() != QSize(w, h) || outImage->format() != QImage::Format_MonoLSB) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
135 | *outImage = QImage(w, h, QImage::Format_MonoLSB); | - |
136 | if (outImage->isNull())TRUE | never evaluated | FALSE | never evaluated |
| 0 |
137 | return false; never executed: return false; | 0 |
138 | } never executed: end of block | 0 |
139 | | - |
140 | outImage->setColorCount(2); | - |
141 | outImage->setColor(0, qRgb(255,255,255)); | - |
142 | outImage->setColor(1, qRgb(0,0,0)); | - |
143 | | - |
144 | int x = 0, y = 0; | - |
145 | uchar *b = outImage->scanLine(0); | - |
146 | w = (w+7)/8; | - |
147 | | - |
148 | while (y < h) { TRUE | never evaluated | FALSE | never evaluated |
| 0 |
149 | if (p) { TRUE | never evaluated | FALSE | never evaluated |
| 0 |
150 | *b++ = hex2byte(p+2); | - |
151 | p += 2; | - |
152 | if (++x == w && ++y < h) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
153 | b = outImage->scanLine(y); | - |
154 | x = 0; | - |
155 | } never executed: end of block | 0 |
156 | p = strstr(p, "0x"); | - |
157 | } else { never executed: end of block | 0 |
158 | if ((readBytes = device->readLine(buf,buflen)) <= 0) TRUE | never evaluated | FALSE | never evaluated |
| 0 |
159 | break; never executed: break; | 0 |
160 | buf[readBytes] = '\0'; | - |
161 | p = strstr(buf, "0x"); | - |
162 | } never executed: end of block | 0 |
163 | } | - |
164 | | - |
165 | return true; never executed: return true; | 0 |
166 | } | - |
167 | | - |
168 | static bool read_xbm_image(QIODevice *device, QImage *outImage) | - |
169 | { | - |
170 | int w = 0, h = 0; | - |
171 | if (!read_xbm_header(device, w, h))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
172 | return false; never executed: return false; | 0 |
173 | return read_xbm_body(device, w, h, outImage); never executed: return read_xbm_body(device, w, h, outImage); | 0 |
174 | } | - |
175 | | - |
176 | static bool write_xbm_image(const QImage &sourceImage, QIODevice *device, const QString &fileName) | - |
177 | { | - |
178 | QImage image = sourceImage; | - |
179 | int w = image.width(); | - |
180 | int h = image.height(); | - |
181 | int i; | - |
182 | QString s = fileName; | - |
183 | int msize = s.length() + 100; | - |
184 | char *buf = new char[msize]; | - |
185 | | - |
186 | qsnprintf(buf, msize, "#define %s_width %d\n", s.toUtf8().data(), w); | - |
187 | device->write(buf, qstrlen(buf)); | - |
188 | qsnprintf(buf, msize, "#define %s_height %d\n", s.toUtf8().data(), h); | - |
189 | device->write(buf, qstrlen(buf)); | - |
190 | qsnprintf(buf, msize, "static char %s_bits[] = {\n ", s.toUtf8().data()); | - |
191 | device->write(buf, qstrlen(buf)); | - |
192 | | - |
193 | if (image.format() != QImage::Format_MonoLSB)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
194 | image = image.convertToFormat(QImage::Format_MonoLSB); never executed: image = image.convertToFormat(QImage::Format_MonoLSB); | 0 |
195 | | - |
196 | bool invert = qGray(image.color(0)) < qGray(image.color(1)); | - |
197 | char hexrep[16]; | - |
198 | for (i=0; i<10; i++)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
199 | hexrep[i] = '0' + i; never executed: hexrep[i] = '0' + i; | 0 |
200 | for (i=10; i<16; i++)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
201 | hexrep[i] = 'a' -10 + i; never executed: hexrep[i] = 'a' -10 + i; | 0 |
202 | if (invert) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
203 | char t; | - |
204 | for (i=0; i<8; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
205 | t = hexrep[15-i]; | - |
206 | hexrep[15-i] = hexrep[i]; | - |
207 | hexrep[i] = t; | - |
208 | } never executed: end of block | 0 |
209 | } never executed: end of block | 0 |
210 | int bcnt = 0; | - |
211 | char *p = buf; | - |
212 | int bpl = (w+7)/8; | - |
213 | for (int y = 0; y < h; ++y) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
214 | const uchar *b = image.constScanLine(y); | - |
215 | for (i = 0; i < bpl; ++i) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
216 | *p++ = '0'; *p++ = 'x'; | - |
217 | *p++ = hexrep[*b >> 4]; | - |
218 | *p++ = hexrep[*b++ & 0xf]; | - |
219 | | - |
220 | if (i < bpl - 1 || y < h - 1) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
221 | *p++ = ','; | - |
222 | if (++bcnt > 14) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
223 | *p++ = '\n'; | - |
224 | *p++ = ' '; | - |
225 | *p = '\0'; | - |
226 | if ((int)qstrlen(buf) != device->write(buf, qstrlen(buf))) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
227 | delete [] buf; | - |
228 | return false; never executed: return false; | 0 |
229 | } | - |
230 | p = buf; | - |
231 | bcnt = 0; | - |
232 | } never executed: end of block | 0 |
233 | } never executed: end of block | 0 |
234 | } never executed: end of block | 0 |
235 | } never executed: end of block | 0 |
236 | #if defined(_MSC_VER) && _MSC_VER >= 1400 | - |
237 | strcpy_s(p, sizeof(" };\n"), " };\n"); | - |
238 | #else | - |
239 | strcpy(p, " };\n"); | - |
240 | #endif | - |
241 | if ((int)qstrlen(buf) != device->write(buf, qstrlen(buf))) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
242 | delete [] buf; | - |
243 | return false; never executed: return false; | 0 |
244 | } | - |
245 | | - |
246 | delete [] buf; | - |
247 | return true; never executed: return true; | 0 |
248 | } | - |
249 | | - |
250 | QXbmHandler::QXbmHandler() | - |
251 | : state(Ready) | - |
252 | { | - |
253 | } never executed: end of block | 0 |
254 | | - |
255 | bool QXbmHandler::readHeader() | - |
256 | { | - |
257 | state = Error; | - |
258 | if (!read_xbm_header(device(), width, height))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
259 | return false; never executed: return false; | 0 |
260 | state = ReadHeader; | - |
261 | return true; never executed: return true; | 0 |
262 | } | - |
263 | | - |
264 | bool QXbmHandler::canRead() const | - |
265 | { | - |
266 | if (state == Ready && !canRead(device()))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
267 | return false; never executed: return false; | 0 |
268 | | - |
269 | if (state != Error) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
270 | setFormat("xbm"); | - |
271 | return true; never executed: return true; | 0 |
272 | } | - |
273 | | - |
274 | return false; never executed: return false; | 0 |
275 | } | - |
276 | | - |
277 | bool QXbmHandler::canRead(QIODevice *device) | - |
278 | { | - |
279 | QImage image; | - |
280 | | - |
281 | | - |
282 | | - |
283 | | - |
284 | if (device->isSequential())TRUE | never evaluated | FALSE | never evaluated |
| 0 |
285 | return false; never executed: return false; | 0 |
286 | | - |
287 | qint64 oldPos = device->pos(); | - |
288 | bool success = read_xbm_image(device, &image); | - |
289 | device->seek(oldPos); | - |
290 | | - |
291 | return success; never executed: return success; | 0 |
292 | } | - |
293 | | - |
294 | bool QXbmHandler::read(QImage *image) | - |
295 | { | - |
296 | if (state == Error)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
297 | return false; never executed: return false; | 0 |
298 | | - |
299 | if (state == Ready && !readHeader()) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
300 | state = Error; | - |
301 | return false; never executed: return false; | 0 |
302 | } | - |
303 | | - |
304 | if (!read_xbm_body(device(), width, height, image)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
305 | state = Error; | - |
306 | return false; never executed: return false; | 0 |
307 | } | - |
308 | | - |
309 | state = Ready; | - |
310 | return true; never executed: return true; | 0 |
311 | } | - |
312 | | - |
313 | bool QXbmHandler::write(const QImage &image) | - |
314 | { | - |
315 | return write_xbm_image(image, device(), fileName); never executed: return write_xbm_image(image, device(), fileName); | 0 |
316 | } | - |
317 | | - |
318 | bool QXbmHandler::supportsOption(ImageOption option) const | - |
319 | { | - |
320 | return option == Name never executed: return option == Name || option == Size || option == ImageFormat; TRUE | never evaluated | FALSE | never evaluated |
| 0 |
321 | || option == Size never executed: return option == Name || option == Size || option == ImageFormat; TRUE | never evaluated | FALSE | never evaluated |
| 0 |
322 | || option == ImageFormat; never executed: return option == Name || option == Size || option == ImageFormat; TRUE | never evaluated | FALSE | never evaluated |
| 0 |
323 | } | - |
324 | | - |
325 | QVariant QXbmHandler::option(ImageOption option) const | - |
326 | { | - |
327 | if (option == Name) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
328 | return fileName; never executed: return fileName; | 0 |
329 | } else if (option == Size) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
330 | if (state == Error)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
331 | return QVariant(); never executed: return QVariant(); | 0 |
332 | if (state == Ready && !const_cast<QXbmHandler*>(this)->readHeader())TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
333 | return QVariant(); never executed: return QVariant(); | 0 |
334 | return QSize(width, height); never executed: return QSize(width, height); | 0 |
335 | } else if (option == ImageFormat) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
336 | return QImage::Format_MonoLSB; never executed: return QImage::Format_MonoLSB; | 0 |
337 | } | - |
338 | return QVariant(); never executed: return QVariant(); | 0 |
339 | } | - |
340 | | - |
341 | void QXbmHandler::setOption(ImageOption option, const QVariant &value) | - |
342 | { | - |
343 | if (option == Name)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
344 | fileName = value.toString(); never executed: fileName = value.toString(); | 0 |
345 | } never executed: end of block | 0 |
346 | | - |
347 | QByteArray QXbmHandler::name() const | - |
348 | { | - |
349 | return "xbm"; never executed: return "xbm"; | 0 |
350 | } | - |
351 | | - |
352 | QT_END_NAMESPACE | - |
353 | | - |
354 | #endif // QT_NO_IMAGEFORMAT_XBM | - |
| | |