You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tqt3/src/kernel/qregion.cpp

384 lines
11 KiB

/****************************************************************************
**
** Implementation of TQRegion class
**
** Created : 950726
**
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the kernel module of the TQt GUI Toolkit.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free TQt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing retquirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** This file may be used under the terms of the Q Public License as
** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
** included in the packaging of this file. Licensees holding valid TQt
** Commercial licenses may use this file in accordance with the TQt
** Commercial License Agreement provided with the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/
#include "qregion.h"
#include "qpointarray.h"
#include "qbuffer.h"
#include "qdatastream.h"
// BEING REVISED: paul
/*!
\class TQRegion qregion.h
\brief The TQRegion class specifies a clip region for a painter.
\ingroup images
\ingroup graphics
TQRegion is used with TQPainter::setClipRegion() to limit the paint
area to what needs to be painted. There is also a
TQWidget::repaint() that takes a TQRegion parameter. TQRegion is the
best tool for reducing flicker.
A region can be created from a rectangle, an ellipse, a polygon or
a bitmap. Complex regions may be created by combining simple
regions using unite(), intersect(), subtract() or eor() (exclusive
or). You can move a region using translate().
You can test whether a region isNull(), isEmpty() or if it
contains() a TQPoint or TQRect. The bounding rectangle is given by
boundingRect().
The function rects() gives a decomposition of the region into
rectangles.
Example of using complex regions:
\code
void MyWidget::paintEvent( TQPaintEvent * )
{
TQPainter p; // our painter
TQRegion r1( TQRect(100,100,200,80), // r1 = elliptic region
TQRegion::Ellipse );
TQRegion r2( TQRect(100,120,90,30) ); // r2 = rectangular region
TQRegion r3 = r1.intersect( r2 ); // r3 = intersection
p.begin( this ); // start painting widget
p.setClipRegion( r3 ); // set clip region
... // paint clipped graphics
p.end(); // painting done
}
\endcode
TQRegion is an \link shclass.html implicitly shared\endlink class.
\warning Due to window system limitations, the whole coordinate
space for a region is limited to the points between -32767 and
32767 on Mac OS X and Windows 95/98/ME.
\sa TQPainter::setClipRegion(), TQPainter::setClipRect()
*/
/*!
\enum TQRegion::RegionType
Specifies the shape of the region to be created.
\value Rectangle the region covers the entire rectangle.
\value Ellipse the region is an ellipse inside the rectangle.
*/
/*!
\fn Region TQRegion::handle() const
Returns the region's handle.
*/
/*****************************************************************************
TQRegion member functions
*****************************************************************************/
/*!
Constructs a rectangular or elliptic region.
If \a t is \c Rectangle, the region is the filled rectangle (\a x,
\a y, \a w, \a h). If \a t is \c Ellipse, the region is the filled
ellipse with center at (\a x + \a w / 2, \a y + \a h / 2) and size
(\a w ,\a h ).
*/
TQRegion::TQRegion( int x, int y, int w, int h, RegionType t )
{
TQRegion tmp(TQRect(x,y,w,h),t);
tmp.data->ref();
data = tmp.data;
}
/*!
Detaches from shared region data to make sure that this region is
the only one referring to the data.
\sa copy(), \link shclass.html shared classes\endlink
*/
void TQRegion::detach()
{
if ( data->count != 1 )
*this = copy();
}
#ifndef QT_NO_DATASTREAM
/*
Executes region commands in the internal buffer and rebuilds the
original region.
We do this when we read a region from the data stream.
If \a ver is non-0, uses the format version \a ver on reading the
byte array.
*/
void TQRegion::exec( const TQByteArray &buffer, int ver )
{
TQBuffer buf( buffer );
TQDataStream s( &buf );
if ( ver )
s.setVersion( ver );
buf.open( IO_ReadOnly );
TQRegion rgn;
#if defined(QT_CHECK_STATE)
int test_cnt = 0;
#endif
while ( !s.eof() ) {
Q_INT32 id;
if ( s.version() == 1 ) {
int id_int;
s >> id_int;
id = id_int;
} else {
s >> id;
}
#if defined(QT_CHECK_STATE)
if ( test_cnt > 0 && id != TQRGN_TRANSLATE )
qWarning( "TQRegion::exec: Internal error" );
test_cnt++;
#endif
if ( id == TQRGN_SETRECT || id == TQRGN_SETELLIPSE ) {
TQRect r;
s >> r;
rgn = TQRegion( r, id == TQRGN_SETRECT ? Rectangle : Ellipse );
} else if ( id == TQRGN_SETPTARRAY_ALT || id == TQRGN_SETPTARRAY_WIND ) {
TQPointArray a;
s >> a;
rgn = TQRegion( a, id == TQRGN_SETPTARRAY_WIND );
} else if ( id == TQRGN_TRANSLATE ) {
TQPoint p;
s >> p;
rgn.translate( p.x(), p.y() );
} else if ( id >= TQRGN_OR && id <= TQRGN_XOR ) {
TQByteArray bop1, bop2;
TQRegion r1, r2;
s >> bop1; r1.exec( bop1 );
s >> bop2; r2.exec( bop2 );
switch ( id ) {
case TQRGN_OR:
rgn = r1.unite( r2 );
break;
case TQRGN_AND:
rgn = r1.intersect( r2 );
break;
case TQRGN_SUB:
rgn = r1.subtract( r2 );
break;
case TQRGN_XOR:
rgn = r1.eor( r2 );
break;
}
} else if ( id == TQRGN_RECTS ) {
// (This is the only form used in TQt 2.0)
Q_UINT32 n;
s >> n;
TQRect r;
for ( int i=0; i<(int)n; i++ ) {
s >> r;
rgn = rgn.unite( TQRegion(r) );
}
}
}
buf.close();
*this = rgn;
}
/*****************************************************************************
TQRegion stream functions
*****************************************************************************/
/*!
\relates TQRegion
Writes the region \a r to the stream \a s and returns a reference
to the stream.
\sa \link datastreamformat.html Format of the TQDataStream operators \endlink
*/
TQDataStream &operator<<( TQDataStream &s, const TQRegion &r )
{
TQMemArray<TQRect> a = r.rects();
if ( a.isEmpty() ) {
s << (Q_UINT32)0;
} else {
if ( s.version() == 1 ) {
int i;
for ( i=(int)a.size()-1; i>0; i-- ) {
s << (Q_UINT32)(12+i*24);
s << (int)TQRGN_OR;
}
for ( i=0; i<(int)a.size(); i++ ) {
s << (Q_UINT32)(4+8) << (int)TQRGN_SETRECT << a[i];
}
}
else {
s << (Q_UINT32)(4+4+16*a.size()); // 16: storage size of TQRect
s << (Q_INT32)TQRGN_RECTS;
s << (Q_UINT32)a.size();
for ( int i=0; i<(int)a.size(); i++ )
s << a[i];
}
}
return s;
}
/*!
\relates TQRegion
Reads a region from the stream \a s into \a r and returns a
reference to the stream.
\sa \link datastreamformat.html Format of the TQDataStream operators \endlink
*/
TQDataStream &operator>>( TQDataStream &s, TQRegion &r )
{
TQByteArray b;
s >> b;
r.exec( b, s.version() );
return s;
}
#endif //QT_NO_DATASTREAM
// These are not inline - they can be implemented better on some platforms
// (eg. Windows at least provides 3-variable operations). For now, simple.
/*!
Applies the unite() function to this region and \a r. \c r1|r2 is
equivalent to \c r1.unite(r2)
\sa unite(), operator+()
*/
const TQRegion TQRegion::operator|( const TQRegion &r ) const
{ return unite(r); }
/*!
Applies the unite() function to this region and \a r. \c r1+r2 is
equivalent to \c r1.unite(r2)
\sa unite(), operator|()
*/
const TQRegion TQRegion::operator+( const TQRegion &r ) const
{ return unite(r); }
/*!
Applies the intersect() function to this region and \a r. \c r1&r2
is equivalent to \c r1.intersect(r2)
\sa intersect()
*/
const TQRegion TQRegion::operator&( const TQRegion &r ) const
{ return intersect(r); }
/*!
Applies the subtract() function to this region and \a r. \c r1-r2
is equivalent to \c r1.subtract(r2)
\sa subtract()
*/
const TQRegion TQRegion::operator-( const TQRegion &r ) const
{ return subtract(r); }
/*!
Applies the eor() function to this region and \a r. \c r1^r2 is
equivalent to \c r1.eor(r2)
\sa eor()
*/
const TQRegion TQRegion::operator^( const TQRegion &r ) const
{ return eor(r); }
/*!
Applies the unite() function to this region and \a r and assigns
the result to this region. \c r1|=r2 is equivalent to \c
r1=r1.unite(r2)
\sa unite()
*/
TQRegion& TQRegion::operator|=( const TQRegion &r )
{ return *this = *this | r; }
/*!
Applies the unite() function to this region and \a r and assigns
the result to this region. \c r1+=r2 is equivalent to \c
r1=r1.unite(r2)
\sa intersect()
*/
TQRegion& TQRegion::operator+=( const TQRegion &r )
{ return *this = *this + r; }
/*!
Applies the intersect() function to this region and \a r and
assigns the result to this region. \c r1&=r2 is equivalent to \c
r1=r1.intersect(r2)
\sa intersect()
*/
TQRegion& TQRegion::operator&=( const TQRegion &r )
{ return *this = *this & r; }
/*!
Applies the subtract() function to this region and \a r and
assigns the result to this region. \c r1-=r2 is equivalent to \c
r1=r1.subtract(r2)
\sa subtract()
*/
TQRegion& TQRegion::operator-=( const TQRegion &r )
{ return *this = *this - r; }
/*!
Applies the eor() function to this region and \a r and
assigns the result to this region. \c r1^=r2 is equivalent to \c
r1=r1.eor(r2)
\sa eor()
*/
TQRegion& TQRegion::operator^=( const TQRegion &r )
{ return *this = *this ^ r; }