|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qscreentransformed_qws.h" |
|
43 |
|
44 #ifndef QT_NO_QWS_TRANSFORMED |
|
45 #include <qscreendriverfactory_qws.h> |
|
46 #include <qvector.h> |
|
47 #include <private/qpainter_p.h> |
|
48 #include <private/qmemrotate_p.h> |
|
49 #include <qmatrix.h> |
|
50 |
|
51 #include <unistd.h> |
|
52 #include <sys/ioctl.h> |
|
53 #include <sys/types.h> |
|
54 #include <sys/stat.h> |
|
55 #include <sys/mman.h> |
|
56 #include <fcntl.h> |
|
57 #include <errno.h> |
|
58 |
|
59 #include <qwindowsystem_qws.h> |
|
60 #include <qwsdisplay_qws.h> |
|
61 |
|
62 QT_BEGIN_NAMESPACE |
|
63 |
|
64 //#define QT_REGION_DEBUG |
|
65 |
|
66 #ifdef QT_REGION_DEBUG |
|
67 #include <QDebug> |
|
68 #endif |
|
69 |
|
70 class QTransformedScreenPrivate |
|
71 { |
|
72 public: |
|
73 QTransformedScreenPrivate(QTransformedScreen *parent); |
|
74 |
|
75 void configure(); |
|
76 |
|
77 QTransformedScreen::Transformation transformation; |
|
78 #ifdef QT_QWS_DEPTH_GENERIC |
|
79 bool doGenericColors; |
|
80 #endif |
|
81 QTransformedScreen *q; |
|
82 }; |
|
83 |
|
84 QTransformedScreenPrivate::QTransformedScreenPrivate(QTransformedScreen *parent) |
|
85 : transformation(QTransformedScreen::None), |
|
86 #ifdef QT_QWS_DEPTH_GENERIC |
|
87 doGenericColors(false), |
|
88 #endif |
|
89 q(parent) |
|
90 { |
|
91 } |
|
92 |
|
93 extern "C" |
|
94 #ifndef QT_BUILD_GUI_LIB |
|
95 Q_DECL_EXPORT |
|
96 #endif |
|
97 void qws_setScreenTransformation(QScreen *that, int t) |
|
98 { |
|
99 QTransformedScreen *tscreen = static_cast<QTransformedScreen*>(that); |
|
100 tscreen->setTransformation((QTransformedScreen::Transformation)t); |
|
101 } |
|
102 |
|
103 // --------------------------------------------------------------------------- |
|
104 // Transformed Screen |
|
105 // --------------------------------------------------------------------------- |
|
106 |
|
107 /*! |
|
108 \internal |
|
109 |
|
110 \class QTransformedScreen |
|
111 \ingroup qws |
|
112 |
|
113 \brief The QTransformedScreen class implements a screen driver for |
|
114 a transformed screen. |
|
115 |
|
116 Note that this class is only available in \l{Qt for Embedded Linux}. |
|
117 Custom screen drivers can be added by subclassing the |
|
118 QScreenDriverPlugin class, using the QScreenDriverFactory class to |
|
119 dynamically load the driver into the application, but there should |
|
120 only be one screen object per application. |
|
121 |
|
122 Use the QScreen::isTransformed() function to determine if a screen |
|
123 is transformed. The QTransformedScreen class itself provides means |
|
124 of rotating the screen with its setTransformation() function; the |
|
125 transformation() function returns the currently set rotation in |
|
126 terms of the \l Transformation enum (which describes the various |
|
127 available rotation settings). Alternatively, QTransformedScreen |
|
128 provides an implementation of the QScreen::transformOrientation() |
|
129 function, returning the current rotation as an integer value. |
|
130 |
|
131 \sa QScreen, QScreenDriverPlugin, {Running Applications} |
|
132 */ |
|
133 |
|
134 /*! |
|
135 \enum QTransformedScreen::Transformation |
|
136 |
|
137 This enum describes the various rotations a transformed screen can |
|
138 have. |
|
139 |
|
140 \value None No rotation |
|
141 \value Rot90 90 degrees rotation |
|
142 \value Rot180 180 degrees rotation |
|
143 \value Rot270 270 degrees rotation |
|
144 */ |
|
145 |
|
146 /*! |
|
147 \fn bool QTransformedScreen::isTransformed() const |
|
148 \reimp |
|
149 */ |
|
150 |
|
151 /*! |
|
152 Constructs a QTransformedScreen object. The \a displayId argument |
|
153 identifies the Qt for Embedded Linux server to connect to. |
|
154 */ |
|
155 QTransformedScreen::QTransformedScreen(int displayId) |
|
156 : QProxyScreen(displayId, QScreen::TransformedClass) |
|
157 { |
|
158 d_ptr = new QTransformedScreenPrivate(this); |
|
159 d_ptr->transformation = None; |
|
160 |
|
161 #ifdef QT_REGION_DEBUG |
|
162 qDebug() << "QTransformedScreen::QTransformedScreen"; |
|
163 #endif |
|
164 } |
|
165 |
|
166 void QTransformedScreenPrivate::configure() |
|
167 { |
|
168 // ###: works because setTransformation recalculates unconditionally |
|
169 q->setTransformation(transformation); |
|
170 } |
|
171 |
|
172 /*! |
|
173 Destroys the QTransformedScreen object. |
|
174 */ |
|
175 QTransformedScreen::~QTransformedScreen() |
|
176 { |
|
177 delete d_ptr; |
|
178 } |
|
179 |
|
180 static int getDisplayId(const QString &spec) |
|
181 { |
|
182 QRegExp regexp(QLatin1String(":(\\d+)\\b")); |
|
183 if (regexp.lastIndexIn(spec) != -1) { |
|
184 const QString capture = regexp.cap(1); |
|
185 return capture.toInt(); |
|
186 } |
|
187 return 0; |
|
188 } |
|
189 |
|
190 static QTransformedScreen::Transformation filterTransformation(QString &spec) |
|
191 { |
|
192 QRegExp regexp(QLatin1String("\\bRot(\\d+):?\\b"), Qt::CaseInsensitive); |
|
193 if (regexp.indexIn(spec) == -1) |
|
194 return QTransformedScreen::None; |
|
195 |
|
196 const int degrees = regexp.cap(1).toInt(); |
|
197 spec.remove(regexp.pos(0), regexp.matchedLength()); |
|
198 |
|
199 return static_cast<QTransformedScreen::Transformation>(degrees / 90); |
|
200 } |
|
201 |
|
202 /*! |
|
203 \reimp |
|
204 */ |
|
205 bool QTransformedScreen::connect(const QString &displaySpec) |
|
206 { |
|
207 QString dspec = displaySpec.trimmed(); |
|
208 if (dspec.startsWith(QLatin1String("Transformed:"), Qt::CaseInsensitive)) |
|
209 dspec = dspec.mid(QString::fromLatin1("Transformed:").size()); |
|
210 else if (!dspec.compare(QLatin1String("Transformed"), Qt::CaseInsensitive)) |
|
211 dspec = QString(); |
|
212 |
|
213 const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId); |
|
214 if (dspec.endsWith(displayIdSpec)) |
|
215 dspec = dspec.left(dspec.size() - displayIdSpec.size()); |
|
216 |
|
217 d_ptr->transformation = filterTransformation(dspec); |
|
218 |
|
219 QString driver = dspec; |
|
220 int colon = driver.indexOf(QLatin1Char(':')); |
|
221 if (colon >= 0) |
|
222 driver.truncate(colon); |
|
223 |
|
224 if (!QScreenDriverFactory::keys().contains(driver, Qt::CaseInsensitive)) |
|
225 if (!dspec.isEmpty()) |
|
226 dspec.prepend(QLatin1Char(':')); |
|
227 |
|
228 const int id = getDisplayId(dspec); |
|
229 QScreen *s = qt_get_screen(id, dspec.toLatin1().constData()); |
|
230 setScreen(s); |
|
231 |
|
232 #ifdef QT_QWS_DEPTH_GENERIC |
|
233 d_ptr->doGenericColors = dspec.contains(QLatin1String("genericcolors")); |
|
234 #endif |
|
235 |
|
236 d_ptr->configure(); |
|
237 |
|
238 // XXX |
|
239 qt_screen = this; |
|
240 |
|
241 return true; |
|
242 } |
|
243 |
|
244 /*! |
|
245 Returns the currently set rotation. |
|
246 |
|
247 \sa setTransformation(), QScreen::transformOrientation() |
|
248 */ |
|
249 QTransformedScreen::Transformation QTransformedScreen::transformation() const |
|
250 { |
|
251 return d_ptr->transformation; |
|
252 } |
|
253 |
|
254 /*! |
|
255 \reimp |
|
256 */ |
|
257 int QTransformedScreen::transformOrientation() const |
|
258 { |
|
259 return (int)d_ptr->transformation; |
|
260 } |
|
261 |
|
262 /*! |
|
263 \reimp |
|
264 */ |
|
265 void QTransformedScreen::exposeRegion(QRegion region, int changing) |
|
266 { |
|
267 if (!data || d_ptr->transformation == None) { |
|
268 QProxyScreen::exposeRegion(region, changing); |
|
269 return; |
|
270 } |
|
271 QScreen::exposeRegion(region, changing); |
|
272 } |
|
273 |
|
274 /*! |
|
275 Rotates this screen object according to the specified \a transformation. |
|
276 |
|
277 \sa transformation() |
|
278 */ |
|
279 void QTransformedScreen::setTransformation(Transformation transformation) |
|
280 { |
|
281 d_ptr->transformation = transformation; |
|
282 QSize size = mapFromDevice(QSize(dw, dh)); |
|
283 w = size.width(); |
|
284 h = size.height(); |
|
285 |
|
286 const QScreen *s = screen(); |
|
287 size = mapFromDevice(QSize(s->physicalWidth(), s->physicalHeight())); |
|
288 physWidth = size.width(); |
|
289 physHeight = size.height(); |
|
290 |
|
291 #ifdef QT_REGION_DEBUG |
|
292 qDebug() << "QTransformedScreen::setTransformation" << transformation |
|
293 << "size" << w << h << "dev size" << dw << dh; |
|
294 #endif |
|
295 |
|
296 } |
|
297 |
|
298 static inline QRect correctNormalized(const QRect &r) { |
|
299 const int x1 = qMin(r.left(), r.right()); |
|
300 const int x2 = qMax(r.left(), r.right()); |
|
301 const int y1 = qMin(r.top(), r.bottom()); |
|
302 const int y2 = qMax(r.top(), r.bottom()); |
|
303 |
|
304 return QRect( QPoint(x1,y1), QPoint(x2,y2) ); |
|
305 } |
|
306 |
|
307 template <class DST, class SRC> |
|
308 static inline void blit90(QScreen *screen, const QImage &image, |
|
309 const QRect &rect, const QPoint &topLeft) |
|
310 { |
|
311 const SRC *src = (const SRC*)(image.scanLine(rect.top())) + rect.left(); |
|
312 DST *dest = (DST*)(screen->base() + topLeft.y() * screen->linestep()) |
|
313 + topLeft.x(); |
|
314 qt_memrotate90(src, rect.width(), rect.height(), image.bytesPerLine(), |
|
315 dest, screen->linestep()); |
|
316 } |
|
317 |
|
318 template <class DST, class SRC> |
|
319 static inline void blit180(QScreen *screen, const QImage &image, |
|
320 const QRect &rect, const QPoint &topLeft) |
|
321 { |
|
322 const SRC *src = (const SRC*)(image.scanLine(rect.top())) + rect.left(); |
|
323 DST *dest = (DST*)(screen->base() + topLeft.y() * screen->linestep()) |
|
324 + topLeft.x(); |
|
325 qt_memrotate180(src, rect.width(), rect.height(), image.bytesPerLine(), |
|
326 dest, screen->linestep()); |
|
327 } |
|
328 |
|
329 template <class DST, class SRC> |
|
330 static inline void blit270(QScreen *screen, const QImage &image, |
|
331 const QRect &rect, const QPoint &topLeft) |
|
332 { |
|
333 const SRC *src = (const SRC *)(image.scanLine(rect.top())) + rect.left(); |
|
334 DST *dest = (DST*)(screen->base() + topLeft.y() * screen->linestep()) |
|
335 + topLeft.x(); |
|
336 qt_memrotate270(src, rect.width(), rect.height(), image.bytesPerLine(), |
|
337 dest, screen->linestep()); |
|
338 } |
|
339 |
|
340 typedef void (*BlitFunc)(QScreen *, const QImage &, const QRect &, const QPoint &); |
|
341 |
|
342 #define SET_BLIT_FUNC(dst, src, rotation, func) \ |
|
343 do { \ |
|
344 switch (rotation) { \ |
|
345 case Rot90: \ |
|
346 func = blit90<dst, src>; \ |
|
347 break; \ |
|
348 case Rot180: \ |
|
349 func = blit180<dst, src>; \ |
|
350 break; \ |
|
351 case Rot270: \ |
|
352 func = blit270<dst, src>; \ |
|
353 break; \ |
|
354 default: \ |
|
355 break; \ |
|
356 } \ |
|
357 } while (0) |
|
358 |
|
359 /*! |
|
360 \reimp |
|
361 */ |
|
362 void QTransformedScreen::blit(const QImage &image, const QPoint &topLeft, |
|
363 const QRegion ®ion) |
|
364 { |
|
365 const Transformation trans = d_ptr->transformation; |
|
366 if (trans == None) { |
|
367 QProxyScreen::blit(image, topLeft, region); |
|
368 return; |
|
369 } |
|
370 |
|
371 const QVector<QRect> rects = region.rects(); |
|
372 const QRect bound = QRect(0, 0, QScreen::w, QScreen::h) |
|
373 & QRect(topLeft, image.size()); |
|
374 |
|
375 BlitFunc func = 0; |
|
376 #ifdef QT_QWS_DEPTH_GENERIC |
|
377 if (d_ptr->doGenericColors && depth() == 16) { |
|
378 if (image.depth() == 16) |
|
379 SET_BLIT_FUNC(qrgb_generic16, quint16, trans, func); |
|
380 else |
|
381 SET_BLIT_FUNC(qrgb_generic16, quint32, trans, func); |
|
382 } else |
|
383 #endif |
|
384 switch (depth()) { |
|
385 #ifdef QT_QWS_DEPTH_32 |
|
386 case 32: |
|
387 #ifdef QT_QWS_DEPTH_16 |
|
388 if (image.depth() == 16) |
|
389 SET_BLIT_FUNC(quint32, quint16, trans, func); |
|
390 else |
|
391 #endif |
|
392 SET_BLIT_FUNC(quint32, quint32, trans, func); |
|
393 break; |
|
394 #endif |
|
395 #if defined(QT_QWS_DEPTH_24) || defined(QT_QWS_DEPTH18) |
|
396 case 24: |
|
397 case 18: |
|
398 SET_BLIT_FUNC(quint24, quint24, trans, func); |
|
399 break; |
|
400 #endif |
|
401 #if defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_15) || defined(QT_QWS_DEPTH_12) |
|
402 case 16: |
|
403 #if defined QT_QWS_ROTATE_BGR |
|
404 if (pixelType() == BGRPixel && image.depth() == 16) { |
|
405 SET_BLIT_FUNC(qbgr565, quint16, trans, func); |
|
406 break; |
|
407 } //fall-through here!!! |
|
408 #endif |
|
409 case 15: |
|
410 #if defined QT_QWS_ROTATE_BGR |
|
411 if (pixelType() == BGRPixel && image.format() == QImage::Format_RGB555) { |
|
412 SET_BLIT_FUNC(qbgr555, qrgb555, trans, func); |
|
413 break; |
|
414 } //fall-through here!!! |
|
415 #endif |
|
416 case 12: |
|
417 if (image.depth() == 16) |
|
418 SET_BLIT_FUNC(quint16, quint16, trans, func); |
|
419 else |
|
420 SET_BLIT_FUNC(quint16, quint32, trans, func); |
|
421 break; |
|
422 #endif |
|
423 #ifdef QT_QWS_DEPTH_8 |
|
424 case 8: |
|
425 if (image.format() == QImage::Format_RGB444) |
|
426 SET_BLIT_FUNC(quint8, qrgb444, trans, func); |
|
427 else if (image.depth() == 16) |
|
428 SET_BLIT_FUNC(quint8, quint16, trans, func); |
|
429 else |
|
430 SET_BLIT_FUNC(quint8, quint32, trans, func); |
|
431 break; |
|
432 #endif |
|
433 default: |
|
434 return; |
|
435 } |
|
436 if (!func) |
|
437 return; |
|
438 |
|
439 QWSDisplay::grab(); |
|
440 for (int i = 0; i < rects.size(); ++i) { |
|
441 const QRect r = rects.at(i) & bound; |
|
442 |
|
443 QPoint dst; |
|
444 switch (trans) { |
|
445 case Rot90: |
|
446 dst = mapToDevice(r.topRight(), QSize(w, h)); |
|
447 break; |
|
448 case Rot180: |
|
449 dst = mapToDevice(r.bottomRight(), QSize(w, h)); |
|
450 break; |
|
451 case Rot270: |
|
452 dst = mapToDevice(r.bottomLeft(), QSize(w, h)); |
|
453 break; |
|
454 default: |
|
455 break; |
|
456 } |
|
457 func(this, image, r.translated(-topLeft), dst); |
|
458 } |
|
459 QWSDisplay::ungrab(); |
|
460 |
|
461 } |
|
462 |
|
463 /*! |
|
464 \reimp |
|
465 */ |
|
466 void QTransformedScreen::solidFill(const QColor &color, const QRegion ®ion) |
|
467 { |
|
468 const QRegion tr = mapToDevice(region, QSize(w,h)); |
|
469 |
|
470 Q_ASSERT(tr.boundingRect() == mapToDevice(region.boundingRect(), QSize(w,h))); |
|
471 |
|
472 #ifdef QT_REGION_DEBUG |
|
473 qDebug() << "QTransformedScreen::solidFill region" << region << "transformed" << tr; |
|
474 #endif |
|
475 QProxyScreen::solidFill(color, tr); |
|
476 } |
|
477 |
|
478 /*! |
|
479 \reimp |
|
480 */ |
|
481 QSize QTransformedScreen::mapToDevice(const QSize &s) const |
|
482 { |
|
483 switch (d_ptr->transformation) { |
|
484 case None: |
|
485 case Rot180: |
|
486 break; |
|
487 case Rot90: |
|
488 case Rot270: |
|
489 return QSize(s.height(), s.width()); |
|
490 break; |
|
491 } |
|
492 return s; |
|
493 } |
|
494 |
|
495 /*! |
|
496 \reimp |
|
497 */ |
|
498 QSize QTransformedScreen::mapFromDevice(const QSize &s) const |
|
499 { |
|
500 switch (d_ptr->transformation) { |
|
501 case None: |
|
502 case Rot180: |
|
503 break; |
|
504 case Rot90: |
|
505 case Rot270: |
|
506 return QSize(s.height(), s.width()); |
|
507 break; |
|
508 } |
|
509 return s; |
|
510 } |
|
511 |
|
512 /*! |
|
513 \reimp |
|
514 */ |
|
515 QPoint QTransformedScreen::mapToDevice(const QPoint &p, const QSize &s) const |
|
516 { |
|
517 QPoint rp(p); |
|
518 |
|
519 switch (d_ptr->transformation) { |
|
520 case None: |
|
521 break; |
|
522 case Rot90: |
|
523 rp.setX(p.y()); |
|
524 rp.setY(s.width() - p.x() - 1); |
|
525 break; |
|
526 case Rot180: |
|
527 rp.setX(s.width() - p.x() - 1); |
|
528 rp.setY(s.height() - p.y() - 1); |
|
529 break; |
|
530 case Rot270: |
|
531 rp.setX(s.height() - p.y() - 1); |
|
532 rp.setY(p.x()); |
|
533 break; |
|
534 } |
|
535 |
|
536 return rp; |
|
537 } |
|
538 |
|
539 /*! |
|
540 \reimp |
|
541 */ |
|
542 QPoint QTransformedScreen::mapFromDevice(const QPoint &p, const QSize &s) const |
|
543 { |
|
544 QPoint rp(p); |
|
545 |
|
546 switch (d_ptr->transformation) { |
|
547 case None: |
|
548 break; |
|
549 case Rot90: |
|
550 rp.setX(s.height() - p.y() - 1); |
|
551 rp.setY(p.x()); |
|
552 break; |
|
553 case Rot180: |
|
554 rp.setX(s.width() - p.x() - 1); |
|
555 rp.setY(s.height() - p.y() - 1); |
|
556 break; |
|
557 case Rot270: |
|
558 rp.setX(p.y()); |
|
559 rp.setY(s.width() - p.x() - 1); |
|
560 break; |
|
561 } |
|
562 |
|
563 return rp; |
|
564 } |
|
565 |
|
566 /*! |
|
567 \reimp |
|
568 */ |
|
569 QRect QTransformedScreen::mapToDevice(const QRect &r, const QSize &s) const |
|
570 { |
|
571 if (r.isNull()) |
|
572 return QRect(); |
|
573 |
|
574 QRect tr; |
|
575 switch (d_ptr->transformation) { |
|
576 case None: |
|
577 tr = r; |
|
578 break; |
|
579 case Rot90: |
|
580 tr.setCoords(r.y(), s.width() - r.x() - 1, |
|
581 r.bottom(), s.width() - r.right() - 1); |
|
582 break; |
|
583 case Rot180: |
|
584 tr.setCoords(s.width() - r.x() - 1, s.height() - r.y() - 1, |
|
585 s.width() - r.right() - 1, s.height() - r.bottom() - 1); |
|
586 break; |
|
587 case Rot270: |
|
588 tr.setCoords(s.height() - r.y() - 1, r.x(), |
|
589 s.height() - r.bottom() - 1, r.right()); |
|
590 break; |
|
591 } |
|
592 |
|
593 return correctNormalized(tr); |
|
594 } |
|
595 |
|
596 /*! |
|
597 \reimp |
|
598 */ |
|
599 QRect QTransformedScreen::mapFromDevice(const QRect &r, const QSize &s) const |
|
600 { |
|
601 if (r.isNull()) |
|
602 return QRect(); |
|
603 |
|
604 QRect tr; |
|
605 switch (d_ptr->transformation) { |
|
606 case None: |
|
607 tr = r; |
|
608 break; |
|
609 case Rot90: |
|
610 tr.setCoords(s.height() - r.y() - 1, r.x(), |
|
611 s.height() - r.bottom() - 1, r.right()); |
|
612 break; |
|
613 case Rot180: |
|
614 tr.setCoords(s.width() - r.x() - 1, s.height() - r.y() - 1, |
|
615 s.width() - r.right() - 1, s.height() - r.bottom() - 1); |
|
616 break; |
|
617 case Rot270: |
|
618 tr.setCoords(r.y(), s.width() - r.x() - 1, |
|
619 r.bottom(), s.width() - r.right() - 1); |
|
620 break; |
|
621 } |
|
622 |
|
623 return correctNormalized(tr); |
|
624 } |
|
625 |
|
626 /*! |
|
627 \reimp |
|
628 */ |
|
629 QRegion QTransformedScreen::mapToDevice(const QRegion &rgn, const QSize &s) const |
|
630 { |
|
631 if (d_ptr->transformation == None) |
|
632 return QProxyScreen::mapToDevice(rgn, s); |
|
633 |
|
634 #ifdef QT_REGION_DEBUG |
|
635 qDebug() << "mapToDevice size" << s << "rgn: " << rgn; |
|
636 #endif |
|
637 QRect tr; |
|
638 QRegion trgn; |
|
639 QVector<QRect> a = rgn.rects(); |
|
640 const QRect *r = a.data(); |
|
641 |
|
642 int w = s.width(); |
|
643 int h = s.height(); |
|
644 int size = a.size(); |
|
645 |
|
646 switch (d_ptr->transformation) { |
|
647 case None: |
|
648 break; |
|
649 case Rot90: |
|
650 for (int i = 0; i < size; i++, r++) { |
|
651 tr.setCoords(r->y(), w - r->x() - 1, |
|
652 r->bottom(), w - r->right() - 1); |
|
653 trgn |= correctNormalized(tr); |
|
654 } |
|
655 break; |
|
656 case Rot180: |
|
657 for (int i = 0; i < size; i++, r++) { |
|
658 tr.setCoords(w - r->x() - 1, h - r->y() - 1, |
|
659 w - r->right() - 1, h - r->bottom() - 1); |
|
660 trgn |= correctNormalized(tr); |
|
661 } |
|
662 break; |
|
663 case Rot270: |
|
664 for (int i = 0; i < size; i++, r++) { |
|
665 tr.setCoords(h - r->y() - 1, r->x(), |
|
666 h - r->bottom() - 1, r->right()); |
|
667 trgn |= correctNormalized(tr); |
|
668 } |
|
669 break; |
|
670 } |
|
671 #ifdef QT_REGION_DEBUG |
|
672 qDebug() << "mapToDevice trgn: " << trgn; |
|
673 #endif |
|
674 return trgn; |
|
675 } |
|
676 |
|
677 /*! |
|
678 \reimp |
|
679 */ |
|
680 QRegion QTransformedScreen::mapFromDevice(const QRegion &rgn, const QSize &s) const |
|
681 { |
|
682 if (d_ptr->transformation == None) |
|
683 return QProxyScreen::mapFromDevice(rgn, s); |
|
684 |
|
685 #ifdef QT_REGION_DEBUG |
|
686 qDebug() << "fromDevice: realRegion count: " << rgn.rects().size() << " isEmpty? " << rgn.isEmpty() << " bounds:" << rgn.boundingRect(); |
|
687 #endif |
|
688 QRect tr; |
|
689 QRegion trgn; |
|
690 QVector<QRect> a = rgn.rects(); |
|
691 const QRect *r = a.data(); |
|
692 |
|
693 int w = s.width(); |
|
694 int h = s.height(); |
|
695 int size = a.size(); |
|
696 |
|
697 switch (d_ptr->transformation) { |
|
698 case None: |
|
699 break; |
|
700 case Rot90: |
|
701 for (int i = 0; i < size; i++, r++) { |
|
702 tr.setCoords(h - r->y() - 1, r->x(), |
|
703 h - r->bottom() - 1, r->right()); |
|
704 trgn |= correctNormalized(tr); |
|
705 } |
|
706 break; |
|
707 case Rot180: |
|
708 for (int i = 0; i < size; i++, r++) { |
|
709 tr.setCoords(w - r->x() - 1, h - r->y() - 1, |
|
710 w - r->right() - 1, h - r->bottom() - 1); |
|
711 trgn |= correctNormalized(tr); |
|
712 } |
|
713 break; |
|
714 case Rot270: |
|
715 for (int i = 0; i < size; i++, r++) { |
|
716 tr.setCoords(r->y(), w - r->x() - 1, |
|
717 r->bottom(), w - r->right() - 1); |
|
718 trgn |= correctNormalized(tr); |
|
719 } |
|
720 break; |
|
721 } |
|
722 #ifdef QT_REGION_DEBUG |
|
723 qDebug() << "fromDevice: transRegion count: " << trgn.rects().size() << " isEmpty? " << trgn.isEmpty() << " bounds:" << trgn.boundingRect(); |
|
724 #endif |
|
725 return trgn; |
|
726 } |
|
727 |
|
728 /*! |
|
729 \reimp |
|
730 */ |
|
731 void QTransformedScreen::setDirty(const QRect& rect) |
|
732 { |
|
733 const QRect r = mapToDevice(rect, QSize(width(), height())); |
|
734 QProxyScreen::setDirty(r); |
|
735 } |
|
736 |
|
737 /*! |
|
738 \reimp |
|
739 */ |
|
740 QRegion QTransformedScreen::region() const |
|
741 { |
|
742 QRegion deviceRegion = QProxyScreen::region(); |
|
743 return mapFromDevice(deviceRegion, QSize(deviceWidth(), deviceHeight())); |
|
744 } |
|
745 |
|
746 QT_END_NAMESPACE |
|
747 |
|
748 #endif // QT_NO_QWS_TRANSFORMED |