Refactor glyph pretransform check
authorJiang Jiang <jiang.jiang@nokia.com>
Wed, 1 Jun 2011 09:06:55 +0000 (11:06 +0200)
committerQt Continuous Integration System <qt-info@nokia.com>
Fri, 3 Jun 2011 08:57:42 +0000 (10:57 +0200)
Move paintEngineSupportsTransformations logic from QPainter to paint
engine subclasses. Simplify and consolidate checks for cached drawing
(pretransformed) and path drawing (untransformed) in raster paint
engine. Fix unnecessary transform when paint engines actually take
the path drawing track. Fix scaling and rotation transform in raster
engine for Mac.

Task-number: QTBUG-19086
Change-Id: I1c0c1800a5173d3db765b9fccfd0e7a3628e3815
Reviewed-on: http://codereview.qt.nokia.com/298
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
src/gui/painting/qpaintengine_mac_p.h
src/gui/painting/qpaintengine_raster.cpp
src/gui/painting/qpaintengine_raster_p.h
src/gui/painting/qpaintengineex.cpp
src/gui/painting/qpaintengineex_p.h
src/gui/painting/qpainter.cpp
src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
src/opengl/qpaintengine_opengl_p.h
src/openvg/qpaintengine_vg_p.h

index c87501e..2434011 100644 (file)
@@ -121,6 +121,8 @@ public:
     void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
     { QPaintEngine::drawPolygon(points, pointCount, mode); }
 
+    bool supportsTransformations(qreal, const QTransform &) const { return true; };
+
 protected:
     friend class QMacPrintEngine;
     friend class QMacPrintEnginePrivate;
index 1f7ab21..f5daef7 100644 (file)
@@ -3029,11 +3029,8 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
     ensurePen();
     ensureState();
 
-    QRasterPaintEngineState *s = state();
-
     QFontEngine *fontEngine = textItem->fontEngine();
-    const qreal pixelSize = fontEngine->fontDef.pixelSize;
-    if (pixelSize * pixelSize * qAbs(s->matrix.determinant()) < 64 * 64) {
+    if (!supportsTransformations(fontEngine)) {
         drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
                          fontEngine);
     } else {
@@ -3061,36 +3058,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
 
 #if defined (Q_WS_WIN) || defined(Q_WS_MAC)
 
-    bool drawCached = true;
-
-    if (s->matrix.type() >= QTransform::TxProject)
-        drawCached = false;
-
-    // don't try to cache huge fonts
-    const qreal pixelSize = ti.fontEngine->fontDef.pixelSize;
-    if (pixelSize * pixelSize * qAbs(s->matrix.determinant()) >= 64 * 64)
-        drawCached = false;
-
-    // ### Remove the TestFontEngine and Box engine crap, in these
-    // ### cases we should delegate painting to the font engine
-    // ### directly...
-
-#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
-    QFontEngine::Type fontEngineType = ti.fontEngine->type();
-    // qDebug() << "type" << fontEngineType << s->matrix.type();
-    if ((fontEngineType == QFontEngine::Win && !((QFontEngineWin *) ti.fontEngine)->ttf && s->matrix.type() > QTransform::TxTranslate)
-        || (s->matrix.type() <= QTransform::TxTranslate
-            && (fontEngineType == QFontEngine::TestFontEngine
-                || fontEngineType == QFontEngine::Box))) {
-            drawCached = false;
-    }
-#else
-    if (s->matrix.type() > QTransform::TxTranslate)
-        drawCached = false;
-#endif
-    if (drawCached) {
-        QRasterPaintEngineState *s = state();
-
+    if (!supportsTransformations(ti.fontEngine)) {
         QVarLengthArray<QFixedPoint> positions;
         QVarLengthArray<glyph_t> glyphs;
 
@@ -3386,6 +3354,37 @@ void QRasterPaintEngine::releaseDC(HDC) const
 
 #endif
 
+bool QRasterPaintEngine::supportsTransformations(const QFontEngine *fontEngine) const
+{
+    const QTransform &m = state()->matrix;
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
+    QFontEngine::Type fontEngineType = ti.fontEngine->type();
+    if ((fontEngineType == QFontEngine::Win && !((QFontEngineWin *) ti.fontEngine)->ttf && m.type() > QTransform::TxTranslate)
+        || (m.type() <= QTransform::TxTranslate
+            && (fontEngineType == QFontEngine::TestFontEngine
+                || fontEngineType == QFontEngine::Box))) {
+            return true;
+    }
+#endif
+    return supportsTransformations(fontEngine->fontDef.pixelSize, m);
+}
+
+bool QRasterPaintEngine::supportsTransformations(qreal pixelSize, const QTransform &m) const
+{
+#if defined(Q_WS_MAC)
+    // Mac font engines don't support scaling and rotation
+    if (m.type() > QTransform::TxTranslate)
+#else
+    if (m.type() >= QTransform::TxProject)
+#endif
+        return true;
+
+    if (pixelSize * pixelSize * qAbs(m.determinant()) >= 64 * 64)
+        return true;
+
+    return false;
+}
+
 /*!
     \internal
 */
index f7f605d..2bf25f9 100644 (file)
@@ -246,6 +246,8 @@ public:
     virtual void drawBufferSpan(const uint *buffer, int bufsize,
                                 int x, int y, int length, uint const_alpha);
 #endif
+    bool supportsTransformations(const QFontEngine *fontEngine) const;
+    bool supportsTransformations(qreal pixelSize, const QTransform &m) const;
 
 protected:
     QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *);
index 3b52a78..8510416 100644 (file)
@@ -1093,4 +1093,14 @@ void QPaintEngineEx::drawStaticTextItem(QStaticTextItem *staticTextItem)
     }
 }
 
+bool QPaintEngineEx::supportsTransformations(qreal pixelSize, const QTransform &m) const
+{
+    Q_UNUSED(pixelSize);
+
+    if (!m.isAffine())
+        return true;
+
+    return false;
+}
+
 QT_END_NAMESPACE
index 3a34515..c605685 100644 (file)
@@ -227,6 +227,7 @@ public:
         IsEmulationEngine = 0x02    // If set, this object is a QEmulationEngine.
     };
     virtual uint flags() const {return 0;}
+    virtual bool supportsTransformations(qreal pixelSize, const QTransform &m) const;
 
 protected:
     QPaintEngineEx(QPaintEngineExPrivate &data);
index 811e59b..e7b5f18 100644 (file)
@@ -152,14 +152,6 @@ static inline uint line_emulation(uint emulation)
                         | QPaintEngine_OpaqueBackground);
 }
 
-static bool qt_paintengine_supports_transformations(QPaintEngine::Type type)
-{
-    return type == QPaintEngine::OpenGL2
-            || type == QPaintEngine::OpenVG
-            || type == QPaintEngine::OpenGL
-            || type == QPaintEngine::CoreGraphics;
-}
-
 #ifndef QT_NO_DEBUG
 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
 {
@@ -5815,20 +5807,19 @@ void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
     int count = qMin(glyphIndexes.size(), glyphPositions.size());
     QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
 
-    bool paintEngineSupportsTransformations =
-            d->extended != 0
-            ? qt_paintengine_supports_transformations(d->extended->type())
-            : qt_paintengine_supports_transformations(d->engine->type());
-
-    // If the matrix is not affine, the paint engine will fall back to
-    // drawing the glyphs as paths, which in turn means we should not
-    // preprocess the glyph positions
-    if (!d->state->matrix.isAffine())
-        paintEngineSupportsTransformations = true;
+    QRawFontPrivate *fontD = QRawFontPrivate::get(font);
+    bool supportsTransformations;
+    if (d->extended != 0) {
+        supportsTransformations = d->extended->supportsTransformations(fontD->fontEngine->fontDef.pixelSize,
+                                                                       d->state->matrix);
+    } else {
+        supportsTransformations = d->engine->type() == QPaintEngine::CoreGraphics
+                                  || d->state->matrix.isAffine();
+    }
 
     for (int i=0; i<count; ++i) {
         QPointF processedPosition = position + glyphPositions.at(i);
-        if (!paintEngineSupportsTransformations)
+        if (!supportsTransformations)
             processedPosition = d->state->transform().map(processedPosition);
         fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
     }
@@ -6004,11 +5995,12 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText
         return;
     }
 
-    bool paintEngineSupportsTransformations = qt_paintengine_supports_transformations(d->extended->type());
-    if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) {
+    bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.pixelSize(),
+                                                                        d->state->matrix);
+    if (supportsTransformations && !staticText_d->untransformedCoordinates) {
         staticText_d->untransformedCoordinates = true;
         staticText_d->needsRelayout = true;
-    } else if (!paintEngineSupportsTransformations && staticText_d->untransformedCoordinates) {
+    } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
         staticText_d->untransformedCoordinates = false;
         staticText_d->needsRelayout = true;
     }
index 7ba92e4..2895d5a 100644 (file)
@@ -158,6 +158,7 @@ public:
     void setRenderTextActive(bool);
 
     bool isNativePaintingActive() const;
+    bool supportsTransformations(qreal, const QTransform &) const { return true; }
 private:
     Q_DISABLE_COPY(QGL2PaintEngineEx)
 };
index 5d5f5ce..8d0ea83 100644 (file)
@@ -143,6 +143,7 @@ public:
     Qt::HANDLE handle() const;
 #endif
     inline Type type() const { return QPaintEngine::OpenGL; }
+    bool supportsTransformations(qreal, const QTransform &) const { return true; }
 
 private:
     void drawPolyInternal(const QPolygonF &pa, bool close = true);
index f1ef0fb..267ecd4 100644 (file)
@@ -159,6 +159,7 @@ public:
     QVGPaintEnginePrivate *vgPrivate() { Q_D(QVGPaintEngine); return d; }
 
     void fillRegion(const QRegion& region, const QColor& color, const QSize& surfaceSize);
+    bool supportsTransformations(qreal, const QTransform &) const { return true; }
 
 protected:
     QVGPaintEngine(QVGPaintEnginePrivate &data);