Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the tools applications of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #include "qvfbview.h" |
43 | #include "qvfbshmem.h" |
44 | #include "qvfbmmap.h" |
45 | |
46 | #include "qanimationwriter.h" |
47 | #include <QApplication> |
48 | #include <QPainter> |
49 | #include <QImage> |
50 | #include <QBitmap> |
51 | #include <QMatrix> |
52 | #include <QPaintEvent> |
53 | #include <QScrollArea> |
54 | #include <QFile> |
55 | #include <QDebug> |
56 | |
57 | #ifdef Q_WS_X11 |
58 | #include <QX11EmbedContainer> |
59 | #include <QHBoxLayout> |
60 | #endif |
61 | |
62 | #include <stdlib.h> |
63 | #include <unistd.h> |
64 | #include <sys/types.h> |
65 | #include <errno.h> |
66 | #include <math.h> |
67 | |
68 | QT_BEGIN_NAMESPACE |
69 | |
70 | extern int qvfb_protocol; |
71 | |
72 | QVFbAbstractView::QVFbAbstractView( QWidget *parent ) |
73 | #ifdef QVFB_USE_GLWIDGET |
74 | : QGLWidget( parent ) |
75 | #else |
76 | : QWidget( parent ) |
77 | #endif |
78 | { |
79 | } |
80 | |
81 | QVFbAbstractView::~QVFbAbstractView() |
82 | { |
83 | } |
84 | |
85 | QVFbView::QVFbView(int id, int w, int h, int d, Rotation r, QWidget *parent) |
86 | : QVFbAbstractView(parent), |
87 | viewdepth(d), viewFormat(DefaultFormat), rgb_swapped(0), rsh(0), gsh(0), bsh(0), rmax(15), gmax(15), bmax(15), |
88 | contentsWidth(w), contentsHeight(h), gred(1.0), ggreen(1.0), gblue(1.0), |
89 | gammatable(0), refreshRate(30), animation(0), |
90 | hzm(0.0), vzm(0.0), mView(0), |
91 | emulateTouchscreen(false), emulateLcdScreen(false), rotation(r) |
92 | #ifdef Q_WS_X11 |
93 | , embedContainer(0) |
94 | #endif |
95 | { |
96 | switch(qvfb_protocol) { |
97 | default: |
98 | case 0: |
99 | mView = new QShMemViewProtocol(id, QSize(w, h), d, this); |
100 | break; |
101 | case 1: |
102 | mView = new QMMapViewProtocol(id, QSize(w, h), d, this); |
103 | break; |
104 | } |
105 | |
106 | connect(mView, SIGNAL(displayDataChanged(QRect)), |
107 | SLOT(refreshDisplay(QRect))); |
108 | #ifdef Q_WS_X11 |
109 | connect(mView, SIGNAL(displayEmbedRequested(WId)), |
110 | this, SLOT(embedDisplay(WId))); |
111 | #endif |
112 | |
113 | setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat); |
114 | setMouseTracking(true); |
115 | setFocusPolicy(Qt::StrongFocus); |
116 | setAttribute(Qt::WA_NoSystemBackground); |
117 | |
118 | setZoom(1.0,1.0); |
119 | |
120 | setGamma(1.0,1.0,1.0); |
121 | mView->setRate(30); |
122 | } |
123 | |
124 | QVFbView::~QVFbView() |
125 | { |
126 | stopAnimation(); |
127 | sendKeyboardData(0, 0, 0, true, false); // magic die key |
128 | #ifdef Q_WS_X11 |
129 | delete embedContainer; |
130 | #endif |
131 | } |
132 | |
133 | QSize QVFbView::sizeHint() const |
134 | { |
135 | return QSize(contentsWidth, contentsHeight); |
136 | } |
137 | |
138 | void QVFbView::setRate(int i) |
139 | { |
140 | mView->setRate(i); |
141 | } |
142 | |
143 | void QVFbView::setGamma(double gr, double gg, double gb) |
144 | { |
145 | gred = gr; ggreen = gg; gblue = gb; |
146 | |
147 | switch (viewdepth) { |
148 | case 12: |
149 | rsh = 12; |
150 | gsh = 7; |
151 | bsh = 1; |
152 | rmax = 15; |
153 | gmax = 15; |
154 | bmax = 15; |
155 | break; |
156 | case 15: |
157 | rsh = 10; |
158 | gsh = 5; |
159 | bsh = 0; |
160 | rmax = 31; |
161 | gmax = 31; |
162 | bmax = 31; |
163 | break; |
164 | case 16: |
165 | rsh = 11; |
166 | gsh = 5; |
167 | bsh = 0; |
168 | rmax = 31; |
169 | gmax = 63; |
170 | bmax = 31; |
171 | break; |
172 | case 18: |
173 | rsh = 12; |
174 | gsh = 6; |
175 | bsh = 0; |
176 | rmax = 63; |
177 | gmax = 63; |
178 | bmax = 63; |
179 | break; |
180 | case 24: |
181 | case 32: |
182 | rsh = 16; |
183 | gsh = 8; |
184 | bsh = 0; |
185 | rmax = 255; |
186 | gmax = 255; |
187 | bmax = 255; |
188 | } |
189 | int mm = qMax(rmax,qMax(gmax,bmax))+1; |
190 | if (gammatable) |
191 | delete [] gammatable; |
192 | gammatable = new QRgb[mm]; |
193 | for (int i=0; i<mm; i++) { |
194 | int r = int(pow(i,gr)*255/rmax); |
195 | int g = int(pow(i,gg)*255/gmax); |
196 | int b = int(pow(i,gb)*255/bmax); |
197 | if (r > 255) r = 255; |
198 | if (g > 255) g = 255; |
199 | if (b > 255) b = 255; |
200 | gammatable[i] = qRgb(r,g,b); |
201 | //qDebug("%d: %d,%d,%d",i,r,g,b); |
202 | } |
203 | |
204 | mView->flushChanges(); |
205 | } |
206 | |
207 | void QVFbView::getGamma(int i, QRgb& rgb) |
208 | { |
209 | if (i > 255) i = 255; |
210 | if (i < 0) i = 0; |
211 | rgb = qRgb(qRed(gammatable[i*rmax/255]), |
212 | qGreen(gammatable[i*rmax/255]), |
213 | qBlue(gammatable[i*rmax/255])); |
214 | } |
215 | |
216 | int QVFbView::displayId() const |
217 | { |
218 | return mView->id(); |
219 | } |
220 | |
221 | int QVFbView::displayWidth() const |
222 | { |
223 | return mView->width(); |
224 | } |
225 | |
226 | int QVFbView::displayHeight() const |
227 | { |
228 | return mView->height(); |
229 | } |
230 | |
231 | int QVFbView::displayDepth() const |
232 | { |
233 | return viewdepth; |
234 | } |
235 | |
236 | QVFbView::PixelFormat QVFbView::displayFormat() const |
237 | { |
238 | return viewFormat; |
239 | } |
240 | |
241 | QVFbView::Rotation QVFbView::displayRotation() const |
242 | { |
243 | return rotation; |
244 | } |
245 | |
246 | void QVFbView::setZoom(double hz, double vz) |
247 | { |
248 | if (hzm != hz || vzm != vz) { |
249 | hzm = hz; |
250 | vzm = vz; |
251 | mView->flushChanges(); |
252 | |
253 | contentsWidth = int(displayWidth()*hz); |
254 | contentsHeight = int(displayHeight()*vz); |
255 | if (rotation & 1) |
256 | qSwap(contentsWidth,contentsHeight); |
257 | resize(contentsWidth, contentsHeight); |
258 | |
259 | if (isVisible()) { |
260 | updateGeometry(); |
261 | qApp->sendPostedEvents(); |
262 | topLevelWidget()->adjustSize(); |
263 | update(); |
264 | } |
265 | } |
266 | } |
267 | |
268 | void QVFbView::setRotation(QVFbView::Rotation r) |
269 | { |
270 | rotation = r; |
271 | // Force update... |
272 | double ohzm = hzm; |
273 | hzm=0.0; |
274 | setZoom(ohzm,vzm); |
275 | } |
276 | |
277 | static QRect mapToDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation) |
278 | { |
279 | int x1 = r.x(); |
280 | int y1 = r.y(); |
281 | int x2 = r.right(); |
282 | int y2 = r.bottom(); |
283 | int w = s.width(); |
284 | int h = s.height(); |
285 | switch (rotation) { |
286 | case QVFbView::Rot90: |
287 | return QRect( |
288 | QPoint(y1, w - x1), |
289 | QPoint(y2, w - x2)).normalized(); |
290 | case QVFbView::Rot180: |
291 | return QRect( |
292 | QPoint(w - x1, h - y1), |
293 | QPoint(w - x2, h - y2)).normalized(); |
294 | case QVFbView::Rot270: |
295 | return QRect( |
296 | QPoint(h - y1, x1), |
297 | QPoint(h - y2, x2)).normalized(); |
298 | default: |
299 | break; |
300 | } |
301 | return r; |
302 | } |
303 | |
304 | static QRect mapFromDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation) |
305 | { |
306 | return mapToDevice(r,s,QVFbView::Rotation(4-(int)rotation)); |
307 | } |
308 | |
309 | void QVFbView::sendMouseData(const QPoint &pos, int buttons, int wheel) |
310 | { |
311 | QPoint p = mapToDevice(QRect(pos,QSize(1,1)), QSize(int(width()/hzm), int(height()/vzm)), rotation).topLeft(); |
312 | mView->sendMouseData(p, buttons, wheel); |
313 | } |
314 | |
315 | void QVFbView::sendKeyboardData(QString unicode, int keycode, int modifiers, |
316 | bool press, bool repeat) |
317 | { |
318 | mView->sendKeyboardData(unicode, keycode, modifiers, press, repeat); |
319 | } |
320 | |
321 | void QVFbView::refreshDisplay(const QRect &r) |
322 | { |
323 | if (animation) { |
324 | if (r.isEmpty()) { |
325 | animation->appendBlankFrame(); |
326 | } else { |
327 | int l; |
328 | QImage img = getBuffer(r, l); |
329 | animation->appendFrame(img,QPoint(r.x(),r.y())); |
330 | } |
331 | } |
332 | if (!r.isNull()) { |
333 | if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1 |
334 | update(mapFromDevice(r, QSize(displayWidth(), displayHeight()), rotation)); |
335 | else |
336 | update(); |
337 | } |
338 | } |
339 | |
340 | static void dim(QRgb* rgb, int n, int brightness) |
341 | { |
342 | uchar* b = (uchar*)rgb; |
343 | #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
344 | b++; |
345 | #endif |
346 | while (n--) { |
347 | b[0] = (uint)b[0] * brightness / 255; |
348 | b[1] = (uint)b[1] * brightness / 255; |
349 | b[2] = (uint)b[2] * brightness / 255; |
350 | b += 4; |
351 | } |
352 | } |
353 | |
354 | QImage QVFbView::getBuffer(const QRect &r, int &leading) const |
355 | { |
356 | const int brightness = mView->brightness(); |
357 | if ( brightness == 0 ) { |
358 | QImage img(r.size(),QImage::Format_RGB32); |
359 | img.fill(0); |
360 | leading = 0; |
361 | return img; |
362 | } |
363 | |
364 | static QByteArray buffer; |
365 | |
366 | const int requiredSize = r.width() * r.height() * 4; |
367 | |
368 | QImage img; |
369 | leading = 0; |
370 | |
371 | switch (viewdepth) { |
372 | case 1: { |
373 | if (requiredSize > buffer.size()) |
374 | buffer.resize(requiredSize); |
375 | |
376 | // XXX: hw: replace by drawhelper functionality |
377 | |
378 | const int pixelsPerByte = 8; |
379 | quint8 *src = reinterpret_cast<quint8*>(mView->data()) |
380 | + r.y() * mView->linestep() + r.x() / pixelsPerByte; |
381 | const int align = qMin(r.width(), (8 - (r.x() & 7)) & 7); |
382 | const int doAlign = (align > 0 ? 1 : 0); |
383 | const int tail = qMin(r.width(), (r.width() - align) & 7); |
384 | const int doTail = (tail > 0 ? 1 : 0); |
385 | const int width8 = (r.width() - align) / pixelsPerByte; |
386 | const int stride = mView->linestep() - (width8 + doAlign); |
387 | |
388 | uchar *b = reinterpret_cast<uchar*>(buffer.data()); |
389 | img = QImage(b, r.width(), r.height(), QImage::Format_RGB32); |
390 | for (int y = 0; y < r.height(); ++y) { |
391 | quint32 *dest = reinterpret_cast<quint32*>(img.scanLine(y)); |
392 | quint8 c; |
393 | |
394 | if (doAlign) { |
395 | switch (align) { |
396 | case 7: c = ((*src & 0x40) >> 6) * 0xff; |
397 | *dest++ = qRgb(c, c, c); |
398 | case 6: c = ((*src & 0x20) >> 5) * 0xff; |
399 | *dest++ = qRgb(c, c, c); |
400 | case 5: c = ((*src & 0x10) >> 4) * 0xff; |
401 | *dest++ = qRgb(c, c, c); |
402 | case 4: c = ((*src & 0x08) >> 3) * 0xff; |
403 | *dest++ = qRgb(c, c, c); |
404 | case 3: c = ((*src & 0x04) >> 2) * 0xff; |
405 | *dest++ = qRgb(c, c, c); |
406 | case 2: c = ((*src & 0x02) >> 1) * 0xff; |
407 | *dest++ = qRgb(c, c, c); |
408 | case 1: c = ((*src & 0x01)) * 0xff; |
409 | *dest++ = qRgb(c, c, c); |
410 | } |
411 | ++src; |
412 | } |
413 | for (int i = 0; i < width8; ++i) { |
414 | c = ((*src & 0x80) >> 7) * 0xff; |
415 | *dest++ = qRgb(c, c, c); |
416 | c = ((*src & 0x40) >> 6) * 0xff; |
417 | *dest++ = qRgb(c, c, c); |
418 | c = ((*src & 0x20) >> 5) * 0xff; |
419 | *dest++ = qRgb(c, c, c); |
420 | c = ((*src & 0x10) >> 4) * 0xff; |
421 | *dest++ = qRgb(c, c, c); |
422 | c = ((*src & 0x08) >> 3) * 0xff; |
423 | *dest++ = qRgb(c, c, c); |
424 | c = ((*src & 0x04) >> 2) * 0xff; |
425 | *dest++ = qRgb(c, c, c); |
426 | c = ((*src & 0x02) >> 1) * 0xff; |
427 | *dest++ = qRgb(c, c, c); |
428 | c = ((*src & 0x01)) * 0xff; |
429 | *dest++ = qRgb(c, c, c); |
430 | |
431 | ++src; |
432 | } |
433 | if (doTail) { |
434 | switch (tail) { |
435 | case 7: c = ((*src & 0x02) >> 1) * 0xff; |
436 | dest[6] = qRgb(c, c, c); |
437 | case 6: c = ((*src & 0x04) >> 2) * 0xff; |
438 | dest[5] = qRgb(c, c, c); |
439 | case 5: c = ((*src & 0x08) >> 3) * 0xff; |
440 | dest[4] = qRgb(c, c, c); |
441 | case 4: c = ((*src & 0x10) >> 4) * 0xff; |
442 | dest[3] = qRgb(c, c, c); |
443 | case 3: c = ((*src & 0x20) >> 5) * 0xff; |
444 | dest[2] = qRgb(c, c, c); |
445 | case 2: c = ((*src & 0x40) >> 6) * 0xff; |
446 | dest[1] = qRgb(c, c, c); |
447 | case 1: c = ((*src & 0x80) >> 7) * 0xff; |
448 | dest[0] = qRgb(c, c, c); |
449 | } |
450 | } |
451 | src += stride; |
452 | } |
453 | break; |
454 | } |
455 | |
456 | case 2: { |
457 | if (requiredSize > buffer.size()) |
458 | buffer.resize(requiredSize); |
459 | |
460 | // XXX: hw: replace by drawhelper functionality |
461 | |
462 | const int pixelsPerByte = 4; |
463 | quint8 *src = reinterpret_cast<quint8*>(mView->data()) |
464 | + r.y() * mView->linestep() + r.x() / pixelsPerByte; |
465 | const int align = qMin(r.width(), (4 - (r.x() & 3)) & 3); |
466 | const int doAlign = (align > 0 ? 1 : 0); |
467 | const int tail = qMin(r.width(), (r.width() - align) & 3); |
468 | const int doTail = (tail > 0 ? 1 : 0); |
469 | const int width8 = (r.width() - align) / pixelsPerByte; |
470 | const int stride = mView->linestep() - (width8 + doAlign); |
471 | |
472 | uchar *b = reinterpret_cast<uchar*>(buffer.data()); |
473 | img = QImage(b, r.width(), r.height(), QImage::Format_RGB32); |
474 | for (int y = 0; y < r.height(); ++y) { |
475 | quint32 *dest = reinterpret_cast<quint32*>(img.scanLine(y)); |
476 | quint8 c; |
477 | |
478 | if (doAlign) { |
479 | switch (align) { |
480 | case 3: c = ((*src & 0x30) >> 4) * 0x55; |
481 | *dest++ = qRgb(c, c, c); |
482 | case 2: c = ((*src & 0x0c) >> 2) * 0x55; |
483 | *dest++ = qRgb(c, c, c); |
484 | case 1: c = ((*src & 0x03)) * 0x55; |
485 | *dest++ = qRgb(c, c, c); |
486 | } |
487 | ++src; |
488 | } |
489 | for (int i = 0; i < width8; ++i) { |
490 | c = ((*src & 0xc0) >> 6) * 0x55; |
491 | *dest++ = qRgb(c, c, c); |
492 | c = ((*src & 0x30) >> 4) * 0x55; |
493 | *dest++ = qRgb(c, c, c); |
494 | c = ((*src & 0x0c) >> 2) * 0x55; |
495 | *dest++ = qRgb(c, c, c); |
496 | c = ((*src & 0x03)) * 0x55; |
497 | *dest++ = qRgb(c, c, c); |
498 | |
499 | ++src; |
500 | } |
501 | if (doTail) { |
502 | switch (tail) { |
503 | case 3: c = ((*src & 0x0c) >> 2) * 0x55; |
504 | dest[2] = qRgb(c, c, c); |
505 | case 2: c = ((*src & 0x30) >> 4) * 0x55; |
506 | dest[1] = qRgb(c, c, c); |
507 | case 1: c = ((*src & 0xc0) >> 6) * 0x55; |
508 | dest[0] = qRgb(c, c, c); |
509 | } |
510 | } |
511 | src += stride; |
512 | } |
513 | break; |
514 | } |
515 | |
516 | case 4: { |
517 | if (requiredSize > buffer.size()) |
518 | buffer.resize(requiredSize); |
519 | |
520 | // XXX: hw: replace by drawhelper functionality |
521 | |
522 | const int pixelsPerByte = 2; |
523 | const int doAlign = r.x() & 1; |
524 | const int doTail = (r.width() - doAlign) & 1; |
525 | const int width8 = (r.width() - doAlign) / pixelsPerByte; |
526 | |
527 | uchar *b = reinterpret_cast<uchar*>(buffer.data()); |
528 | img = QImage(b, r.width(), r.height(), QImage::Format_RGB32); |
529 | for (int y = 0; y < r.height(); ++y) { |
530 | const quint8 *sptr = mView->data() |
531 | + (r.y() + y) * mView->linestep() |
532 | + r.x() / pixelsPerByte; |
533 | quint32 *dptr = reinterpret_cast<quint32*>(img.scanLine(y)); |
534 | |
535 | if (doAlign) { |
536 | quint8 c = (*sptr++ & 0x0f); |
537 | c |= (c << 4); |
538 | *dptr++ = qRgb(c, c, c); |
539 | } |
540 | |
541 | for (int i = 0; i < width8; ++i) { |
542 | quint8 c1 = (*sptr >> 4); |
543 | quint8 c2 = (*sptr & 0x0f); |
544 | c1 |= (c1 << 4); |
545 | c2 |= (c2 << 4); |
546 | *dptr++ = qRgb(c1, c1, c1); |
547 | *dptr++ = qRgb(c2, c2, c2); |
548 | ++sptr; |
549 | } |
550 | |
551 | if (doTail) { |
552 | quint8 c = *sptr >> 4; |
553 | c |= (c << 4); |
554 | *dptr = qRgb(c, c, c); |
555 | } |
556 | } |
557 | break; |
558 | } |
559 | case 12: |
560 | img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2), |
561 | r.width(), r.height(), mView->linestep(), |
562 | QImage::Format_RGB444); |
563 | break; |
564 | case 15: |
565 | img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2), |
566 | r.width(), r.height(), mView->linestep(), |
567 | QImage::Format_RGB555); |
568 | break; |
569 | case 16: |
570 | img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2), |
571 | r.width(), r.height(), mView->linestep(), |
572 | QImage::Format_RGB16); |
573 | break; |
574 | case 18: |
575 | img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 3), |
576 | r.width(), r.height(), mView->linestep(), |
577 | QImage::Format_RGB666); |
578 | break; |
579 | case 24: |
580 | img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 3), |
581 | r.width(), r.height(), mView->linestep(), |
582 | QImage::Format_RGB888); |
583 | break; |
584 | case 32: |
585 | img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 4), |
586 | r.width(), r.height(), mView->linestep(), |
587 | viewFormat == ARGBFormat ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); |
588 | break; |
589 | case 8: |
590 | img = QImage(mView->data() + r.y() * mView->linestep() + r.x(), |
591 | r.width(), r.height(), mView->linestep(), |
592 | QImage::Format_Indexed8); |
593 | img.setColorTable(mView->clut()); |
594 | if (img.colorCount() <= 0) |
595 | img = QImage(); |
596 | break; |
597 | } |
598 | |
599 | if (rgb_swapped) |
600 | img = img.rgbSwapped(); |
601 | |
602 | if ( brightness != 255 ) { |
603 | if (img.format() == QImage::Format_Indexed8) { |
604 | QVector<QRgb> c = img.colorTable(); |
605 | dim(c.data(),c.count(),brightness); |
606 | img.setColorTable(c); |
607 | } else { |
608 | if ( img.format() != QImage::Format_ARGB32_Premultiplied ) |
609 | img = img.convertToFormat(QImage::Format_RGB32); |
610 | |
611 | // NOTE: calling bits() may change byteCount(), so do not |
612 | // pass them as parameters (which are evaluated right-to-left). |
613 | QRgb *b = (QRgb*)img.bits(); |
614 | int n = img.byteCount()/4; |
615 | dim(b,n,brightness); |
616 | } |
617 | } |
618 | |
619 | return img; |
620 | } |
621 | |
622 | static int findMultiple(int start, double m, int limit, int step) |
623 | { |
624 | int r = start; |
625 | while (r != limit) { |
626 | if (int(int(r * m)/m) == r) |
627 | break; |
628 | r += step; |
629 | } |
630 | return r; |
631 | } |
632 | |
633 | void QVFbView::drawScreen(const QRect &rect) |
634 | { |
635 | QRect r = QRect(0, 0, mView->width(), mView->height()); |
636 | |
637 | if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1 |
638 | r &= rect; |
639 | |
640 | if (int(hzm) != hzm || int(vzm) != vzm) { |
641 | r.setLeft(findMultiple(r.left(),hzm,0,-1)); |
642 | r.setTop(findMultiple(r.top(),vzm,0,-1)); |
643 | int w = findMultiple(r.width(),hzm,mView->width(),1); |
644 | int h = findMultiple(r.height(),vzm,mView->height(),1); |
645 | r.setRight(r.left()+w-1); |
646 | r.setBottom(r.top()+h-1); |
647 | } |
648 | |
649 | int leading; |
650 | const QImage img = getBuffer(r, leading); |
651 | |
652 | QPixmap pm; |
653 | if (hzm == 1.0 && vzm == 1.0) { |
654 | pm = QPixmap::fromImage(img); |
655 | } else if (emulateLcdScreen && hzm == 3.0 && vzm == 3.0) { |
656 | QImage img2(img.width()*3, img.height(), QImage::Format_RGB32); |
657 | for (int row = 0; row < img2.height(); row++) { |
658 | QRgb *dptr = (QRgb*)img2.scanLine(row); |
659 | QRgb *sptr = (QRgb*)img.scanLine(row); |
660 | for (int col = 0; col < img.width(); col++) { |
661 | QRgb s = *sptr++; |
662 | *dptr++ = qRgb(qRed(s),0,0); |
663 | *dptr++ = qRgb(0,qGreen(s),0); |
664 | *dptr++ = qRgb(0,0,qBlue(s)); |
665 | } |
666 | } |
667 | QMatrix m; |
668 | m.scale(1.0, 3.0); |
669 | pm = QPixmap::fromImage(img2); |
670 | pm = pm.transformed(m); |
671 | } else if (int(hzm) == hzm && int(vzm) == vzm) { |
672 | QMatrix m; |
673 | m.scale(hzm,vzm); |
674 | pm = QPixmap::fromImage(img); |
675 | pm = pm.transformed(m); |
676 | } else { |
677 | pm = QPixmap::fromImage(img.scaled(int(img.width()*hzm),int(img.height()*vzm), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); |
678 | } |
679 | |
680 | int x1 = r.x(); |
681 | int y1 = r.y(); |
682 | int leadingX = leading; |
683 | int leadingY = 0; |
684 | |
685 | // Do the rotation thing |
686 | int rotX1 = mView->width() - x1 - img.width(); |
687 | int rotY1 = mView->height() - y1 - img.height(); |
688 | int rotLeadingX = (leading) ? mView->width() - leadingX - img.width() : 0; |
689 | int rotLeadingY = 0; |
690 | switch (rotation) { |
691 | case Rot0: |
692 | break; |
693 | case Rot90: |
694 | leadingY = leadingX; |
695 | leadingX = rotLeadingY; |
696 | y1 = x1; |
697 | x1 = rotY1; |
698 | break; |
699 | case Rot180: |
700 | leadingX = rotLeadingX; |
701 | leadingY = leadingY; |
702 | x1 = rotX1; |
703 | y1 = rotY1; |
704 | break; |
705 | case Rot270: |
706 | leadingX = leadingY; |
707 | leadingY = rotLeadingX; |
708 | x1 = y1; |
709 | y1 = rotX1; |
710 | break; |
711 | default: |
712 | break; |
713 | } |
714 | x1 = int(x1*hzm); |
715 | y1 = int(y1*vzm); |
716 | leadingX = int(leadingX*hzm); |
717 | leadingY = int(leadingY*vzm); |
718 | if (rotation != 0) { |
719 | QMatrix m; |
720 | m.rotate(rotation * 90.0); |
721 | pm = pm.transformed(m); |
722 | } |
723 | |
724 | QPainter p(this); |
725 | if (viewFormat == ARGBFormat) { |
726 | QPixmap bg(":/res/images/logo-nt.png"); |
727 | p.fillRect(x1,y1,pm.width(), pm.height(), QBrush(bg)); |
728 | } |
729 | p.drawPixmap(x1, y1, pm, leadingX, leadingY, pm.width(), pm.height()); |
730 | } |
731 | |
732 | //bool QVFbView::eventFilter(QObject *obj, QEvent *e) |
733 | //{ |
734 | // if (obj == this && |
735 | // (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut)) |
736 | // return true; |
737 | // |
738 | // return QWidgetView::eventFilter(obj, e); |
739 | //} |
740 | |
741 | void QVFbView::paintEvent(QPaintEvent *e) |
742 | { |
743 | drawScreen(mapToDevice(e->rect(),QSize(int(width()/hzm), int(height()/vzm)),rotation)); |
744 | } |
745 | |
746 | void QVFbView::mousePressEvent(QMouseEvent *e) |
747 | { |
748 | sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); |
749 | } |
750 | |
751 | void QVFbView::contextMenuEvent(QContextMenuEvent*) |
752 | { |
753 | |
754 | } |
755 | |
756 | void QVFbView::mouseDoubleClickEvent(QMouseEvent *e) |
757 | { |
758 | sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); |
759 | } |
760 | |
761 | void QVFbView::mouseReleaseEvent(QMouseEvent *e) |
762 | { |
763 | sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); |
764 | } |
765 | |
766 | void QVFbView::skinMouseEvent(QMouseEvent *e) |
767 | { |
768 | sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); |
769 | } |
770 | |
771 | void QVFbView::mouseMoveEvent(QMouseEvent *e) |
772 | { |
773 | if (!emulateTouchscreen || (e->buttons() & Qt::MouseButtonMask)) |
774 | sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); |
775 | } |
776 | |
777 | void QVFbView::wheelEvent(QWheelEvent *e) |
778 | { |
779 | if (!e) |
780 | return; |
781 | sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), e->delta()); |
782 | } |
783 | |
784 | void QVFbView::setTouchscreenEmulation(bool b) |
785 | { |
786 | emulateTouchscreen = b; |
787 | } |
788 | |
789 | void QVFbView::setLcdScreenEmulation(bool b) |
790 | { |
791 | emulateLcdScreen = b; |
792 | } |
793 | |
794 | void QVFbView::setViewFormat(PixelFormat f) |
795 | { |
796 | if (viewFormat == f) |
797 | return; |
798 | viewFormat = f; |
799 | setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat); |
800 | } |
801 | |
802 | #ifdef Q_WS_X11 |
803 | void QVFbView::embedDisplay(WId windowId) |
804 | { |
805 | if (windowId == 0) { |
806 | delete embedContainer; |
807 | embedContainer = 0; |
808 | return; |
809 | } |
810 | |
811 | if (!embedContainer) { |
812 | embedContainer = new QX11EmbedContainer(this); |
813 | embedContainer->setGeometry(rect()); |
814 | embedContainer->show(); |
815 | } |
816 | embedContainer->embedClient(windowId); |
817 | } |
818 | #endif |
819 | |
820 | bool QVFbView::event(QEvent *e) |
821 | { |
822 | if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) { |
823 | QKeyEvent *ke = static_cast<QKeyEvent*>(e); |
824 | sendKeyboardData(ke->text(), ke->key(), |
825 | ke->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier), |
826 | ke->type() == QEvent::KeyPress, ke->isAutoRepeat()); |
827 | ke->accept(); |
828 | return true; |
829 | } |
830 | return QVFbAbstractView::event(e); |
831 | } |
832 | |
833 | void QVFbView::keyPressEvent(QKeyEvent *e) |
834 | { |
835 | sendKeyboardData(e->text(), e->key(), |
836 | e->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier), |
837 | true, e->isAutoRepeat()); |
838 | } |
839 | |
840 | void QVFbView::keyReleaseEvent(QKeyEvent *e) |
841 | { |
842 | sendKeyboardData(e->text(), e->key(), |
843 | e->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier), |
844 | false, e->isAutoRepeat()); |
845 | } |
846 | |
847 | |
848 | QImage QVFbView::image() const |
849 | { |
850 | int l; |
851 | QImage r = getBuffer(QRect(0, 0, mView->width(), mView->height()), l).copy(); |
852 | return r; |
853 | } |
854 | |
855 | void QVFbView::startAnimation(const QString& filename) |
856 | { |
857 | delete animation; |
858 | animation = new QAnimationWriter(filename,"MNG"); |
859 | animation->setFrameRate(refreshRate); |
860 | animation->appendFrame(QImage(mView->data(), |
861 | mView->width(), mView->height(), QImage::Format_RGB32)); |
862 | } |
863 | |
864 | void QVFbView::stopAnimation() |
865 | { |
866 | delete animation; |
867 | animation = 0; |
868 | } |
869 | |
870 | |
871 | void QVFbView::skinKeyPressEvent(int code, const QString& text, bool autorep) |
872 | { |
873 | QKeyEvent e(QEvent::KeyPress,code,0,text,autorep); |
874 | keyPressEvent(&e); |
875 | } |
876 | |
877 | void QVFbView::skinKeyReleaseEvent(int code, const QString& text, bool autorep) |
878 | { |
879 | QKeyEvent e(QEvent::KeyRelease,code,0,text,autorep); |
880 | keyReleaseEvent(&e); |
881 | } |
882 | |
883 | QT_END_NAMESPACE |
884 |
Warning: That file was not part of the compilation database. It may have many parsing errors.