summaryrefslogtreecommitdiffstats
path: root/src/openvg
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvg')
-rw-r--r--src/openvg/qpaintengine_vg.cpp130
-rw-r--r--src/openvg/qpaintengine_vg_p.h1
2 files changed, 129 insertions, 2 deletions
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index 8ce3f69..48953ac 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -142,6 +142,8 @@ public:
void ensureMask(QVGPaintEngine *engine, int width, int height);
void modifyMask
(QVGPaintEngine *engine, VGMaskOperation op, const QRegion& region);
+ void modifyMask
+ (QVGPaintEngine *engine, VGMaskOperation op, const QRect& rect);
#endif
VGint maxScissorRects; // Maximum scissor rectangles for clipping.
@@ -1611,13 +1613,106 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
{
- clip(QRegion(rect), op);
+ Q_D(QVGPaintEngine);
+
+ d->dirty |= QPaintEngine::DirtyClipRegion;
+
+ // If we have a non-simple transform, then use path-based clipping.
+ if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) {
+ QPaintEngineEx::clip(rect, op);
+ return;
+ }
+
+ switch (op) {
+ case Qt::NoClip:
+ {
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ vgSeti(VG_MASKING, VG_FALSE);
+ }
+ break;
+
+ case Qt::ReplaceClip:
+ {
+ QRect r = d->transform.mapRect(rect);
+ if (isDefaultClipRect(r)) {
+ // Replacing the clip with a full-window region is the
+ // same as turning off clipping.
+ if (d->maskValid)
+ vgSeti(VG_MASKING, VG_FALSE);
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ } else {
+ // Special case: if the intersection of the system
+ // clip and "r" is a single rectangle, then use the
+ // scissor for clipping. We try to avoid allocating a
+ // QRegion copy on the heap for the test if we can.
+ QRegion clip = d->systemClip; // Reference-counted, no alloc.
+ QRect clipRect;
+ if (clip.numRects() == 1) {
+ clipRect = clip.boundingRect().intersected(r);
+ } else if (clip.isEmpty()) {
+ clipRect = r;
+ } else {
+ clip = clip.intersect(r);
+ if (clip.numRects() != 1) {
+ d->maskValid = false;
+ d->maskIsSet = false;
+ d->maskRect = QRect();
+ d->modifyMask(this, VG_FILL_MASK, r);
+ break;
+ }
+ clipRect = clip.boundingRect();
+ }
+ d->maskValid = false;
+ d->maskIsSet = false;
+ d->maskRect = clipRect;
+ vgSeti(VG_MASKING, VG_FALSE);
+ updateScissor();
+ }
+ }
+ break;
+
+ case Qt::IntersectClip:
+ {
+ QRect r = d->transform.mapRect(rect);
+ if (d->maskIsSet && isDefaultClipRect(r)) {
+ // Intersecting a full-window clip with a full-window
+ // region is the same as turning off clipping.
+ if (d->maskValid)
+ vgSeti(VG_MASKING, VG_FALSE);
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ } else {
+ d->modifyMask(this, VG_INTERSECT_MASK, r);
+ }
+ }
+ break;
+
+ case Qt::UniteClip:
+ {
+ // If we already have a full-window clip, then uniting a
+ // region with it will do nothing. Otherwise union.
+ if (!(d->maskIsSet))
+ d->modifyMask(this, VG_UNION_MASK, d->transform.mapRect(rect));
+ }
+ break;
+ }
}
void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
{
Q_D(QVGPaintEngine);
+ // Use the QRect case if the region consists of a single rectangle.
+ if (region.numRects() == 1) {
+ clip(region.boundingRect(), op);
+ return;
+ }
+
d->dirty |= QPaintEngine::DirtyClipRegion;
// If we have a non-simple transform, then use path-based clipping.
@@ -1765,7 +1860,7 @@ void QVGPaintEnginePrivate::ensureMask
maskRect = QRect();
} else {
vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height);
- if (!maskRect.isNull()) {
+ if (maskRect.isValid()) {
vgMask(VG_INVALID_HANDLE, VG_FILL_MASK,
maskRect.x(), height - maskRect.y() - maskRect.height(),
maskRect.width(), maskRect.height());
@@ -1797,6 +1892,27 @@ void QVGPaintEnginePrivate::modifyMask
maskIsSet = false;
}
+void QVGPaintEnginePrivate::modifyMask
+ (QVGPaintEngine *engine, VGMaskOperation op, const QRect& rect)
+{
+ QPaintDevice *pdev = engine->paintDevice();
+ int width = pdev->width();
+ int height = pdev->height();
+
+ if (!maskValid)
+ ensureMask(engine, width, height);
+
+ if (rect.isValid()) {
+ vgMask(VG_INVALID_HANDLE, op,
+ rect.x(), height - rect.y() - rect.height(),
+ rect.width(), rect.height());
+ }
+
+ vgSeti(VG_MASKING, VG_TRUE);
+ maskValid = true;
+ maskIsSet = false;
+}
+
#endif // !QVG_SCISSOR_CLIP
void QVGPaintEngine::updateScissor()
@@ -1892,6 +2008,16 @@ bool QVGPaintEngine::isDefaultClipRegion(const QRegion& region)
rect.width() == width && rect.height() == height);
}
+bool QVGPaintEngine::isDefaultClipRect(const QRect& rect)
+{
+ QPaintDevice *pdev = paintDevice();
+ int width = pdev->width();
+ int height = pdev->height();
+
+ return (rect.x() == 0 && rect.y() == 0 &&
+ rect.width() == width && rect.height() == height);
+}
+
void QVGPaintEngine::clipEnabledChanged()
{
#if defined(QVG_SCISSOR_CLIP)
diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h
index a390c80..bde06e5 100644
--- a/src/openvg/qpaintengine_vg_p.h
+++ b/src/openvg/qpaintengine_vg_p.h
@@ -154,6 +154,7 @@ private:
void updateScissor();
QRegion defaultClipRegion();
bool isDefaultClipRegion(const QRegion& region);
+ bool isDefaultClipRect(const QRect& rect);
bool clearRect(const QRectF &rect, const QColor &color);
};