~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/painting/qregion.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the painting module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qregion.h"
 
30
#include "qpolygon.h"
 
31
#include "qbuffer.h"
 
32
#include "qdatastream.h"
 
33
#include "qvariant.h"
 
34
 
 
35
#include <qdebug.h>
 
36
 
 
37
/*!
 
38
    \class QRegion
 
39
    \brief The QRegion class specifies a clip region for a painter.
 
40
 
 
41
    \ingroup multimedia
 
42
 
 
43
    QRegion is used with QPainter::setClipRegion() to limit the paint
 
44
    area to what needs to be painted. There is also a
 
45
    QWidget::repaint() function that takes a QRegion parameter.
 
46
    QRegion is the best tool for reducing flicker.
 
47
 
 
48
    A region can be created from a rectangle, an ellipse, a polygon or
 
49
    a bitmap. Complex regions may be created by combining simple
 
50
    regions using unite(), intersect(), subtract(), or eor() (exclusive
 
51
    or). You can move a region using translate().
 
52
 
 
53
    You can test whether a region isEmpty() or if it
 
54
    contains() a QPoint or QRect. The bounding rectangle can be found
 
55
    with boundingRect().
 
56
 
 
57
    The function rects() gives a decomposition of the region into
 
58
    rectangles.
 
59
 
 
60
    Example of using complex regions:
 
61
    \code
 
62
        void MyWidget::paintEvent(QPaintEvent *)
 
63
        {
 
64
            QPainter p;                       // our painter
 
65
            QRegion r1(QRect(100,100,200,80), // r1 = elliptic region
 
66
                       QRegion::Ellipse);
 
67
            QRegion r2(QRect(100,120,90,30)); // r2 = rectangular region
 
68
            QRegion r3 = r1.intersect(r2);    // r3 = intersection
 
69
            p.begin(this);                    // start painting widget
 
70
            p.setClipRegion(r3);              // set clip region
 
71
            ...                               // paint clipped graphics
 
72
            p.end();                          // painting done
 
73
        }
 
74
    \endcode
 
75
 
 
76
    QRegion is an \link shclass.html implicitly shared\endlink class.
 
77
 
 
78
    \warning Due to window system limitations, the whole coordinate space for a
 
79
    region is limited to the points between -32767 and 32767 on Windows
 
80
    95/98/ME. You can circumvent this limitation by using a QPainterPath.
 
81
 
 
82
    \sa QPainter::setClipRegion(), QPainter::setClipRect()
 
83
 
 
84
    \sa QPainterPath
 
85
*/
 
86
 
 
87
 
 
88
/*!
 
89
    \enum QRegion::RegionType
 
90
 
 
91
    Specifies the shape of the region to be created.
 
92
 
 
93
    \value Rectangle  the region covers the entire rectangle.
 
94
    \value Ellipse  the region is an ellipse inside the rectangle.
 
95
*/
 
96
 
 
97
/*!
 
98
    \fn void QRegion::translate(const QPoint &point)
 
99
 
 
100
    \overload
 
101
 
 
102
    Translates to the given \a point.
 
103
*/
 
104
 
 
105
/*!
 
106
    \fn Handle QRegion::handle() const
 
107
 
 
108
    Returns a platform-specific region handle. The \c Handle type is
 
109
    \c HRGN on Windows, \c Region on X11, and \c RgnHandle on Mac OS
 
110
    X.
 
111
 
 
112
    \warning This function is not portable.
 
113
*/
 
114
 
 
115
/*****************************************************************************
 
116
  QRegion member functions
 
117
 *****************************************************************************/
 
118
 
 
119
/*!
 
120
    Constructs a rectangular or elliptic region.
 
121
 
 
122
    If \a t is \c Rectangle, the region is the filled rectangle (\a x,
 
123
    \a y, \a w, \a h). If \a t is \c Ellipse, the region is the filled
 
124
    ellipse with center at (\a x + \a w / 2, \a y + \a h / 2) and size
 
125
    (\a w ,\a h).
 
126
*/
 
127
QRegion::QRegion(int x, int y, int w, int h, RegionType t)
 
128
{
 
129
    QRegion tmp(QRect(x, y, w, h), t);
 
130
    tmp.d->ref.ref();
 
131
    d = tmp.d;
 
132
}
 
133
 
 
134
#ifdef QT3_SUPPORT
 
135
/*!
 
136
    Use the constructor tha takes a Qt::FillRule as the second
 
137
    argument instead.
 
138
*/
 
139
QRegion::QRegion(const QPolygon &pa, bool winding)
 
140
{
 
141
    new (this) QRegion(pa, winding ? Qt::WindingFill : Qt::OddEvenFill);
 
142
}
 
143
#endif
 
144
 
 
145
/*!
 
146
    Detaches from shared region data to make sure that this region is
 
147
    the only one referring to the data.
 
148
 
 
149
    \sa copy(), \link shclass.html shared classes\endlink
 
150
*/
 
151
 
 
152
void QRegion::detach()
 
153
{
 
154
    if (d->ref != 1)
 
155
        *this = copy();
 
156
}
 
157
 
 
158
// duplicates in qregion_win.cpp and qregion_wce.cpp
 
159
#define QRGN_SETRECT          1                // region stream commands
 
160
#define QRGN_SETELLIPSE       2                //  (these are internal)
 
161
#define QRGN_SETPTARRAY_ALT   3
 
162
#define QRGN_SETPTARRAY_WIND  4
 
163
#define QRGN_TRANSLATE        5
 
164
#define QRGN_OR               6
 
165
#define QRGN_AND              7
 
166
#define QRGN_SUB              8
 
167
#define QRGN_XOR              9
 
168
#define QRGN_RECTS            10
 
169
 
 
170
 
 
171
#ifndef QT_NO_DATASTREAM
 
172
/*
 
173
    Executes region commands in the internal buffer and rebuilds the
 
174
    original region.
 
175
 
 
176
    We do this when we read a region from the data stream.
 
177
 
 
178
    If \a ver is non-0, uses the format version \a ver on reading the
 
179
    byte array.
 
180
*/
 
181
 
 
182
void QRegion::exec(const QByteArray &buffer, int ver)
 
183
{
 
184
    QByteArray copy = buffer;
 
185
    QDataStream s(&copy, QIODevice::ReadOnly);
 
186
    if (ver)
 
187
        s.setVersion(ver);
 
188
    QRegion rgn;
 
189
#ifndef QT_NO_DEBUG
 
190
    int test_cnt = 0;
 
191
#endif
 
192
    while (!s.atEnd()) {
 
193
        qint32 id;
 
194
        if (s.version() == 1) {
 
195
            int id_int;
 
196
            s >> id_int;
 
197
            id = id_int;
 
198
        } else {
 
199
            s >> id;
 
200
        }
 
201
#ifndef QT_NO_DEBUG
 
202
        if (test_cnt > 0 && id != QRGN_TRANSLATE)
 
203
            qWarning("QRegion::exec: Internal error");
 
204
        test_cnt++;
 
205
#endif
 
206
        if (id == QRGN_SETRECT || id == QRGN_SETELLIPSE) {
 
207
            QRect r;
 
208
            s >> r;
 
209
            rgn = QRegion(r, id == QRGN_SETRECT ? Rectangle : Ellipse);
 
210
        } else if (id == QRGN_SETPTARRAY_ALT || id == QRGN_SETPTARRAY_WIND) {
 
211
            QPolygon a;
 
212
            s >> a;
 
213
            rgn = QRegion(a, id == QRGN_SETPTARRAY_WIND ? Qt::WindingFill : Qt::OddEvenFill);
 
214
        } else if (id == QRGN_TRANSLATE) {
 
215
            QPoint p;
 
216
            s >> p;
 
217
            rgn.translate(p.x(), p.y());
 
218
        } else if (id >= QRGN_OR && id <= QRGN_XOR) {
 
219
            QByteArray bop1, bop2;
 
220
            QRegion r1, r2;
 
221
            s >> bop1;
 
222
            r1.exec(bop1);
 
223
            s >> bop2;
 
224
            r2.exec(bop2);
 
225
 
 
226
            switch (id) {
 
227
                case QRGN_OR:
 
228
                    rgn = r1.unite(r2);
 
229
                    break;
 
230
                case QRGN_AND:
 
231
                    rgn = r1.intersect(r2);
 
232
                    break;
 
233
                case QRGN_SUB:
 
234
                    rgn = r1.subtract(r2);
 
235
                    break;
 
236
                case QRGN_XOR:
 
237
                    rgn = r1.eor(r2);
 
238
                    break;
 
239
            }
 
240
        } else if (id == QRGN_RECTS) {
 
241
            // (This is the only form used in Qt 2.0)
 
242
            quint32 n;
 
243
            s >> n;
 
244
            QRect r;
 
245
            for (int i=0; i<(int)n; i++) {
 
246
                s >> r;
 
247
                rgn = rgn.unite(QRegion(r));
 
248
            }
 
249
        }
 
250
    }
 
251
    *this = rgn;
 
252
}
 
253
 
 
254
 
 
255
/*****************************************************************************
 
256
  QRegion stream functions
 
257
 *****************************************************************************/
 
258
 
 
259
/*!
 
260
    \relates QRegion
 
261
 
 
262
    Writes the region \a r to the stream \a s and returns a reference
 
263
    to the stream.
 
264
 
 
265
    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
 
266
*/
 
267
 
 
268
QDataStream &operator<<(QDataStream &s, const QRegion &r)
 
269
{
 
270
    QVector<QRect> a = r.rects();
 
271
    if (a.isEmpty()) {
 
272
        s << (quint32)0;
 
273
    } else {
 
274
        if (s.version() == 1) {
 
275
            int i;
 
276
            for (i = a.size() - 1; i > 0; --i) {
 
277
                s << (quint32)(12 + i * 24);
 
278
                s << (int)QRGN_OR;
 
279
            }
 
280
            for (i = 0; i < a.size(); ++i) {
 
281
                s << (quint32)(4+8) << (int)QRGN_SETRECT << a[i];
 
282
            }
 
283
        } else {
 
284
            s << (quint32)(4 + 4 + 16 * a.size()); // 16: storage size of QRect
 
285
            s << (qint32)QRGN_RECTS;
 
286
            s << a;
 
287
        }
 
288
    }
 
289
    return s;
 
290
}
 
291
 
 
292
/*!
 
293
    \relates QRegion
 
294
 
 
295
    Reads a region from the stream \a s into \a r and returns a
 
296
    reference to the stream.
 
297
 
 
298
    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
 
299
*/
 
300
 
 
301
QDataStream &operator>>(QDataStream &s, QRegion &r)
 
302
{
 
303
    QByteArray b;
 
304
    s >> b;
 
305
    r.exec(b, s.version());
 
306
    return s;
 
307
}
 
308
#endif //QT_NO_DATASTREAM
 
309
 
 
310
#ifndef QT_NO_DEBUG_STREAM
 
311
QDebug operator<<(QDebug s, const QRegion &r)
 
312
{
 
313
    QVector<QRect> rects = r.rects();
 
314
    s.nospace() << "QRegion(size=" << rects.size() << "), "
 
315
                << "bounds = " << r.boundingRect() << "\n";
 
316
    for (int i=0; i<rects.size(); ++i)
 
317
        s << "- " << i << rects.at(i) << "\n";
 
318
    return s;
 
319
}
 
320
#endif
 
321
 
 
322
 
 
323
// These are not inline - they can be implemented better on some platforms
 
324
//  (eg. Windows at least provides 3-variable operations).  For now, simple.
 
325
 
 
326
 
 
327
/*!
 
328
    Applies the unite() function to this region and \a r. \c r1|r2 is
 
329
    equivalent to \c r1.unite(r2)
 
330
 
 
331
    \sa unite(), operator+()
 
332
*/
 
333
const QRegion QRegion::operator|(const QRegion &r) const
 
334
    { return unite(r); }
 
335
 
 
336
/*!
 
337
    Applies the unite() function to this region and \a r. \c r1+r2 is
 
338
    equivalent to \c r1.unite(r2)
 
339
 
 
340
    \sa unite(), operator|()
 
341
*/
 
342
const QRegion QRegion::operator+(const QRegion &r) const
 
343
    { return unite(r); }
 
344
 
 
345
/*!
 
346
    Applies the intersect() function to this region and \a r. \c r1&r2
 
347
    is equivalent to \c r1.intersect(r2)
 
348
 
 
349
    \sa intersect()
 
350
*/
 
351
const QRegion QRegion::operator&(const QRegion &r) const
 
352
    { return intersect(r); }
 
353
 
 
354
/*!
 
355
    Applies the subtract() function to this region and \a r. \c r1-r2
 
356
    is equivalent to \c r1.subtract(r2)
 
357
 
 
358
    \sa subtract()
 
359
*/
 
360
const QRegion QRegion::operator-(const QRegion &r) const
 
361
    { return subtract(r); }
 
362
 
 
363
/*!
 
364
    Applies the eor() function to this region and \a r. \c r1^r2 is
 
365
    equivalent to \c r1.eor(r2)
 
366
 
 
367
    \sa eor()
 
368
*/
 
369
const QRegion QRegion::operator^(const QRegion &r) const
 
370
    { return eor(r); }
 
371
 
 
372
/*!
 
373
    Applies the unite() function to this region and \a r and assigns
 
374
    the result to this region. \c r1|=r2 is equivalent to \c
 
375
    r1=r1.unite(r2)
 
376
 
 
377
    \sa unite()
 
378
*/
 
379
QRegion& QRegion::operator|=(const QRegion &r)
 
380
    { return *this = *this | r; }
 
381
 
 
382
/*!
 
383
    Applies the unite() function to this region and \a r and assigns
 
384
    the result to this region. \c r1+=r2 is equivalent to \c
 
385
    r1=r1.unite(r2)
 
386
 
 
387
    \sa intersect()
 
388
*/
 
389
QRegion& QRegion::operator+=(const QRegion &r)
 
390
    { return *this = *this + r; }
 
391
 
 
392
/*!
 
393
    Applies the intersect() function to this region and \a r and
 
394
    assigns the result to this region. \c r1&=r2 is equivalent to \c
 
395
    r1=r1.intersect(r2)
 
396
 
 
397
    \sa intersect()
 
398
*/
 
399
QRegion& QRegion::operator&=(const QRegion &r)
 
400
    { return *this = *this & r; }
 
401
 
 
402
/*!
 
403
    Applies the subtract() function to this region and \a r and
 
404
    assigns the result to this region. \c r1-=r2 is equivalent to \c
 
405
    r1=r1.subtract(r2)
 
406
 
 
407
    \sa subtract()
 
408
*/
 
409
QRegion& QRegion::operator-=(const QRegion &r)
 
410
    { return *this = *this - r; }
 
411
 
 
412
/*!
 
413
    Applies the eor() function to this region and \a r and
 
414
    assigns the result to this region. \c r1^=r2 is equivalent to \c
 
415
    r1=r1.eor(r2)
 
416
 
 
417
    \sa eor()
 
418
*/
 
419
QRegion& QRegion::operator^=(const QRegion &r)
 
420
    { return *this = *this ^ r; }
 
421
 
 
422
/*!
 
423
    \fn bool QRegion::operator!=(const QRegion &other) const
 
424
 
 
425
    Returns true if this region is different from the \a other region;
 
426
    otherwise returns false.
 
427
*/
 
428
 
 
429
/*!
 
430
   Returns the region as a QVariant
 
431
*/
 
432
QRegion::operator QVariant() const
 
433
{
 
434
    return QVariant(QVariant::Region, this);
 
435
}
 
436
 
 
437
/*!
 
438
    \fn bool QRegion::isNull() const
 
439
 
 
440
    Use isEmpty() instead.
 
441
*/