src/gui/painting/qregion.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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 "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_WS_WIN)
       
    53 #include "qimage.h"
       
    54 #include "qbitmap.h"
       
    55 #include <stdlib.h>
       
    56 #endif
       
    57 
       
    58 QT_BEGIN_NAMESPACE
       
    59 
       
    60 /*!
       
    61     \class QRegion
       
    62     \brief The QRegion class specifies a clip region for a painter.
       
    63 
       
    64     \ingroup painting
       
    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     \section1 Additional License Information
       
    96 
       
    97     On Embedded Linux, Windows CE and X11 platforms, parts of this class rely on
       
    98     code obtained under the following licenses:
       
    99 
       
   100     \legalese
       
   101     Copyright (c) 1987  X Consortium
       
   102 
       
   103     Permission is hereby granted, free of charge, to any person obtaining a copy
       
   104     of this software and associated documentation files (the "Software"), to deal
       
   105     in the Software without restriction, including without limitation the rights
       
   106     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
   107     copies of the Software, and to permit persons to whom the Software is
       
   108     furnished to do so, subject to the following conditions:
       
   109 
       
   110     The above copyright notice and this permission notice shall be included in
       
   111     all copies or substantial portions of the Software.
       
   112 
       
   113     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
   114     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
   115     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
       
   116     X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
       
   117     AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
   118     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
   119 
       
   120     Except as contained in this notice, the name of the X Consortium shall not be
       
   121     used in advertising or otherwise to promote the sale, use or other dealings
       
   122     in this Software without prior written authorization from the X Consortium.
       
   123     \endlegalese
       
   124 
       
   125     \br
       
   126 
       
   127     \legalese
       
   128     Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
       
   129 
       
   130                             All Rights Reserved
       
   131 
       
   132     Permission to use, copy, modify, and distribute this software and its
       
   133     documentation for any purpose and without fee is hereby granted,
       
   134     provided that the above copyright notice appear in all copies and that
       
   135     both that copyright notice and this permission notice appear in
       
   136     supporting documentation, and that the name of Digital not be
       
   137     used in advertising or publicity pertaining to distribution of the
       
   138     software without specific, written prior permission.
       
   139 
       
   140     DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
       
   141     ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
       
   142     DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
       
   143     ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
       
   144     WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
       
   145     ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
       
   146     SOFTWARE.
       
   147     \endlegalese
       
   148 
       
   149     \sa QPainter::setClipRegion(), QPainter::setClipRect(), QPainterPath
       
   150 */
       
   151 
       
   152 
       
   153 /*!
       
   154     \enum QRegion::RegionType
       
   155 
       
   156     Specifies the shape of the region to be created.
       
   157 
       
   158     \value Rectangle  the region covers the entire rectangle.
       
   159     \value Ellipse  the region is an ellipse inside the rectangle.
       
   160 */
       
   161 
       
   162 /*!
       
   163     \fn void QRegion::translate(const QPoint &point)
       
   164 
       
   165     \overload
       
   166 
       
   167     Translates the region \a{point}\e{.x()} along the x axis and
       
   168     \a{point}\e{.y()} along the y axis, relative to the current
       
   169     position. Positive values move the region to the right and down.
       
   170 
       
   171     Translates to the given \a point.
       
   172 */
       
   173 
       
   174 /*!
       
   175     \fn Handle QRegion::handle() const
       
   176 
       
   177     Returns a platform-specific region handle. The \c Handle type is
       
   178     \c HRGN on Windows, \c Region on X11, and \c RgnHandle on Mac OS
       
   179     X. On \l{Qt for Embedded Linux} it is \c {void *}.
       
   180 
       
   181     \warning This function is not portable.
       
   182 */
       
   183 
       
   184 /*****************************************************************************
       
   185   QRegion member functions
       
   186  *****************************************************************************/
       
   187 
       
   188 /*!
       
   189     \fn QRegion::QRegion()
       
   190 
       
   191     Constructs an empty region.
       
   192 
       
   193     \sa isEmpty()
       
   194 */
       
   195 
       
   196 /*!
       
   197     \fn QRegion::QRegion(const QRect &r, RegionType t)
       
   198     \overload
       
   199 
       
   200     Create a region based on the rectange \a r with region type \a t.
       
   201 
       
   202     If the rectangle is invalid a null region will be created.
       
   203 
       
   204     \sa QRegion::RegionType
       
   205 */
       
   206 
       
   207 /*!
       
   208     \fn QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
       
   209 
       
   210     Constructs a polygon region from the point array \a a with the fill rule
       
   211     specified by \a fillRule.
       
   212 
       
   213     If \a fillRule is \l{Qt::WindingFill}, the polygon region is defined
       
   214     using the winding algorithm; if it is \l{Qt::OddEvenFill}, the odd-even fill
       
   215     algorithm is used.
       
   216 
       
   217     \warning This constructor can be used to create complex regions that will
       
   218     slow down painting when used.
       
   219 */
       
   220 
       
   221 /*!
       
   222     \fn QRegion::QRegion(const QRegion &r)
       
   223 
       
   224     Constructs a new region which is equal to region \a r.
       
   225 */
       
   226 
       
   227 /*!
       
   228     \fn QRegion::QRegion(const QBitmap &bm)
       
   229 
       
   230     Constructs a region from the bitmap \a bm.
       
   231 
       
   232     The resulting region consists of the pixels in bitmap \a bm that
       
   233     are Qt::color1, as if each pixel was a 1 by 1 rectangle.
       
   234 
       
   235     This constructor may create complex regions that will slow down
       
   236     painting when used. Note that drawing masked pixmaps can be done
       
   237     much faster using QPixmap::setMask().
       
   238 */
       
   239 
       
   240 /*!
       
   241     Constructs a rectangular or elliptic region.
       
   242 
       
   243     If \a t is \c Rectangle, the region is the filled rectangle (\a x,
       
   244     \a y, \a w, \a h). If \a t is \c Ellipse, the region is the filled
       
   245     ellipse with center at (\a x + \a w / 2, \a y + \a h / 2) and size
       
   246     (\a w ,\a h).
       
   247 */
       
   248 QRegion::QRegion(int x, int y, int w, int h, RegionType t)
       
   249 {
       
   250     QRegion tmp(QRect(x, y, w, h), t);
       
   251     tmp.d->ref.ref();
       
   252     d = tmp.d;
       
   253 }
       
   254 
       
   255 #ifdef QT3_SUPPORT
       
   256 /*!
       
   257     Use the constructor tha takes a Qt::FillRule as the second
       
   258     argument instead.
       
   259 */
       
   260 QRegion::QRegion(const QPolygon &pa, bool winding)
       
   261 {
       
   262     new (this) QRegion(pa, winding ? Qt::WindingFill : Qt::OddEvenFill);
       
   263 }
       
   264 #endif
       
   265 
       
   266 /*!
       
   267     \fn QRegion::~QRegion()
       
   268     \internal
       
   269 
       
   270     Destroys the region.
       
   271 */
       
   272 
       
   273 void QRegion::detach()
       
   274 {
       
   275     if (d->ref != 1)
       
   276         *this = copy();
       
   277 #if defined(Q_WS_X11)
       
   278     else if (d->xrectangles) {
       
   279         free(d->xrectangles);
       
   280         d->xrectangles = 0;
       
   281     }
       
   282 #endif
       
   283 }
       
   284 
       
   285 // duplicates in qregion_win.cpp and qregion_wce.cpp
       
   286 #define QRGN_SETRECT          1                // region stream commands
       
   287 #define QRGN_SETELLIPSE       2                //  (these are internal)
       
   288 #define QRGN_SETPTARRAY_ALT   3
       
   289 #define QRGN_SETPTARRAY_WIND  4
       
   290 #define QRGN_TRANSLATE        5
       
   291 #define QRGN_OR               6
       
   292 #define QRGN_AND              7
       
   293 #define QRGN_SUB              8
       
   294 #define QRGN_XOR              9
       
   295 #define QRGN_RECTS            10
       
   296 
       
   297 
       
   298 #ifndef QT_NO_DATASTREAM
       
   299 
       
   300 /*
       
   301     Executes region commands in the internal buffer and rebuilds the
       
   302     original region.
       
   303 
       
   304     We do this when we read a region from the data stream.
       
   305 
       
   306     If \a ver is non-0, uses the format version \a ver on reading the
       
   307     byte array.
       
   308 */
       
   309 void QRegion::exec(const QByteArray &buffer, int ver, QDataStream::ByteOrder byteOrder)
       
   310 {
       
   311     QByteArray copy = buffer;
       
   312     QDataStream s(&copy, QIODevice::ReadOnly);
       
   313     if (ver)
       
   314         s.setVersion(ver);
       
   315     s.setByteOrder(byteOrder);
       
   316     QRegion rgn;
       
   317 #ifndef QT_NO_DEBUG
       
   318     int test_cnt = 0;
       
   319 #endif
       
   320     while (!s.atEnd()) {
       
   321         qint32 id;
       
   322         if (s.version() == 1) {
       
   323             int id_int;
       
   324             s >> id_int;
       
   325             id = id_int;
       
   326         } else {
       
   327             s >> id;
       
   328         }
       
   329 #ifndef QT_NO_DEBUG
       
   330         if (test_cnt > 0 && id != QRGN_TRANSLATE)
       
   331             qWarning("QRegion::exec: Internal error");
       
   332         test_cnt++;
       
   333 #endif
       
   334         if (id == QRGN_SETRECT || id == QRGN_SETELLIPSE) {
       
   335             QRect r;
       
   336             s >> r;
       
   337             rgn = QRegion(r, id == QRGN_SETRECT ? Rectangle : Ellipse);
       
   338         } else if (id == QRGN_SETPTARRAY_ALT || id == QRGN_SETPTARRAY_WIND) {
       
   339             QPolygon a;
       
   340             s >> a;
       
   341             rgn = QRegion(a, id == QRGN_SETPTARRAY_WIND ? Qt::WindingFill : Qt::OddEvenFill);
       
   342         } else if (id == QRGN_TRANSLATE) {
       
   343             QPoint p;
       
   344             s >> p;
       
   345             rgn.translate(p.x(), p.y());
       
   346         } else if (id >= QRGN_OR && id <= QRGN_XOR) {
       
   347             QByteArray bop1, bop2;
       
   348             QRegion r1, r2;
       
   349             s >> bop1;
       
   350             r1.exec(bop1);
       
   351             s >> bop2;
       
   352             r2.exec(bop2);
       
   353 
       
   354             switch (id) {
       
   355                 case QRGN_OR:
       
   356                     rgn = r1.united(r2);
       
   357                     break;
       
   358                 case QRGN_AND:
       
   359                     rgn = r1.intersected(r2);
       
   360                     break;
       
   361                 case QRGN_SUB:
       
   362                     rgn = r1.subtracted(r2);
       
   363                     break;
       
   364                 case QRGN_XOR:
       
   365                     rgn = r1.xored(r2);
       
   366                     break;
       
   367             }
       
   368         } else if (id == QRGN_RECTS) {
       
   369             // (This is the only form used in Qt 2.0)
       
   370             quint32 n;
       
   371             s >> n;
       
   372             QRect r;
       
   373             for (int i=0; i<(int)n; i++) {
       
   374                 s >> r;
       
   375                 rgn = rgn.united(QRegion(r));
       
   376             }
       
   377         }
       
   378     }
       
   379     *this = rgn;
       
   380 }
       
   381 
       
   382 
       
   383 /*****************************************************************************
       
   384   QRegion stream functions
       
   385  *****************************************************************************/
       
   386 
       
   387 /*!
       
   388     \fn QRegion &QRegion::operator=(const QRegion &r)
       
   389 
       
   390     Assigns \a r to this region and returns a reference to the region.
       
   391 */
       
   392 
       
   393 /*!
       
   394     \relates QRegion
       
   395 
       
   396     Writes the region \a r to the stream \a s and returns a reference
       
   397     to the stream.
       
   398 
       
   399     \sa \link datastreamformat.html Format of the QDataStream operators \endlink
       
   400 */
       
   401 
       
   402 QDataStream &operator<<(QDataStream &s, const QRegion &r)
       
   403 {
       
   404     QVector<QRect> a = r.rects();
       
   405     if (a.isEmpty()) {
       
   406         s << (quint32)0;
       
   407     } else {
       
   408         if (s.version() == 1) {
       
   409             int i;
       
   410             for (i = a.size() - 1; i > 0; --i) {
       
   411                 s << (quint32)(12 + i * 24);
       
   412                 s << (int)QRGN_OR;
       
   413             }
       
   414             for (i = 0; i < a.size(); ++i) {
       
   415                 s << (quint32)(4+8) << (int)QRGN_SETRECT << a[i];
       
   416             }
       
   417         } else {
       
   418             s << (quint32)(4 + 4 + 16 * a.size()); // 16: storage size of QRect
       
   419             s << (qint32)QRGN_RECTS;
       
   420             s << a;
       
   421         }
       
   422     }
       
   423     return s;
       
   424 }
       
   425 
       
   426 /*!
       
   427     \relates QRegion
       
   428 
       
   429     Reads a region from the stream \a s into \a r and returns a
       
   430     reference to the stream.
       
   431 
       
   432     \sa \link datastreamformat.html Format of the QDataStream operators \endlink
       
   433 */
       
   434 
       
   435 QDataStream &operator>>(QDataStream &s, QRegion &r)
       
   436 {
       
   437     QByteArray b;
       
   438     s >> b;
       
   439     r.exec(b, s.version(), s.byteOrder());
       
   440     return s;
       
   441 }
       
   442 #endif //QT_NO_DATASTREAM
       
   443 
       
   444 #ifndef QT_NO_DEBUG_STREAM
       
   445 QDebug operator<<(QDebug s, const QRegion &r)
       
   446 {
       
   447     QVector<QRect> rects = r.rects();
       
   448     s.nospace() << "QRegion(size=" << rects.size() << "), "
       
   449                 << "bounds = " << r.boundingRect() << '\n';
       
   450     for (int i=0; i<rects.size(); ++i)
       
   451         s << "- " << i << rects.at(i) << '\n';
       
   452     return s;
       
   453 }
       
   454 #endif
       
   455 
       
   456 
       
   457 // These are not inline - they can be implemented better on some platforms
       
   458 //  (eg. Windows at least provides 3-variable operations).  For now, simple.
       
   459 
       
   460 
       
   461 /*!
       
   462     Applies the united() function to this region and \a r. \c r1|r2 is
       
   463     equivalent to \c r1.united(r2).
       
   464 
       
   465     \sa united(), operator+()
       
   466 */
       
   467 const QRegion QRegion::operator|(const QRegion &r) const
       
   468     { return united(r); }
       
   469 
       
   470 /*!
       
   471     Applies the united() function to this region and \a r. \c r1+r2 is
       
   472     equivalent to \c r1.united(r2).
       
   473 
       
   474     \sa united(), operator|()
       
   475 */
       
   476 const QRegion QRegion::operator+(const QRegion &r) const
       
   477     { return united(r); }
       
   478 
       
   479 /*!
       
   480    \overload
       
   481    \since 4.4
       
   482  */
       
   483 const QRegion QRegion::operator+(const QRect &r) const
       
   484     { return united(r); }
       
   485 
       
   486 /*!
       
   487     Applies the intersected() function to this region and \a r. \c r1&r2
       
   488     is equivalent to \c r1.intersected(r2).
       
   489 
       
   490     \sa intersected()
       
   491 */
       
   492 const QRegion QRegion::operator&(const QRegion &r) const
       
   493     { return intersected(r); }
       
   494 
       
   495 /*!
       
   496    \overload
       
   497    \since 4.4
       
   498  */
       
   499 const QRegion QRegion::operator&(const QRect &r) const
       
   500 {
       
   501     return intersected(r);
       
   502 }
       
   503 
       
   504 /*!
       
   505     Applies the subtracted() function to this region and \a r. \c r1-r2
       
   506     is equivalent to \c r1.subtracted(r2).
       
   507 
       
   508     \sa subtracted()
       
   509 */
       
   510 const QRegion QRegion::operator-(const QRegion &r) const
       
   511     { return subtracted(r); }
       
   512 
       
   513 /*!
       
   514     Applies the xored() function to this region and \a r. \c r1^r2 is
       
   515     equivalent to \c r1.xored(r2).
       
   516 
       
   517     \sa xored()
       
   518 */
       
   519 const QRegion QRegion::operator^(const QRegion &r) const
       
   520     { return xored(r); }
       
   521 
       
   522 /*!
       
   523     Applies the united() function to this region and \a r and assigns
       
   524     the result to this region. \c r1|=r2 is equivalent to \c
       
   525     {r1 = r1.united(r2)}.
       
   526 
       
   527     \sa united()
       
   528 */
       
   529 QRegion& QRegion::operator|=(const QRegion &r)
       
   530     { return *this = *this | r; }
       
   531 
       
   532 /*!
       
   533     \fn QRegion& QRegion::operator+=(const QRect &rect)
       
   534 
       
   535     Returns a region that is the union of this region with the specified \a rect.
       
   536 
       
   537     \sa united()
       
   538 */
       
   539 /*!
       
   540     \fn QRegion& QRegion::operator+=(const QRegion &r)
       
   541 
       
   542     Applies the united() function to this region and \a r and assigns
       
   543     the result to this region. \c r1+=r2 is equivalent to \c
       
   544     {r1 = r1.united(r2)}.
       
   545 
       
   546     \sa intersected()
       
   547 */
       
   548 #if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN)
       
   549 QRegion& QRegion::operator+=(const QRect &r)
       
   550 {
       
   551     return operator+=(QRegion(r));
       
   552 }
       
   553 #endif
       
   554 
       
   555 /*!
       
   556   \fn QRegion& QRegion::operator&=(const QRegion &r)
       
   557 
       
   558   Applies the intersected() function to this region and \a r and
       
   559   assigns the result to this region. \c r1&=r2 is equivalent to \c
       
   560   r1 = r1.intersected(r2).
       
   561 
       
   562   \sa intersected()
       
   563 */
       
   564 QRegion& QRegion::operator&=(const QRegion &r)
       
   565     { return *this = *this & r; }
       
   566 
       
   567 /*!
       
   568    \overload
       
   569    \since 4.4
       
   570  */
       
   571 #if defined (Q_OS_UNIX) || defined (Q_WS_WIN)
       
   572 QRegion& QRegion::operator&=(const QRect &r)
       
   573 {
       
   574     return *this = *this & r;
       
   575 }
       
   576 #else
       
   577 QRegion& QRegion::operator&=(const QRect &r)
       
   578 {
       
   579     return *this &= (QRegion(r));
       
   580 }
       
   581 #endif
       
   582 
       
   583 /*!
       
   584   \fn QRegion& QRegion::operator-=(const QRegion &r)
       
   585 
       
   586   Applies the subtracted() function to this region and \a r and
       
   587   assigns the result to this region. \c r1-=r2 is equivalent to \c
       
   588   {r1 = r1.subtracted(r2)}.
       
   589 
       
   590   \sa subtracted()
       
   591 */
       
   592 QRegion& QRegion::operator-=(const QRegion &r)
       
   593     { return *this = *this - r; }
       
   594 
       
   595 /*!
       
   596     Applies the xored() function to this region and \a r and
       
   597     assigns the result to this region. \c r1^=r2 is equivalent to \c
       
   598     {r1 = r1.xored(r2)}.
       
   599 
       
   600     \sa xored()
       
   601 */
       
   602 QRegion& QRegion::operator^=(const QRegion &r)
       
   603     { return *this = *this ^ r; }
       
   604 
       
   605 /*!
       
   606     \fn bool QRegion::operator!=(const QRegion &other) const
       
   607 
       
   608     Returns true if this region is different from the \a other region;
       
   609     otherwise returns false.
       
   610 */
       
   611 
       
   612 /*!
       
   613    Returns the region as a QVariant
       
   614 */
       
   615 QRegion::operator QVariant() const
       
   616 {
       
   617     return QVariant(QVariant::Region, this);
       
   618 }
       
   619 
       
   620 /*!
       
   621     \fn bool QRegion::operator==(const QRegion &r) const
       
   622 
       
   623     Returns true if the region is equal to \a r; otherwise returns
       
   624     false.
       
   625 */
       
   626 
       
   627 /*!
       
   628     \fn bool QRegion::isNull() const
       
   629 
       
   630     Use isEmpty() instead.
       
   631 */
       
   632 
       
   633 
       
   634 /*!
       
   635     \fn void QRegion::translate(int dx, int dy)
       
   636 
       
   637     Translates (moves) the region \a dx along the X axis and \a dy
       
   638     along the Y axis.
       
   639 */
       
   640 
       
   641 /*!
       
   642     \fn QRegion QRegion::translated(const QPoint &p) const
       
   643     \overload
       
   644     \since 4.1
       
   645 
       
   646     Returns a copy of the regtion that is translated \a{p}\e{.x()}
       
   647     along the x axis and \a{p}\e{.y()} along the y axis, relative to
       
   648     the current position.  Positive values move the rectangle to the
       
   649     right and down.
       
   650 
       
   651     \sa translate()
       
   652 */
       
   653 
       
   654 /*!
       
   655     \since 4.1
       
   656 
       
   657     Returns a copy of the region that is translated \a dx along the
       
   658     x axis and \a dy along the y axis, relative to the current
       
   659     position. Positive values move the region to the right and
       
   660     down.
       
   661 
       
   662     \sa translate()
       
   663 */
       
   664 
       
   665 QRegion
       
   666 QRegion::translated(int dx, int dy) const
       
   667 {
       
   668     QRegion ret(*this);
       
   669     ret.translate(dx, dy);
       
   670     return ret;
       
   671 }
       
   672 
       
   673 
       
   674 inline bool rect_intersects(const QRect &r1, const QRect &r2)
       
   675 {
       
   676     return (r1.right() >= r2.left() && r1.left() <= r2.right() &&
       
   677             r1.bottom() >= r2.top() && r1.top() <= r2.bottom());
       
   678 }
       
   679 
       
   680 /*!
       
   681     \since 4.2
       
   682 
       
   683     Returns true if this region intersects with \a region, otherwise
       
   684     returns false.
       
   685 */
       
   686 bool QRegion::intersects(const QRegion &region) const
       
   687 {
       
   688     if (isEmpty() || region.isEmpty())
       
   689         return false;
       
   690 
       
   691     if (!rect_intersects(boundingRect(), region.boundingRect()))
       
   692         return false;
       
   693     if (numRects() == 1 && region.numRects() == 1)
       
   694         return true;
       
   695 
       
   696     const QVector<QRect> myRects = rects();
       
   697     const QVector<QRect> otherRects = region.rects();
       
   698 
       
   699     for (QVector<QRect>::const_iterator i1 = myRects.constBegin(); i1 < myRects.constEnd(); ++i1)
       
   700         for (QVector<QRect>::const_iterator i2 = otherRects.constBegin(); i2 < otherRects.constEnd(); ++i2)
       
   701             if (rect_intersects(*i1, *i2))
       
   702                 return true;
       
   703     return false;
       
   704 }
       
   705 
       
   706 /*!
       
   707     \since 4.2
       
   708 
       
   709     Returns true if this region intersects with \a rect, otherwise
       
   710     returns false.
       
   711 */
       
   712 bool QRegion::intersects(const QRect &rect) const
       
   713 {
       
   714     if (isEmpty() || rect.isNull())
       
   715         return false;
       
   716 
       
   717     const QRect r = rect.normalized();
       
   718     if (!rect_intersects(boundingRect(), r))
       
   719         return false;
       
   720     if (numRects() == 1)
       
   721         return true;
       
   722 
       
   723     const QVector<QRect> myRects = rects();
       
   724     for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it)
       
   725         if (rect_intersects(r, *it))
       
   726             return true;
       
   727     return false;
       
   728 }
       
   729 
       
   730 #if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN)
       
   731 /*!
       
   732     \overload
       
   733     \since 4.4
       
   734 */
       
   735 QRegion QRegion::intersect(const QRect &r) const
       
   736 {
       
   737     return intersect(QRegion(r));
       
   738 }
       
   739 #endif
       
   740 
       
   741 /*!
       
   742     \fn int QRegion::numRects() const
       
   743     \since 4.4
       
   744 
       
   745     Returns the number of rectangles that will be returned in rects().
       
   746 */
       
   747 
       
   748 /*!
       
   749     \fn bool QRegion::isEmpty() const
       
   750 
       
   751     Returns true if the region is empty; otherwise returns false. An
       
   752     empty region is a region that contains no points.
       
   753 
       
   754     Example:
       
   755     \snippet doc/src/snippets/code/src_gui_painting_qregion_unix.cpp 0
       
   756 */
       
   757 
       
   758 /*!
       
   759     \fn bool QRegion::contains(const QPoint &p) const
       
   760 
       
   761     Returns true if the region contains the point \a p; otherwise
       
   762     returns false.
       
   763 */
       
   764 
       
   765 /*!
       
   766     \fn bool QRegion::contains(const QRect &r) const
       
   767     \overload
       
   768 
       
   769     Returns true if the region overlaps the rectangle \a r; otherwise
       
   770     returns false.
       
   771 */
       
   772 
       
   773 /*!
       
   774     \fn QRegion QRegion::unite(const QRegion &r) const
       
   775     \obsolete
       
   776 
       
   777     Use united(\a r) instead.
       
   778 */
       
   779 
       
   780 /*!
       
   781     \fn QRegion QRegion::unite(const QRect &rect) const
       
   782     \since 4.4
       
   783     \obsolete
       
   784 
       
   785     Use united(\a rect) instead.
       
   786 */
       
   787 
       
   788 /*!
       
   789     \fn QRegion QRegion::united(const QRect &rect) const
       
   790     \since 4.4
       
   791 
       
   792     Returns a region which is the union of this region and the given \a rect.
       
   793 
       
   794     \sa intersected(), subtracted(), xored()
       
   795 */
       
   796 
       
   797 /*!
       
   798     \fn QRegion QRegion::united(const QRegion &r) const
       
   799     \since 4.2
       
   800 
       
   801     Returns a region which is the union of this region and \a r.
       
   802 
       
   803     \img runion.png Region Union
       
   804 
       
   805     The figure shows the union of two elliptical regions.
       
   806 
       
   807     \sa intersected(), subtracted(), xored()
       
   808 */
       
   809 
       
   810 /*!
       
   811     \fn QRegion QRegion::intersect(const QRegion &r) const
       
   812     \obsolete
       
   813 
       
   814     Use intersected(\a r) instead.
       
   815 */
       
   816 
       
   817 /*!
       
   818     \fn QRegion QRegion::intersect(const QRect &rect) const
       
   819     \since 4.4
       
   820     \obsolete
       
   821 
       
   822     Use intersected(\a rect) instead.
       
   823 */
       
   824 
       
   825 /*!
       
   826     \fn QRegion QRegion::intersected(const QRect &rect) const
       
   827     \since 4.4
       
   828 
       
   829     Returns a region which is the intersection of this region and the given \a rect.
       
   830 
       
   831     \sa subtracted(), united(), xored()
       
   832 */
       
   833 
       
   834 /*!
       
   835     \fn QRegion QRegion::intersected(const QRegion &r) const
       
   836     \since 4.2
       
   837 
       
   838     Returns a region which is the intersection of this region and \a r.
       
   839 
       
   840     \img rintersect.png Region Intersection
       
   841 
       
   842     The figure shows the intersection of two elliptical regions.
       
   843 
       
   844     \sa subtracted(), united(), xored()
       
   845 */
       
   846 
       
   847 /*!
       
   848     \fn QRegion QRegion::subtract(const QRegion &r) const
       
   849     \obsolete
       
   850 
       
   851     Use subtracted(\a r) instead.
       
   852 */
       
   853 
       
   854 /*!
       
   855     \fn QRegion QRegion::subtracted(const QRegion &r) const
       
   856     \since 4.2
       
   857 
       
   858     Returns a region which is \a r subtracted from this region.
       
   859 
       
   860     \img rsubtract.png Region Subtraction
       
   861 
       
   862     The figure shows the result when the ellipse on the right is
       
   863     subtracted from the ellipse on the left (\c {left - right}).
       
   864 
       
   865     \sa intersected(), united(), xored()
       
   866 */
       
   867 
       
   868 /*!
       
   869     \fn QRegion QRegion::eor(const QRegion &r) const
       
   870     \obsolete
       
   871 
       
   872     Use xored(\a r) instead.
       
   873 */
       
   874 
       
   875 /*!
       
   876     \fn QRegion QRegion::xored(const QRegion &r) const
       
   877     \since 4.2
       
   878 
       
   879     Returns a region which is the exclusive or (XOR) of this region
       
   880     and \a r.
       
   881 
       
   882     \img rxor.png Region XORed
       
   883 
       
   884     The figure shows the exclusive or of two elliptical regions.
       
   885 
       
   886     \sa intersected(), united(), subtracted()
       
   887 */
       
   888 
       
   889 /*!
       
   890     \fn QRect QRegion::boundingRect() const
       
   891 
       
   892     Returns the bounding rectangle of this region. An empty region
       
   893     gives a rectangle that is QRect::isNull().
       
   894 */
       
   895 
       
   896 /*!
       
   897     \fn QVector<QRect> QRegion::rects() const
       
   898 
       
   899     Returns an array of non-overlapping rectangles that make up the
       
   900     region.
       
   901 
       
   902     The union of all the rectangles is equal to the original region.
       
   903 */
       
   904 
       
   905 /*!
       
   906     \fn void QRegion::setRects(const QRect *rects, int number)
       
   907 
       
   908     Sets the region using the array of rectangles specified by \a rects and
       
   909     \a number.
       
   910     The rectangles \e must be optimally Y-X sorted and follow these restrictions:
       
   911 
       
   912     \list
       
   913     \o The rectangles must not intersect.
       
   914     \o All rectangles with a given top coordinate must have the same height.
       
   915     \o No two rectangles may abut horizontally (they should be combined
       
   916        into a single wider rectangle in that case).
       
   917     \o The rectangles must be sorted in ascending order, with Y as the major
       
   918        sort key and X as the minor sort key.
       
   919     \endlist
       
   920     \omit
       
   921     Only some platforms have these restrictions (Qt for Embedded Linux, X11 and Mac OS X).
       
   922     \endomit
       
   923 */
       
   924 
       
   925 namespace {
       
   926 
       
   927 struct Segment
       
   928 {
       
   929     Segment() {}
       
   930     Segment(const QPoint &p)
       
   931         : added(false)
       
   932         , point(p)
       
   933     {
       
   934     }
       
   935 
       
   936     int left() const
       
   937     {
       
   938         return qMin(point.x(), next->point.x());
       
   939     }
       
   940 
       
   941     int right() const
       
   942     {
       
   943         return qMax(point.x(), next->point.x());
       
   944     }
       
   945 
       
   946     bool overlaps(const Segment &other) const
       
   947     {
       
   948         return left() < other.right() && other.left() < right();
       
   949     }
       
   950 
       
   951     void connect(Segment &other)
       
   952     {
       
   953         next = &other;
       
   954         other.prev = this;
       
   955 
       
   956         horizontal = (point.y() == other.point.y());
       
   957     }
       
   958 
       
   959     void merge(Segment &other)
       
   960     {
       
   961         if (right() <= other.right()) {
       
   962             QPoint p = other.point;
       
   963             Segment *oprev = other.prev;
       
   964 
       
   965             other.point = point;
       
   966             other.prev = prev;
       
   967             prev->next = &other;
       
   968 
       
   969             point = p;
       
   970             prev = oprev;
       
   971             oprev->next = this;
       
   972         } else {
       
   973             Segment *onext = other.next;
       
   974             other.next = next;
       
   975             next->prev = &other;
       
   976 
       
   977             next = onext;
       
   978             next->prev = this;
       
   979         }
       
   980     }
       
   981 
       
   982     int horizontal : 1;
       
   983     int added : 1;
       
   984 
       
   985     QPoint point;
       
   986     Segment *prev;
       
   987     Segment *next;
       
   988 };
       
   989 
       
   990 void mergeSegments(Segment *a, int na, Segment *b, int nb)
       
   991 {
       
   992     int i = 0;
       
   993     int j = 0;
       
   994 
       
   995     while (i != na && j != nb) {
       
   996         Segment &sa = a[i];
       
   997         Segment &sb = b[j];
       
   998         const int ra = sa.right();
       
   999         const int rb = sb.right();
       
  1000         if (sa.overlaps(sb))
       
  1001             sa.merge(sb);
       
  1002         i += (rb >= ra);
       
  1003         j += (ra >= rb);
       
  1004     }
       
  1005 }
       
  1006 
       
  1007 void addSegmentsToPath(Segment *segment, QPainterPath &path)
       
  1008 {
       
  1009     Segment *current = segment;
       
  1010     path.moveTo(current->point);
       
  1011 
       
  1012     current->added = true;
       
  1013 
       
  1014     Segment *last = current;
       
  1015     current = current->next;
       
  1016     while (current != segment) {
       
  1017         if (current->horizontal != last->horizontal)
       
  1018             path.lineTo(current->point);
       
  1019         current->added = true;
       
  1020         last = current;
       
  1021         current = current->next;
       
  1022     }
       
  1023 }
       
  1024 
       
  1025 }
       
  1026 
       
  1027 Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion &region)
       
  1028 {
       
  1029     QPainterPath result;
       
  1030     if (region.numRects() == 1) {
       
  1031         result.addRect(region.boundingRect());
       
  1032         return result;
       
  1033     }
       
  1034 
       
  1035     const QVector<QRect> rects = region.rects();
       
  1036 
       
  1037     QVarLengthArray<Segment> segments;
       
  1038     segments.resize(4 * rects.size());
       
  1039 
       
  1040     const QRect *rect = rects.constData();
       
  1041     const QRect *end = rect + rects.size();
       
  1042 
       
  1043     int lastRowSegmentCount = 0;
       
  1044     Segment *lastRowSegments = 0;
       
  1045 
       
  1046     int lastSegment = 0;
       
  1047     int lastY = 0;
       
  1048     while (rect != end) {
       
  1049         const int y = rect[0].y();
       
  1050         int count = 0;
       
  1051         while (&rect[count] != end && rect[count].y() == y)
       
  1052             ++count;
       
  1053 
       
  1054         for (int i = 0; i < count; ++i) {
       
  1055             int offset = lastSegment + i;
       
  1056             segments[offset] = Segment(rect[i].topLeft());
       
  1057             segments[offset += count] = Segment(rect[i].topRight() + QPoint(1, 0));
       
  1058             segments[offset += count] = Segment(rect[i].bottomRight() + QPoint(1, 1));
       
  1059             segments[offset += count] = Segment(rect[i].bottomLeft() + QPoint(0, 1));
       
  1060 
       
  1061             offset = lastSegment + i;
       
  1062             for (int j = 0; j < 4; ++j)
       
  1063                 segments[offset + j * count].connect(segments[offset + ((j + 1) % 4) * count]);
       
  1064         }
       
  1065 
       
  1066         if (lastRowSegments && lastY == y)
       
  1067             mergeSegments(lastRowSegments, lastRowSegmentCount, &segments[lastSegment], count);
       
  1068 
       
  1069         lastRowSegments = &segments[lastSegment + 2 * count];
       
  1070         lastRowSegmentCount = count;
       
  1071         lastSegment += 4 * count;
       
  1072         lastY = y + rect[0].height();
       
  1073         rect += count;
       
  1074     }
       
  1075 
       
  1076     for (int i = 0; i < lastSegment; ++i) {
       
  1077         Segment *segment = &segments[i];
       
  1078         if (!segment->added)
       
  1079             addSegmentsToPath(segment, result);
       
  1080     }
       
  1081 
       
  1082     return result;
       
  1083 }
       
  1084 
       
  1085 #if defined(Q_OS_UNIX) || defined(Q_WS_WIN)
       
  1086 
       
  1087 //#define QT_REGION_DEBUG
       
  1088 /*
       
  1089  *   clip region
       
  1090  */
       
  1091 
       
  1092 struct QRegionPrivate {
       
  1093     int numRects;
       
  1094     QVector<QRect> rects;
       
  1095     QRect extents;
       
  1096     QRect innerRect;
       
  1097     int innerArea;
       
  1098 
       
  1099     inline QRegionPrivate() : numRects(0), innerArea(-1) {}
       
  1100     inline QRegionPrivate(const QRect &r) {
       
  1101         numRects = 1;
       
  1102         extents = r;
       
  1103         innerRect = r;
       
  1104         innerArea = r.width() * r.height();
       
  1105     }
       
  1106 
       
  1107     inline QRegionPrivate(const QRegionPrivate &r) {
       
  1108         rects = r.rects;
       
  1109         numRects = r.numRects;
       
  1110         extents = r.extents;
       
  1111         innerRect = r.innerRect;
       
  1112         innerArea = r.innerArea;
       
  1113     }
       
  1114 
       
  1115     inline QRegionPrivate &operator=(const QRegionPrivate &r) {
       
  1116         rects = r.rects;
       
  1117         numRects = r.numRects;
       
  1118         extents = r.extents;
       
  1119         innerRect = r.innerRect;
       
  1120         innerArea = r.innerArea;
       
  1121         return *this;
       
  1122     }
       
  1123 
       
  1124     void intersect(const QRect &r);
       
  1125 
       
  1126     /*
       
  1127      * Returns true if r is guaranteed to be fully contained in this region.
       
  1128      * A false return value does not guarantee the opposite.
       
  1129      */
       
  1130     inline bool contains(const QRegionPrivate &r) const {
       
  1131         return contains(r.extents);
       
  1132     }
       
  1133 
       
  1134     inline bool contains(const QRect &r2) const {
       
  1135         const QRect &r1 = innerRect;
       
  1136         return r2.left() >= r1.left() && r2.right() <= r1.right()
       
  1137             && r2.top() >= r1.top() && r2.bottom() <= r1.bottom();
       
  1138     }
       
  1139 
       
  1140     /*
       
  1141      * Returns true if this region is guaranteed to be fully contained in r.
       
  1142      */
       
  1143     inline bool within(const QRect &r1) const {
       
  1144         const QRect &r2 = extents;
       
  1145         return r2.left() >= r1.left() && r2.right() <= r1.right()
       
  1146             && r2.top() >= r1.top() && r2.bottom() <= r1.bottom();
       
  1147     }
       
  1148 
       
  1149     inline void updateInnerRect(const QRect &rect) {
       
  1150         const int area = rect.width() * rect.height();
       
  1151         if (area > innerArea) {
       
  1152             innerArea = area;
       
  1153             innerRect = rect;
       
  1154         }
       
  1155     }
       
  1156 
       
  1157     inline void vectorize() {
       
  1158         if (numRects == 1) {
       
  1159             if (!rects.size())
       
  1160                 rects.resize(1);
       
  1161             rects[0] = extents;
       
  1162         }
       
  1163     }
       
  1164 
       
  1165     inline void append(const QRect *r);
       
  1166     void append(const QRegionPrivate *r);
       
  1167     void prepend(const QRect *r);
       
  1168     void prepend(const QRegionPrivate *r);
       
  1169     inline bool canAppend(const QRect *r) const;
       
  1170     inline bool canAppend(const QRegionPrivate *r) const;
       
  1171     inline bool canPrepend(const QRect *r) const;
       
  1172     inline bool canPrepend(const QRegionPrivate *r) const;
       
  1173 
       
  1174     inline bool mergeFromRight(QRect *left, const QRect *right);
       
  1175     inline bool mergeFromLeft(QRect *left, const QRect *right);
       
  1176     inline bool mergeFromBelow(QRect *top, const QRect *bottom,
       
  1177                                const QRect *nextToTop,
       
  1178                                const QRect *nextToBottom);
       
  1179     inline bool mergeFromAbove(QRect *bottom, const QRect *top,
       
  1180                                const QRect *nextToBottom,
       
  1181                                const QRect *nextToTop);
       
  1182 
       
  1183 #ifdef QT_REGION_DEBUG
       
  1184     void selfTest() const;
       
  1185 #endif
       
  1186 };
       
  1187 
       
  1188 static inline bool isEmptyHelper(const QRegionPrivate *preg)
       
  1189 {
       
  1190     return !preg || preg->numRects == 0;
       
  1191 }
       
  1192 
       
  1193 static inline bool canMergeFromRight(const QRect *left, const QRect *right)
       
  1194 {
       
  1195     return (right->top() == left->top()
       
  1196             && right->bottom() == left->bottom()
       
  1197             && right->left() <= (left->right() + 1));
       
  1198 }
       
  1199 
       
  1200 static inline bool canMergeFromLeft(const QRect *right, const QRect *left)
       
  1201 {
       
  1202     return canMergeFromRight(left, right);
       
  1203 }
       
  1204 
       
  1205 bool QRegionPrivate::mergeFromRight(QRect *left, const QRect *right)
       
  1206 {
       
  1207     if (canMergeFromRight(left, right)) {
       
  1208         left->setRight(right->right());
       
  1209         updateInnerRect(*left);
       
  1210         return true;
       
  1211     }
       
  1212     return false;
       
  1213 }
       
  1214 
       
  1215 bool QRegionPrivate::mergeFromLeft(QRect *right, const QRect *left)
       
  1216 {
       
  1217     if (canMergeFromLeft(right, left)) {
       
  1218         right->setLeft(left->left());
       
  1219         updateInnerRect(*right);
       
  1220         return true;
       
  1221     }
       
  1222     return false;
       
  1223 }
       
  1224 
       
  1225 static inline bool canMergeFromBelow(const QRect *top, const QRect *bottom,
       
  1226                                      const QRect *nextToTop,
       
  1227                                      const QRect *nextToBottom)
       
  1228 {
       
  1229     if (nextToTop && nextToTop->y() == top->y())
       
  1230         return false;
       
  1231     if (nextToBottom && nextToBottom->y() == bottom->y())
       
  1232         return false;
       
  1233 
       
  1234     return ((top->bottom() >= (bottom->top() - 1))
       
  1235             && top->left() == bottom->left()
       
  1236             && top->right() == bottom->right());
       
  1237 }
       
  1238 
       
  1239 bool QRegionPrivate::mergeFromBelow(QRect *top, const QRect *bottom,
       
  1240                                     const QRect *nextToTop,
       
  1241                                     const QRect *nextToBottom)
       
  1242 {
       
  1243     if (canMergeFromBelow(top, bottom, nextToTop, nextToBottom)) {
       
  1244         top->setBottom(bottom->bottom());
       
  1245         updateInnerRect(*top);
       
  1246         return true;
       
  1247     }
       
  1248     return false;
       
  1249 }
       
  1250 
       
  1251 bool QRegionPrivate::mergeFromAbove(QRect *bottom, const QRect *top,
       
  1252                                     const QRect *nextToBottom,
       
  1253                                     const QRect *nextToTop)
       
  1254 {
       
  1255     if (canMergeFromBelow(top, bottom, nextToTop, nextToBottom)) {
       
  1256         bottom->setTop(top->top());
       
  1257         updateInnerRect(*bottom);
       
  1258         return true;
       
  1259     }
       
  1260     return false;
       
  1261 }
       
  1262 
       
  1263 static inline QRect qt_rect_intersect_normalized(const QRect &r1,
       
  1264                                                  const QRect &r2)
       
  1265 {
       
  1266     QRect r;
       
  1267     r.setLeft(qMax(r1.left(), r2.left()));
       
  1268     r.setRight(qMin(r1.right(), r2.right()));
       
  1269     r.setTop(qMax(r1.top(), r2.top()));
       
  1270     r.setBottom(qMin(r1.bottom(), r2.bottom()));
       
  1271     return r;
       
  1272 }
       
  1273 
       
  1274 void QRegionPrivate::intersect(const QRect &rect)
       
  1275 {
       
  1276     Q_ASSERT(extents.intersects(rect));
       
  1277     Q_ASSERT(numRects > 1);
       
  1278 
       
  1279 #ifdef QT_REGION_DEBUG
       
  1280     selfTest();
       
  1281 #endif
       
  1282 
       
  1283     const QRect r = rect.normalized();
       
  1284     extents = QRect();
       
  1285     innerRect = QRect();
       
  1286     innerArea = -1;
       
  1287 
       
  1288     QRect *dest = rects.data();
       
  1289     const QRect *src = dest;
       
  1290     int n = numRects;
       
  1291     numRects = 0;
       
  1292     while (n--) {
       
  1293         *dest = qt_rect_intersect_normalized(*src++, r);
       
  1294         if (dest->isEmpty())
       
  1295             continue;
       
  1296 
       
  1297         if (numRects == 0) {
       
  1298             extents = *dest;
       
  1299         } else {
       
  1300             extents.setLeft(qMin(extents.left(), dest->left()));
       
  1301             // hw: extents.top() will never change after initialization
       
  1302             //extents.setTop(qMin(extents.top(), dest->top()));
       
  1303             extents.setRight(qMax(extents.right(), dest->right()));
       
  1304             extents.setBottom(qMax(extents.bottom(), dest->bottom()));
       
  1305 
       
  1306             const QRect *nextToLast = (numRects > 1 ? dest - 2 : 0);
       
  1307 
       
  1308             // mergeFromBelow inlined and optimized
       
  1309             if (canMergeFromBelow(dest - 1, dest, nextToLast, 0)) {
       
  1310                 if (!n || src->y() != dest->y() || src->left() > r.right()) {
       
  1311                     QRect *prev = dest - 1;
       
  1312                     prev->setBottom(dest->bottom());
       
  1313                     updateInnerRect(*prev);
       
  1314                     continue;
       
  1315                 }
       
  1316             }
       
  1317         }
       
  1318         updateInnerRect(*dest);
       
  1319         ++dest;
       
  1320         ++numRects;
       
  1321     }
       
  1322 #ifdef QT_REGION_DEBUG
       
  1323     selfTest();
       
  1324 #endif
       
  1325 }
       
  1326 
       
  1327 void QRegionPrivate::append(const QRect *r)
       
  1328 {
       
  1329     Q_ASSERT(!r->isEmpty());
       
  1330 
       
  1331     QRect *myLast = (numRects == 1 ? &extents : rects.data() + (numRects - 1));
       
  1332     if (mergeFromRight(myLast, r)) {
       
  1333         if (numRects > 1) {
       
  1334             const QRect *nextToTop = (numRects > 2 ? myLast - 2 : 0);
       
  1335             if (mergeFromBelow(myLast - 1, myLast, nextToTop, 0))
       
  1336                 --numRects;
       
  1337         }
       
  1338     } else if (mergeFromBelow(myLast, r, (numRects > 1 ? myLast - 1 : 0), 0)) {
       
  1339         // nothing
       
  1340     } else {
       
  1341         vectorize();
       
  1342         ++numRects;
       
  1343         updateInnerRect(*r);
       
  1344         if (rects.size() < numRects)
       
  1345             rects.resize(numRects);
       
  1346         rects[numRects - 1] = *r;
       
  1347     }
       
  1348     extents.setCoords(qMin(extents.left(), r->left()),
       
  1349                       qMin(extents.top(), r->top()),
       
  1350                       qMax(extents.right(), r->right()),
       
  1351                       qMax(extents.bottom(), r->bottom()));
       
  1352 
       
  1353 #ifdef QT_REGION_DEBUG
       
  1354     selfTest();
       
  1355 #endif
       
  1356 }
       
  1357 
       
  1358 void QRegionPrivate::append(const QRegionPrivate *r)
       
  1359 {
       
  1360     Q_ASSERT(!isEmptyHelper(r));
       
  1361 
       
  1362     if (r->numRects == 1) {
       
  1363         append(&r->extents);
       
  1364         return;
       
  1365     }
       
  1366 
       
  1367     vectorize();
       
  1368 
       
  1369     QRect *destRect = rects.data() + numRects;
       
  1370     const QRect *srcRect = r->rects.constData();
       
  1371     int numAppend = r->numRects;
       
  1372 
       
  1373     // try merging
       
  1374     {
       
  1375         const QRect *rFirst = srcRect;
       
  1376         QRect *myLast = destRect - 1;
       
  1377         const QRect *nextToLast = (numRects > 1 ? myLast - 1 : 0);
       
  1378         if (mergeFromRight(myLast, rFirst)) {
       
  1379             ++srcRect;
       
  1380             --numAppend;
       
  1381             const QRect *rNextToFirst = (numAppend > 1 ? rFirst + 2 : 0);
       
  1382             if (mergeFromBelow(myLast, rFirst + 1, nextToLast, rNextToFirst)) {
       
  1383                 ++srcRect;
       
  1384                 --numAppend;
       
  1385             }
       
  1386             if (numRects  > 1) {
       
  1387                 nextToLast = (numRects > 2 ? myLast - 2 : 0);
       
  1388                 rNextToFirst = (numAppend > 0 ? srcRect : 0);
       
  1389                 if (mergeFromBelow(myLast - 1, myLast, nextToLast, rNextToFirst)) {
       
  1390                     --destRect;
       
  1391                     --numRects;
       
  1392                 }
       
  1393             }
       
  1394         } else if (mergeFromBelow(myLast, rFirst, nextToLast, rFirst + 1)) {
       
  1395             ++srcRect;
       
  1396             --numAppend;
       
  1397         }
       
  1398     }
       
  1399 
       
  1400     // append rectangles
       
  1401     if (numAppend > 0) {
       
  1402         const int newNumRects = numRects + numAppend;
       
  1403         if (newNumRects > rects.size()) {
       
  1404             rects.resize(newNumRects);
       
  1405             destRect = rects.data() + numRects;
       
  1406         }
       
  1407         memcpy(destRect, srcRect, numAppend * sizeof(QRect));
       
  1408 
       
  1409         numRects = newNumRects;
       
  1410     }
       
  1411 
       
  1412     // update inner rectangle
       
  1413     if (innerArea < r->innerArea) {
       
  1414         innerArea = r->innerArea;
       
  1415         innerRect = r->innerRect;
       
  1416     }
       
  1417 
       
  1418     // update extents
       
  1419     destRect = &extents;
       
  1420     srcRect = &r->extents;
       
  1421     extents.setCoords(qMin(destRect->left(), srcRect->left()),
       
  1422                       qMin(destRect->top(), srcRect->top()),
       
  1423                       qMax(destRect->right(), srcRect->right()),
       
  1424                       qMax(destRect->bottom(), srcRect->bottom()));
       
  1425 
       
  1426 #ifdef QT_REGION_DEBUG
       
  1427     selfTest();
       
  1428 #endif
       
  1429 }
       
  1430 
       
  1431 void QRegionPrivate::prepend(const QRegionPrivate *r)
       
  1432 {
       
  1433     Q_ASSERT(!isEmptyHelper(r));
       
  1434 
       
  1435     if (r->numRects == 1) {
       
  1436         prepend(&r->extents);
       
  1437         return;
       
  1438     }
       
  1439 
       
  1440     vectorize();
       
  1441 
       
  1442     int numPrepend = r->numRects;
       
  1443     int numSkip = 0;
       
  1444 
       
  1445     // try merging
       
  1446     {
       
  1447         QRect *myFirst = rects.data();
       
  1448         const QRect *nextToFirst = (numRects > 1 ? myFirst + 1 : 0);
       
  1449         const QRect *rLast = r->rects.constData() + r->numRects - 1;
       
  1450         const QRect *rNextToLast = (r->numRects > 1 ? rLast - 1 : 0);
       
  1451         if (mergeFromLeft(myFirst, rLast)) {
       
  1452             --numPrepend;
       
  1453             --rLast;
       
  1454             rNextToLast = (numPrepend > 1 ? rLast - 1 : 0);
       
  1455             if (mergeFromAbove(myFirst, rLast, nextToFirst, rNextToLast)) {
       
  1456                 --numPrepend;
       
  1457                 --rLast;
       
  1458             }
       
  1459             if (numRects  > 1) {
       
  1460                 nextToFirst = (numRects > 2? myFirst + 2 : 0);
       
  1461                 rNextToLast = (numPrepend > 0 ? rLast : 0);
       
  1462                 if (mergeFromAbove(myFirst + 1, myFirst, nextToFirst, rNextToLast)) {
       
  1463                     --numRects;
       
  1464                     ++numSkip;
       
  1465                 }
       
  1466             }
       
  1467         } else if (mergeFromAbove(myFirst, rLast, nextToFirst, rNextToLast)) {
       
  1468             --numPrepend;
       
  1469         }
       
  1470     }
       
  1471 
       
  1472     if (numPrepend > 0) {
       
  1473         const int newNumRects = numRects + numPrepend;
       
  1474         if (newNumRects > rects.size())
       
  1475             rects.resize(newNumRects);
       
  1476 
       
  1477         // move existing rectangles
       
  1478         memmove(rects.data() + numPrepend, rects.constData() + numSkip,
       
  1479                 numRects * sizeof(QRect));
       
  1480 
       
  1481         // prepend new rectangles
       
  1482         memcpy(rects.data(), r->rects.constData(), numPrepend * sizeof(QRect));
       
  1483 
       
  1484         numRects = newNumRects;
       
  1485     }
       
  1486 
       
  1487     // update inner rectangle
       
  1488     if (innerArea < r->innerArea) {
       
  1489         innerArea = r->innerArea;
       
  1490         innerRect = r->innerRect;
       
  1491     }
       
  1492 
       
  1493     // update extents
       
  1494     extents.setCoords(qMin(extents.left(), r->extents.left()),
       
  1495                       qMin(extents.top(), r->extents.top()),
       
  1496                       qMax(extents.right(), r->extents.right()),
       
  1497                       qMax(extents.bottom(), r->extents.bottom()));
       
  1498 
       
  1499 #ifdef QT_REGION_DEBUG
       
  1500     selfTest();
       
  1501 #endif
       
  1502 }
       
  1503 
       
  1504 void QRegionPrivate::prepend(const QRect *r)
       
  1505 {
       
  1506     Q_ASSERT(!r->isEmpty());
       
  1507 
       
  1508     QRect *myFirst = (numRects == 1 ? &extents : rects.data());
       
  1509     if (mergeFromLeft(myFirst, r)) {
       
  1510         if (numRects > 1) {
       
  1511             const QRect *nextToFirst = (numRects > 2 ? myFirst + 2 : 0);
       
  1512             if (mergeFromAbove(myFirst + 1, myFirst, nextToFirst, 0)) {
       
  1513                 --numRects;
       
  1514                 memmove(rects.data(), rects.constData() + 1,
       
  1515                         numRects * sizeof(QRect));
       
  1516             }
       
  1517         }
       
  1518     } else if (mergeFromAbove(myFirst, r, (numRects > 1 ? myFirst + 1 : 0), 0)) {
       
  1519         // nothing
       
  1520     } else {
       
  1521         vectorize();
       
  1522         ++numRects;
       
  1523         updateInnerRect(*r);
       
  1524         rects.prepend(*r);
       
  1525     }
       
  1526     extents.setCoords(qMin(extents.left(), r->left()),
       
  1527                       qMin(extents.top(), r->top()),
       
  1528                       qMax(extents.right(), r->right()),
       
  1529                       qMax(extents.bottom(), r->bottom()));
       
  1530 
       
  1531 #ifdef QT_REGION_DEBUG
       
  1532     selfTest();
       
  1533 #endif
       
  1534 }
       
  1535 
       
  1536 bool QRegionPrivate::canAppend(const QRect *r) const
       
  1537 {
       
  1538     Q_ASSERT(!r->isEmpty());
       
  1539 
       
  1540     const QRect *myLast = (numRects == 1) ? &extents : (rects.constData() + (numRects - 1));
       
  1541     if (r->top() > myLast->bottom())
       
  1542         return true;
       
  1543     if (r->top() == myLast->top()
       
  1544         && r->height() == myLast->height()
       
  1545         && r->left() > myLast->right())
       
  1546     {
       
  1547         return true;
       
  1548     }
       
  1549 
       
  1550     return false;
       
  1551 }
       
  1552 
       
  1553 bool QRegionPrivate::canAppend(const QRegionPrivate *r) const
       
  1554 {
       
  1555     return canAppend(r->numRects == 1 ? &r->extents : r->rects.constData());
       
  1556 }
       
  1557 
       
  1558 bool QRegionPrivate::canPrepend(const QRect *r) const
       
  1559 {
       
  1560     Q_ASSERT(!r->isEmpty());
       
  1561 
       
  1562     const QRect *myFirst = (numRects == 1) ? &extents : rects.constData();
       
  1563     if (r->bottom() < myFirst->top()) // not overlapping
       
  1564         return true;
       
  1565     if (r->top() == myFirst->top()
       
  1566         && r->height() == myFirst->height()
       
  1567         && r->right() < myFirst->left())
       
  1568     {
       
  1569         return true;
       
  1570     }
       
  1571 
       
  1572     return false;
       
  1573 }
       
  1574 
       
  1575 bool QRegionPrivate::canPrepend(const QRegionPrivate *r) const
       
  1576 {
       
  1577     return canPrepend(r->numRects == 1 ? &r->extents : r->rects.constData() + r->numRects - 1);
       
  1578 }
       
  1579 
       
  1580 #ifdef QT_REGION_DEBUG
       
  1581 void QRegionPrivate::selfTest() const
       
  1582 {
       
  1583     if (numRects == 0) {
       
  1584         Q_ASSERT(extents.isEmpty());
       
  1585         Q_ASSERT(innerRect.isEmpty());
       
  1586         return;
       
  1587     }
       
  1588 
       
  1589     Q_ASSERT(innerArea == (innerRect.width() * innerRect.height()));
       
  1590 
       
  1591     if (numRects == 1) {
       
  1592         Q_ASSERT(innerRect == extents);
       
  1593         Q_ASSERT(!innerRect.isEmpty());
       
  1594         return;
       
  1595     }
       
  1596 
       
  1597     for (int i = 0; i < numRects; ++i) {
       
  1598         const QRect r = rects.at(i);
       
  1599         if ((r.width() * r.height()) > innerArea)
       
  1600             qDebug() << "selfTest(): innerRect" << innerRect << '<' << r;
       
  1601     }
       
  1602 
       
  1603     QRect r = rects.first();
       
  1604     for (int i = 1; i < numRects; ++i) {
       
  1605         const QRect r2 = rects.at(i);
       
  1606         Q_ASSERT(!r2.isEmpty());
       
  1607         if (r2.y() == r.y()) {
       
  1608             Q_ASSERT(r.bottom() == r2.bottom());
       
  1609             Q_ASSERT(r.right() < (r2.left() + 1));
       
  1610         } else {
       
  1611             Q_ASSERT(r2.y() >= r.bottom());
       
  1612         }
       
  1613         r = r2;
       
  1614     }
       
  1615 }
       
  1616 #endif // QT_REGION_DEBUG
       
  1617 
       
  1618 #if defined(Q_WS_X11)
       
  1619 QT_BEGIN_INCLUDE_NAMESPACE
       
  1620 # include "qregion_x11.cpp"
       
  1621 QT_END_INCLUDE_NAMESPACE
       
  1622 #elif defined(Q_WS_MAC)
       
  1623 QT_BEGIN_INCLUDE_NAMESPACE
       
  1624 # include "qregion_mac.cpp"
       
  1625 QT_END_INCLUDE_NAMESPACE
       
  1626 #elif defined(Q_WS_WIN)
       
  1627 QT_BEGIN_INCLUDE_NAMESPACE
       
  1628 # include "qregion_win.cpp"
       
  1629 QT_END_INCLUDE_NAMESPACE
       
  1630 #elif defined(Q_WS_QWS)
       
  1631 static QRegionPrivate qrp;
       
  1632 QRegion::QRegionData QRegion::shared_empty = {Q_BASIC_ATOMIC_INITIALIZER(1), &qrp};
       
  1633 #endif
       
  1634 
       
  1635 typedef void (*OverlapFunc)(register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End,
       
  1636                             register const QRect *r2, const QRect *r2End, register int y1, register int y2);
       
  1637 typedef void (*NonOverlapFunc)(register QRegionPrivate &dest, register const QRect *r, const QRect *rEnd,
       
  1638                                register int y1, register int y2);
       
  1639 
       
  1640 static bool EqualRegion(const QRegionPrivate *r1, const QRegionPrivate *r2);
       
  1641 static void UnionRegion(const QRegionPrivate *reg1, const QRegionPrivate *reg2, QRegionPrivate &dest);
       
  1642 static void miRegionOp(register QRegionPrivate &dest, const QRegionPrivate *reg1, const QRegionPrivate *reg2,
       
  1643                        OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,
       
  1644                        NonOverlapFunc nonOverlap2Func);
       
  1645 
       
  1646 #define RectangleOut 0
       
  1647 #define RectangleIn 1
       
  1648 #define RectanglePart 2
       
  1649 #define EvenOddRule 0
       
  1650 #define WindingRule 1
       
  1651 
       
  1652 // START OF region.h extract
       
  1653 /* $XConsortium: region.h,v 11.14 94/04/17 20:22:20 rws Exp $ */
       
  1654 /************************************************************************
       
  1655 
       
  1656 Copyright (c) 1987  X Consortium
       
  1657 
       
  1658 Permission is hereby granted, free of charge, to any person obtaining a copy
       
  1659 of this software and associated documentation files (the "Software"), to deal
       
  1660 in the Software without restriction, including without limitation the rights
       
  1661 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
  1662 copies of the Software, and to permit persons to whom the Software is
       
  1663 furnished to do so, subject to the following conditions:
       
  1664 
       
  1665 The above copyright notice and this permission notice shall be included in
       
  1666 all copies or substantial portions of the Software.
       
  1667 
       
  1668 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
  1669 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
  1670 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
       
  1671 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
       
  1672 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
  1673 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
  1674 
       
  1675 Except as contained in this notice, the name of the X Consortium shall not be
       
  1676 used in advertising or otherwise to promote the sale, use or other dealings
       
  1677 in this Software without prior written authorization from the X Consortium.
       
  1678 
       
  1679 
       
  1680 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
       
  1681 
       
  1682                         All Rights Reserved
       
  1683 
       
  1684 Permission to use, copy, modify, and distribute this software and its
       
  1685 documentation for any purpose and without fee is hereby granted,
       
  1686 provided that the above copyright notice appear in all copies and that
       
  1687 both that copyright notice and this permission notice appear in
       
  1688 supporting documentation, and that the name of Digital not be
       
  1689 used in advertising or publicity pertaining to distribution of the
       
  1690 software without specific, written prior permission.
       
  1691 
       
  1692 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
       
  1693 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
       
  1694 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
       
  1695 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
       
  1696 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
       
  1697 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
       
  1698 SOFTWARE.
       
  1699 
       
  1700 ************************************************************************/
       
  1701 
       
  1702 #ifndef _XREGION_H
       
  1703 #define _XREGION_H
       
  1704 
       
  1705 QT_BEGIN_INCLUDE_NAMESPACE
       
  1706 #include <limits.h>
       
  1707 QT_END_INCLUDE_NAMESPACE
       
  1708 
       
  1709 /*  1 if two BOXs overlap.
       
  1710  *  0 if two BOXs do not overlap.
       
  1711  *  Remember, x2 and y2 are not in the region
       
  1712  */
       
  1713 #define EXTENTCHECK(r1, r2) \
       
  1714         ((r1)->right() >= (r2)->left() && \
       
  1715          (r1)->left() <= (r2)->right() && \
       
  1716          (r1)->bottom() >= (r2)->top() && \
       
  1717          (r1)->top() <= (r2)->bottom())
       
  1718 
       
  1719 /*
       
  1720  *  update region extents
       
  1721  */
       
  1722 #define EXTENTS(r,idRect){\
       
  1723             if((r)->left() < (idRect)->extents.left())\
       
  1724               (idRect)->extents.setLeft((r)->left());\
       
  1725             if((r)->top() < (idRect)->extents.top())\
       
  1726               (idRect)->extents.setTop((r)->top());\
       
  1727             if((r)->right() > (idRect)->extents.right())\
       
  1728               (idRect)->extents.setRight((r)->right());\
       
  1729             if((r)->bottom() > (idRect)->extents.bottom())\
       
  1730               (idRect)->extents.setBottom((r)->bottom());\
       
  1731         }
       
  1732 
       
  1733 /*
       
  1734  *   Check to see if there is enough memory in the present region.
       
  1735  */
       
  1736 #define MEMCHECK(dest, rect, firstrect){\
       
  1737         if ((dest).numRects >= ((dest).rects.size()-1)){\
       
  1738           firstrect.resize(firstrect.size() * 2); \
       
  1739           (rect) = (firstrect).data() + (dest).numRects;\
       
  1740         }\
       
  1741       }
       
  1742 
       
  1743 
       
  1744 /*
       
  1745  * number of points to buffer before sending them off
       
  1746  * to scanlines(): Must be an even number
       
  1747  */
       
  1748 #define NUMPTSTOBUFFER 200
       
  1749 
       
  1750 /*
       
  1751  * used to allocate buffers for points and link
       
  1752  * the buffers together
       
  1753  */
       
  1754 typedef struct _POINTBLOCK {
       
  1755     int data[NUMPTSTOBUFFER * sizeof(QPoint)];
       
  1756     QPoint *pts;
       
  1757     struct _POINTBLOCK *next;
       
  1758 } POINTBLOCK;
       
  1759 
       
  1760 #endif
       
  1761 // END OF region.h extract
       
  1762 
       
  1763 // START OF Region.c extract
       
  1764 /* $XConsortium: Region.c /main/30 1996/10/22 14:21:24 kaleb $ */
       
  1765 /************************************************************************
       
  1766 
       
  1767 Copyright (c) 1987, 1988  X Consortium
       
  1768 
       
  1769 Permission is hereby granted, free of charge, to any person obtaining a copy
       
  1770 of this software and associated documentation files (the "Software"), to deal
       
  1771 in the Software without restriction, including without limitation the rights
       
  1772 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
  1773 copies of the Software, and to permit persons to whom the Software is
       
  1774 furnished to do so, subject to the following conditions:
       
  1775 
       
  1776 The above copyright notice and this permission notice shall be included in
       
  1777 all copies or substantial portions of the Software.
       
  1778 
       
  1779 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
  1780 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
  1781 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
       
  1782 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
       
  1783 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
  1784 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
  1785 
       
  1786 Except as contained in this notice, the name of the X Consortium shall not be
       
  1787 used in advertising or otherwise to promote the sale, use or other dealings
       
  1788 in this Software without prior written authorization from the X Consortium.
       
  1789 
       
  1790 
       
  1791 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
       
  1792 
       
  1793                         All Rights Reserved
       
  1794 
       
  1795 Permission to use, copy, modify, and distribute this software and its
       
  1796 documentation for any purpose and without fee is hereby granted,
       
  1797 provided that the above copyright notice appear in all copies and that
       
  1798 both that copyright notice and this permission notice appear in
       
  1799 supporting documentation, and that the name of Digital not be
       
  1800 used in advertising or publicity pertaining to distribution of the
       
  1801 software without specific, written prior permission.
       
  1802 
       
  1803 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
       
  1804 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
       
  1805 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
       
  1806 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
       
  1807 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
       
  1808 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
       
  1809 SOFTWARE.
       
  1810 
       
  1811 ************************************************************************/
       
  1812 /*
       
  1813  * The functions in this file implement the Region abstraction, similar to one
       
  1814  * used in the X11 sample server. A Region is simply an area, as the name
       
  1815  * implies, and is implemented as a "y-x-banded" array of rectangles. To
       
  1816  * explain: Each Region is made up of a certain number of rectangles sorted
       
  1817  * by y coordinate first, and then by x coordinate.
       
  1818  *
       
  1819  * Furthermore, the rectangles are banded such that every rectangle with a
       
  1820  * given upper-left y coordinate (y1) will have the same lower-right y
       
  1821  * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it
       
  1822  * will span the entire vertical distance of the band. This means that some
       
  1823  * areas that could be merged into a taller rectangle will be represented as
       
  1824  * several shorter rectangles to account for shorter rectangles to its left
       
  1825  * or right but within its "vertical scope".
       
  1826  *
       
  1827  * An added constraint on the rectangles is that they must cover as much
       
  1828  * horizontal area as possible. E.g. no two rectangles in a band are allowed
       
  1829  * to touch.
       
  1830  *
       
  1831  * Whenever possible, bands will be merged together to cover a greater vertical
       
  1832  * distance (and thus reduce the number of rectangles). Two bands can be merged
       
  1833  * only if the bottom of one touches the top of the other and they have
       
  1834  * rectangles in the same places (of the same width, of course). This maintains
       
  1835  * the y-x-banding that's so nice to have...
       
  1836  */
       
  1837 /* $XFree86: xc/lib/X11/Region.c,v 1.1.1.2.2.2 1998/10/04 15:22:50 hohndel Exp $ */
       
  1838 
       
  1839 static void UnionRectWithRegion(register const QRect *rect, const QRegionPrivate *source,
       
  1840                                 QRegionPrivate &dest)
       
  1841 {
       
  1842     if (rect->isEmpty())
       
  1843         return;
       
  1844 
       
  1845     Q_ASSERT(EqualRegion(source, &dest));
       
  1846 
       
  1847     if (dest.numRects == 0) {
       
  1848         dest = QRegionPrivate(*rect);
       
  1849     } else if (dest.canAppend(rect)) {
       
  1850         dest.append(rect);
       
  1851     } else {
       
  1852         QRegionPrivate p(*rect);
       
  1853         UnionRegion(&p, source, dest);
       
  1854     }
       
  1855 }
       
  1856 
       
  1857 /*-
       
  1858  *-----------------------------------------------------------------------
       
  1859  * miSetExtents --
       
  1860  *      Reset the extents and innerRect of a region to what they should be.
       
  1861  *      Called by miSubtract and miIntersect b/c they can't figure it out
       
  1862  *      along the way or do so easily, as miUnion can.
       
  1863  *
       
  1864  * Results:
       
  1865  *      None.
       
  1866  *
       
  1867  * Side Effects:
       
  1868  *      The region's 'extents' and 'innerRect' structure is overwritten.
       
  1869  *
       
  1870  *-----------------------------------------------------------------------
       
  1871  */
       
  1872 static void miSetExtents(QRegionPrivate &dest)
       
  1873 {
       
  1874     register const QRect *pBox,
       
  1875                          *pBoxEnd;
       
  1876     register QRect *pExtents;
       
  1877 
       
  1878     dest.innerRect.setCoords(0, 0, -1, -1);
       
  1879     dest.innerArea = -1;
       
  1880     if (dest.numRects == 0) {
       
  1881         dest.extents.setCoords(0, 0, -1, -1);
       
  1882         return;
       
  1883     }
       
  1884 
       
  1885     pExtents = &dest.extents;
       
  1886     if (dest.rects.isEmpty())
       
  1887         pBox = &dest.extents;
       
  1888     else
       
  1889         pBox = dest.rects.constData();
       
  1890     pBoxEnd = pBox + dest.numRects - 1;
       
  1891 
       
  1892     /*
       
  1893      * Since pBox is the first rectangle in the region, it must have the
       
  1894      * smallest y1 and since pBoxEnd is the last rectangle in the region,
       
  1895      * it must have the largest y2, because of banding. Initialize x1 and
       
  1896      * x2 from  pBox and pBoxEnd, resp., as good things to initialize them
       
  1897      * to...
       
  1898      */
       
  1899     pExtents->setLeft(pBox->left());
       
  1900     pExtents->setTop(pBox->top());
       
  1901     pExtents->setRight(pBoxEnd->right());
       
  1902     pExtents->setBottom(pBoxEnd->bottom());
       
  1903 
       
  1904     Q_ASSERT(pExtents->top() <= pExtents->bottom());
       
  1905     while (pBox <= pBoxEnd) {
       
  1906         if (pBox->left() < pExtents->left())
       
  1907             pExtents->setLeft(pBox->left());
       
  1908         if (pBox->right() > pExtents->right())
       
  1909             pExtents->setRight(pBox->right());
       
  1910         dest.updateInnerRect(*pBox);
       
  1911         ++pBox;
       
  1912     }
       
  1913     Q_ASSERT(pExtents->left() <= pExtents->right());
       
  1914 }
       
  1915 
       
  1916 /* TranslateRegion(pRegion, x, y)
       
  1917    translates in place
       
  1918    added by raymond
       
  1919 */
       
  1920 
       
  1921 static void OffsetRegion(register QRegionPrivate &region, register int x, register int y)
       
  1922 {
       
  1923     if (region.rects.size()) {
       
  1924         register QRect *pbox = region.rects.data();
       
  1925         register int nbox = region.numRects;
       
  1926 
       
  1927         while (nbox--) {
       
  1928             pbox->translate(x, y);
       
  1929             ++pbox;
       
  1930         }
       
  1931     }
       
  1932     region.extents.translate(x, y);
       
  1933     region.innerRect.translate(x, y);
       
  1934 }
       
  1935 
       
  1936 /*======================================================================
       
  1937  *          Region Intersection
       
  1938  *====================================================================*/
       
  1939 /*-
       
  1940  *-----------------------------------------------------------------------
       
  1941  * miIntersectO --
       
  1942  *      Handle an overlapping band for miIntersect.
       
  1943  *
       
  1944  * Results:
       
  1945  *      None.
       
  1946  *
       
  1947  * Side Effects:
       
  1948  *      Rectangles may be added to the region.
       
  1949  *
       
  1950  *-----------------------------------------------------------------------
       
  1951  */
       
  1952 static void miIntersectO(register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End,
       
  1953                          register const QRect *r2, const QRect *r2End, int y1, int y2)
       
  1954 {
       
  1955     register int x1;
       
  1956     register int x2;
       
  1957     register QRect *pNextRect;
       
  1958 
       
  1959     pNextRect = dest.rects.data() + dest.numRects;
       
  1960 
       
  1961     while (r1 != r1End && r2 != r2End) {
       
  1962         x1 = qMax(r1->left(), r2->left());
       
  1963         x2 = qMin(r1->right(), r2->right());
       
  1964 
       
  1965         /*
       
  1966          * If there's any overlap between the two rectangles, add that
       
  1967          * overlap to the new region.
       
  1968          * There's no need to check for subsumption because the only way
       
  1969          * such a need could arise is if some region has two rectangles
       
  1970          * right next to each other. Since that should never happen...
       
  1971          */
       
  1972         if (x1 <= x2) {
       
  1973             Q_ASSERT(y1 <= y2);
       
  1974             MEMCHECK(dest, pNextRect, dest.rects)
       
  1975             pNextRect->setCoords(x1, y1, x2, y2);
       
  1976             ++dest.numRects;
       
  1977             ++pNextRect;
       
  1978         }
       
  1979 
       
  1980         /*
       
  1981          * Need to advance the pointers. Shift the one that extends
       
  1982          * to the right the least, since the other still has a chance to
       
  1983          * overlap with that region's next rectangle, if you see what I mean.
       
  1984          */
       
  1985         if (r1->right() < r2->right()) {
       
  1986             ++r1;
       
  1987         } else if (r2->right() < r1->right()) {
       
  1988             ++r2;
       
  1989         } else {
       
  1990             ++r1;
       
  1991             ++r2;
       
  1992         }
       
  1993     }
       
  1994 }
       
  1995 
       
  1996 /*======================================================================
       
  1997  *          Generic Region Operator
       
  1998  *====================================================================*/
       
  1999 
       
  2000 /*-
       
  2001  *-----------------------------------------------------------------------
       
  2002  * miCoalesce --
       
  2003  *      Attempt to merge the boxes in the current band with those in the
       
  2004  *      previous one. Used only by miRegionOp.
       
  2005  *
       
  2006  * Results:
       
  2007  *      The new index for the previous band.
       
  2008  *
       
  2009  * Side Effects:
       
  2010  *      If coalescing takes place:
       
  2011  *          - rectangles in the previous band will have their y2 fields
       
  2012  *            altered.
       
  2013  *          - dest.numRects will be decreased.
       
  2014  *
       
  2015  *-----------------------------------------------------------------------
       
  2016  */
       
  2017 static int miCoalesce(register QRegionPrivate &dest, int prevStart, int curStart)
       
  2018 {
       
  2019     register QRect *pPrevBox;   /* Current box in previous band */
       
  2020     register QRect *pCurBox;    /* Current box in current band */
       
  2021     register QRect *pRegEnd;    /* End of region */
       
  2022     int curNumRects;    /* Number of rectangles in current band */
       
  2023     int prevNumRects;   /* Number of rectangles in previous band */
       
  2024     int bandY1;         /* Y1 coordinate for current band */
       
  2025     QRect *rData = dest.rects.data();
       
  2026 
       
  2027     pRegEnd = rData + dest.numRects;
       
  2028 
       
  2029     pPrevBox = rData + prevStart;
       
  2030     prevNumRects = curStart - prevStart;
       
  2031 
       
  2032     /*
       
  2033      * Figure out how many rectangles are in the current band. Have to do
       
  2034      * this because multiple bands could have been added in miRegionOp
       
  2035      * at the end when one region has been exhausted.
       
  2036      */
       
  2037     pCurBox = rData + curStart;
       
  2038     bandY1 = pCurBox->top();
       
  2039     for (curNumRects = 0; pCurBox != pRegEnd && pCurBox->top() == bandY1; ++curNumRects) {
       
  2040         ++pCurBox;
       
  2041     }
       
  2042 
       
  2043     if (pCurBox != pRegEnd) {
       
  2044         /*
       
  2045          * If more than one band was added, we have to find the start
       
  2046          * of the last band added so the next coalescing job can start
       
  2047          * at the right place... (given when multiple bands are added,
       
  2048          * this may be pointless -- see above).
       
  2049          */
       
  2050         --pRegEnd;
       
  2051         while ((pRegEnd - 1)->top() == pRegEnd->top())
       
  2052             --pRegEnd;
       
  2053         curStart = pRegEnd - rData;
       
  2054         pRegEnd = rData + dest.numRects;
       
  2055     }
       
  2056 
       
  2057     if (curNumRects == prevNumRects && curNumRects != 0) {
       
  2058         pCurBox -= curNumRects;
       
  2059         /*
       
  2060          * The bands may only be coalesced if the bottom of the previous
       
  2061          * matches the top scanline of the current.
       
  2062          */
       
  2063         if (pPrevBox->bottom() == pCurBox->top() - 1) {
       
  2064             /*
       
  2065              * Make sure the bands have boxes in the same places. This
       
  2066              * assumes that boxes have been added in such a way that they
       
  2067              * cover the most area possible. I.e. two boxes in a band must
       
  2068              * have some horizontal space between them.
       
  2069              */
       
  2070             do {
       
  2071                 if (pPrevBox->left() != pCurBox->left() || pPrevBox->right() != pCurBox->right()) {
       
  2072                      // The bands don't line up so they can't be coalesced.
       
  2073                     return curStart;
       
  2074                 }
       
  2075                 ++pPrevBox;
       
  2076                 ++pCurBox;
       
  2077                 --prevNumRects;
       
  2078             } while (prevNumRects != 0);
       
  2079 
       
  2080             dest.numRects -= curNumRects;
       
  2081             pCurBox -= curNumRects;
       
  2082             pPrevBox -= curNumRects;
       
  2083 
       
  2084             /*
       
  2085              * The bands may be merged, so set the bottom y of each box
       
  2086              * in the previous band to that of the corresponding box in
       
  2087              * the current band.
       
  2088              */
       
  2089             do {
       
  2090                 pPrevBox->setBottom(pCurBox->bottom());
       
  2091                 dest.updateInnerRect(*pPrevBox);
       
  2092                 ++pPrevBox;
       
  2093                 ++pCurBox;
       
  2094                 curNumRects -= 1;
       
  2095             } while (curNumRects != 0);
       
  2096 
       
  2097             /*
       
  2098              * If only one band was added to the region, we have to backup
       
  2099              * curStart to the start of the previous band.
       
  2100              *
       
  2101              * If more than one band was added to the region, copy the
       
  2102              * other bands down. The assumption here is that the other bands
       
  2103              * came from the same region as the current one and no further
       
  2104              * coalescing can be done on them since it's all been done
       
  2105              * already... curStart is already in the right place.
       
  2106              */
       
  2107             if (pCurBox == pRegEnd) {
       
  2108                 curStart = prevStart;
       
  2109             } else {
       
  2110                 do {
       
  2111                     *pPrevBox++ = *pCurBox++;
       
  2112                     dest.updateInnerRect(*pPrevBox);
       
  2113                 } while (pCurBox != pRegEnd);
       
  2114             }
       
  2115         }
       
  2116     }
       
  2117     return curStart;
       
  2118 }
       
  2119 
       
  2120 /*-
       
  2121  *-----------------------------------------------------------------------
       
  2122  * miRegionOp --
       
  2123  *      Apply an operation to two regions. Called by miUnion, miInverse,
       
  2124  *      miSubtract, miIntersect...
       
  2125  *
       
  2126  * Results:
       
  2127  *      None.
       
  2128  *
       
  2129  * Side Effects:
       
  2130  *      The new region is overwritten.
       
  2131  *
       
  2132  * Notes:
       
  2133  *      The idea behind this function is to view the two regions as sets.
       
  2134  *      Together they cover a rectangle of area that this function divides
       
  2135  *      into horizontal bands where points are covered only by one region
       
  2136  *      or by both. For the first case, the nonOverlapFunc is called with
       
  2137  *      each the band and the band's upper and lower extents. For the
       
  2138  *      second, the overlapFunc is called to process the entire band. It
       
  2139  *      is responsible for clipping the rectangles in the band, though
       
  2140  *      this function provides the boundaries.
       
  2141  *      At the end of each band, the new region is coalesced, if possible,
       
  2142  *      to reduce the number of rectangles in the region.
       
  2143  *
       
  2144  *-----------------------------------------------------------------------
       
  2145  */
       
  2146 static void miRegionOp(register QRegionPrivate &dest,
       
  2147                        const QRegionPrivate *reg1, const QRegionPrivate *reg2,
       
  2148                        OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,
       
  2149                        NonOverlapFunc nonOverlap2Func)
       
  2150 {
       
  2151     register const QRect *r1;         // Pointer into first region
       
  2152     register const QRect *r2;         // Pointer into 2d region
       
  2153     const QRect *r1End;               // End of 1st region
       
  2154     const QRect *r2End;               // End of 2d region
       
  2155     register int ybot;          // Bottom of intersection
       
  2156     register int ytop;          // Top of intersection
       
  2157     int prevBand;               // Index of start of previous band in dest
       
  2158     int curBand;                // Index of start of current band in dest
       
  2159     register const QRect *r1BandEnd;  // End of current band in r1
       
  2160     register const QRect *r2BandEnd;  // End of current band in r2
       
  2161     int top;                    // Top of non-overlapping band
       
  2162     int bot;                    // Bottom of non-overlapping band
       
  2163 
       
  2164     /*
       
  2165      * Initialization:
       
  2166      *  set r1, r2, r1End and r2End appropriately, preserve the important
       
  2167      * parts of the destination region until the end in case it's one of
       
  2168      * the two source regions, then mark the "new" region empty, allocating
       
  2169      * another array of rectangles for it to use.
       
  2170      */
       
  2171     if (reg1->numRects == 1)
       
  2172         r1 = &reg1->extents;
       
  2173     else
       
  2174         r1 = reg1->rects.constData();
       
  2175     if (reg2->numRects == 1)
       
  2176         r2 = &reg2->extents;
       
  2177     else
       
  2178         r2 = reg2->rects.constData();
       
  2179 
       
  2180     r1End = r1 + reg1->numRects;
       
  2181     r2End = r2 + reg2->numRects;
       
  2182 
       
  2183     dest.vectorize();
       
  2184 
       
  2185     QVector<QRect> oldRects = dest.rects;
       
  2186 
       
  2187     dest.numRects = 0;
       
  2188 
       
  2189     /*
       
  2190      * Allocate a reasonable number of rectangles for the new region. The idea
       
  2191      * is to allocate enough so the individual functions don't need to
       
  2192      * reallocate and copy the array, which is time consuming, yet we don't
       
  2193      * have to worry about using too much memory. I hope to be able to
       
  2194      * nuke the realloc() at the end of this function eventually.
       
  2195      */
       
  2196     dest.rects.resize(qMax(reg1->numRects,reg2->numRects) * 2);
       
  2197 
       
  2198     /*
       
  2199      * Initialize ybot and ytop.
       
  2200      * In the upcoming loop, ybot and ytop serve different functions depending
       
  2201      * on whether the band being handled is an overlapping or non-overlapping
       
  2202      * band.
       
  2203      *  In the case of a non-overlapping band (only one of the regions
       
  2204      * has points in the band), ybot is the bottom of the most recent
       
  2205      * intersection and thus clips the top of the rectangles in that band.
       
  2206      * ytop is the top of the next intersection between the two regions and
       
  2207      * serves to clip the bottom of the rectangles in the current band.
       
  2208      *  For an overlapping band (where the two regions intersect), ytop clips
       
  2209      * the top of the rectangles of both regions and ybot clips the bottoms.
       
  2210      */
       
  2211     if (reg1->extents.top() < reg2->extents.top())
       
  2212         ybot = reg1->extents.top() - 1;
       
  2213     else
       
  2214         ybot = reg2->extents.top() - 1;
       
  2215 
       
  2216     /*
       
  2217      * prevBand serves to mark the start of the previous band so rectangles
       
  2218      * can be coalesced into larger rectangles. qv. miCoalesce, above.
       
  2219      * In the beginning, there is no previous band, so prevBand == curBand
       
  2220      * (curBand is set later on, of course, but the first band will always
       
  2221      * start at index 0). prevBand and curBand must be indices because of
       
  2222      * the possible expansion, and resultant moving, of the new region's
       
  2223      * array of rectangles.
       
  2224      */
       
  2225     prevBand = 0;
       
  2226 
       
  2227     do {
       
  2228         curBand = dest.numRects;
       
  2229 
       
  2230         /*
       
  2231          * This algorithm proceeds one source-band (as opposed to a
       
  2232          * destination band, which is determined by where the two regions
       
  2233          * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
       
  2234          * rectangle after the last one in the current band for their
       
  2235          * respective regions.
       
  2236          */
       
  2237         r1BandEnd = r1;
       
  2238         while (r1BandEnd != r1End && r1BandEnd->top() == r1->top())
       
  2239             ++r1BandEnd;
       
  2240 
       
  2241         r2BandEnd = r2;
       
  2242         while (r2BandEnd != r2End && r2BandEnd->top() == r2->top())
       
  2243             ++r2BandEnd;
       
  2244 
       
  2245         /*
       
  2246          * First handle the band that doesn't intersect, if any.
       
  2247          *
       
  2248          * Note that attention is restricted to one band in the
       
  2249          * non-intersecting region at once, so if a region has n
       
  2250          * bands between the current position and the next place it overlaps
       
  2251          * the other, this entire loop will be passed through n times.
       
  2252          */
       
  2253         if (r1->top() < r2->top()) {
       
  2254             top = qMax(r1->top(), ybot + 1);
       
  2255             bot = qMin(r1->bottom(), r2->top() - 1);
       
  2256 
       
  2257             if (nonOverlap1Func != 0 && bot >= top)
       
  2258                 (*nonOverlap1Func)(dest, r1, r1BandEnd, top, bot);
       
  2259             ytop = r2->top();
       
  2260         } else if (r2->top() < r1->top()) {
       
  2261             top = qMax(r2->top(), ybot + 1);
       
  2262             bot = qMin(r2->bottom(), r1->top() - 1);
       
  2263 
       
  2264             if (nonOverlap2Func != 0 && bot >= top)
       
  2265                 (*nonOverlap2Func)(dest, r2, r2BandEnd, top, bot);
       
  2266             ytop = r1->top();
       
  2267         } else {
       
  2268             ytop = r1->top();
       
  2269         }
       
  2270 
       
  2271         /*
       
  2272          * If any rectangles got added to the region, try and coalesce them
       
  2273          * with rectangles from the previous band. Note we could just do
       
  2274          * this test in miCoalesce, but some machines incur a not
       
  2275          * inconsiderable cost for function calls, so...
       
  2276          */
       
  2277         if (dest.numRects != curBand)
       
  2278             prevBand = miCoalesce(dest, prevBand, curBand);
       
  2279 
       
  2280         /*
       
  2281          * Now see if we've hit an intersecting band. The two bands only
       
  2282          * intersect if ybot >= ytop
       
  2283          */
       
  2284         ybot = qMin(r1->bottom(), r2->bottom());
       
  2285         curBand = dest.numRects;
       
  2286         if (ybot >= ytop)
       
  2287             (*overlapFunc)(dest, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
       
  2288 
       
  2289         if (dest.numRects != curBand)
       
  2290             prevBand = miCoalesce(dest, prevBand, curBand);
       
  2291 
       
  2292         /*
       
  2293          * If we've finished with a band (y2 == ybot) we skip forward
       
  2294          * in the region to the next band.
       
  2295          */
       
  2296         if (r1->bottom() == ybot)
       
  2297             r1 = r1BandEnd;
       
  2298         if (r2->bottom() == ybot)
       
  2299             r2 = r2BandEnd;
       
  2300     } while (r1 != r1End && r2 != r2End);
       
  2301 
       
  2302     /*
       
  2303      * Deal with whichever region still has rectangles left.
       
  2304      */
       
  2305     curBand = dest.numRects;
       
  2306     if (r1 != r1End) {
       
  2307         if (nonOverlap1Func != 0) {
       
  2308             do {
       
  2309                 r1BandEnd = r1;
       
  2310                 while (r1BandEnd < r1End && r1BandEnd->top() == r1->top())
       
  2311                     ++r1BandEnd;
       
  2312                 (*nonOverlap1Func)(dest, r1, r1BandEnd, qMax(r1->top(), ybot + 1), r1->bottom());
       
  2313                 r1 = r1BandEnd;
       
  2314             } while (r1 != r1End);
       
  2315         }
       
  2316     } else if ((r2 != r2End) && (nonOverlap2Func != 0)) {
       
  2317         do {
       
  2318             r2BandEnd = r2;
       
  2319             while (r2BandEnd < r2End && r2BandEnd->top() == r2->top())
       
  2320                  ++r2BandEnd;
       
  2321             (*nonOverlap2Func)(dest, r2, r2BandEnd, qMax(r2->top(), ybot + 1), r2->bottom());
       
  2322             r2 = r2BandEnd;
       
  2323         } while (r2 != r2End);
       
  2324     }
       
  2325 
       
  2326     if (dest.numRects != curBand)
       
  2327         (void)miCoalesce(dest, prevBand, curBand);
       
  2328 
       
  2329     /*
       
  2330      * A bit of cleanup. To keep regions from growing without bound,
       
  2331      * we shrink the array of rectangles to match the new number of
       
  2332      * rectangles in the region.
       
  2333      *
       
  2334      * Only do this stuff if the number of rectangles allocated is more than
       
  2335      * twice the number of rectangles in the region (a simple optimization).
       
  2336      */
       
  2337     if (qMax(4, dest.numRects) < (dest.rects.size() >> 1))
       
  2338         dest.rects.resize(dest.numRects);
       
  2339 }
       
  2340 
       
  2341 /*======================================================================
       
  2342  *          Region Union
       
  2343  *====================================================================*/
       
  2344 
       
  2345 /*-
       
  2346  *-----------------------------------------------------------------------
       
  2347  * miUnionNonO --
       
  2348  *      Handle a non-overlapping band for the union operation. Just
       
  2349  *      Adds the rectangles into the region. Doesn't have to check for
       
  2350  *      subsumption or anything.
       
  2351  *
       
  2352  * Results:
       
  2353  *      None.
       
  2354  *
       
  2355  * Side Effects:
       
  2356  *      dest.numRects is incremented and the final rectangles overwritten
       
  2357  *      with the rectangles we're passed.
       
  2358  *
       
  2359  *-----------------------------------------------------------------------
       
  2360  */
       
  2361 
       
  2362 static void miUnionNonO(register QRegionPrivate &dest, register const QRect *r, const QRect *rEnd,
       
  2363                         register int y1, register int y2)
       
  2364 {
       
  2365     register QRect *pNextRect;
       
  2366 
       
  2367     pNextRect = dest.rects.data() + dest.numRects;
       
  2368 
       
  2369     Q_ASSERT(y1 <= y2);
       
  2370 
       
  2371     while (r != rEnd) {
       
  2372         Q_ASSERT(r->left() <= r->right());
       
  2373         MEMCHECK(dest, pNextRect, dest.rects)
       
  2374         pNextRect->setCoords(r->left(), y1, r->right(), y2);
       
  2375         dest.numRects++;
       
  2376         ++pNextRect;
       
  2377         ++r;
       
  2378     }
       
  2379 }
       
  2380 
       
  2381 
       
  2382 /*-
       
  2383  *-----------------------------------------------------------------------
       
  2384  * miUnionO --
       
  2385  *      Handle an overlapping band for the union operation. Picks the
       
  2386  *      left-most rectangle each time and merges it into the region.
       
  2387  *
       
  2388  * Results:
       
  2389  *      None.
       
  2390  *
       
  2391  * Side Effects:
       
  2392  *      Rectangles are overwritten in dest.rects and dest.numRects will
       
  2393  *      be changed.
       
  2394  *
       
  2395  *-----------------------------------------------------------------------
       
  2396  */
       
  2397 
       
  2398 static void miUnionO(register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End,
       
  2399                      register const QRect *r2, const QRect *r2End, register int y1, register int y2)
       
  2400 {
       
  2401     register QRect *pNextRect;
       
  2402 
       
  2403     pNextRect = dest.rects.data() + dest.numRects;
       
  2404 
       
  2405 #define MERGERECT(r)             \
       
  2406     if ((dest.numRects != 0) &&  \
       
  2407         (pNextRect[-1].top() == y1) &&  \
       
  2408         (pNextRect[-1].bottom() == y2) &&  \
       
  2409         (pNextRect[-1].right() >= r->left()-1)) { \
       
  2410         if (pNextRect[-1].right() < r->right()) { \
       
  2411             pNextRect[-1].setRight(r->right());  \
       
  2412             dest.updateInnerRect(pNextRect[-1]); \
       
  2413             Q_ASSERT(pNextRect[-1].left() <= pNextRect[-1].right()); \
       
  2414         }  \
       
  2415     } else { \
       
  2416         MEMCHECK(dest, pNextRect, dest.rects)  \
       
  2417         pNextRect->setCoords(r->left(), y1, r->right(), y2); \
       
  2418         dest.updateInnerRect(*pNextRect); \
       
  2419         dest.numRects++;  \
       
  2420         pNextRect++;  \
       
  2421     }  \
       
  2422     r++;
       
  2423 
       
  2424     Q_ASSERT(y1 <= y2);
       
  2425     while (r1 != r1End && r2 != r2End) {
       
  2426         if (r1->left() < r2->left()) {
       
  2427             MERGERECT(r1)
       
  2428         } else {
       
  2429             MERGERECT(r2)
       
  2430         }
       
  2431     }
       
  2432 
       
  2433     if (r1 != r1End) {
       
  2434         do {
       
  2435             MERGERECT(r1)
       
  2436         } while (r1 != r1End);
       
  2437     } else {
       
  2438         while (r2 != r2End) {
       
  2439             MERGERECT(r2)
       
  2440         }
       
  2441     }
       
  2442 }
       
  2443 
       
  2444 static void UnionRegion(const QRegionPrivate *reg1, const QRegionPrivate *reg2, QRegionPrivate &dest)
       
  2445 {
       
  2446     Q_ASSERT(!isEmptyHelper(reg1) && !isEmptyHelper(reg2));
       
  2447     Q_ASSERT(!reg1->contains(*reg2));
       
  2448     Q_ASSERT(!reg2->contains(*reg1));
       
  2449     Q_ASSERT(!EqualRegion(reg1, reg2));
       
  2450     Q_ASSERT(!reg1->canAppend(reg2));
       
  2451     Q_ASSERT(!reg2->canAppend(reg1));
       
  2452 
       
  2453     if (reg1->innerArea > reg2->innerArea) {
       
  2454         dest.innerArea = reg1->innerArea;
       
  2455         dest.innerRect = reg1->innerRect;
       
  2456     } else {
       
  2457         dest.innerArea = reg2->innerArea;
       
  2458         dest.innerRect = reg2->innerRect;
       
  2459     }
       
  2460     miRegionOp(dest, reg1, reg2, miUnionO, miUnionNonO, miUnionNonO);
       
  2461 
       
  2462     dest.extents.setCoords(qMin(reg1->extents.left(), reg2->extents.left()),
       
  2463                            qMin(reg1->extents.top(), reg2->extents.top()),
       
  2464                            qMax(reg1->extents.right(), reg2->extents.right()),
       
  2465                            qMax(reg1->extents.bottom(), reg2->extents.bottom()));
       
  2466 }
       
  2467 
       
  2468 /*======================================================================
       
  2469  *        Region Subtraction
       
  2470  *====================================================================*/
       
  2471 
       
  2472 /*-
       
  2473  *-----------------------------------------------------------------------
       
  2474  * miSubtractNonO --
       
  2475  *      Deal with non-overlapping band for subtraction. Any parts from
       
  2476  *      region 2 we discard. Anything from region 1 we add to the region.
       
  2477  *
       
  2478  * Results:
       
  2479  *      None.
       
  2480  *
       
  2481  * Side Effects:
       
  2482  *      dest may be affected.
       
  2483  *
       
  2484  *-----------------------------------------------------------------------
       
  2485  */
       
  2486 
       
  2487 static void miSubtractNonO1(register QRegionPrivate &dest, register const QRect *r,
       
  2488                             const QRect *rEnd, register int y1, register int y2)
       
  2489 {
       
  2490     register QRect *pNextRect;
       
  2491 
       
  2492     pNextRect = dest.rects.data() + dest.numRects;
       
  2493 
       
  2494     Q_ASSERT(y1<=y2);
       
  2495 
       
  2496     while (r != rEnd) {
       
  2497         Q_ASSERT(r->left() <= r->right());
       
  2498         MEMCHECK(dest, pNextRect, dest.rects)
       
  2499         pNextRect->setCoords(r->left(), y1, r->right(), y2);
       
  2500         ++dest.numRects;
       
  2501         ++pNextRect;
       
  2502         ++r;
       
  2503     }
       
  2504 }
       
  2505 
       
  2506 /*-
       
  2507  *-----------------------------------------------------------------------
       
  2508  * miSubtractO --
       
  2509  *      Overlapping band subtraction. x1 is the left-most point not yet
       
  2510  *      checked.
       
  2511  *
       
  2512  * Results:
       
  2513  *      None.
       
  2514  *
       
  2515  * Side Effects:
       
  2516  *      dest may have rectangles added to it.
       
  2517  *
       
  2518  *-----------------------------------------------------------------------
       
  2519  */
       
  2520 
       
  2521 static void miSubtractO(register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End,
       
  2522                         register const QRect *r2, const QRect *r2End, register int y1, register int y2)
       
  2523 {
       
  2524     register QRect *pNextRect;
       
  2525     register int x1;
       
  2526 
       
  2527     x1 = r1->left();
       
  2528 
       
  2529     Q_ASSERT(y1 <= y2);
       
  2530     pNextRect = dest.rects.data() + dest.numRects;
       
  2531 
       
  2532     while (r1 != r1End && r2 != r2End) {
       
  2533         if (r2->right() < x1) {
       
  2534             /*
       
  2535              * Subtrahend missed the boat: go to next subtrahend.
       
  2536              */
       
  2537             ++r2;
       
  2538         } else if (r2->left() <= x1) {
       
  2539             /*
       
  2540              * Subtrahend precedes minuend: nuke left edge of minuend.
       
  2541              */
       
  2542             x1 = r2->right() + 1;
       
  2543             if (x1 > r1->right()) {
       
  2544                 /*
       
  2545                  * Minuend completely covered: advance to next minuend and
       
  2546                  * reset left fence to edge of new minuend.
       
  2547                  */
       
  2548                 ++r1;
       
  2549                 if (r1 != r1End)
       
  2550                     x1 = r1->left();
       
  2551             } else {
       
  2552                 // Subtrahend now used up since it doesn't extend beyond minuend
       
  2553                 ++r2;
       
  2554             }
       
  2555         } else if (r2->left() <= r1->right()) {
       
  2556             /*
       
  2557              * Left part of subtrahend covers part of minuend: add uncovered
       
  2558              * part of minuend to region and skip to next subtrahend.
       
  2559              */
       
  2560             Q_ASSERT(x1 < r2->left());
       
  2561             MEMCHECK(dest, pNextRect, dest.rects)
       
  2562             pNextRect->setCoords(x1, y1, r2->left() - 1, y2);
       
  2563             ++dest.numRects;
       
  2564             ++pNextRect;
       
  2565 
       
  2566             x1 = r2->right() + 1;
       
  2567             if (x1 > r1->right()) {
       
  2568                 /*
       
  2569                  * Minuend used up: advance to new...
       
  2570                  */
       
  2571                 ++r1;
       
  2572                 if (r1 != r1End)
       
  2573                     x1 = r1->left();
       
  2574             } else {
       
  2575                 // Subtrahend used up
       
  2576                 ++r2;
       
  2577             }
       
  2578         } else {
       
  2579             /*
       
  2580              * Minuend used up: add any remaining piece before advancing.
       
  2581              */
       
  2582             if (r1->right() >= x1) {
       
  2583                 MEMCHECK(dest, pNextRect, dest.rects)
       
  2584                 pNextRect->setCoords(x1, y1, r1->right(), y2);
       
  2585                 ++dest.numRects;
       
  2586                 ++pNextRect;
       
  2587             }
       
  2588             ++r1;
       
  2589             if (r1 != r1End)
       
  2590                 x1 = r1->left();
       
  2591         }
       
  2592     }
       
  2593 
       
  2594     /*
       
  2595      * Add remaining minuend rectangles to region.
       
  2596      */
       
  2597     while (r1 != r1End) {
       
  2598         Q_ASSERT(x1 <= r1->right());
       
  2599         MEMCHECK(dest, pNextRect, dest.rects)
       
  2600         pNextRect->setCoords(x1, y1, r1->right(), y2);
       
  2601         ++dest.numRects;
       
  2602         ++pNextRect;
       
  2603 
       
  2604         ++r1;
       
  2605         if (r1 != r1End)
       
  2606             x1 = r1->left();
       
  2607     }
       
  2608 }
       
  2609 
       
  2610 /*-
       
  2611  *-----------------------------------------------------------------------
       
  2612  * miSubtract --
       
  2613  *      Subtract regS from regM and leave the result in regD.
       
  2614  *      S stands for subtrahend, M for minuend and D for difference.
       
  2615  *
       
  2616  * Side Effects:
       
  2617  *      regD is overwritten.
       
  2618  *
       
  2619  *-----------------------------------------------------------------------
       
  2620  */
       
  2621 
       
  2622 static void SubtractRegion(QRegionPrivate *regM, QRegionPrivate *regS,
       
  2623                            register QRegionPrivate &dest)
       
  2624 {
       
  2625     Q_ASSERT(!isEmptyHelper(regM));
       
  2626     Q_ASSERT(!isEmptyHelper(regS));
       
  2627     Q_ASSERT(EXTENTCHECK(&regM->extents, &regS->extents));
       
  2628     Q_ASSERT(!regS->contains(*regM));
       
  2629     Q_ASSERT(!EqualRegion(regM, regS));
       
  2630 
       
  2631     miRegionOp(dest, regM, regS, miSubtractO, miSubtractNonO1, 0);
       
  2632 
       
  2633     /*
       
  2634      * Can't alter dest's extents before we call miRegionOp because
       
  2635      * it might be one of the source regions and miRegionOp depends
       
  2636      * on the extents of those regions being the unaltered. Besides, this
       
  2637      * way there's no checking against rectangles that will be nuked
       
  2638      * due to coalescing, so we have to examine fewer rectangles.
       
  2639      */
       
  2640     miSetExtents(dest);
       
  2641 }
       
  2642 
       
  2643 static void XorRegion(QRegionPrivate *sra, QRegionPrivate *srb, QRegionPrivate &dest)
       
  2644 {
       
  2645     Q_ASSERT(!isEmptyHelper(sra) && !isEmptyHelper(srb));
       
  2646     Q_ASSERT(EXTENTCHECK(&sra->extents, &srb->extents));
       
  2647     Q_ASSERT(!EqualRegion(sra, srb));
       
  2648 
       
  2649     QRegionPrivate tra, trb;
       
  2650 
       
  2651     if (!srb->contains(*sra))
       
  2652         SubtractRegion(sra, srb, tra);
       
  2653     if (!sra->contains(*srb))
       
  2654         SubtractRegion(srb, sra, trb);
       
  2655 
       
  2656     Q_ASSERT(isEmptyHelper(&trb) || !tra.contains(trb));
       
  2657     Q_ASSERT(isEmptyHelper(&tra) || !trb.contains(tra));
       
  2658 
       
  2659     if (isEmptyHelper(&tra)) {
       
  2660         dest = trb;
       
  2661     } else if (isEmptyHelper(&trb)) {
       
  2662         dest = tra;
       
  2663     } else if (tra.canAppend(&trb)) {
       
  2664         dest = tra;
       
  2665         dest.append(&trb);
       
  2666     } else if (trb.canAppend(&tra)) {
       
  2667         dest = trb;
       
  2668         dest.append(&tra);
       
  2669     } else {
       
  2670         UnionRegion(&tra, &trb, dest);
       
  2671     }
       
  2672 }
       
  2673 
       
  2674 /*
       
  2675  *      Check to see if two regions are equal
       
  2676  */
       
  2677 static bool EqualRegion(const QRegionPrivate *r1, const QRegionPrivate *r2)
       
  2678 {
       
  2679     if (r1->numRects != r2->numRects) {
       
  2680         return false;
       
  2681     } else if (r1->numRects == 0) {
       
  2682         return true;
       
  2683     } else if (r1->extents != r2->extents) {
       
  2684         return false;
       
  2685     } else if (r1->numRects == 1 && r2->numRects == 1) {
       
  2686         return true; // equality tested in previous if-statement
       
  2687     } else {
       
  2688         const QRect *rr1 = (r1->numRects == 1) ? &r1->extents : r1->rects.constData();
       
  2689         const QRect *rr2 = (r2->numRects == 1) ? &r2->extents : r2->rects.constData();
       
  2690         for (int i = 0; i < r1->numRects; ++i, ++rr1, ++rr2) {
       
  2691             if (*rr1 != *rr2)
       
  2692                 return false;
       
  2693         }
       
  2694     }
       
  2695 
       
  2696     return true;
       
  2697 }
       
  2698 
       
  2699 static bool PointInRegion(QRegionPrivate *pRegion, int x, int y)
       
  2700 {
       
  2701     int i;
       
  2702 
       
  2703     if (isEmptyHelper(pRegion))
       
  2704         return false;
       
  2705     if (!pRegion->extents.contains(x, y))
       
  2706         return false;
       
  2707     if (pRegion->numRects == 1)
       
  2708         return pRegion->extents.contains(x, y);
       
  2709     if (pRegion->innerRect.contains(x, y))
       
  2710         return true;
       
  2711     for (i = 0; i < pRegion->numRects; ++i) {
       
  2712         if (pRegion->rects[i].contains(x, y))
       
  2713             return true;
       
  2714     }
       
  2715     return false;
       
  2716 }
       
  2717 
       
  2718 static bool RectInRegion(register QRegionPrivate *region, int rx, int ry, uint rwidth, uint rheight)
       
  2719 {
       
  2720     register const QRect *pbox;
       
  2721     register const QRect *pboxEnd;
       
  2722     QRect rect(rx, ry, rwidth, rheight);
       
  2723     register QRect *prect = &rect;
       
  2724     int partIn, partOut;
       
  2725 
       
  2726     if (!region || region->numRects == 0 || !EXTENTCHECK(&region->extents, prect))
       
  2727         return RectangleOut;
       
  2728 
       
  2729     partOut = false;
       
  2730     partIn = false;
       
  2731 
       
  2732     /* can stop when both partOut and partIn are true, or we reach prect->y2 */
       
  2733     pbox = (region->numRects == 1) ? &region->extents : region->rects.constData();
       
  2734     pboxEnd = pbox + region->numRects;
       
  2735     for (; pbox < pboxEnd; ++pbox) {
       
  2736         if (pbox->bottom() < ry)
       
  2737            continue;
       
  2738 
       
  2739         if (pbox->top() > ry) {
       
  2740            partOut = true;
       
  2741            if (partIn || pbox->top() > prect->bottom())
       
  2742               break;
       
  2743            ry = pbox->top();
       
  2744         }
       
  2745 
       
  2746         if (pbox->right() < rx)
       
  2747            continue;            /* not far enough over yet */
       
  2748 
       
  2749         if (pbox->left() > rx) {
       
  2750            partOut = true;      /* missed part of rectangle to left */
       
  2751            if (partIn)
       
  2752               break;
       
  2753         }
       
  2754 
       
  2755         if (pbox->left() <= prect->right()) {
       
  2756             partIn = true;      /* definitely overlap */
       
  2757             if (partOut)
       
  2758                break;
       
  2759         }
       
  2760 
       
  2761         if (pbox->right() >= prect->right()) {
       
  2762            ry = pbox->bottom() + 1;     /* finished with this band */
       
  2763            if (ry > prect->bottom())
       
  2764               break;
       
  2765            rx = prect->left();  /* reset x out to left again */
       
  2766         } else {
       
  2767             /*
       
  2768              * Because boxes in a band are maximal width, if the first box
       
  2769              * to overlap the rectangle doesn't completely cover it in that
       
  2770              * band, the rectangle must be partially out, since some of it
       
  2771              * will be uncovered in that band. partIn will have been set true
       
  2772              * by now...
       
  2773              */
       
  2774             break;
       
  2775         }
       
  2776     }
       
  2777     return partIn ? ((ry <= prect->bottom()) ? RectanglePart : RectangleIn) : RectangleOut;
       
  2778 }
       
  2779 // END OF Region.c extract
       
  2780 // START OF poly.h extract
       
  2781 /* $XConsortium: poly.h,v 1.4 94/04/17 20:22:19 rws Exp $ */
       
  2782 /************************************************************************
       
  2783 
       
  2784 Copyright (c) 1987  X Consortium
       
  2785 
       
  2786 Permission is hereby granted, free of charge, to any person obtaining a copy
       
  2787 of this software and associated documentation files (the "Software"), to deal
       
  2788 in the Software without restriction, including without limitation the rights
       
  2789 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
  2790 copies of the Software, and to permit persons to whom the Software is
       
  2791 furnished to do so, subject to the following conditions:
       
  2792 
       
  2793 The above copyright notice and this permission notice shall be included in
       
  2794 all copies or substantial portions of the Software.
       
  2795 
       
  2796 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
  2797 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
  2798 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
       
  2799 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
       
  2800 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
  2801 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
  2802 
       
  2803 Except as contained in this notice, the name of the X Consortium shall not be
       
  2804 used in advertising or otherwise to promote the sale, use or other dealings
       
  2805 in this Software without prior written authorization from the X Consortium.
       
  2806 
       
  2807 
       
  2808 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
       
  2809 
       
  2810                         All Rights Reserved
       
  2811 
       
  2812 Permission to use, copy, modify, and distribute this software and its
       
  2813 documentation for any purpose and without fee is hereby granted,
       
  2814 provided that the above copyright notice appear in all copies and that
       
  2815 both that copyright notice and this permission notice appear in
       
  2816 supporting documentation, and that the name of Digital not be
       
  2817 used in advertising or publicity pertaining to distribution of the
       
  2818 software without specific, written prior permission.
       
  2819 
       
  2820 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
       
  2821 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
       
  2822 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
       
  2823 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
       
  2824 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
       
  2825 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
       
  2826 SOFTWARE.
       
  2827 
       
  2828 ************************************************************************/
       
  2829 
       
  2830 /*
       
  2831  *     This file contains a few macros to help track
       
  2832  *     the edge of a filled object.  The object is assumed
       
  2833  *     to be filled in scanline order, and thus the
       
  2834  *     algorithm used is an extension of Bresenham's line
       
  2835  *     drawing algorithm which assumes that y is always the
       
  2836  *     major axis.
       
  2837  *     Since these pieces of code are the same for any filled shape,
       
  2838  *     it is more convenient to gather the library in one
       
  2839  *     place, but since these pieces of code are also in
       
  2840  *     the inner loops of output primitives, procedure call
       
  2841  *     overhead is out of the question.
       
  2842  *     See the author for a derivation if needed.
       
  2843  */
       
  2844 
       
  2845 
       
  2846 /*
       
  2847  *  In scan converting polygons, we want to choose those pixels
       
  2848  *  which are inside the polygon.  Thus, we add .5 to the starting
       
  2849  *  x coordinate for both left and right edges.  Now we choose the
       
  2850  *  first pixel which is inside the pgon for the left edge and the
       
  2851  *  first pixel which is outside the pgon for the right edge.
       
  2852  *  Draw the left pixel, but not the right.
       
  2853  *
       
  2854  *  How to add .5 to the starting x coordinate:
       
  2855  *      If the edge is moving to the right, then subtract dy from the
       
  2856  *  error term from the general form of the algorithm.
       
  2857  *      If the edge is moving to the left, then add dy to the error term.
       
  2858  *
       
  2859  *  The reason for the difference between edges moving to the left
       
  2860  *  and edges moving to the right is simple:  If an edge is moving
       
  2861  *  to the right, then we want the algorithm to flip immediately.
       
  2862  *  If it is moving to the left, then we don't want it to flip until
       
  2863  *  we traverse an entire pixel.
       
  2864  */
       
  2865 #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
       
  2866     int dx;      /* local storage */ \
       
  2867 \
       
  2868     /* \
       
  2869      *  if the edge is horizontal, then it is ignored \
       
  2870      *  and assumed not to be processed.  Otherwise, do this stuff. \
       
  2871      */ \
       
  2872     if ((dy) != 0) { \
       
  2873         xStart = (x1); \
       
  2874         dx = (x2) - xStart; \
       
  2875         if (dx < 0) { \
       
  2876             m = dx / (dy); \
       
  2877             m1 = m - 1; \
       
  2878             incr1 = -2 * dx + 2 * (dy) * m1; \
       
  2879             incr2 = -2 * dx + 2 * (dy) * m; \
       
  2880             d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
       
  2881         } else { \
       
  2882             m = dx / (dy); \
       
  2883             m1 = m + 1; \
       
  2884             incr1 = 2 * dx - 2 * (dy) * m1; \
       
  2885             incr2 = 2 * dx - 2 * (dy) * m; \
       
  2886             d = -2 * m * (dy) + 2 * dx; \
       
  2887         } \
       
  2888     } \
       
  2889 }
       
  2890 
       
  2891 #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
       
  2892     if (m1 > 0) { \
       
  2893         if (d > 0) { \
       
  2894             minval += m1; \
       
  2895             d += incr1; \
       
  2896         } \
       
  2897         else { \
       
  2898             minval += m; \
       
  2899             d += incr2; \
       
  2900         } \
       
  2901     } else {\
       
  2902         if (d >= 0) { \
       
  2903             minval += m1; \
       
  2904             d += incr1; \
       
  2905         } \
       
  2906         else { \
       
  2907             minval += m; \
       
  2908             d += incr2; \
       
  2909         } \
       
  2910     } \
       
  2911 }
       
  2912 
       
  2913 
       
  2914 /*
       
  2915  *     This structure contains all of the information needed
       
  2916  *     to run the bresenham algorithm.
       
  2917  *     The variables may be hardcoded into the declarations
       
  2918  *     instead of using this structure to make use of
       
  2919  *     register declarations.
       
  2920  */
       
  2921 typedef struct {
       
  2922     int minor_axis;     /* minor axis        */
       
  2923     int d;              /* decision variable */
       
  2924     int m, m1;          /* slope and slope+1 */
       
  2925     int incr1, incr2;   /* error increments */
       
  2926 } BRESINFO;
       
  2927 
       
  2928 
       
  2929 #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
       
  2930         BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
       
  2931                      bres.m, bres.m1, bres.incr1, bres.incr2)
       
  2932 
       
  2933 #define BRESINCRPGONSTRUCT(bres) \
       
  2934         BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
       
  2935 
       
  2936 
       
  2937 
       
  2938 /*
       
  2939  *     These are the data structures needed to scan
       
  2940  *     convert regions.  Two different scan conversion
       
  2941  *     methods are available -- the even-odd method, and
       
  2942  *     the winding number method.
       
  2943  *     The even-odd rule states that a point is inside
       
  2944  *     the polygon if a ray drawn from that point in any
       
  2945  *     direction will pass through an odd number of
       
  2946  *     path segments.
       
  2947  *     By the winding number rule, a point is decided
       
  2948  *     to be inside the polygon if a ray drawn from that
       
  2949  *     point in any direction passes through a different
       
  2950  *     number of clockwise and counter-clockwise path
       
  2951  *     segments.
       
  2952  *
       
  2953  *     These data structures are adapted somewhat from
       
  2954  *     the algorithm in (Foley/Van Dam) for scan converting
       
  2955  *     polygons.
       
  2956  *     The basic algorithm is to start at the top (smallest y)
       
  2957  *     of the polygon, stepping down to the bottom of
       
  2958  *     the polygon by incrementing the y coordinate.  We
       
  2959  *     keep a list of edges which the current scanline crosses,
       
  2960  *     sorted by x.  This list is called the Active Edge Table (AET)
       
  2961  *     As we change the y-coordinate, we update each entry in
       
  2962  *     in the active edge table to reflect the edges new xcoord.
       
  2963  *     This list must be sorted at each scanline in case
       
  2964  *     two edges intersect.
       
  2965  *     We also keep a data structure known as the Edge Table (ET),
       
  2966  *     which keeps track of all the edges which the current
       
  2967  *     scanline has not yet reached.  The ET is basically a
       
  2968  *     list of ScanLineList structures containing a list of
       
  2969  *     edges which are entered at a given scanline.  There is one
       
  2970  *     ScanLineList per scanline at which an edge is entered.
       
  2971  *     When we enter a new edge, we move it from the ET to the AET.
       
  2972  *
       
  2973  *     From the AET, we can implement the even-odd rule as in
       
  2974  *     (Foley/Van Dam).
       
  2975  *     The winding number rule is a little trickier.  We also
       
  2976  *     keep the EdgeTableEntries in the AET linked by the
       
  2977  *     nextWETE (winding EdgeTableEntry) link.  This allows
       
  2978  *     the edges to be linked just as before for updating
       
  2979  *     purposes, but only uses the edges linked by the nextWETE
       
  2980  *     link as edges representing spans of the polygon to
       
  2981  *     drawn (as with the even-odd rule).
       
  2982  */
       
  2983 
       
  2984 /*
       
  2985  * for the winding number rule
       
  2986  */
       
  2987 #define CLOCKWISE          1
       
  2988 #define COUNTERCLOCKWISE  -1
       
  2989 
       
  2990 typedef struct _EdgeTableEntry {
       
  2991      int ymax;             /* ycoord at which we exit this edge. */
       
  2992      BRESINFO bres;        /* Bresenham info to run the edge     */
       
  2993      struct _EdgeTableEntry *next;       /* next in the list     */
       
  2994      struct _EdgeTableEntry *back;       /* for insertion sort   */
       
  2995      struct _EdgeTableEntry *nextWETE;   /* for winding num rule */
       
  2996      int ClockWise;        /* flag for winding number rule       */
       
  2997 } EdgeTableEntry;
       
  2998 
       
  2999 
       
  3000 typedef struct _ScanLineList{
       
  3001      int scanline;              /* the scanline represented */
       
  3002      EdgeTableEntry *edgelist;  /* header node              */
       
  3003      struct _ScanLineList *next;  /* next in the list       */
       
  3004 } ScanLineList;
       
  3005 
       
  3006 
       
  3007 typedef struct {
       
  3008      int ymax;                 /* ymax for the polygon     */
       
  3009      int ymin;                 /* ymin for the polygon     */
       
  3010      ScanLineList scanlines;   /* header node              */
       
  3011 } EdgeTable;
       
  3012 
       
  3013 
       
  3014 /*
       
  3015  * Here is a struct to help with storage allocation
       
  3016  * so we can allocate a big chunk at a time, and then take
       
  3017  * pieces from this heap when we need to.
       
  3018  */
       
  3019 #define SLLSPERBLOCK 25
       
  3020 
       
  3021 typedef struct _ScanLineListBlock {
       
  3022      ScanLineList SLLs[SLLSPERBLOCK];
       
  3023      struct _ScanLineListBlock *next;
       
  3024 } ScanLineListBlock;
       
  3025 
       
  3026 
       
  3027 
       
  3028 /*
       
  3029  *
       
  3030  *     a few macros for the inner loops of the fill code where
       
  3031  *     performance considerations don't allow a procedure call.
       
  3032  *
       
  3033  *     Evaluate the given edge at the given scanline.
       
  3034  *     If the edge has expired, then we leave it and fix up
       
  3035  *     the active edge table; otherwise, we increment the
       
  3036  *     x value to be ready for the next scanline.
       
  3037  *     The winding number rule is in effect, so we must notify
       
  3038  *     the caller when the edge has been removed so he
       
  3039  *     can reorder the Winding Active Edge Table.
       
  3040  */
       
  3041 #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
       
  3042    if (pAET->ymax == y) {          /* leaving this edge */ \
       
  3043       pPrevAET->next = pAET->next; \
       
  3044       pAET = pPrevAET->next; \
       
  3045       fixWAET = 1; \
       
  3046       if (pAET) \
       
  3047          pAET->back = pPrevAET; \
       
  3048    } \
       
  3049    else { \
       
  3050       BRESINCRPGONSTRUCT(pAET->bres) \
       
  3051       pPrevAET = pAET; \
       
  3052       pAET = pAET->next; \
       
  3053    } \
       
  3054 }
       
  3055 
       
  3056 
       
  3057 /*
       
  3058  *     Evaluate the given edge at the given scanline.
       
  3059  *     If the edge has expired, then we leave it and fix up
       
  3060  *     the active edge table; otherwise, we increment the
       
  3061  *     x value to be ready for the next scanline.
       
  3062  *     The even-odd rule is in effect.
       
  3063  */
       
  3064 #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
       
  3065    if (pAET->ymax == y) {          /* leaving this edge */ \
       
  3066       pPrevAET->next = pAET->next; \
       
  3067       pAET = pPrevAET->next; \
       
  3068       if (pAET) \
       
  3069          pAET->back = pPrevAET; \
       
  3070    } \
       
  3071    else { \
       
  3072       BRESINCRPGONSTRUCT(pAET->bres) \
       
  3073       pPrevAET = pAET; \
       
  3074       pAET = pAET->next; \
       
  3075    } \
       
  3076 }
       
  3077 // END OF poly.h extract
       
  3078 // START OF PolyReg.c extract
       
  3079 /* $XConsortium: PolyReg.c,v 11.23 94/11/17 21:59:37 converse Exp $ */
       
  3080 /************************************************************************
       
  3081 
       
  3082 Copyright (c) 1987  X Consortium
       
  3083 
       
  3084 Permission is hereby granted, free of charge, to any person obtaining a copy
       
  3085 of this software and associated documentation files (the "Software"), to deal
       
  3086 in the Software without restriction, including without limitation the rights
       
  3087 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
  3088 copies of the Software, and to permit persons to whom the Software is
       
  3089 furnished to do so, subject to the following conditions:
       
  3090 
       
  3091 The above copyright notice and this permission notice shall be included in
       
  3092 all copies or substantial portions of the Software.
       
  3093 
       
  3094 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
  3095 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
  3096 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
       
  3097 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
       
  3098 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
  3099 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
  3100 
       
  3101 Except as contained in this notice, the name of the X Consortium shall not be
       
  3102 used in advertising or otherwise to promote the sale, use or other dealings
       
  3103 in this Software without prior written authorization from the X Consortium.
       
  3104 
       
  3105 
       
  3106 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
       
  3107 
       
  3108                         All Rights Reserved
       
  3109 
       
  3110 Permission to use, copy, modify, and distribute this software and its
       
  3111 documentation for any purpose and without fee is hereby granted,
       
  3112 provided that the above copyright notice appear in all copies and that
       
  3113 both that copyright notice and this permission notice appear in
       
  3114 supporting documentation, and that the name of Digital not be
       
  3115 used in advertising or publicity pertaining to distribution of the
       
  3116 software without specific, written prior permission.
       
  3117 
       
  3118 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
       
  3119 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
       
  3120 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
       
  3121 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
       
  3122 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
       
  3123 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
       
  3124 SOFTWARE.
       
  3125 
       
  3126 ************************************************************************/
       
  3127 /* $XFree86: xc/lib/X11/PolyReg.c,v 1.1.1.2.8.2 1998/10/04 15:22:49 hohndel Exp $ */
       
  3128 
       
  3129 #define LARGE_COORDINATE 1000000
       
  3130 #define SMALL_COORDINATE -LARGE_COORDINATE
       
  3131 
       
  3132 /*
       
  3133  *     InsertEdgeInET
       
  3134  *
       
  3135  *     Insert the given edge into the edge table.
       
  3136  *     First we must find the correct bucket in the
       
  3137  *     Edge table, then find the right slot in the
       
  3138  *     bucket.  Finally, we can insert it.
       
  3139  *
       
  3140  */
       
  3141 static void InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline,
       
  3142                            ScanLineListBlock **SLLBlock, int *iSLLBlock)
       
  3143 {
       
  3144     register EdgeTableEntry *start, *prev;
       
  3145     register ScanLineList *pSLL, *pPrevSLL;
       
  3146     ScanLineListBlock *tmpSLLBlock;
       
  3147 
       
  3148     /*
       
  3149      * find the right bucket to put the edge into
       
  3150      */
       
  3151     pPrevSLL = &ET->scanlines;
       
  3152     pSLL = pPrevSLL->next;
       
  3153     while (pSLL && (pSLL->scanline < scanline)) {
       
  3154         pPrevSLL = pSLL;
       
  3155         pSLL = pSLL->next;
       
  3156     }
       
  3157 
       
  3158     /*
       
  3159      * reassign pSLL (pointer to ScanLineList) if necessary
       
  3160      */
       
  3161     if ((!pSLL) || (pSLL->scanline > scanline)) {
       
  3162         if (*iSLLBlock > SLLSPERBLOCK-1)
       
  3163         {
       
  3164             tmpSLLBlock =
       
  3165                   (ScanLineListBlock *)malloc(sizeof(ScanLineListBlock));
       
  3166             Q_CHECK_PTR(tmpSLLBlock);
       
  3167             (*SLLBlock)->next = tmpSLLBlock;
       
  3168             tmpSLLBlock->next = (ScanLineListBlock *)NULL;
       
  3169             *SLLBlock = tmpSLLBlock;
       
  3170             *iSLLBlock = 0;
       
  3171         }
       
  3172         pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
       
  3173 
       
  3174         pSLL->next = pPrevSLL->next;
       
  3175         pSLL->edgelist = (EdgeTableEntry *)NULL;
       
  3176         pPrevSLL->next = pSLL;
       
  3177     }
       
  3178     pSLL->scanline = scanline;
       
  3179 
       
  3180     /*
       
  3181      * now insert the edge in the right bucket
       
  3182      */
       
  3183     prev = 0;
       
  3184     start = pSLL->edgelist;
       
  3185     while (start && (start->bres.minor_axis < ETE->bres.minor_axis)) {
       
  3186         prev = start;
       
  3187         start = start->next;
       
  3188     }
       
  3189     ETE->next = start;
       
  3190 
       
  3191     if (prev)
       
  3192         prev->next = ETE;
       
  3193     else
       
  3194         pSLL->edgelist = ETE;
       
  3195 }
       
  3196 
       
  3197 /*
       
  3198  *     CreateEdgeTable
       
  3199  *
       
  3200  *     This routine creates the edge table for
       
  3201  *     scan converting polygons.
       
  3202  *     The Edge Table (ET) looks like:
       
  3203  *
       
  3204  *    EdgeTable
       
  3205  *     --------
       
  3206  *    |  ymax  |        ScanLineLists
       
  3207  *    |scanline|-->------------>-------------->...
       
  3208  *     --------   |scanline|   |scanline|
       
  3209  *                |edgelist|   |edgelist|
       
  3210  *                ---------    ---------
       
  3211  *                    |             |
       
  3212  *                    |             |
       
  3213  *                    V             V
       
  3214  *              list of ETEs   list of ETEs
       
  3215  *
       
  3216  *     where ETE is an EdgeTableEntry data structure,
       
  3217  *     and there is one ScanLineList per scanline at
       
  3218  *     which an edge is initially entered.
       
  3219  *
       
  3220  */
       
  3221 
       
  3222 static void CreateETandAET(register int count, register const QPoint *pts,
       
  3223                            EdgeTable *ET, EdgeTableEntry *AET, register EdgeTableEntry *pETEs,
       
  3224                            ScanLineListBlock *pSLLBlock)
       
  3225 {
       
  3226     register const QPoint *top,
       
  3227                           *bottom,
       
  3228                           *PrevPt,
       
  3229                           *CurrPt;
       
  3230     int iSLLBlock = 0;
       
  3231     int dy;
       
  3232 
       
  3233     if (count < 2)
       
  3234         return;
       
  3235 
       
  3236     /*
       
  3237      *  initialize the Active Edge Table
       
  3238      */
       
  3239     AET->next = 0;
       
  3240     AET->back = 0;
       
  3241     AET->nextWETE = 0;
       
  3242     AET->bres.minor_axis = SMALL_COORDINATE;
       
  3243 
       
  3244     /*
       
  3245      *  initialize the Edge Table.
       
  3246      */
       
  3247     ET->scanlines.next = 0;
       
  3248     ET->ymax = SMALL_COORDINATE;
       
  3249     ET->ymin = LARGE_COORDINATE;
       
  3250     pSLLBlock->next = 0;
       
  3251 
       
  3252     PrevPt = &pts[count - 1];
       
  3253 
       
  3254     /*
       
  3255      *  for each vertex in the array of points.
       
  3256      *  In this loop we are dealing with two vertices at
       
  3257      *  a time -- these make up one edge of the polygon.
       
  3258      */
       
  3259     while (count--) {
       
  3260         CurrPt = pts++;
       
  3261 
       
  3262         /*
       
  3263          *  find out which point is above and which is below.
       
  3264          */
       
  3265         if (PrevPt->y() > CurrPt->y()) {
       
  3266             bottom = PrevPt;
       
  3267             top = CurrPt;
       
  3268             pETEs->ClockWise = 0;
       
  3269         } else {
       
  3270             bottom = CurrPt;
       
  3271             top = PrevPt;
       
  3272             pETEs->ClockWise = 1;
       
  3273         }
       
  3274 
       
  3275         /*
       
  3276          * don't add horizontal edges to the Edge table.
       
  3277          */
       
  3278         if (bottom->y() != top->y()) {
       
  3279             pETEs->ymax = bottom->y() - 1;  /* -1 so we don't get last scanline */
       
  3280 
       
  3281             /*
       
  3282              *  initialize integer edge algorithm
       
  3283              */
       
  3284             dy = bottom->y() - top->y();
       
  3285             BRESINITPGONSTRUCT(dy, top->x(), bottom->x(), pETEs->bres)
       
  3286 
       
  3287             InsertEdgeInET(ET, pETEs, top->y(), &pSLLBlock, &iSLLBlock);
       
  3288 
       
  3289             if (PrevPt->y() > ET->ymax)
       
  3290                 ET->ymax = PrevPt->y();
       
  3291             if (PrevPt->y() < ET->ymin)
       
  3292                 ET->ymin = PrevPt->y();
       
  3293             ++pETEs;
       
  3294         }
       
  3295 
       
  3296         PrevPt = CurrPt;
       
  3297     }
       
  3298 }
       
  3299 
       
  3300 /*
       
  3301  *     loadAET
       
  3302  *
       
  3303  *     This routine moves EdgeTableEntries from the
       
  3304  *     EdgeTable into the Active Edge Table,
       
  3305  *     leaving them sorted by smaller x coordinate.
       
  3306  *
       
  3307  */
       
  3308 
       
  3309 static void loadAET(register EdgeTableEntry *AET, register EdgeTableEntry *ETEs)
       
  3310 {
       
  3311     register EdgeTableEntry *pPrevAET;
       
  3312     register EdgeTableEntry *tmp;
       
  3313 
       
  3314     pPrevAET = AET;
       
  3315     AET = AET->next;
       
  3316     while (ETEs) {
       
  3317         while (AET && AET->bres.minor_axis < ETEs->bres.minor_axis) {
       
  3318             pPrevAET = AET;
       
  3319             AET = AET->next;
       
  3320         }
       
  3321         tmp = ETEs->next;
       
  3322         ETEs->next = AET;
       
  3323         if (AET)
       
  3324             AET->back = ETEs;
       
  3325         ETEs->back = pPrevAET;
       
  3326         pPrevAET->next = ETEs;
       
  3327         pPrevAET = ETEs;
       
  3328 
       
  3329         ETEs = tmp;
       
  3330     }
       
  3331 }
       
  3332 
       
  3333 /*
       
  3334  *     computeWAET
       
  3335  *
       
  3336  *     This routine links the AET by the
       
  3337  *     nextWETE (winding EdgeTableEntry) link for
       
  3338  *     use by the winding number rule.  The final
       
  3339  *     Active Edge Table (AET) might look something
       
  3340  *     like:
       
  3341  *
       
  3342  *     AET
       
  3343  *     ----------  ---------   ---------
       
  3344  *     |ymax    |  |ymax    |  |ymax    |
       
  3345  *     | ...    |  |...     |  |...     |
       
  3346  *     |next    |->|next    |->|next    |->...
       
  3347  *     |nextWETE|  |nextWETE|  |nextWETE|
       
  3348  *     ---------   ---------   ^--------
       
  3349  *         |                   |       |
       
  3350  *         V------------------->       V---> ...
       
  3351  *
       
  3352  */
       
  3353 static void computeWAET(register EdgeTableEntry *AET)
       
  3354 {
       
  3355     register EdgeTableEntry *pWETE;
       
  3356     register int inside = 1;
       
  3357     register int isInside = 0;
       
  3358 
       
  3359     AET->nextWETE = 0;
       
  3360     pWETE = AET;
       
  3361     AET = AET->next;
       
  3362     while (AET) {
       
  3363         if (AET->ClockWise)
       
  3364             ++isInside;
       
  3365         else
       
  3366             --isInside;
       
  3367 
       
  3368         if ((!inside && !isInside) || (inside && isInside)) {
       
  3369             pWETE->nextWETE = AET;
       
  3370             pWETE = AET;
       
  3371             inside = !inside;
       
  3372         }
       
  3373         AET = AET->next;
       
  3374     }
       
  3375     pWETE->nextWETE = 0;
       
  3376 }
       
  3377 
       
  3378 /*
       
  3379  *     InsertionSort
       
  3380  *
       
  3381  *     Just a simple insertion sort using
       
  3382  *     pointers and back pointers to sort the Active
       
  3383  *     Edge Table.
       
  3384  *
       
  3385  */
       
  3386 
       
  3387 static int InsertionSort(register EdgeTableEntry *AET)
       
  3388 {
       
  3389     register EdgeTableEntry *pETEchase;
       
  3390     register EdgeTableEntry *pETEinsert;
       
  3391     register EdgeTableEntry *pETEchaseBackTMP;
       
  3392     register int changed = 0;
       
  3393 
       
  3394     AET = AET->next;
       
  3395     while (AET) {
       
  3396         pETEinsert = AET;
       
  3397         pETEchase = AET;
       
  3398         while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
       
  3399             pETEchase = pETEchase->back;
       
  3400 
       
  3401         AET = AET->next;
       
  3402         if (pETEchase != pETEinsert) {
       
  3403             pETEchaseBackTMP = pETEchase->back;
       
  3404             pETEinsert->back->next = AET;
       
  3405             if (AET)
       
  3406                 AET->back = pETEinsert->back;
       
  3407             pETEinsert->next = pETEchase;
       
  3408             pETEchase->back->next = pETEinsert;
       
  3409             pETEchase->back = pETEinsert;
       
  3410             pETEinsert->back = pETEchaseBackTMP;
       
  3411             changed = 1;
       
  3412         }
       
  3413     }
       
  3414     return changed;
       
  3415 }
       
  3416 
       
  3417 /*
       
  3418  *     Clean up our act.
       
  3419  */
       
  3420 static void FreeStorage(register ScanLineListBlock *pSLLBlock)
       
  3421 {
       
  3422     register ScanLineListBlock *tmpSLLBlock;
       
  3423 
       
  3424     while (pSLLBlock) {
       
  3425         tmpSLLBlock = pSLLBlock->next;
       
  3426         free(pSLLBlock);
       
  3427         pSLLBlock = tmpSLLBlock;
       
  3428     }
       
  3429 }
       
  3430 
       
  3431 struct QRegionSpan {
       
  3432     QRegionSpan() {}
       
  3433     QRegionSpan(int x1_, int x2_) : x1(x1_), x2(x2_) {}
       
  3434 
       
  3435     int x1;
       
  3436     int x2;
       
  3437     int width() const { return x2 - x1; }
       
  3438 };
       
  3439 
       
  3440 Q_DECLARE_TYPEINFO(QRegionSpan, Q_PRIMITIVE_TYPE);
       
  3441 
       
  3442 static inline void flushRow(const QRegionSpan *spans, int y, int numSpans, QRegionPrivate *reg, int *lastRow, int *extendTo, bool *needsExtend)
       
  3443 {
       
  3444     QRect *regRects = reg->rects.data() + *lastRow;
       
  3445     bool canExtend = reg->rects.size() - *lastRow == numSpans
       
  3446         && !(*needsExtend && *extendTo + 1 != y)
       
  3447         && (*needsExtend || regRects[0].y() + regRects[0].height() == y);
       
  3448 
       
  3449     for (int i = 0; i < numSpans && canExtend; ++i) {
       
  3450         if (regRects[i].x() != spans[i].x1 || regRects[i].right() != spans[i].x2 - 1)
       
  3451             canExtend = false;
       
  3452     }
       
  3453 
       
  3454     if (canExtend) {
       
  3455         *extendTo = y;
       
  3456         *needsExtend = true;
       
  3457     } else {
       
  3458         if (*needsExtend) {
       
  3459             for (int i = 0; i < reg->rects.size() - *lastRow; ++i)
       
  3460                 regRects[i].setBottom(*extendTo);
       
  3461         }
       
  3462 
       
  3463         *lastRow = reg->rects.size();
       
  3464         reg->rects.reserve(*lastRow + numSpans);
       
  3465         for (int i = 0; i < numSpans; ++i)
       
  3466             reg->rects << QRect(spans[i].x1, y, spans[i].width(), 1);
       
  3467 
       
  3468         if (spans[0].x1 < reg->extents.left())
       
  3469             reg->extents.setLeft(spans[0].x1);
       
  3470 
       
  3471         if (spans[numSpans-1].x2 - 1 > reg->extents.right())
       
  3472             reg->extents.setRight(spans[numSpans-1].x2 - 1);
       
  3473 
       
  3474         *needsExtend = false;
       
  3475     }
       
  3476 }
       
  3477 
       
  3478 /*
       
  3479  *     Create an array of rectangles from a list of points.
       
  3480  *     If indeed these things (POINTS, RECTS) are the same,
       
  3481  *     then this proc is still needed, because it allocates
       
  3482  *     storage for the array, which was allocated on the
       
  3483  *     stack by the calling procedure.
       
  3484  *
       
  3485  */
       
  3486 static void PtsToRegion(register int numFullPtBlocks, register int iCurPtBlock,
       
  3487                        POINTBLOCK *FirstPtBlock, QRegionPrivate *reg)
       
  3488 {
       
  3489     int lastRow = 0;
       
  3490     int extendTo = 0;
       
  3491     bool needsExtend = false;
       
  3492     QVarLengthArray<QRegionSpan> row;
       
  3493     int rowSize = 0;
       
  3494 
       
  3495     reg->extents.setLeft(INT_MAX);
       
  3496     reg->extents.setRight(INT_MIN);
       
  3497     reg->innerArea = -1;
       
  3498 
       
  3499     POINTBLOCK *CurPtBlock = FirstPtBlock;
       
  3500     for (; numFullPtBlocks >= 0; --numFullPtBlocks) {
       
  3501         /* the loop uses 2 points per iteration */
       
  3502         int i = NUMPTSTOBUFFER >> 1;
       
  3503         if (!numFullPtBlocks)
       
  3504             i = iCurPtBlock >> 1;
       
  3505         if(i) {
       
  3506             row.resize(qMax(row.size(), rowSize + i));
       
  3507             for (QPoint *pts = CurPtBlock->pts; i--; pts += 2) {
       
  3508                 const int width = pts[1].x() - pts[0].x();
       
  3509                 if (width) {
       
  3510                     if (rowSize && row[rowSize-1].x2 == pts[0].x())
       
  3511                         row[rowSize-1].x2 = pts[1].x();
       
  3512                     else
       
  3513                         row[rowSize++] = QRegionSpan(pts[0].x(), pts[1].x());
       
  3514                 }
       
  3515 
       
  3516                 if (rowSize) {
       
  3517                     QPoint *next = i ? &pts[2] : (numFullPtBlocks ? CurPtBlock->next->pts : 0);
       
  3518 
       
  3519                     if (!next || next->y() != pts[0].y()) {
       
  3520                         flushRow(row.data(), pts[0].y(), rowSize, reg, &lastRow, &extendTo, &needsExtend);
       
  3521                         rowSize = 0;
       
  3522                     }
       
  3523                 }
       
  3524             }
       
  3525         }
       
  3526         CurPtBlock = CurPtBlock->next;
       
  3527     }
       
  3528 
       
  3529     if (needsExtend) {
       
  3530         for (int i = lastRow; i < reg->rects.size(); ++i)
       
  3531             reg->rects[i].setBottom(extendTo);
       
  3532     }
       
  3533 
       
  3534     reg->numRects = reg->rects.size();
       
  3535 
       
  3536     if (reg->numRects) {
       
  3537         reg->extents.setTop(reg->rects[0].top());
       
  3538         reg->extents.setBottom(reg->rects[lastRow].bottom());
       
  3539 
       
  3540         for (int i = 0; i < reg->rects.size(); ++i)
       
  3541             reg->updateInnerRect(reg->rects[i]);
       
  3542     } else {
       
  3543         reg->extents.setCoords(0, 0, 0, 0);
       
  3544     }
       
  3545 }
       
  3546 
       
  3547 /*
       
  3548  *     polytoregion
       
  3549  *
       
  3550  *     Scan converts a polygon by returning a run-length
       
  3551  *     encoding of the resultant bitmap -- the run-length
       
  3552  *     encoding is in the form of an array of rectangles.
       
  3553  *
       
  3554  *     Can return 0 in case of errors.
       
  3555  */
       
  3556 static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
       
  3557     //Point     *Pts;                /* the pts                 */
       
  3558     //int       Count;                 /* number of pts           */
       
  3559     //int       rule;                        /* winding rule */
       
  3560 {
       
  3561     QRegionPrivate *region;
       
  3562     register EdgeTableEntry *pAET;   /* Active Edge Table       */
       
  3563     register int y;                  /* current scanline        */
       
  3564     register int iPts = 0;           /* number of pts in buffer */
       
  3565     register EdgeTableEntry *pWETE;  /* Winding Edge Table Entry*/
       
  3566     register ScanLineList *pSLL;     /* current scanLineList    */
       
  3567     register QPoint *pts;             /* output buffer           */
       
  3568     EdgeTableEntry *pPrevAET;        /* ptr to previous AET     */
       
  3569     EdgeTable ET;                    /* header node for ET      */
       
  3570     EdgeTableEntry AET;              /* header node for AET     */
       
  3571     EdgeTableEntry *pETEs;           /* EdgeTableEntries pool   */
       
  3572     ScanLineListBlock SLLBlock;      /* header for scanlinelist */
       
  3573     int fixWAET = false;
       
  3574     POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers    */
       
  3575     FirstPtBlock.pts = reinterpret_cast<QPoint *>(FirstPtBlock.data);
       
  3576     POINTBLOCK *tmpPtBlock;
       
  3577     int numFullPtBlocks = 0;
       
  3578 
       
  3579     if (!(region = new QRegionPrivate))
       
  3580         return 0;
       
  3581 
       
  3582         /* special case a rectangle */
       
  3583     if (((Count == 4) ||
       
  3584          ((Count == 5) && (Pts[4].x() == Pts[0].x()) && (Pts[4].y() == Pts[0].y())))
       
  3585          && (((Pts[0].y() == Pts[1].y()) && (Pts[1].x() == Pts[2].x()) && (Pts[2].y() == Pts[3].y())
       
  3586                && (Pts[3].x() == Pts[0].x())) || ((Pts[0].x() == Pts[1].x())
       
  3587                && (Pts[1].y() == Pts[2].y()) && (Pts[2].x() == Pts[3].x())
       
  3588                && (Pts[3].y() == Pts[0].y())))) {
       
  3589         int x = qMin(Pts[0].x(), Pts[2].x());
       
  3590         region->extents.setLeft(x);
       
  3591         int y = qMin(Pts[0].y(), Pts[2].y());
       
  3592         region->extents.setTop(y);
       
  3593         region->extents.setWidth(qMax(Pts[0].x(), Pts[2].x()) - x);
       
  3594         region->extents.setHeight(qMax(Pts[0].y(), Pts[2].y()) - y);
       
  3595         if ((region->extents.left() <= region->extents.right()) &&
       
  3596             (region->extents.top() <= region->extents.bottom())) {
       
  3597             region->numRects = 1;
       
  3598             region->innerRect = region->extents;
       
  3599             region->innerArea = region->innerRect.width() * region->innerRect.height();
       
  3600         }
       
  3601         return region;
       
  3602     }
       
  3603 
       
  3604     if (!(pETEs = static_cast<EdgeTableEntry *>(malloc(sizeof(EdgeTableEntry) * Count))))
       
  3605         return 0;
       
  3606 
       
  3607     region->vectorize();
       
  3608 
       
  3609     pts = FirstPtBlock.pts;
       
  3610     CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock);
       
  3611 
       
  3612     pSLL = ET.scanlines.next;
       
  3613     curPtBlock = &FirstPtBlock;
       
  3614 
       
  3615     // sanity check that the region won't become too big...
       
  3616     if (ET.ymax - ET.ymin > 100000) {
       
  3617         // clean up region ptr
       
  3618 #ifndef QT_NO_DEBUG
       
  3619         qWarning("QRegion: creating region from big polygon failed...!");
       
  3620 #endif
       
  3621         delete region;
       
  3622         return 0;
       
  3623     }
       
  3624 
       
  3625 
       
  3626     QT_TRY {
       
  3627         if (rule == EvenOddRule) {
       
  3628             /*
       
  3629              *  for each scanline
       
  3630              */
       
  3631             for (y = ET.ymin; y < ET.ymax; ++y) {
       
  3632 
       
  3633                 /*
       
  3634                  *  Add a new edge to the active edge table when we
       
  3635                  *  get to the next edge.
       
  3636                  */
       
  3637                 if (pSLL && y == pSLL->scanline) {
       
  3638                     loadAET(&AET, pSLL->edgelist);
       
  3639                     pSLL = pSLL->next;
       
  3640                 }
       
  3641                 pPrevAET = &AET;
       
  3642                 pAET = AET.next;
       
  3643 
       
  3644                 /*
       
  3645                  *  for each active edge
       
  3646                  */
       
  3647                 while (pAET) {
       
  3648                     pts->setX(pAET->bres.minor_axis);
       
  3649                     pts->setY(y);
       
  3650                     ++pts;
       
  3651                     ++iPts;
       
  3652 
       
  3653                     /*
       
  3654                      *  send out the buffer
       
  3655                      */
       
  3656                     if (iPts == NUMPTSTOBUFFER) {
       
  3657                         tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK));
       
  3658                         Q_CHECK_PTR(tmpPtBlock);
       
  3659                         tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data);
       
  3660                         curPtBlock->next = tmpPtBlock;
       
  3661                         curPtBlock = tmpPtBlock;
       
  3662                         pts = curPtBlock->pts;
       
  3663                         ++numFullPtBlocks;
       
  3664                         iPts = 0;
       
  3665                     }
       
  3666                     EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
       
  3667                 }
       
  3668                 InsertionSort(&AET);
       
  3669             }
       
  3670         } else {
       
  3671             /*
       
  3672              *  for each scanline
       
  3673              */
       
  3674             for (y = ET.ymin; y < ET.ymax; ++y) {
       
  3675                 /*
       
  3676                  *  Add a new edge to the active edge table when we
       
  3677                  *  get to the next edge.
       
  3678                  */
       
  3679                 if (pSLL && y == pSLL->scanline) {
       
  3680                     loadAET(&AET, pSLL->edgelist);
       
  3681                     computeWAET(&AET);
       
  3682                     pSLL = pSLL->next;
       
  3683                 }
       
  3684                 pPrevAET = &AET;
       
  3685                 pAET = AET.next;
       
  3686                 pWETE = pAET;
       
  3687 
       
  3688                 /*
       
  3689                  *  for each active edge
       
  3690                  */
       
  3691                 while (pAET) {
       
  3692                     /*
       
  3693                      *  add to the buffer only those edges that
       
  3694                      *  are in the Winding active edge table.
       
  3695                      */
       
  3696                     if (pWETE == pAET) {
       
  3697                         pts->setX(pAET->bres.minor_axis);
       
  3698                         pts->setY(y);
       
  3699                         ++pts;
       
  3700                         ++iPts;
       
  3701 
       
  3702                         /*
       
  3703                          *  send out the buffer
       
  3704                          */
       
  3705                         if (iPts == NUMPTSTOBUFFER) {
       
  3706                             tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK)));
       
  3707                             tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data);
       
  3708                             curPtBlock->next = tmpPtBlock;
       
  3709                             curPtBlock = tmpPtBlock;
       
  3710                             pts = curPtBlock->pts;
       
  3711                             ++numFullPtBlocks;
       
  3712                             iPts = 0;
       
  3713                         }
       
  3714                         pWETE = pWETE->nextWETE;
       
  3715                     }
       
  3716                     EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
       
  3717                 }
       
  3718 
       
  3719                 /*
       
  3720                  *  recompute the winding active edge table if
       
  3721                  *  we just resorted or have exited an edge.
       
  3722                  */
       
  3723                 if (InsertionSort(&AET) || fixWAET) {
       
  3724                     computeWAET(&AET);
       
  3725                     fixWAET = false;
       
  3726                 }
       
  3727             }
       
  3728         }
       
  3729     } QT_CATCH(...) {
       
  3730         FreeStorage(SLLBlock.next);
       
  3731         PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
       
  3732         for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
       
  3733             tmpPtBlock = curPtBlock->next;
       
  3734             free(curPtBlock);
       
  3735             curPtBlock = tmpPtBlock;
       
  3736         }
       
  3737         free(pETEs);
       
  3738         return 0; // this function returns 0 in case of an error
       
  3739     }
       
  3740 
       
  3741     FreeStorage(SLLBlock.next);
       
  3742     PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
       
  3743     for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
       
  3744         tmpPtBlock = curPtBlock->next;
       
  3745         free(curPtBlock);
       
  3746         curPtBlock = tmpPtBlock;
       
  3747     }
       
  3748     free(pETEs);
       
  3749     return region;
       
  3750 }
       
  3751 // END OF PolyReg.c extract
       
  3752 
       
  3753 QRegionPrivate *qt_bitmapToRegion(const QBitmap& bitmap)
       
  3754 {
       
  3755     QImage image = bitmap.toImage();
       
  3756 
       
  3757     QRegionPrivate *region = new QRegionPrivate;
       
  3758 
       
  3759     QRect xr;
       
  3760 
       
  3761 #define AddSpan \
       
  3762         { \
       
  3763             xr.setCoords(prev1, y, x-1, y); \
       
  3764             UnionRectWithRegion(&xr, region, *region); \
       
  3765         }
       
  3766 
       
  3767     const uchar zero = 0;
       
  3768     bool little = image.format() == QImage::Format_MonoLSB;
       
  3769 
       
  3770     int x,
       
  3771         y;
       
  3772     for (y = 0; y < image.height(); ++y) {
       
  3773         uchar *line = image.scanLine(y);
       
  3774         int w = image.width();
       
  3775         uchar all = zero;
       
  3776         int prev1 = -1;
       
  3777         for (x = 0; x < w;) {
       
  3778             uchar byte = line[x / 8];
       
  3779             if (x > w - 8 || byte!=all) {
       
  3780                 if (little) {
       
  3781                     for (int b = 8; b > 0 && x < w; --b) {
       
  3782                         if (!(byte & 0x01) == !all) {
       
  3783                             // More of the same
       
  3784                         } else {
       
  3785                             // A change.
       
  3786                             if (all!=zero) {
       
  3787                                 AddSpan
       
  3788                                 all = zero;
       
  3789                             } else {
       
  3790                                 prev1 = x;
       
  3791                                 all = ~zero;
       
  3792                             }
       
  3793                         }
       
  3794                         byte >>= 1;
       
  3795                         ++x;
       
  3796                     }
       
  3797                 } else {
       
  3798                     for (int b = 8; b > 0 && x < w; --b) {
       
  3799                         if (!(byte & 0x80) == !all) {
       
  3800                             // More of the same
       
  3801                         } else {
       
  3802                             // A change.
       
  3803                             if (all != zero) {
       
  3804                                 AddSpan
       
  3805                                 all = zero;
       
  3806                             } else {
       
  3807                                 prev1 = x;
       
  3808                                 all = ~zero;
       
  3809                             }
       
  3810                         }
       
  3811                         byte <<= 1;
       
  3812                         ++x;
       
  3813                     }
       
  3814                 }
       
  3815             } else {
       
  3816                 x += 8;
       
  3817             }
       
  3818         }
       
  3819         if (all != zero) {
       
  3820             AddSpan
       
  3821         }
       
  3822     }
       
  3823 #undef AddSpan
       
  3824 
       
  3825     return region;
       
  3826 }
       
  3827 
       
  3828 QRegion::QRegion()
       
  3829     : d(&shared_empty)
       
  3830 {
       
  3831     d->ref.ref();
       
  3832 }
       
  3833 
       
  3834 QRegion::QRegion(const QRect &r, RegionType t)
       
  3835 {
       
  3836     if (r.isEmpty()) {
       
  3837         d = &shared_empty;
       
  3838         d->ref.ref();
       
  3839     } else {
       
  3840         d = new QRegionData;
       
  3841         d->ref = 1;
       
  3842 #if defined(Q_WS_X11)
       
  3843         d->rgn = 0;
       
  3844         d->xrectangles = 0;
       
  3845 #elif defined(Q_WS_WIN)
       
  3846         d->rgn = 0;
       
  3847 #endif
       
  3848         if (t == Rectangle) {
       
  3849             d->qt_rgn = new QRegionPrivate(r);
       
  3850         } else if (t == Ellipse) {
       
  3851             QPainterPath path;
       
  3852             path.addEllipse(r.x(), r.y(), r.width(), r.height());
       
  3853             QPolygon a = path.toSubpathPolygons().at(0).toPolygon();
       
  3854             d->qt_rgn = PolygonRegion(a.constData(), a.size(), EvenOddRule);
       
  3855         }
       
  3856     }
       
  3857 }
       
  3858 
       
  3859 QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
       
  3860 {
       
  3861     if (a.count() > 2) {
       
  3862         d =  new QRegionData;
       
  3863         d->ref = 1;
       
  3864 #if defined(Q_WS_X11)
       
  3865         d->rgn = 0;
       
  3866         d->xrectangles = 0;
       
  3867 #elif defined(Q_WS_WIN)
       
  3868         d->rgn = 0;
       
  3869 #endif
       
  3870         d->qt_rgn = PolygonRegion(a.constData(), a.size(),
       
  3871                                   fillRule == Qt::WindingFill ? WindingRule : EvenOddRule);
       
  3872     } else {
       
  3873         d = &shared_empty;
       
  3874         d->ref.ref();
       
  3875     }
       
  3876 }
       
  3877 
       
  3878 
       
  3879 QRegion::QRegion(const QRegion &r)
       
  3880 {
       
  3881     d = r.d;
       
  3882     d->ref.ref();
       
  3883 }
       
  3884 
       
  3885 
       
  3886 QRegion::QRegion(const QBitmap &bm)
       
  3887 {
       
  3888     if (bm.isNull()) {
       
  3889         d = &shared_empty;
       
  3890         d->ref.ref();
       
  3891     } else {
       
  3892         d = new QRegionData;
       
  3893         d->ref = 1;
       
  3894 #if defined(Q_WS_X11)
       
  3895         d->rgn = 0;
       
  3896         d->xrectangles = 0;
       
  3897 #elif defined(Q_WS_WIN)
       
  3898         d->rgn = 0;
       
  3899 #endif
       
  3900         d->qt_rgn = qt_bitmapToRegion(bm);
       
  3901     }
       
  3902 }
       
  3903 
       
  3904 void QRegion::cleanUp(QRegion::QRegionData *x)
       
  3905 {
       
  3906     delete x->qt_rgn;
       
  3907 #if defined(Q_WS_X11)
       
  3908     if (x->rgn)
       
  3909         XDestroyRegion(x->rgn);
       
  3910     if (x->xrectangles)
       
  3911         free(x->xrectangles);
       
  3912 #elif defined(Q_WS_WIN)
       
  3913     if (x->rgn)
       
  3914         qt_win_dispose_rgn(x->rgn);
       
  3915 #endif
       
  3916     delete x;
       
  3917 }
       
  3918 
       
  3919 QRegion::~QRegion()
       
  3920 {
       
  3921     if (!d->ref.deref())
       
  3922         cleanUp(d);
       
  3923 }
       
  3924 
       
  3925 
       
  3926 QRegion &QRegion::operator=(const QRegion &r)
       
  3927 {
       
  3928     r.d->ref.ref();
       
  3929     if (!d->ref.deref())
       
  3930         cleanUp(d);
       
  3931     d = r.d;
       
  3932     return *this;
       
  3933 }
       
  3934 
       
  3935 
       
  3936 /*!
       
  3937     \internal
       
  3938 */
       
  3939 QRegion QRegion::copy() const
       
  3940 {
       
  3941     QRegion r;
       
  3942     QScopedPointer<QRegionData> x(new QRegionData);
       
  3943     x->ref = 1;
       
  3944 #if defined(Q_WS_X11)
       
  3945     x->rgn = 0;
       
  3946     x->xrectangles = 0;
       
  3947 #elif defined(Q_WS_WIN)
       
  3948     x->rgn = 0;
       
  3949 #endif
       
  3950     if (d->qt_rgn)
       
  3951         x->qt_rgn = new QRegionPrivate(*d->qt_rgn);
       
  3952     else
       
  3953         x->qt_rgn = new QRegionPrivate;
       
  3954     if (!r.d->ref.deref())
       
  3955         cleanUp(r.d);
       
  3956     r.d = x.take();
       
  3957     return r;
       
  3958 }
       
  3959 
       
  3960 bool QRegion::isEmpty() const
       
  3961 {
       
  3962     return d == &shared_empty || d->qt_rgn->numRects == 0;
       
  3963 }
       
  3964 
       
  3965 
       
  3966 bool QRegion::contains(const QPoint &p) const
       
  3967 {
       
  3968     return PointInRegion(d->qt_rgn, p.x(), p.y());
       
  3969 }
       
  3970 
       
  3971 bool QRegion::contains(const QRect &r) const
       
  3972 {
       
  3973     return RectInRegion(d->qt_rgn, r.left(), r.top(), r.width(), r.height()) != RectangleOut;
       
  3974 }
       
  3975 
       
  3976 
       
  3977 
       
  3978 void QRegion::translate(int dx, int dy)
       
  3979 {
       
  3980     if ((dx == 0 && dy == 0) || isEmptyHelper(d->qt_rgn))
       
  3981         return;
       
  3982 
       
  3983     detach();
       
  3984     OffsetRegion(*d->qt_rgn, dx, dy);
       
  3985 }
       
  3986 
       
  3987 QRegion QRegion::unite(const QRegion &r) const
       
  3988 {
       
  3989     if (isEmptyHelper(d->qt_rgn))
       
  3990         return r;
       
  3991     if (isEmptyHelper(r.d->qt_rgn))
       
  3992         return *this;
       
  3993     if (d == r.d)
       
  3994         return *this;
       
  3995 
       
  3996     if (d->qt_rgn->contains(*r.d->qt_rgn)) {
       
  3997         return *this;
       
  3998     } else if (r.d->qt_rgn->contains(*d->qt_rgn)) {
       
  3999         return r;
       
  4000     } else if (d->qt_rgn->canAppend(r.d->qt_rgn)) {
       
  4001         QRegion result(*this);
       
  4002         result.detach();
       
  4003         result.d->qt_rgn->append(r.d->qt_rgn);
       
  4004         return result;
       
  4005     } else if (d->qt_rgn->canPrepend(r.d->qt_rgn)) {
       
  4006         QRegion result(*this);
       
  4007         result.detach();
       
  4008         result.d->qt_rgn->prepend(r.d->qt_rgn);
       
  4009         return result;
       
  4010     } else if (EqualRegion(d->qt_rgn, r.d->qt_rgn)) {
       
  4011         return *this;
       
  4012     } else {
       
  4013         QRegion result;
       
  4014         result.detach();
       
  4015         UnionRegion(d->qt_rgn, r.d->qt_rgn, *result.d->qt_rgn);
       
  4016         return result;
       
  4017     }
       
  4018 }
       
  4019 
       
  4020 QRegion& QRegion::operator+=(const QRegion &r)
       
  4021 {
       
  4022     if (isEmptyHelper(d->qt_rgn))
       
  4023         return *this = r;
       
  4024     if (isEmptyHelper(r.d->qt_rgn))
       
  4025         return *this;
       
  4026     if (d == r.d)
       
  4027         return *this;
       
  4028 
       
  4029     if (d->qt_rgn->contains(*r.d->qt_rgn)) {
       
  4030         return *this;
       
  4031     } else if (r.d->qt_rgn->contains(*d->qt_rgn)) {
       
  4032         return *this = r;
       
  4033     } else if (d->qt_rgn->canAppend(r.d->qt_rgn)) {
       
  4034         detach();
       
  4035         d->qt_rgn->append(r.d->qt_rgn);
       
  4036         return *this;
       
  4037     } else if (d->qt_rgn->canPrepend(r.d->qt_rgn)) {
       
  4038         detach();
       
  4039         d->qt_rgn->prepend(r.d->qt_rgn);
       
  4040         return *this;
       
  4041     } else if (EqualRegion(d->qt_rgn, r.d->qt_rgn)) {
       
  4042         return *this;
       
  4043     } else {
       
  4044         detach();
       
  4045         UnionRegion(d->qt_rgn, r.d->qt_rgn, *d->qt_rgn);
       
  4046         return *this;
       
  4047     }
       
  4048 }
       
  4049 
       
  4050 QRegion QRegion::unite(const QRect &r) const
       
  4051 {
       
  4052     if (isEmptyHelper(d->qt_rgn))
       
  4053         return r;
       
  4054     if (r.isEmpty())
       
  4055         return *this;
       
  4056 
       
  4057     if (d->qt_rgn->contains(r)) {
       
  4058         return *this;
       
  4059     } else if (d->qt_rgn->within(r)) {
       
  4060         return r;
       
  4061     } else if (d->qt_rgn->numRects == 1 && d->qt_rgn->extents == r) {
       
  4062         return *this;
       
  4063     } else if (d->qt_rgn->canAppend(&r)) {
       
  4064         QRegion result(*this);
       
  4065         result.detach();
       
  4066         result.d->qt_rgn->append(&r);
       
  4067         return result;
       
  4068     } else if (d->qt_rgn->canPrepend(&r)) {
       
  4069         QRegion result(*this);
       
  4070         result.detach();
       
  4071         result.d->qt_rgn->prepend(&r);
       
  4072         return result;
       
  4073     } else {
       
  4074         QRegion result;
       
  4075         result.detach();
       
  4076         QRegionPrivate rp(r);
       
  4077         UnionRegion(d->qt_rgn, &rp, *result.d->qt_rgn);
       
  4078         return result;
       
  4079     }
       
  4080 }
       
  4081 
       
  4082 QRegion& QRegion::operator+=(const QRect &r)
       
  4083 {
       
  4084     if (isEmptyHelper(d->qt_rgn))
       
  4085         return *this = r;
       
  4086     if (r.isEmpty())
       
  4087         return *this;
       
  4088 
       
  4089     if (d->qt_rgn->contains(r)) {
       
  4090         return *this;
       
  4091     } else if (d->qt_rgn->within(r)) {
       
  4092         return *this = r;
       
  4093     } else if (d->qt_rgn->canAppend(&r)) {
       
  4094         detach();
       
  4095         d->qt_rgn->append(&r);
       
  4096         return *this;
       
  4097     } else if (d->qt_rgn->canPrepend(&r)) {
       
  4098         detach();
       
  4099         d->qt_rgn->prepend(&r);
       
  4100         return *this;
       
  4101     } else if (d->qt_rgn->numRects == 1 && d->qt_rgn->extents == r) {
       
  4102         return *this;
       
  4103     } else {
       
  4104         detach();
       
  4105         QRegionPrivate p(r);
       
  4106         UnionRegion(d->qt_rgn, &p, *d->qt_rgn);
       
  4107         return *this;
       
  4108     }
       
  4109 }
       
  4110 
       
  4111 QRegion QRegion::intersect(const QRegion &r) const
       
  4112 {
       
  4113     if (isEmptyHelper(d->qt_rgn) || isEmptyHelper(r.d->qt_rgn)
       
  4114         || !EXTENTCHECK(&d->qt_rgn->extents, &r.d->qt_rgn->extents))
       
  4115         return QRegion();
       
  4116 
       
  4117     /* this is fully contained in r */
       
  4118     if (r.d->qt_rgn->contains(*d->qt_rgn))
       
  4119         return *this;
       
  4120 
       
  4121     /* r is fully contained in this */
       
  4122     if (d->qt_rgn->contains(*r.d->qt_rgn))
       
  4123         return r;
       
  4124 
       
  4125     if (r.d->qt_rgn->numRects == 1 && d->qt_rgn->numRects == 1) {
       
  4126         const QRect rect = qt_rect_intersect_normalized(r.d->qt_rgn->extents,
       
  4127                                                         d->qt_rgn->extents);
       
  4128         return QRegion(rect);
       
  4129     } else if (r.d->qt_rgn->numRects == 1) {
       
  4130         QRegion result(*this);
       
  4131         result.detach();
       
  4132         result.d->qt_rgn->intersect(r.d->qt_rgn->extents);
       
  4133         return result;
       
  4134     } else if (d->qt_rgn->numRects == 1) {
       
  4135         QRegion result(r);
       
  4136         result.detach();
       
  4137         result.d->qt_rgn->intersect(d->qt_rgn->extents);
       
  4138         return result;
       
  4139     }
       
  4140 
       
  4141     QRegion result;
       
  4142     result.detach();
       
  4143     miRegionOp(*result.d->qt_rgn, d->qt_rgn, r.d->qt_rgn, miIntersectO, 0, 0);
       
  4144 
       
  4145     /*
       
  4146      * Can't alter dest's extents before we call miRegionOp because
       
  4147      * it might be one of the source regions and miRegionOp depends
       
  4148      * on the extents of those regions being the same. Besides, this
       
  4149      * way there's no checking against rectangles that will be nuked
       
  4150      * due to coalescing, so we have to examine fewer rectangles.
       
  4151      */
       
  4152     miSetExtents(*result.d->qt_rgn);
       
  4153     return result;
       
  4154 }
       
  4155 
       
  4156 QRegion QRegion::intersect(const QRect &r) const
       
  4157 {
       
  4158     if (isEmptyHelper(d->qt_rgn) || r.isEmpty()
       
  4159         || !EXTENTCHECK(&d->qt_rgn->extents, &r))
       
  4160         return QRegion();
       
  4161 
       
  4162     /* this is fully contained in r */
       
  4163     if (d->qt_rgn->within(r))
       
  4164         return *this;
       
  4165 
       
  4166     /* r is fully contained in this */
       
  4167     if (d->qt_rgn->contains(r))
       
  4168         return r;
       
  4169 
       
  4170     if (d->qt_rgn->numRects == 1) {
       
  4171         const QRect rect = qt_rect_intersect_normalized(d->qt_rgn->extents,
       
  4172                                                         r.normalized());
       
  4173         return QRegion(rect);
       
  4174     }
       
  4175 
       
  4176     QRegion result(*this);
       
  4177     result.detach();
       
  4178     result.d->qt_rgn->intersect(r);
       
  4179     return result;
       
  4180 }
       
  4181 
       
  4182 QRegion QRegion::subtract(const QRegion &r) const
       
  4183 {
       
  4184     if (isEmptyHelper(d->qt_rgn) || isEmptyHelper(r.d->qt_rgn))
       
  4185         return *this;
       
  4186     if (r.d->qt_rgn->contains(*d->qt_rgn))
       
  4187         return QRegion();
       
  4188     if (!EXTENTCHECK(&d->qt_rgn->extents, &r.d->qt_rgn->extents))
       
  4189         return *this;
       
  4190     if (d == r.d || EqualRegion(d->qt_rgn, r.d->qt_rgn))
       
  4191         return QRegion();
       
  4192 
       
  4193 #ifdef QT_REGION_DEBUG
       
  4194     d->qt_rgn->selfTest();
       
  4195     r.d->qt_rgn->selfTest();
       
  4196 #endif
       
  4197 
       
  4198     QRegion result;
       
  4199     result.detach();
       
  4200     SubtractRegion(d->qt_rgn, r.d->qt_rgn, *result.d->qt_rgn);
       
  4201 #ifdef QT_REGION_DEBUG
       
  4202     result.d->qt_rgn->selfTest();
       
  4203 #endif
       
  4204     return result;
       
  4205 }
       
  4206 
       
  4207 QRegion QRegion::eor(const QRegion &r) const
       
  4208 {
       
  4209     if (isEmptyHelper(d->qt_rgn)) {
       
  4210         return r;
       
  4211     } else if (isEmptyHelper(r.d->qt_rgn)) {
       
  4212         return *this;
       
  4213     } else if (!EXTENTCHECK(&d->qt_rgn->extents, &r.d->qt_rgn->extents)) {
       
  4214         return (*this + r);
       
  4215     } else if (d == r.d || EqualRegion(d->qt_rgn, r.d->qt_rgn)) {
       
  4216         return QRegion();
       
  4217     } else {
       
  4218         QRegion result;
       
  4219         result.detach();
       
  4220         XorRegion(d->qt_rgn, r.d->qt_rgn, *result.d->qt_rgn);
       
  4221         return result;
       
  4222     }
       
  4223 }
       
  4224 
       
  4225 QRect QRegion::boundingRect() const
       
  4226 {
       
  4227     if (isEmpty())
       
  4228         return QRect();
       
  4229     return d->qt_rgn->extents;
       
  4230 }
       
  4231 
       
  4232 /*! \internal
       
  4233     Returns true if \a rect is guaranteed to be fully contained in \a region.
       
  4234     A false return value does not guarantee the opposite.
       
  4235 */
       
  4236 #ifdef Q_WS_QWS
       
  4237 Q_GUI_EXPORT
       
  4238 #endif
       
  4239 bool qt_region_strictContains(const QRegion &region, const QRect &rect)
       
  4240 {
       
  4241     if (isEmptyHelper(region.d->qt_rgn) || !rect.isValid())
       
  4242         return false;
       
  4243 
       
  4244 #if 0 // TEST_INNERRECT
       
  4245     static bool guard = false;
       
  4246     if (guard)
       
  4247         return false;
       
  4248     guard = true;
       
  4249     QRegion inner = region.d->qt_rgn->innerRect;
       
  4250     Q_ASSERT((inner - region).isEmpty());
       
  4251     guard = false;
       
  4252 
       
  4253     int maxArea = 0;
       
  4254     for (int i = 0; i < region.d->qt_rgn->numRects; ++i) {
       
  4255         const QRect r = region.d->qt_rgn->rects.at(i);
       
  4256         if (r.width() * r.height() > maxArea)
       
  4257             maxArea = r.width() * r.height();
       
  4258     }
       
  4259 
       
  4260     if (maxArea > region.d->qt_rgn->innerArea) {
       
  4261         qDebug() << "not largest rectangle" << region << region.d->qt_rgn->innerRect;
       
  4262     }
       
  4263     Q_ASSERT(maxArea <= region.d->qt_rgn->innerArea);
       
  4264 #endif
       
  4265 
       
  4266     const QRect r1 = region.d->qt_rgn->innerRect;
       
  4267     return (rect.left() >= r1.left() && rect.right() <= r1.right()
       
  4268             && rect.top() >= r1.top() && rect.bottom() <= r1.bottom());
       
  4269 }
       
  4270 
       
  4271 QVector<QRect> QRegion::rects() const
       
  4272 {
       
  4273     if (d->qt_rgn) {
       
  4274         d->qt_rgn->vectorize();
       
  4275         // hw: modify the vector size directly to avoid reallocation
       
  4276         d->qt_rgn->rects.d->size = d->qt_rgn->numRects;
       
  4277         return d->qt_rgn->rects;
       
  4278     } else {
       
  4279         return QVector<QRect>();
       
  4280     }
       
  4281 }
       
  4282 
       
  4283 void QRegion::setRects(const QRect *rects, int num)
       
  4284 {
       
  4285     *this = QRegion();
       
  4286     if (!rects || num == 0 || (num == 1 && rects->isEmpty()))
       
  4287         return;
       
  4288 
       
  4289     detach();
       
  4290 
       
  4291     d->qt_rgn->numRects = num;
       
  4292     if (num == 1) {
       
  4293         d->qt_rgn->extents = *rects;
       
  4294         d->qt_rgn->innerRect = *rects;
       
  4295     } else {
       
  4296         d->qt_rgn->rects.resize(num);
       
  4297 
       
  4298         int left = INT_MAX,
       
  4299             right = INT_MIN,
       
  4300             top = INT_MAX,
       
  4301             bottom = INT_MIN;
       
  4302         for (int i = 0; i < num; ++i) {
       
  4303             const QRect &rect = rects[i];
       
  4304             d->qt_rgn->rects[i] = rect;
       
  4305             left = qMin(rect.left(), left);
       
  4306             right = qMax(rect.right(), right);
       
  4307             top = qMin(rect.top(), top);
       
  4308             bottom = qMax(rect.bottom(), bottom);
       
  4309             d->qt_rgn->updateInnerRect(rect);
       
  4310         }
       
  4311         d->qt_rgn->extents = QRect(QPoint(left, top), QPoint(right, bottom));
       
  4312     }
       
  4313 }
       
  4314 
       
  4315 int QRegion::numRects() const
       
  4316 {
       
  4317     return (d->qt_rgn ? d->qt_rgn->numRects : 0);
       
  4318 }
       
  4319 
       
  4320 bool QRegion::operator==(const QRegion &r) const
       
  4321 {
       
  4322     if (!d->qt_rgn)
       
  4323         return r.isEmpty();
       
  4324     if (!r.d->qt_rgn)
       
  4325         return isEmpty();
       
  4326 
       
  4327     if (d == r.d)
       
  4328         return true;
       
  4329     else
       
  4330         return EqualRegion(d->qt_rgn, r.d->qt_rgn);
       
  4331 }
       
  4332 
       
  4333 #endif
       
  4334 QT_END_NAMESPACE