1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module 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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
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 
QTransformedScreenPrivate(QTransformedScreen * parent)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
qws_setScreenTransformation(QScreen * that,int t)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 */
QTransformedScreen(int displayId)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 
configure()166 void QTransformedScreenPrivate::configure()
167 {
168     // ###: works because setTransformation recalculates unconditionally
169     q->setTransformation(transformation);
170 }
171 
172 /*!
173     Destroys the QTransformedScreen object.
174 */
~QTransformedScreen()175 QTransformedScreen::~QTransformedScreen()
176 {
177     delete d_ptr;
178 }
179 
getDisplayId(const QString & spec)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 
filterTransformation(QString & spec)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 */
connect(const QString & displaySpec)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 */
transformation() const249 QTransformedScreen::Transformation QTransformedScreen::transformation() const
250 {
251     return d_ptr->transformation;
252 }
253 
254 /*!
255     \reimp
256 */
transformOrientation() const257 int QTransformedScreen::transformOrientation() const
258 {
259     return (int)d_ptr->transformation;
260 }
261 
262 /*!
263     \reimp
264 */
exposeRegion(QRegion region,int changing)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 */
setTransformation(Transformation transformation)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 
correctNormalized(const QRect & r)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>
blit90(QScreen * screen,const QImage & image,const QRect & rect,const QPoint & topLeft)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>
blit180(QScreen * screen,const QImage & image,const QRect & rect,const QPoint & topLeft)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>
blit270(QScreen * screen,const QImage & image,const QRect & rect,const QPoint & topLeft)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 */
blit(const QImage & image,const QPoint & topLeft,const QRegion & region)362 void QTransformedScreen::blit(const QImage &image, const QPoint &topLeft,
363                               const QRegion &region)
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 */
solidFill(const QColor & color,const QRegion & region)466 void QTransformedScreen::solidFill(const QColor &color, const QRegion &region)
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 */
mapToDevice(const QSize & s) const481 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 */
mapFromDevice(const QSize & s) const498 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 */
mapToDevice(const QPoint & p,const QSize & s) const515 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 */
mapFromDevice(const QPoint & p,const QSize & s) const542 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 */
mapToDevice(const QRect & r,const QSize & s) const569 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 */
mapFromDevice(const QRect & r,const QSize & s) const599 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 */
mapToDevice(const QRegion & rgn,const QSize & s) const629 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 */
mapFromDevice(const QRegion & rgn,const QSize & s) const680 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 */
setDirty(const QRect & rect)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 */
region() const740 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
749