/*!
 *  \internal
 *  Updates the region handle so that it is suitable for selection to
 *  a device with the given \a height.
 */
void QRegion::updateHandle( int target_height ) const
{
    QRegion *that = const_cast< QRegion *>( this ); // we're const here
    if ( !data->rgn ) {
        // a handle of a null region is requested, allocate an empty region
        that->data->rgn = GpiCreateRegion( qt_display_ps(), 0, NULL );
        that->data->hgt = target_height;
    } else if ( data->hgt != target_height ) {
        // align region y axis to the top of the device
        POINTL ptl = { 0, target_height - data->hgt };
        GpiOffsetRegion( qt_display_ps(), data->rgn, &ptl );
        that->data->hgt = target_height;
    }
}
Exemple #2
0
/*!
    \internal

    Updates the region handle so that it is suitable for selection to
    a device with the given \a height.
 */
void QRegion::updateHandle(int targetHeight) const
{
    QRegion *self = const_cast<QRegion*>(this); // we're const here

    if (d->rgn != 0) {
        if (self->d->ref == 1) {
            // align region y axis to the top of the device
            POINTL ptl = { 0, targetHeight - d->height };
            GpiOffsetRegion(qt_display_ps(), d->rgn, &ptl);
            self->d->height = targetHeight;
            return;
        }
        // create a copy since the hande may be in use (this will reset d->rgn)
        *self = copy();
    }

    Q_ASSERT(d->rgn == 0);

    // new/updated/copied Qt region data, create a new HRGN for it
    self->d->height = targetHeight;
    if (d->qt_rgn) {
        if (d->qt_rgn->numRects > 0) {
            if (d->qt_rgn->numRects == 1) {
                // d->qt_rgn->rects is empty, use d->qt_rgn->extents instead
                const QRect r = d->qt_rgn->extents;
                RECTL rcl = { r.left(), d->height - (r.bottom() + 1),
                              r.right() + 1, d->height - r.top() };
                self->d->rgn = GpiCreateRegion(qt_display_ps(), 1, &rcl);
            } else {
                PRECTL rcls = new RECTL[d->qt_rgn->numRects];
                for (int i = 0; i < d->qt_rgn->numRects; ++i) {
                    QRect r = d->qt_rgn->rects.at(i);
                    // note RECTL is inclusive-exclusive here
                    rcls[i].xLeft = r.left();
                    rcls[i].yBottom = d->height - (r.bottom() + 1);
                    rcls[i].xRight = r.right() + 1;
                    rcls[i].yTop = d->height - r.top();
                }
                self->d->rgn = GpiCreateRegion(qt_display_ps(),
                                               d->qt_rgn->numRects, rcls);
                delete[] rcls;
            }
            return;
        }
    }

    // create an empty region
    self->d->rgn = GpiCreateRegion(qt_display_ps(), 0, NULL);
}
QRegion::QRegion( const QPointArray &a, bool winding )
{
    data = new QRegionData;
    Q_CHECK_PTR( data );
    data->hgt = 0;
    data->is_null = FALSE;
    QRect r = a.boundingRect();
    if ( a.isEmpty() || r.isEmpty() ) {
	data->rgn = 0;
    } else {
        HPS hps = qt_display_ps();
        POINTL *pts = new POINTL[ a.size() ]; 
        for ( uint i = 0; i < a.size(); ++ i ) {
            pts[i].x = a[i].x();
            pts[i].y = - (a[i].y() + 1);
        }
        // GpiCreatePolygonRegion() is bogus and always starts a poligon from
        // the current position. Make the last point the current one and reduce
        // the number of points by one.
        GpiMove( hps, &pts[ a.size() - 1 ] );
        POLYGON poly = { a.size() - 1, pts };
        ULONG opts = winding ? POLYGON_WINDING : POLYGON_ALTERNATE;
        data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, opts );
        delete[] pts;
    }
}
QRegion::QRegion( const QRect &r, RegionType t )
{
    data = new QRegionData;
    Q_CHECK_PTR( data );
    data->hgt = 0;
    data->is_null = FALSE;
    if ( r.isEmpty() ) {
	data->rgn = 0;
    } else {
        HPS hps = qt_display_ps();
	if ( t == Rectangle ) {			// rectangular region
            RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() };
            data->rgn = GpiCreateRegion( hps, 1, &rcl );
	} else if ( t == Ellipse ) {		// elliptic region
            // if the width or height of the ellipse is odd, GPI always
            // converts it to a nearest even value, which is obviously stupid
            // (see also QPainter::drawArcInternal()). So, we don't use
            // GpiCreateEllipticRegion(), but create an array of points to
            // call GpiCreatePolygonRegion() instead.
            QPointArray a;
            a.makeArc( r.x(), r.y(), r.width(), r.height(), 0, 360 * 16 );
            for ( uint i = 0; i < a.size(); ++ i )
                a[i].ry() = -(a[i].y() + 1);
            // GpiCreatePolygonRegion() is bogus and always starts a poligon from
            // the current position. Make the last point the current one and reduce
            // the number of points by one.
            GpiMove( hps, (PPOINTL) &a[ a.size() - 1 ] );
            POLYGON poly = { a.size() - 1, (PPOINTL) a.data() };
            data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, POLYGON_ALTERNATE );
	}
    }
}
bool QRegion::isEmpty() const
{
    if ( data->is_null || data->rgn == 0 )
        return TRUE;
    RECTL rcl;
    return GpiQueryRegionBox( qt_display_ps(), data->rgn, &rcl ) == RGN_NULL;
}
QMemArray<QRect> QRegion::rects() const
{
    QMemArray<QRect> a;
    if ( !data->rgn )
	return a;

    HPS hps = qt_display_ps();
    RGNRECT ctl = {1, 0, 0, RECTDIR_LFRT_TOPBOT};
    if ( !GpiQueryRegionRects( hps, data->rgn, NULL, &ctl, NULL ) )
        return a;

    ctl.crc = ctl.crcReturned;
    PRECTL rcls = new RECTL[ctl.crcReturned];
    if ( !GpiQueryRegionRects( hps, data->rgn, NULL, &ctl, rcls ) ) {
        delete [] rcls;
        return a;
    }

    a = QMemArray<QRect>( ctl.crcReturned );
    PRECTL r = rcls;
    for ( int i=0; i<(int)a.size(); i++ ) {
        a[i].setRect( r->xLeft, data->hgt - r->yTop,
                      r->xRight - r->xLeft, r->yTop - r->yBottom );
	r++;
    }

    delete [] rcls;

    return a;
}
QRegion::~QRegion()
{
    if ( data->deref() ) {
	if ( data->rgn )
            GpiDestroyRegion( qt_display_ps(), data->rgn );
	delete data;
    }
}
void QRegion::translate( int dx, int dy )
{
    if ( !data->rgn )
	return;
    detach();
    POINTL ptl = { dx, -dy };
    GpiOffsetRegion( qt_display_ps(), data->rgn, &ptl);
}
bool QRegion::contains( const QPoint &p ) const
{
    LONG rc = PRGN_OUTSIDE;
    if ( data->rgn ) {
        POINTL ptl = { p.x(), data->hgt - (p.y() + 1) };
        rc = GpiPtInRegion( qt_display_ps(), data->rgn, &ptl );
    }
    return rc == PRGN_INSIDE;
}
bool QRegion::contains( const QRect &r ) const
{
    LONG rc = PRGN_OUTSIDE;
    if ( data->rgn ) {
        RECTL rcl = { r.left(), data->hgt - (r.bottom() + 1),
                      r.right() + 1, data->hgt - r.top() };
        rc = GpiRectInRegion( qt_display_ps(), data->rgn, &rcl );
    }
    return rc == RRGN_INSIDE || rc == RRGN_PARTIAL;
}
QRegion &QRegion::operator=( const QRegion &r )
{
    r.data->ref();				// beware of r = r
    if ( data->deref() ) {
	if ( data->rgn )
            GpiDestroyRegion( qt_display_ps(), data->rgn );
	delete data;
    }
    data = r.data;
    return *this;
}
QRect QRegion::boundingRect() const
{
    RECTL rcl;
    LONG rc = RGN_NULL;
    if ( data->rgn )
        rc = GpiQueryRegionBox( qt_display_ps(), data->rgn, &rcl );
    if ( rc == RGN_NULL || rc == RGN_ERROR )
	return QRect(0,0,0,0);
    else
        return QRect( rcl.xLeft, data->hgt - rcl.yTop,
                      rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom );
}
QRegion QRegion::copy() const
{
    QRegion r ( data->is_null );
    r.data->hgt = 0;
    if ( !data->is_null && data->rgn ) {
        HPS hps = qt_display_ps();
        r.data->rgn = GpiCreateRegion( hps, 0, NULL );
        GpiCombineRegion( hps, r.data->rgn, data->rgn, NULL, CRGN_COPY );
        r.data->hgt = data->hgt;
    }
    return r;
}
bool QRegion::operator==( const QRegion &r ) const
{
    if ( data == r.data )			// share the same data
	return TRUE;
    bool is_empty = data->is_null || data->rgn == 0;
    bool r_is_empty = r.data->is_null || r.data->rgn == 0;
    if ( (is_empty ^ r_is_empty ) )             // one is empty, not both
	return FALSE;
    if ( is_empty )				// both empty
        return TRUE;
    updateHandle( r.data->hgt ); // bring to the same coordinate space
    return
	GpiEqualRegion( qt_display_ps(), data->rgn, r.data->rgn ) == EQRGN_EQUAL;
}
QRegion QRegion::pmCombine( const QRegion &r, int op ) const
{
    LONG both = CRGN_NOP, left = CRGN_NOP, right = CRGN_NOP;
    switch ( op ) {
	case QRGN_OR:
	    both = CRGN_OR;
	    left = right = CRGN_COPY;
	    break;
	case QRGN_AND:
	    both = CRGN_AND;
	    break;
	case QRGN_SUB:
	    both = CRGN_DIFF;
	    left = CRGN_COPY;
	    break;
	case QRGN_XOR:
	    both = CRGN_XOR;
	    left = right = CRGN_COPY;
	    break;
	default:
#if defined(QT_CHECK_RANGE)
	    qWarning( "QRegion: Internal error in pmCombine" );
#else
	    ;
#endif
    }

    QRegion result( FALSE );
    if ( !data->rgn && !r.data->rgn )
        return result;
    HPS hps = qt_display_ps();
    result.data->rgn = GpiCreateRegion( hps, 0, NULL );
    LONG rc = RGN_NULL; 
    if ( data->rgn && r.data->rgn ) {
        updateHandle( r.data->hgt ); // bring to the same coordinate space
	rc = GpiCombineRegion( hps, result.data->rgn, data->rgn, r.data->rgn, both );
        result.data->hgt = r.data->hgt;
    } else if ( data->rgn && left != CRGN_NOP ) {
	rc = GpiCombineRegion( hps, result.data->rgn, data->rgn, 0, left );
        result.data->hgt = data->hgt;
    } else if ( r.data->rgn && right != CRGN_NOP ) {
	rc = GpiCombineRegion( hps, result.data->rgn, r.data->rgn, 0, right );
        result.data->hgt = r.data->hgt;
    }
    if ( rc == RGN_NULL || rc == RGN_ERROR ) {
        GpiDestroyRegion( hps, result.data->rgn );
        result.data->rgn = result.data->hgt = 0;
    }
    return result;
}
Exemple #16
0
/*!
    \internal

    Deletes the given region handle.
 */
void QRegion::disposeHandle(HRGN hrgn)
{
    if (hrgn != 0)
        GpiDestroyRegion(qt_display_ps(), hrgn);
}
HRGN qt_pm_bitmapToRegion( const QBitmap& bitmap )
{
    HRGN region = 0;
    QImage image = bitmap.convertToImage();
    const int maxrect = 256;
    RECTL rects[maxrect];
    HPS hps = qt_display_ps();

#define FlushSpans \
    { \
        HRGN r = GpiCreateRegion( hps, n, rects ); \
	if ( region ) { \
	    GpiCombineRegion( hps, region, region, r, CRGN_OR ); \
	    GpiDestroyRegion( hps, r ); \
	} else { \
	    region = r; \
	} \
    }

#define AddSpan \
    { \
        rects[n].xLeft = prev1; \
        rects[n].yBottom = -(y+1); \
        rects[n].xRight = x-1+1; \
        rects[n].yTop = -y; \
        n++; \
        if ( n == maxrect ) { \
            FlushSpans \
            n = 0; \
        } \
    }

    int n = 0;
    int zero = 0x00;

    int x, y;
    for ( y = 0; y < image.height(); y++ ) {
	uchar *line = image.scanLine(y);
	int w = image.width();
	uchar all = zero;
	int prev1 = -1;
	for ( x = 0; x < w; ) {
	    uchar byte = line[x/8];
	    if ( x > w-8 || byte != all ) {
		for ( int b = 8; b > 0 && x < w; b-- ) {
		    if ( !(byte & 0x80) == !all ) {
			// More of the same
		    } else {
			// A change.
			if ( all != zero ) {
			    AddSpan;
			    all = zero;
			} else {
			    prev1 = x;
			    all = ~zero;
			}
		    }
		    byte <<= 1;
		    x++;
		}
	    } else {
		x += 8;
	    }
	}
	if ( all != zero ) {
	    AddSpan;
	}
    }
    if ( n ) {
	FlushSpans;
    }

    if ( !region )
        region = GpiCreateRegion( hps, 0, NULL );

    return region;
}