source: trunk/src/gui/painting/qregion.cpp@ 347

Last change on this file since 347 was 95, checked in by Dmitry A. Kuminov, 16 years ago

gui: Added OS/2 stubs for platform-specific parts of all key GUI classes. Non-key classes are temporarily disabled with QT_NO_ defines.

File size: 130.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qregion.h"
43#include "qpainterpath.h"
44#include "qpolygon.h"
45#include "qbuffer.h"
46#include "qdatastream.h"
47#include "qvariant.h"
48#include "qvarlengtharray.h"
49
50#include <qdebug.h>
51
52#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE)
53#include "qimage.h"
54#include "qbitmap.h"
55#include <stdlib.h>
56#endif
57
58QT_BEGIN_NAMESPACE
59
60/*!
61 \class QRegion
62 \brief The QRegion class specifies a clip region for a painter.
63
64 \ingroup multimedia
65 \ingroup shared
66
67 QRegion is used with QPainter::setClipRegion() to limit the paint
68 area to what needs to be painted. There is also a QWidget::repaint()
69 function that takes a QRegion parameter. QRegion is the best tool for
70 minimizing the amount of screen area to be updated by a repaint.
71
72 This class is not suitable for constructing shapes for rendering, especially
73 as outlines. Use QPainterPath to create paths and shapes for use with
74 QPainter.
75
76 QRegion is an \l{implicitly shared} class.
77
78 \section1 Creating and Using Regions
79
80 A region can be created from a rectangle, an ellipse, a polygon or
81 a bitmap. Complex regions may be created by combining simple
82 regions using united(), intersected(), subtracted(), or xored() (exclusive
83 or). You can move a region using translate().
84
85 You can test whether a region isEmpty() or if it
86 contains() a QPoint or QRect. The bounding rectangle can be found
87 with boundingRect().
88
89 The function rects() gives a decomposition of the region into
90 rectangles.
91
92 Example of using complex regions:
93 \snippet doc/src/snippets/code/src_gui_painting_qregion.cpp 0
94
95 \warning Due to window system limitations, the whole coordinate space for a
96 region is limited to the points between -32767 and 32767 on Windows
97 95/98/ME. You can circumvent this limitation by using a QPainterPath.
98
99 \section1 Additional License Information
100
101 On Embedded Linux, Windows CE and X11 platforms, parts of this class rely on
102 code obtained under the following licenses:
103
104 \legalese
105 Copyright (c) 1987 X Consortium
106
107 Permission is hereby granted, free of charge, to any person obtaining a copy
108 of this software and associated documentation files (the "Software"), to deal
109 in the Software without restriction, including without limitation the rights
110 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
111 copies of the Software, and to permit persons to whom the Software is
112 furnished to do so, subject to the following conditions:
113
114 The above copyright notice and this permission notice shall be included in
115 all copies or substantial portions of the Software.
116
117 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
118 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
119 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
120 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
121 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
122 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
123
124 Except as contained in this notice, the name of the X Consortium shall not be
125 used in advertising or otherwise to promote the sale, use or other dealings
126 in this Software without prior written authorization from the X Consortium.
127 \endlegalese
128
129 \br
130
131 \legalese
132 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
133
134 All Rights Reserved
135
136 Permission to use, copy, modify, and distribute this software and its
137 documentation for any purpose and without fee is hereby granted,
138 provided that the above copyright notice appear in all copies and that
139 both that copyright notice and this permission notice appear in
140 supporting documentation, and that the name of Digital not be
141 used in advertising or publicity pertaining to distribution of the
142 software without specific, written prior permission.
143
144 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
145 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
146 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
147 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
148 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
149 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
150 SOFTWARE.
151 \endlegalese
152
153 \sa QPainter::setClipRegion(), QPainter::setClipRect(), QPainterPath
154*/
155
156
157/*!
158 \enum QRegion::RegionType
159
160 Specifies the shape of the region to be created.
161
162 \value Rectangle the region covers the entire rectangle.
163 \value Ellipse the region is an ellipse inside the rectangle.
164*/
165
166/*!
167 \fn void QRegion::translate(const QPoint &point)
168
169 \overload
170
171 Translates the region \a{point}\e{.x()} along the x axis and
172 \a{point}\e{.y()} along the y axis, relative to the current
173 position. Positive values move the region to the right and down.
174
175 Translates to the given \a point.
176*/
177
178/*!
179 \fn Handle QRegion::handle() const
180
181 Returns a platform-specific region handle. The \c Handle type is
182 \c HRGN on Windows, \c Region on X11, and \c RgnHandle on Mac OS
183 X. On \l{Qt for Embedded Linux} it is \c {void *}.
184
185 \warning This function is not portable.
186*/
187
188/*****************************************************************************
189 QRegion member functions
190 *****************************************************************************/
191
192/*!
193 \fn QRegion::QRegion()
194
195 Constructs an empty region.
196
197 \sa isEmpty()
198*/
199
200/*!
201 \fn QRegion::QRegion(const QRect &r, RegionType t)
202 \overload
203
204 Create a region based on the rectange \a r with region type \a t.
205
206 If the rectangle is invalid a null region will be created.
207
208 \sa QRegion::RegionType
209*/
210
211/*!
212 \fn QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
213
214 Constructs a polygon region from the point array \a a with the fill rule
215 specified by \a fillRule.
216
217 If \a fillRule is \l{Qt::WindingFill}, the polygon region is defined
218 using the winding algorithm; if it is \l{Qt::OddEvenFill}, the odd-even fill
219 algorithm is used.
220
221 \warning This constructor can be used to create complex regions that will
222 slow down painting when used.
223*/
224
225/*!
226 \fn QRegion::QRegion(const QRegion &r)
227
228 Constructs a new region which is equal to region \a r.
229*/
230
231/*!
232 \fn QRegion::QRegion(const QBitmap &bm)
233
234 Constructs a region from the bitmap \a bm.
235
236 The resulting region consists of the pixels in bitmap \a bm that
237 are Qt::color1, as if each pixel was a 1 by 1 rectangle.
238
239 This constructor may create complex regions that will slow down
240 painting when used. Note that drawing masked pixmaps can be done
241 much faster using QPixmap::setMask().
242*/
243
244/*!
245 Constructs a rectangular or elliptic region.
246
247 If \a t is \c Rectangle, the region is the filled rectangle (\a x,
248 \a y, \a w, \a h). If \a t is \c Ellipse, the region is the filled
249 ellipse with center at (\a x + \a w / 2, \a y + \a h / 2) and size
250 (\a w ,\a h).
251*/
252QRegion::QRegion(int x, int y, int w, int h, RegionType t)
253{
254 QRegion tmp(QRect(x, y, w, h), t);
255 tmp.d->ref.ref();
256 d = tmp.d;
257}
258
259#ifdef QT3_SUPPORT
260/*!
261 Use the constructor tha takes a Qt::FillRule as the second
262 argument instead.
263*/
264QRegion::QRegion(const QPolygon &pa, bool winding)
265{
266 new (this) QRegion(pa, winding ? Qt::WindingFill : Qt::OddEvenFill);
267}
268#endif
269
270/*!
271 \fn QRegion::~QRegion()
272 \internal
273
274 Destroys the region.
275*/
276
277void QRegion::detach()
278{
279 if (d->ref != 1)
280 *this = copy();
281#if defined(Q_WS_X11)
282 else if (d->xrectangles) {
283 free(d->xrectangles);
284 d->xrectangles = 0;
285 }
286#endif
287}
288
289// duplicates in qregion_win.cpp and qregion_wce.cpp
290#define QRGN_SETRECT 1 // region stream commands
291#define QRGN_SETELLIPSE 2 // (these are internal)
292#define QRGN_SETPTARRAY_ALT 3
293#define QRGN_SETPTARRAY_WIND 4
294#define QRGN_TRANSLATE 5
295#define QRGN_OR 6
296#define QRGN_AND 7
297#define QRGN_SUB 8
298#define QRGN_XOR 9
299#define QRGN_RECTS 10
300
301
302#ifndef QT_NO_DATASTREAM
303
304/*
305 Executes region commands in the internal buffer and rebuilds the
306 original region.
307
308 We do this when we read a region from the data stream.
309
310 If \a ver is non-0, uses the format version \a ver on reading the
311 byte array.
312*/
313void QRegion::exec(const QByteArray &buffer, int ver, QDataStream::ByteOrder byteOrder)
314{
315 QByteArray copy = buffer;
316 QDataStream s(&copy, QIODevice::ReadOnly);
317 if (ver)
318 s.setVersion(ver);
319 s.setByteOrder(byteOrder);
320 QRegion rgn;
321#ifndef QT_NO_DEBUG
322 int test_cnt = 0;
323#endif
324 while (!s.atEnd()) {
325 qint32 id;
326 if (s.version() == 1) {
327 int id_int;
328 s >> id_int;
329 id = id_int;
330 } else {
331 s >> id;
332 }
333#ifndef QT_NO_DEBUG
334 if (test_cnt > 0 && id != QRGN_TRANSLATE)
335 qWarning("QRegion::exec: Internal error");
336 test_cnt++;
337#endif
338 if (id == QRGN_SETRECT || id == QRGN_SETELLIPSE) {
339 QRect r;
340 s >> r;
341 rgn = QRegion(r, id == QRGN_SETRECT ? Rectangle : Ellipse);
342 } else if (id == QRGN_SETPTARRAY_ALT || id == QRGN_SETPTARRAY_WIND) {
343 QPolygon a;
344 s >> a;
345 rgn = QRegion(a, id == QRGN_SETPTARRAY_WIND ? Qt::WindingFill : Qt::OddEvenFill);
346 } else if (id == QRGN_TRANSLATE) {
347 QPoint p;
348 s >> p;
349 rgn.translate(p.x(), p.y());
350 } else if (id >= QRGN_OR && id <= QRGN_XOR) {
351 QByteArray bop1, bop2;
352 QRegion r1, r2;
353 s >> bop1;
354 r1.exec(bop1);
355 s >> bop2;
356 r2.exec(bop2);
357
358 switch (id) {
359 case QRGN_OR:
360 rgn = r1.united(r2);
361 break;
362 case QRGN_AND:
363 rgn = r1.intersected(r2);
364 break;
365 case QRGN_SUB:
366 rgn = r1.subtracted(r2);
367 break;
368 case QRGN_XOR:
369 rgn = r1.xored(r2);
370 break;
371 }
372 } else if (id == QRGN_RECTS) {
373 // (This is the only form used in Qt 2.0)
374 quint32 n;
375 s >> n;
376 QRect r;
377 for (int i=0; i<(int)n; i++) {
378 s >> r;
379 rgn = rgn.united(QRegion(r));
380 }
381 }
382 }
383 *this = rgn;
384}
385
386
387/*****************************************************************************
388 QRegion stream functions
389 *****************************************************************************/
390
391/*!
392 \fn QRegion &QRegion::operator=(const QRegion &r)
393
394 Assigns \a r to this region and returns a reference to the region.
395*/
396
397/*!
398 \relates QRegion
399
400 Writes the region \a r to the stream \a s and returns a reference
401 to the stream.
402
403 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
404*/
405
406QDataStream &operator<<(QDataStream &s, const QRegion &r)
407{
408 QVector<QRect> a = r.rects();
409 if (a.isEmpty()) {
410 s << (quint32)0;
411 } else {
412 if (s.version() == 1) {
413 int i;
414 for (i = a.size() - 1; i > 0; --i) {
415 s << (quint32)(12 + i * 24);
416 s << (int)QRGN_OR;
417 }
418 for (i = 0; i < a.size(); ++i) {
419 s << (quint32)(4+8) << (int)QRGN_SETRECT << a[i];
420 }
421 } else {
422 s << (quint32)(4 + 4 + 16 * a.size()); // 16: storage size of QRect
423 s << (qint32)QRGN_RECTS;
424 s << a;
425 }
426 }
427 return s;
428}
429
430/*!
431 \relates QRegion
432
433 Reads a region from the stream \a s into \a r and returns a
434 reference to the stream.
435
436 \sa \link datastreamformat.html Format of the QDataStream operators \endlink
437*/
438
439QDataStream &operator>>(QDataStream &s, QRegion &r)
440{
441 QByteArray b;
442 s >> b;
443 r.exec(b, s.version(), s.byteOrder());
444 return s;
445}
446#endif //QT_NO_DATASTREAM
447
448#ifndef QT_NO_DEBUG_STREAM
449QDebug operator<<(QDebug s, const QRegion &r)
450{
451 QVector<QRect> rects = r.rects();
452 s.nospace() << "QRegion(size=" << rects.size() << "), "
453 << "bounds = " << r.boundingRect() << "\n";
454 for (int i=0; i<rects.size(); ++i)
455 s << "- " << i << rects.at(i) << "\n";
456 return s;
457}