diff options
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 8 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_x11.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qpaintengineex.cpp | 30 | ||||
-rw-r--r-- | src/gui/painting/qpaintengineex_p.h | 6 | ||||
-rw-r--r-- | src/gui/painting/qpainterpath.cpp | 15 | ||||
-rw-r--r-- | src/gui/painting/qpainterpath_p.h | 39 | ||||
-rw-r--r-- | src/gui/painting/qvectorpath_p.h | 72 | ||||
-rw-r--r-- | src/gui/painting/qwindowsurface_raster.cpp | 6 |
8 files changed, 121 insertions, 57 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index fd0e810..8d0b961 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1686,7 +1686,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) if (!s->penData.blend) return; - if (s->flags.fast_pen && path.shape() <= QVectorPath::NonCurvedShapeHint + if (s->flags.fast_pen && !path.isCurved() && s->lastPen.brush().isOpaque()) { int count = path.elementCount(); QPointF *points = (QPointF *) path.points(); @@ -1739,8 +1739,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) const QLineF *lines = reinterpret_cast<const QLineF *>(path.points()); for (int i = 0; i < lineCount; ++i) { - if (path.shape() == QVectorPath::LinesHint) - dashOffset = s->lastPen.dashOffset(); + dashOffset = s->lastPen.dashOffset(); if (lines[i].p1() == lines[i].p2()) { if (s->lastPen.capStyle() != Qt::FlatCap) { QPointF p = lines[i].p1(); @@ -5120,6 +5119,9 @@ void QSpanData::adjustSpanMethods() #else unclipped_blend = qBlendTexture; #endif + if (!texture.imageData) + unclipped_blend = 0; + break; } // setup clipping diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index 59482c6..35b77f7 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -146,7 +146,7 @@ static inline int qpainterOpToXrender(QPainter::CompositionMode mode) // hack, so we don't have to make QRegion::clipRectangles() public or include // X11 headers in qregion.h -Q_AUTOTEST_EXPORT void *qt_getClipRects(const QRegion &r, int &num) +Q_GUI_EXPORT void *qt_getClipRects(const QRegion &r, int &num) { return r.clipRectangles(num); } diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 195be0a..9e21182 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -92,6 +92,24 @@ QRectF QVectorPath::controlPointRect() const return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2)); } + +QVectorPath::CacheEntry *QVectorPath::addCacheData(QPaintEngineEx *engine, void *data, + qvectorpath_cache_cleanup cleanup) { + Q_ASSERT(!lookupCacheData(engine)); + if ((m_hints & IsCachedHint) == 0) { + m_cache = 0; + m_hints |= IsCachedHint; + } + CacheEntry *e = new CacheEntry; + e->engine = engine; + e->data = data; + e->cleanup = cleanup; + e->next = m_cache; + m_cache = e; + return m_cache; +} + + const QVectorPath &qtVectorPathForPath(const QPainterPath &path) { Q_ASSERT(path.d_func()); @@ -414,7 +432,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) // Some engines might decide to optimize for the non-shape hint later on... uint flags = QVectorPath::WindingFill; if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin) - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; // ### Perspective Xforms are currently not supported... if (!pen.isCosmetic()) { @@ -442,7 +460,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) points[4], points[5]); points += 6; types += 3; - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; break; default: break; @@ -504,7 +522,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); points += 6; types += 3; - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; break; } default: @@ -736,7 +754,7 @@ void QPaintEngineEx::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yR x1 + xRadius, y1 }; - QVectorPath path(pts, 17, qpaintengineex_roundedrect_types); + QVectorPath path(pts, 17, qpaintengineex_roundedrect_types, QVectorPath::RoundedRectHint); draw(path); } @@ -827,7 +845,7 @@ void QPaintEngineEx::drawPoints(const QPointF *points, int pointCount) pts[++oset] = points[i].x() + 0.001; pts[++oset] = points[i].y(); } - QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::NonCurvedShapeHint); + QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint); stroke(path, pen); pointCount -= 16; points += 16; @@ -858,7 +876,7 @@ void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount) pts[++oset] = points[i].x() + 0.001; pts[++oset] = points[i].y(); } - QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::NonCurvedShapeHint); + QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint); stroke(path, pen); pointCount -= 16; points += 16; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 3ec9bd6..02d77f4 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -250,9 +250,9 @@ public: inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) { switch (mode) { case QPaintEngine::ConvexMode: return ConvexPolygonHint | ImplicitClose; - case QPaintEngine::OddEvenMode: return NonCurvedShapeHint | OddEvenFill | ImplicitClose; - case QPaintEngine::WindingMode: return NonCurvedShapeHint | WindingFill | ImplicitClose; - case QPaintEngine::PolylineMode: return NonCurvedShapeHint; + case QPaintEngine::OddEvenMode: return PolygonHint | OddEvenFill | ImplicitClose; + case QPaintEngine::WindingMode: return PolygonHint | WindingFill | ImplicitClose; + case QPaintEngine::PolylineMode: return PolygonHint; default: return 0; } } diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 69e189c..c40bcee 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -688,6 +688,8 @@ void QPainterPath::lineTo(const QPointF &p) return; Element elm = { p.x(), p.y(), LineToElement }; d->elements.append(elm); + + d->convex = d->elements.size() == 3 || (d->elements.size() == 4 && d->isClosed()); } /*! @@ -960,6 +962,8 @@ void QPainterPath::addRect(const QRectF &r) ensureData(); detach(); + bool first = d_func()->elements.size() < 2; + d_func()->elements.reserve(d_func()->elements.size() + 5); moveTo(r.x(), r.y()); @@ -970,6 +974,7 @@ void QPainterPath::addRect(const QRectF &r) d_func()->elements << l1 << l2 << l3 << l4; d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -1039,6 +1044,7 @@ void QPainterPath::addEllipse(const QRectF &boundingRect) detach(); Q_D(QPainterPath); + bool first = d_func()->elements.size() < 2; d->elements.reserve(d->elements.size() + 13); QPointF pts[12]; @@ -1051,6 +1057,8 @@ void QPainterPath::addEllipse(const QRectF &boundingRect) cubicTo(pts[6], pts[7], pts[8]); // 180 -> 90 cubicTo(pts[9], pts[10], pts[11]); // 90 - >0 d_func()->require_moveTo = true; + + d_func()->convex = first; } /*! @@ -3027,6 +3035,8 @@ void QPainterPath::addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadi ensureData(); detach(); + bool first = d_func()->elements.size() < 2; + arcMoveTo(x, y, rxx2, ryy2, 90); arcTo(x, y, rxx2, ryy2, 90, 90); arcTo(x, y+h-ryy2, rxx2, ryy2, 2*90, 90); @@ -3035,6 +3045,7 @@ void QPainterPath::addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadi closeSubpath(); d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -3081,6 +3092,8 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd) ensureData(); detach(); + bool first = d_func()->elements.size() < 2; + arcMoveTo(x, y, rxx2, ryy2, 90); arcTo(x, y, rxx2, ryy2, 90, 90); arcTo(x, y+h-ryy2, rxx2, ryy2, 2*90, 90); @@ -3089,6 +3102,7 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd) closeSubpath(); d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -3269,6 +3283,7 @@ void QPainterPath::setDirty(bool dirty) d_func()->dirtyControlBounds = dirty; delete d_func()->pathConverter; d_func()->pathConverter = 0; + d_func()->convex = false; } void QPainterPath::computeBoundingRect() const diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index 54c182d..112c2bd 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -81,8 +81,8 @@ class QVectorPathConverter; class QVectorPathConverter { public: - QVectorPathConverter(const QVector<QPainterPath::Element> &path, uint fillRule) - : pathData(path, fillRule), + QVectorPathConverter(const QVector<QPainterPath::Element> &path, uint fillRule, bool convex) + : pathData(path, fillRule, convex), path(pathData.points.data(), path.size(), pathData.elements.data(), pathData.flags) {} @@ -91,7 +91,7 @@ public: } struct QVectorPathData { - QVectorPathData(const QVector<QPainterPath::Element> &path, uint fillRule) + QVectorPathData(const QVector<QPainterPath::Element> &path, uint fillRule, bool convex) : elements(path.size()), points(path.size() * 2), flags(0) @@ -103,7 +103,7 @@ public: points[ptsPos++] = e.x; points[ptsPos++] = e.y; if (e.type == QPainterPath::CurveToElement) - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; } if (fillRule == Qt::WindingFill) @@ -111,6 +111,8 @@ public: else flags |= QVectorPath::OddEvenFill; + if (!convex) + flags |= QVectorPath::NonConvexShapeMask; } QVarLengthArray<QPainterPath::ElementType> elements; QVarLengthArray<qreal> points; @@ -128,20 +130,26 @@ class QPainterPathData : public QPainterPathPrivate { public: QPainterPathData() : - cStart(0), fillRule(Qt::OddEvenFill), - dirtyBounds(false), dirtyControlBounds(false), - pathConverter(0) + cStart(0), + fillRule(Qt::OddEvenFill), + pathConverter(0), + dirtyBounds(false), + dirtyControlBounds(false) + { ref = 1; require_moveTo = false; + convex = false; } QPainterPathData(const QPainterPathData &other) : QPainterPathPrivate(), cStart(other.cStart), fillRule(other.fillRule), - dirtyBounds(other.dirtyBounds), bounds(other.bounds), - dirtyControlBounds(other.dirtyControlBounds), + bounds(other.bounds), controlBounds(other.controlBounds), - pathConverter(0) + pathConverter(0), + dirtyBounds(other.dirtyBounds), + dirtyControlBounds(other.dirtyControlBounds), + convex(other.convex) { ref = 1; require_moveTo = false; @@ -158,20 +166,21 @@ public: const QVectorPath &vectorPath() { if (!pathConverter) - pathConverter = new QVectorPathConverter(elements, fillRule); + pathConverter = new QVectorPathConverter(elements, fillRule, convex); return pathConverter->path; } int cStart; Qt::FillRule fillRule; - bool require_moveTo; - - bool dirtyBounds; QRectF bounds; - bool dirtyControlBounds; QRectF controlBounds; + uint require_moveTo : 1; + uint dirtyBounds : 1; + uint dirtyControlBounds : 1; + uint convex : 1; + QVectorPathConverter *pathConverter; }; diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h index d023131..ec27970 100644 --- a/src/gui/painting/qvectorpath_p.h +++ b/src/gui/painting/qvectorpath_p.h @@ -66,8 +66,9 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) +class QPaintEngineEx; -#define QVECTORPATH_NO_CACHE +typedef void (*qvectorpath_cache_cleanup)(void *data); struct QRealRect { qreal x1, y1, x2, y2; @@ -77,19 +78,27 @@ class Q_GUI_EXPORT QVectorPath { public: enum Hint { - // Basic shapes... - LinesHint = 0x0001, // Just plain lines... - RectangleHint = 0x0002, - ConvexPolygonHint = 0x0003, // Convex polygon... - NonISectPolygonHint = 0x0004, // concave polygon, but not intersecting.. - NonCurvedShapeHint = 0x0005, // Generic polygon, possibly self-intersecting... - CurvedShapeHint = 0x0006, // Generic vector path.. - EllipseHint = 0x0007, - ShapeHintMask = 0x000f, + // Shape hints, in 0x000000ff, access using shape() + AreaShapeMask = 0x0001, // shape covers an area + NonConvexShapeMask = 0x0002, // shape is not convex + CurvedShapeMask = 0x0004, // shape contains curves... + LinesShapeMask = 0x0008, + RectangleShapeMask = 0x0010, + ShapeMask = 0x001f, + + // Shape hints merged into basic shapes.. + LinesHint = LinesShapeMask, + RectangleHint = AreaShapeMask | RectangleShapeMask, + EllipseHint = AreaShapeMask | CurvedShapeMask, + ConvexPolygonHint = AreaShapeMask, + PolygonHint = AreaShapeMask | NonConvexShapeMask, + RoundedRectHint = AreaShapeMask | CurvedShapeMask, + ArbitraryShapeHint = AreaShapeMask | NonConvexShapeMask | CurvedShapeMask, // Other hints - CacheHint = 0x0100, - ControlPointRect = 0x0200, // Set if the control point rect has been calculated... + IsCachedHint = 0x0100, // Set if the cache hint is set + ShouldUseCacheHint = 0x0200, // Set if the path should be cached when possible.. + ControlPointRect = 0x0400, // Set if the control point rect has been calculated... // Shape rendering specifiers... OddEvenFill = 0x1000, @@ -101,22 +110,21 @@ public: QVectorPath(const qreal *points, int count, const QPainterPath::ElementType *elements = 0, - uint hints = CurvedShapeHint) + uint hints = ArbitraryShapeHint) : m_elements(elements), m_points(points), m_count(count), m_hints(hints) -#ifndef QVECTORPATH_NO_CACHE - , m_cache(0) -#endif { } QRectF controlPointRect() const; - inline Hint shape() const { return (Hint) (m_hints & ShapeHintMask); } + inline Hint shape() const { return (Hint) (m_hints & ShapeMask); } + inline bool isConvex() const { return (m_hints & NonConvexShapeMask) == 0; } + inline bool isCurved() const { return m_hints & CurvedShapeMask; } - inline bool hasCacheHint() const { return m_hints & CacheHint; } + inline bool isCacheable() const { return m_hints & ShouldUseCacheHint; } inline bool hasImplicitClose() const { return m_hints & ImplicitClose; } inline bool hasWindingFill() const { return m_hints & WindingFill; } @@ -131,24 +139,30 @@ public: static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode); -private: - Q_DISABLE_COPY(QVectorPath) - -#ifndef QVECTORPATH_NO_CACHE struct CacheEntry { - void *engine; - int id; - void *extra; + QPaintEngineEx *engine; + void *data; + qvectorpath_cache_cleanup cleanup; CacheEntry *next; }; - void addCacheData(CacheEntry *d) { - d->next = m_cache; - m_cache = d; + CacheEntry *addCacheData(QPaintEngineEx *engine, void *data, qvectorpath_cache_cleanup cleanup); + inline CacheEntry *lookupCacheData(QPaintEngineEx *engine) const { + Q_ASSERT(m_hints & IsCachedHint); + CacheEntry *e = m_cache; + while (e) { + if (e->engine == engine) + return e; + e = e->next; + } + return 0; } + +private: + Q_DISABLE_COPY(QVectorPath) + CacheEntry *m_cache; -#endif const QPainterPath::ElementType *m_elements; const qreal *m_points; diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 3a118bd..d412040 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -215,6 +215,12 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi XCopyArea(X11->display, d_ptr->image->xshmpm, widget->handle(), d_ptr->gc, br.x(), br.y(), br.width(), br.height(), wbr.x(), wbr.y()); XSync(X11->display, False); + } else if (d_ptr->image->xshmimg) { + const QImage &src = d->image->image; + br = br.intersected(src.rect()); + XShmPutImage(X11->display, widget->handle(), d_ptr->gc, d_ptr->image->xshmimg, + br.x(), br.y(), wbr.x(), wbr.y(), br.width(), br.height(), False); + XSync(X11->display, False); } else #endif { |