summaryrefslogtreecommitdiffstats
path: root/src/openvg
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2009-07-24 09:45:33 (GMT)
committerJason Barron <jbarron@trolltech.com>2009-07-27 13:04:30 (GMT)
commit3643028959f0b38350e57e60ba4000435b75e592 (patch)
treec129e4dee11487abd437ab8ebd993ba261e06fa6 /src/openvg
parentcf66c667a97c0079141eb3f2d9e997b7378ae792 (diff)
parentc36139c665e61866aff4bf8572890a735167a7d0 (diff)
downloadQt-3643028959f0b38350e57e60ba4000435b75e592.zip
Qt-3643028959f0b38350e57e60ba4000435b75e592.tar.gz
Qt-3643028959f0b38350e57e60ba4000435b75e592.tar.bz2
Merge commit 'qt/master-stable'
Conflicts: configure.exe qmake/Makefile.unix qmake/generators/makefile.cpp src/corelib/global/qglobal.h src/corelib/kernel/kernel.pri src/corelib/kernel/qcoreevent.cpp src/corelib/kernel/qsharedmemory_unix.cpp src/gui/graphicsview/qgraphicsscene.cpp src/gui/kernel/qaction.cpp src/gui/kernel/qaction.h src/gui/kernel/qaction_p.h src/gui/kernel/qapplication.cpp src/gui/kernel/qapplication.h src/gui/kernel/qwidget.cpp src/gui/kernel/qwidget.h src/gui/kernel/qwidget_mac.mm src/gui/painting/qgraphicssystemfactory.cpp src/gui/styles/qwindowsstyle.cpp src/gui/text/qfontengine_qpf.cpp src/gui/widgets/qabstractscrollarea_p.h src/network/access/qnetworkaccessdebugpipebackend.cpp src/network/socket/qlocalsocket_unix.cpp src/network/socket/qnativesocketengine_p.h src/network/socket/qnativesocketengine_unix.cpp src/openvg/qpaintengine_vg.cpp tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp tests/auto/qcssparser/qcssparser.pro tests/auto/qdir/tst_qdir.cpp tests/auto/qfile/tst_qfile.cpp tests/auto/qobject/tst_qobject.cpp tests/auto/qpathclipper/qpathclipper.pro tests/auto/qprocess/tst_qprocess.cpp tests/auto/qsettings/tst_qsettings.cpp tests/auto/qsharedpointer/qsharedpointer.pro tests/auto/qsqlquerymodel/qsqlquerymodel.pro tests/auto/qsqlrelationaltablemodel/qsqlrelationaltablemodel.pro tests/auto/qsqltablemodel/qsqltablemodel.pro tests/auto/qsqlthread/qsqlthread.pro tests/auto/qwidget/tst_qwidget.cpp
Diffstat (limited to 'src/openvg')
-rw-r--r--src/openvg/qpaintengine_vg.cpp192
-rw-r--r--src/openvg/qpaintengine_vg_p.h1
2 files changed, 185 insertions, 8 deletions
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index 1aed769..a9ecffc 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.
@@ -1320,11 +1322,11 @@ QPainterState *QVGPaintEngine::createState(QPainterState *orig) const
if (!orig) {
return new QVGPainterState();
} else {
- QVGPaintEnginePrivate *d =
- static_cast<QVGPaintEnginePrivate *>(d_ptr.data());
+ Q_D(const QVGPaintEngine);
+ QVGPaintEnginePrivate *d2 = const_cast<QVGPaintEnginePrivate*>(d.data());
QVGPainterState *origState = static_cast<QVGPainterState *>(orig);
- origState->savedDirty = d->dirty;
- d->dirty = 0;
+ origState->savedDirty = d2->dirty;
+ d2->dirty = 0;
return new QVGPainterState(*origState);
}
}
@@ -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.
@@ -1656,10 +1751,10 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
clip = r;
else
clip = clip.intersect(r);
- if (r.numRects() == 1) {
+ if (clip.numRects() == 1) {
d->maskValid = false;
d->maskIsSet = false;
- d->maskRect = r.boundingRect();
+ d->maskRect = clip.boundingRect();
vgSeti(VG_MASKING, VG_FALSE);
updateScissor();
} else {
@@ -1707,11 +1802,61 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
}
}
+#if !defined(QVG_NO_RENDER_TO_MASK)
+
+// Copied from qpathclipper.cpp.
+static bool qt_vg_pathToRect(const QPainterPath &path, QRectF *rect)
+{
+ if (path.elementCount() != 5)
+ return false;
+
+ const bool mightBeRect = path.elementAt(0).isMoveTo()
+ && path.elementAt(1).isLineTo()
+ && path.elementAt(2).isLineTo()
+ && path.elementAt(3).isLineTo()
+ && path.elementAt(4).isLineTo();
+
+ if (!mightBeRect)
+ return false;
+
+ const qreal x1 = path.elementAt(0).x;
+ const qreal y1 = path.elementAt(0).y;
+
+ const qreal x2 = path.elementAt(1).x;
+ const qreal y2 = path.elementAt(2).y;
+
+ if (path.elementAt(1).y != y1)
+ return false;
+
+ if (path.elementAt(2).x != x2)
+ return false;
+
+ if (path.elementAt(3).x != x1 || path.elementAt(3).y != y2)
+ return false;
+
+ if (path.elementAt(4).x != x1 || path.elementAt(4).y != y1)
+ return false;
+
+ if (rect)
+ *rect = QRectF(QPointF(x1, y1), QPointF(x2, y2));
+
+ return true;
+}
+
+#endif
+
void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
{
#if !defined(QVG_NO_RENDER_TO_MASK)
Q_D(QVGPaintEngine);
+ // If the path is a simple rectangle, then use clip(QRect) instead.
+ QRectF simpleRect;
+ if (qt_vg_pathToRect(path, &simpleRect)) {
+ clip(simpleRect.toRect(), op);
+ return;
+ }
+
d->dirty |= QPaintEngine::DirtyClipRegion;
if (op == Qt::NoClip) {
@@ -1765,7 +1910,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 +1942,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 +2058,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);
};