src/openvg/qpaintengine_vg.cpp
changeset 19 fcece45ef507
parent 18 2f34d5167611
child 22 79de32ba3296
--- a/src/openvg/qpaintengine_vg.cpp	Fri Apr 16 15:50:13 2010 +0300
+++ b/src/openvg/qpaintengine_vg.cpp	Mon May 03 13:17:34 2010 +0300
@@ -131,9 +131,8 @@
     void draw(VGPath path, const QPen& pen, const QBrush& brush, VGint rule = VG_EVEN_ODD);
     void stroke(VGPath path, const QPen& pen);
     void fill(VGPath path, const QBrush& brush, VGint rule = VG_EVEN_ODD);
-    inline void releasePath(VGPath path);
-    VGPath vectorPathToVGPath(const QVectorPath& path, bool forceNewPath = false);
-    VGPath painterPathToVGPath(const QPainterPath& path, bool forceNewPath = false);
+    VGPath vectorPathToVGPath(const QVectorPath& path);
+    VGPath painterPathToVGPath(const QPainterPath& path);
     VGPath roundedRectPath(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode);
     VGPaintType setBrush
         (VGPaint paint, const QBrush& brush, VGMatrixMode mode,
@@ -179,13 +178,12 @@
     VGPath roundRectPath;   // Cached path for quick drawing of rounded rects.
 #endif
 
-    VGPath reusablePath;    // Reusable path for vectorPathToVGPath(), etc.
-
     QTransform transform;   // Currently active transform.
     bool simpleTransform;   // True if the transform is simple (non-projective).
     qreal penScale;         // Pen scaling factor from "transform".
 
     QTransform pathTransform;  // Calculated VG path transformation.
+    QTransform glyphTransform; // Calculated VG glyph transformation.
     QTransform imageTransform; // Calculated VG image transformation.
     bool pathTransformSet;  // True if path transform set in the VG context.
 
@@ -353,8 +351,6 @@
     roundRectPath = 0;
 #endif
 
-    reusablePath = 0;
-
     simpleTransform = true;
     pathTransformSet = false;
     penScale = 1.0;
@@ -451,15 +447,6 @@
                             VG_PATH_CAPABILITY_ALL);
     vgAppendPathData(linePath, 2, segments, coords);
 #endif
-
-    // This path can be reused over and over by calling vgClearPath().
-    reusablePath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
-                                VG_PATH_DATATYPE_F,
-                                1.0f,        // scale
-                                0.0f,        // bias
-                                32 + 1,      // segmentCapacityHint
-                                32 * 2,      // coordCapacityHint
-                                VG_PATH_CAPABILITY_ALL);
 }
 
 void QVGPaintEnginePrivate::destroy()
@@ -479,8 +466,6 @@
     if (roundRectPath)
         vgDestroyPath(roundRectPath);
 #endif
-    if (reusablePath)
-        vgDestroyPath(reusablePath);
 
 #if !defined(QVG_NO_DRAW_GLYPHS)
     QVGFontCache::Iterator it;
@@ -516,79 +501,67 @@
 
 void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev)
 {
-    VGfloat devh = pdev->height() - 1;
+    VGfloat devh = pdev->height();
 
     // Construct the VG transform by combining the Qt transform with
     // the following viewport transformation:
-    //        | 1  0  0   |   | 1 0  0.5 |   | 1  0     0.5      |
-    //        | 0 -1 devh | * | 0 1 -0.5 | = | 0 -1 (0.5 + devh) |
-    //        | 0  0  1   |   | 0 0   1  |   | 0  0      1       |
+    //        | 1  0  0   |
+    //        | 0 -1 devh |
+    //        | 0  0  1   |
+    // The glyph transform uses a slightly different transformation:
+    //        | 1  0  0       |   | 1 0  0.5 |   | 1  0     0.5      |
+    //        | 0 -1 devh - 1 | * | 0 1 -0.5 | = | 0 -1 (devh - 0.5) |
+    //        | 0  0  1       |   | 0 0   1  |   | 0  0      1       |
     // The full VG transform is effectively:
     //      1. Apply the user's transformation matrix.
-    //      2. Translate by (0.5, -0.5) to correct for Qt and VG putting
-    //         the centre of the pixel at different positions.
+    //      2. Translate glyphs by an extra (0.5, -0.5).
     //      3. Flip the co-ordinate system upside down.
     QTransform viewport(1.0f, 0.0f, 0.0f,
                         0.0f, -1.0f, 0.0f,
-                        0.5f, devh + 0.5f, 1.0f);
-
-    // Compute the path transform and determine if it is projective. 
-     pathTransform = transform * viewport; 
-     bool projective = (pathTransform.m13() != 0.0f || 
-     pathTransform.m23() != 0.0f || 
-     pathTransform.m33() != 1.0f); 
-    
+                        0.0f, devh, 1.0f);
+    QTransform gviewport(1.0f, 0.0f, 0.0f,
+                        0.0f, -1.0f, 0.0f,
+                        0.5f, devh - 0.5f, 1.0f);
+
+    // Compute the path transform and determine if it is projective.
+    pathTransform = transform * viewport;
+    glyphTransform = transform * gviewport;
+    bool projective = (pathTransform.m13() != 0.0f ||
+                       pathTransform.m23() != 0.0f ||
+                       pathTransform.m33() != 1.0f);
     if (projective) {
         // The engine cannot do projective path transforms for us,
         // so we will have to convert the co-ordinates ourselves.
         // Change the matrix to just the viewport transformation.
         pathTransform = viewport;
+        glyphTransform = gviewport;
         simpleTransform = false;
     } else {
         simpleTransform = true;
     }
     pathTransformSet = false;
 
-    // The image transform is always the full transformation, 
-    // because it can be projective. It also does not need the 
-    // (0.5, -0.5) translation because vgDrawImage() implicitly 
-    // adds 0.5 to each co-ordinate. 
-    QTransform viewport2(1.0f, 0.0f, 0.0f, 
-    0.0f, -1.0f, 0.0f, 
-    0.0f, devh, 1.0f); 
-    imageTransform = transform * viewport2; 
+    // The image transform is always the full transformation,
+    imageTransform = transform * viewport;
 
     // Calculate the scaling factor to use for turning cosmetic pens
     // into ordinary non-cosmetic pens.
     qt_scaleForTransform(transform, &penScale);
 }
 
-inline void QVGPaintEnginePrivate::releasePath(VGPath path)
-{
-    if (path == reusablePath)
-        vgClearPath(path, VG_PATH_CAPABILITY_ALL);
-    else
-        vgDestroyPath(path);
-}
-
-VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path, bool forceNewPath)
+VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path)
 {
     int count = path.elementCount();
     const qreal *points = path.points();
     const QPainterPath::ElementType *elements = path.elements();
 
-    VGPath vgpath;
-    if (forceNewPath) {
-        vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
-                              VG_PATH_DATATYPE_F,
-                              1.0f,        // scale
-                              0.0f,        // bias
-                              count + 1,   // segmentCapacityHint
-                              count * 2,   // coordCapacityHint
-                              VG_PATH_CAPABILITY_ALL);
-    } else {
-        vgpath = reusablePath;
-    }
+    VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+                                 VG_PATH_DATATYPE_F,
+                                 1.0f,        // scale
+                                 0.0f,        // bias
+                                 count + 1,   // segmentCapacityHint
+                                 count * 2,   // coordCapacityHint
+                                 VG_PATH_CAPABILITY_ALL);
 
     // Size is sufficient segments for drawRoundedRect() paths.
     QVarLengthArray<VGubyte, 20> segments;
@@ -760,22 +733,17 @@
     return vgpath;
 }
 
-VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path, bool forceNewPath)
+VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path)
 {
     int count = path.elementCount();
 
-    VGPath vgpath;
-    if (forceNewPath) {
-        vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
-                              VG_PATH_DATATYPE_F,
-                              1.0f,        // scale
-                              0.0f,        // bias
-                              count + 1,   // segmentCapacityHint
-                              count * 2,   // coordCapacityHint
-                              VG_PATH_CAPABILITY_ALL);
-    } else {
-        vgpath = reusablePath;
-    }
+    VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+                                 VG_PATH_DATATYPE_F,
+                                 1.0f,        // scale
+                                 0.0f,        // bias
+                                 count + 1,   // segmentCapacityHint
+                                 count * 2,   // coordCapacityHint
+                                 VG_PATH_CAPABILITY_ALL);
 
     if (count == 0)
         return vgpath;
@@ -994,7 +962,13 @@
         vgModifyPathCoords(vgpath, 0, 9, pts);
     }
 #else
-    VGPath vgpath = reusablePath;
+    VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+                                 VG_PATH_DATATYPE_F,
+                                 1.0f,        // scale
+                                 0.0f,        // bias
+                                 10,          // segmentCapacityHint
+                                 17 * 2,      // coordCapacityHint
+                                 VG_PATH_CAPABILITY_ALL);
     vgAppendPathData(vgpath, 10, roundedrect_types, pts);
 #endif
 
@@ -1550,7 +1524,7 @@
         d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD);
     else
         d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO);
-    d->releasePath(vgpath);
+    vgDestroyPath(vgpath);
 }
 
 void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
@@ -1561,7 +1535,7 @@
         d->fill(vgpath, brush, VG_EVEN_ODD);
     else
         d->fill(vgpath, brush, VG_NON_ZERO);
-    d->releasePath(vgpath);
+    vgDestroyPath(vgpath);
 }
 
 void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
@@ -1569,7 +1543,7 @@
     Q_D(QVGPaintEngine);
     VGPath vgpath = d->vectorPathToVGPath(path);
     d->stroke(vgpath, pen);
-    d->releasePath(vgpath);
+    vgDestroyPath(vgpath);
 }
 
 // Determine if a co-ordinate transform is simple enough to allow
@@ -1765,7 +1739,7 @@
 
         default: break;
     }
-    d->releasePath(vgpath);
+    vgDestroyPath(vgpath);
 
     vgSeti(VG_MASKING, VG_TRUE);
     d->maskValid = true;
@@ -2082,7 +2056,7 @@
 
         default: break;
     }
-    d->releasePath(vgpath);
+    vgDestroyPath(vgpath);
 
     vgSeti(VG_MASKING, VG_TRUE);
     d->maskValid = true;
@@ -2096,7 +2070,7 @@
 void QVGPaintEnginePrivate::ensureMask
         (QVGPaintEngine *engine, int width, int height)
 {
-	  scissorMask = false;
+    scissorMask = false;
     if (maskIsSet) {
         vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, width, height);
         maskRect = QRect();
@@ -2522,7 +2496,7 @@
         VGPath vgpath = d->roundedRectPath(rect, xrad, yrad, mode);
         d->draw(vgpath, s->pen, s->brush);
 #if defined(QVG_NO_MODIFY_PATH)
-        d->releasePath(vgpath);
+        vgDestroyPath(vgpath);
 #endif
     } else {
         QPaintEngineEx::drawRoundedRect(rect, xrad, yrad, mode);
@@ -2671,7 +2645,13 @@
     Q_D(QVGPaintEngine);
     if (d->simpleTransform) {
         QVGPainterState *s = state();
-        VGPath path = d->reusablePath;
+        VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+                                   VG_PATH_DATATYPE_F,
+                                   1.0f, // scale
+                                   0.0f, // bias
+                                   4,    // segmentCapacityHint
+                                   12,   // coordCapacityHint
+                                   VG_PATH_CAPABILITY_ALL);
         static VGubyte segments[4] = {
             VG_MOVE_TO_ABS,
             VG_SCCWARC_TO_REL,
@@ -2695,7 +2675,7 @@
         coords[11] = 0.0f;
         vgAppendPathData(path, 4, segments, coords);
         d->draw(path, s->pen, s->brush);
-        d->releasePath(path);
+        vgDestroyPath(path);
     } else {
         // The projective transform version of an ellipse is difficult.
         // Generate a QVectorPath containing cubic curves and transform that.
@@ -2719,7 +2699,7 @@
         d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD);
     else
         d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO);
-    d->releasePath(vgpath);
+    vgDestroyPath(vgpath);
 }
 
 void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount)
@@ -2794,7 +2774,13 @@
 {
     Q_D(QVGPaintEngine);
     QVGPainterState *s = state();
-    VGPath path = d->reusablePath;
+    VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+                               VG_PATH_DATATYPE_F,
+                               1.0f,             // scale
+                               0.0f,             // bias
+                               pointCount + 1,   // segmentCapacityHint
+                               pointCount * 2,   // coordCapacityHint
+                               VG_PATH_CAPABILITY_ALL);
     QVarLengthArray<VGfloat, 16> coords;
     QVarLengthArray<VGubyte, 10> segments;
     for (int i = 0; i < pointCount; ++i, ++points) {
@@ -2828,14 +2814,20 @@
             d->draw(path, s->pen, s->brush, VG_EVEN_ODD);
             break;
     }
-    d->releasePath(path);
+    vgDestroyPath(path);
 }
 
 void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
 {
     Q_D(QVGPaintEngine);
     QVGPainterState *s = state();
-    VGPath path = d->reusablePath;
+    VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+                               VG_PATH_DATATYPE_F,
+                               1.0f,             // scale
+                               0.0f,             // bias
+                               pointCount + 1,   // segmentCapacityHint
+                               pointCount * 2,   // coordCapacityHint
+                               VG_PATH_CAPABILITY_ALL);
     QVarLengthArray<VGfloat, 16> coords;
     QVarLengthArray<VGubyte, 10> segments;
     for (int i = 0; i < pointCount; ++i, ++points) {
@@ -2869,7 +2861,7 @@
             d->draw(path, s->pen, s->brush, VG_EVEN_ODD);
             break;
     }
-    d->releasePath(path);
+    vgDestroyPath(path);
 }
 
 void QVGPaintEnginePrivate::setImageOptions()
@@ -3268,7 +3260,7 @@
         ti.fontEngine->getUnscaledGlyph(glyph, &path, &metrics);
         VGPath vgPath;
         if (!path.isEmpty()) {
-            vgPath = d->painterPathToVGPath(path, true);
+            vgPath = d->painterPathToVGPath(path);
         } else {
             // Probably a "space" character with no visible outline.
             vgPath = VG_INVALID_HANDLE;
@@ -3328,7 +3320,7 @@
     }
 
     // Set the transformation to use for drawing the current glyphs.
-    QTransform glyphTransform(d->pathTransform);
+    QTransform glyphTransform(d->glyphTransform);
     glyphTransform.translate(p.x(), p.y());
 #if defined(QVG_NO_IMAGE_GLYPHS)
     glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY);
@@ -3661,10 +3653,10 @@
 
     } else {
         // Set the path transform to the default viewport transformation.
-        VGfloat devh = screenSize.height() - 1;
+        VGfloat devh = screenSize.height();
         QTransform viewport(1.0f, 0.0f, 0.0f,
                             0.0f, -1.0f, 0.0f,
-                            -0.5f, devh + 0.5f, 1.0f);
+                            0.0f, devh, 1.0f);
         d->setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, viewport);
 
         // Set the brush to use to fill the background.
@@ -3700,10 +3692,10 @@
     }
 
     // Set the image transformation and modes.
-    VGfloat devh = screenSize.height() - 1;
+    VGfloat devh = screenSize.height();
     QTransform transform(1.0f, 0.0f, 0.0f,
                          0.0f, -1.0f, 0.0f,
-                         -0.5f, devh + 0.5f, 1.0f);
+                         0.0f, devh, 1.0f);
     transform.translate(offset.x(), offset.y());
     d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
     d->setImageMode(VG_DRAW_IMAGE_NORMAL);