src/openvg/qpaintengine_vg.cpp
changeset 19 fcece45ef507
parent 18 2f34d5167611
child 22 79de32ba3296
equal deleted inserted replaced
18:2f34d5167611 19:fcece45ef507
   129     void setTransform(VGMatrixMode mode, const QTransform& transform);
   129     void setTransform(VGMatrixMode mode, const QTransform& transform);
   130     void updateTransform(QPaintDevice *pdev);
   130     void updateTransform(QPaintDevice *pdev);
   131     void draw(VGPath path, const QPen& pen, const QBrush& brush, VGint rule = VG_EVEN_ODD);
   131     void draw(VGPath path, const QPen& pen, const QBrush& brush, VGint rule = VG_EVEN_ODD);
   132     void stroke(VGPath path, const QPen& pen);
   132     void stroke(VGPath path, const QPen& pen);
   133     void fill(VGPath path, const QBrush& brush, VGint rule = VG_EVEN_ODD);
   133     void fill(VGPath path, const QBrush& brush, VGint rule = VG_EVEN_ODD);
   134     inline void releasePath(VGPath path);
   134     VGPath vectorPathToVGPath(const QVectorPath& path);
   135     VGPath vectorPathToVGPath(const QVectorPath& path, bool forceNewPath = false);
   135     VGPath painterPathToVGPath(const QPainterPath& path);
   136     VGPath painterPathToVGPath(const QPainterPath& path, bool forceNewPath = false);
       
   137     VGPath roundedRectPath(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode);
   136     VGPath roundedRectPath(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode);
   138     VGPaintType setBrush
   137     VGPaintType setBrush
   139         (VGPaint paint, const QBrush& brush, VGMatrixMode mode,
   138         (VGPaint paint, const QBrush& brush, VGMatrixMode mode,
   140          VGPaintType prevPaintType);
   139          VGPaintType prevPaintType);
   141     void setPenParams(const QPen& pen);
   140     void setPenParams(const QPen& pen);
   177     VGPath rectPath;        // Cached path for quick drawing of rectangles.
   176     VGPath rectPath;        // Cached path for quick drawing of rectangles.
   178     VGPath linePath;        // Cached path for quick drawing of lines.
   177     VGPath linePath;        // Cached path for quick drawing of lines.
   179     VGPath roundRectPath;   // Cached path for quick drawing of rounded rects.
   178     VGPath roundRectPath;   // Cached path for quick drawing of rounded rects.
   180 #endif
   179 #endif
   181 
   180 
   182     VGPath reusablePath;    // Reusable path for vectorPathToVGPath(), etc.
       
   183 
       
   184     QTransform transform;   // Currently active transform.
   181     QTransform transform;   // Currently active transform.
   185     bool simpleTransform;   // True if the transform is simple (non-projective).
   182     bool simpleTransform;   // True if the transform is simple (non-projective).
   186     qreal penScale;         // Pen scaling factor from "transform".
   183     qreal penScale;         // Pen scaling factor from "transform".
   187 
   184 
   188     QTransform pathTransform;  // Calculated VG path transformation.
   185     QTransform pathTransform;  // Calculated VG path transformation.
       
   186     QTransform glyphTransform; // Calculated VG glyph transformation.
   189     QTransform imageTransform; // Calculated VG image transformation.
   187     QTransform imageTransform; // Calculated VG image transformation.
   190     bool pathTransformSet;  // True if path transform set in the VG context.
   188     bool pathTransformSet;  // True if path transform set in the VG context.
   191 
   189 
   192     bool maskValid;         // True if vgMask() contains valid data.
   190     bool maskValid;         // True if vgMask() contains valid data.
   193     bool maskIsSet;         // True if mask would be fully set if it was valid.
   191     bool maskIsSet;         // True if mask would be fully set if it was valid.
   350 #if !defined(QVG_NO_MODIFY_PATH)
   348 #if !defined(QVG_NO_MODIFY_PATH)
   351     rectPath = 0;
   349     rectPath = 0;
   352     linePath = 0;
   350     linePath = 0;
   353     roundRectPath = 0;
   351     roundRectPath = 0;
   354 #endif
   352 #endif
   355 
       
   356     reusablePath = 0;
       
   357 
   353 
   358     simpleTransform = true;
   354     simpleTransform = true;
   359     pathTransformSet = false;
   355     pathTransformSet = false;
   360     penScale = 1.0;
   356     penScale = 1.0;
   361 
   357 
   449                             2,    // segmentCapacityHint
   445                             2,    // segmentCapacityHint
   450                             4,    // coordCapacityHint
   446                             4,    // coordCapacityHint
   451                             VG_PATH_CAPABILITY_ALL);
   447                             VG_PATH_CAPABILITY_ALL);
   452     vgAppendPathData(linePath, 2, segments, coords);
   448     vgAppendPathData(linePath, 2, segments, coords);
   453 #endif
   449 #endif
   454 
       
   455     // This path can be reused over and over by calling vgClearPath().
       
   456     reusablePath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
       
   457                                 VG_PATH_DATATYPE_F,
       
   458                                 1.0f,        // scale
       
   459                                 0.0f,        // bias
       
   460                                 32 + 1,      // segmentCapacityHint
       
   461                                 32 * 2,      // coordCapacityHint
       
   462                                 VG_PATH_CAPABILITY_ALL);
       
   463 }
   450 }
   464 
   451 
   465 void QVGPaintEnginePrivate::destroy()
   452 void QVGPaintEnginePrivate::destroy()
   466 {
   453 {
   467     if (penPaint)
   454     if (penPaint)
   477     if (linePath)
   464     if (linePath)
   478         vgDestroyPath(linePath);
   465         vgDestroyPath(linePath);
   479     if (roundRectPath)
   466     if (roundRectPath)
   480         vgDestroyPath(roundRectPath);
   467         vgDestroyPath(roundRectPath);
   481 #endif
   468 #endif
   482     if (reusablePath)
       
   483         vgDestroyPath(reusablePath);
       
   484 
   469 
   485 #if !defined(QVG_NO_DRAW_GLYPHS)
   470 #if !defined(QVG_NO_DRAW_GLYPHS)
   486     QVGFontCache::Iterator it;
   471     QVGFontCache::Iterator it;
   487     for (it = fontCache.begin(); it != fontCache.end(); ++it)
   472     for (it = fontCache.begin(); it != fontCache.end(); ++it)
   488         delete it.value();
   473         delete it.value();
   514 
   499 
   515 extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
   500 extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
   516 
   501 
   517 void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev)
   502 void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev)
   518 {
   503 {
   519     VGfloat devh = pdev->height() - 1;
   504     VGfloat devh = pdev->height();
   520 
   505 
   521     // Construct the VG transform by combining the Qt transform with
   506     // Construct the VG transform by combining the Qt transform with
   522     // the following viewport transformation:
   507     // the following viewport transformation:
   523     //        | 1  0  0   |   | 1 0  0.5 |   | 1  0     0.5      |
   508     //        | 1  0  0   |
   524     //        | 0 -1 devh | * | 0 1 -0.5 | = | 0 -1 (0.5 + devh) |
   509     //        | 0 -1 devh |
   525     //        | 0  0  1   |   | 0 0   1  |   | 0  0      1       |
   510     //        | 0  0  1   |
       
   511     // The glyph transform uses a slightly different transformation:
       
   512     //        | 1  0  0       |   | 1 0  0.5 |   | 1  0     0.5      |
       
   513     //        | 0 -1 devh - 1 | * | 0 1 -0.5 | = | 0 -1 (devh - 0.5) |
       
   514     //        | 0  0  1       |   | 0 0   1  |   | 0  0      1       |
   526     // The full VG transform is effectively:
   515     // The full VG transform is effectively:
   527     //      1. Apply the user's transformation matrix.
   516     //      1. Apply the user's transformation matrix.
   528     //      2. Translate by (0.5, -0.5) to correct for Qt and VG putting
   517     //      2. Translate glyphs by an extra (0.5, -0.5).
   529     //         the centre of the pixel at different positions.
       
   530     //      3. Flip the co-ordinate system upside down.
   518     //      3. Flip the co-ordinate system upside down.
   531     QTransform viewport(1.0f, 0.0f, 0.0f,
   519     QTransform viewport(1.0f, 0.0f, 0.0f,
   532                         0.0f, -1.0f, 0.0f,
   520                         0.0f, -1.0f, 0.0f,
   533                         0.5f, devh + 0.5f, 1.0f);
   521                         0.0f, devh, 1.0f);
   534 
   522     QTransform gviewport(1.0f, 0.0f, 0.0f,
   535     // Compute the path transform and determine if it is projective. 
   523                         0.0f, -1.0f, 0.0f,
   536      pathTransform = transform * viewport; 
   524                         0.5f, devh - 0.5f, 1.0f);
   537      bool projective = (pathTransform.m13() != 0.0f || 
   525 
   538      pathTransform.m23() != 0.0f || 
   526     // Compute the path transform and determine if it is projective.
   539      pathTransform.m33() != 1.0f); 
   527     pathTransform = transform * viewport;
   540     
   528     glyphTransform = transform * gviewport;
       
   529     bool projective = (pathTransform.m13() != 0.0f ||
       
   530                        pathTransform.m23() != 0.0f ||
       
   531                        pathTransform.m33() != 1.0f);
   541     if (projective) {
   532     if (projective) {
   542         // The engine cannot do projective path transforms for us,
   533         // The engine cannot do projective path transforms for us,
   543         // so we will have to convert the co-ordinates ourselves.
   534         // so we will have to convert the co-ordinates ourselves.
   544         // Change the matrix to just the viewport transformation.
   535         // Change the matrix to just the viewport transformation.
   545         pathTransform = viewport;
   536         pathTransform = viewport;
       
   537         glyphTransform = gviewport;
   546         simpleTransform = false;
   538         simpleTransform = false;
   547     } else {
   539     } else {
   548         simpleTransform = true;
   540         simpleTransform = true;
   549     }
   541     }
   550     pathTransformSet = false;
   542     pathTransformSet = false;
   551 
   543 
   552     // The image transform is always the full transformation, 
   544     // The image transform is always the full transformation,
   553     // because it can be projective. It also does not need the 
   545     imageTransform = transform * viewport;
   554     // (0.5, -0.5) translation because vgDrawImage() implicitly 
       
   555     // adds 0.5 to each co-ordinate. 
       
   556     QTransform viewport2(1.0f, 0.0f, 0.0f, 
       
   557     0.0f, -1.0f, 0.0f, 
       
   558     0.0f, devh, 1.0f); 
       
   559     imageTransform = transform * viewport2; 
       
   560 
   546 
   561     // Calculate the scaling factor to use for turning cosmetic pens
   547     // Calculate the scaling factor to use for turning cosmetic pens
   562     // into ordinary non-cosmetic pens.
   548     // into ordinary non-cosmetic pens.
   563     qt_scaleForTransform(transform, &penScale);
   549     qt_scaleForTransform(transform, &penScale);
   564 }
   550 }
   565 
   551 
   566 inline void QVGPaintEnginePrivate::releasePath(VGPath path)
   552 VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path)
   567 {
       
   568     if (path == reusablePath)
       
   569         vgClearPath(path, VG_PATH_CAPABILITY_ALL);
       
   570     else
       
   571         vgDestroyPath(path);
       
   572 }
       
   573 
       
   574 VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path, bool forceNewPath)
       
   575 {
   553 {
   576     int count = path.elementCount();
   554     int count = path.elementCount();
   577     const qreal *points = path.points();
   555     const qreal *points = path.points();
   578     const QPainterPath::ElementType *elements = path.elements();
   556     const QPainterPath::ElementType *elements = path.elements();
   579 
   557 
   580     VGPath vgpath;
   558     VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
   581     if (forceNewPath) {
   559                                  VG_PATH_DATATYPE_F,
   582         vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
   560                                  1.0f,        // scale
   583                               VG_PATH_DATATYPE_F,
   561                                  0.0f,        // bias
   584                               1.0f,        // scale
   562                                  count + 1,   // segmentCapacityHint
   585                               0.0f,        // bias
   563                                  count * 2,   // coordCapacityHint
   586                               count + 1,   // segmentCapacityHint
   564                                  VG_PATH_CAPABILITY_ALL);
   587                               count * 2,   // coordCapacityHint
       
   588                               VG_PATH_CAPABILITY_ALL);
       
   589     } else {
       
   590         vgpath = reusablePath;
       
   591     }
       
   592 
   565 
   593     // Size is sufficient segments for drawRoundedRect() paths.
   566     // Size is sufficient segments for drawRoundedRect() paths.
   594     QVarLengthArray<VGubyte, 20> segments;
   567     QVarLengthArray<VGubyte, 20> segments;
   595 
   568 
   596     if (sizeof(qreal) == sizeof(VGfloat) && elements && simpleTransform) {
   569     if (sizeof(qreal) == sizeof(VGfloat) && elements && simpleTransform) {
   758                      segments.constData(), coords.constData());
   731                      segments.constData(), coords.constData());
   759 
   732 
   760     return vgpath;
   733     return vgpath;
   761 }
   734 }
   762 
   735 
   763 VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path, bool forceNewPath)
   736 VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path)
   764 {
   737 {
   765     int count = path.elementCount();
   738     int count = path.elementCount();
   766 
   739 
   767     VGPath vgpath;
   740     VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
   768     if (forceNewPath) {
   741                                  VG_PATH_DATATYPE_F,
   769         vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
   742                                  1.0f,        // scale
   770                               VG_PATH_DATATYPE_F,
   743                                  0.0f,        // bias
   771                               1.0f,        // scale
   744                                  count + 1,   // segmentCapacityHint
   772                               0.0f,        // bias
   745                                  count * 2,   // coordCapacityHint
   773                               count + 1,   // segmentCapacityHint
   746                                  VG_PATH_CAPABILITY_ALL);
   774                               count * 2,   // coordCapacityHint
       
   775                               VG_PATH_CAPABILITY_ALL);
       
   776     } else {
       
   777         vgpath = reusablePath;
       
   778     }
       
   779 
   747 
   780     if (count == 0)
   748     if (count == 0)
   781         return vgpath;
   749         return vgpath;
   782 
   750 
   783     const QPainterPath::Element *elements = &(path.elementAt(0));
   751     const QPainterPath::Element *elements = &(path.elementAt(0));
   992         roundRectPath = vgpath;
   960         roundRectPath = vgpath;
   993     } else {
   961     } else {
   994         vgModifyPathCoords(vgpath, 0, 9, pts);
   962         vgModifyPathCoords(vgpath, 0, 9, pts);
   995     }
   963     }
   996 #else
   964 #else
   997     VGPath vgpath = reusablePath;
   965     VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
       
   966                                  VG_PATH_DATATYPE_F,
       
   967                                  1.0f,        // scale
       
   968                                  0.0f,        // bias
       
   969                                  10,          // segmentCapacityHint
       
   970                                  17 * 2,      // coordCapacityHint
       
   971                                  VG_PATH_CAPABILITY_ALL);
   998     vgAppendPathData(vgpath, 10, roundedrect_types, pts);
   972     vgAppendPathData(vgpath, 10, roundedrect_types, pts);
   999 #endif
   973 #endif
  1000 
   974 
  1001     return vgpath;
   975     return vgpath;
  1002 }
   976 }
  1548     VGPath vgpath = d->vectorPathToVGPath(path);
  1522     VGPath vgpath = d->vectorPathToVGPath(path);
  1549     if (!path.hasWindingFill())
  1523     if (!path.hasWindingFill())
  1550         d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD);
  1524         d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD);
  1551     else
  1525     else
  1552         d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO);
  1526         d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO);
  1553     d->releasePath(vgpath);
  1527     vgDestroyPath(vgpath);
  1554 }
  1528 }
  1555 
  1529 
  1556 void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
  1530 void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
  1557 {
  1531 {
  1558     Q_D(QVGPaintEngine);
  1532     Q_D(QVGPaintEngine);
  1559     VGPath vgpath = d->vectorPathToVGPath(path);
  1533     VGPath vgpath = d->vectorPathToVGPath(path);
  1560     if (!path.hasWindingFill())
  1534     if (!path.hasWindingFill())
  1561         d->fill(vgpath, brush, VG_EVEN_ODD);
  1535         d->fill(vgpath, brush, VG_EVEN_ODD);
  1562     else
  1536     else
  1563         d->fill(vgpath, brush, VG_NON_ZERO);
  1537         d->fill(vgpath, brush, VG_NON_ZERO);
  1564     d->releasePath(vgpath);
  1538     vgDestroyPath(vgpath);
  1565 }
  1539 }
  1566 
  1540 
  1567 void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
  1541 void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
  1568 {
  1542 {
  1569     Q_D(QVGPaintEngine);
  1543     Q_D(QVGPaintEngine);
  1570     VGPath vgpath = d->vectorPathToVGPath(path);
  1544     VGPath vgpath = d->vectorPathToVGPath(path);
  1571     d->stroke(vgpath, pen);
  1545     d->stroke(vgpath, pen);
  1572     d->releasePath(vgpath);
  1546     vgDestroyPath(vgpath);
  1573 }
  1547 }
  1574 
  1548 
  1575 // Determine if a co-ordinate transform is simple enough to allow
  1549 // Determine if a co-ordinate transform is simple enough to allow
  1576 // rectangle-based clipping with vgMask().  Simple transforms most
  1550 // rectangle-based clipping with vgMask().  Simple transforms most
  1577 // often result from origin translations.
  1551 // often result from origin translations.
  1763             vgRenderToMask(vgpath, VG_FILL_PATH, VG_INTERSECT_MASK);
  1737             vgRenderToMask(vgpath, VG_FILL_PATH, VG_INTERSECT_MASK);
  1764             break;
  1738             break;
  1765 
  1739 
  1766         default: break;
  1740         default: break;
  1767     }
  1741     }
  1768     d->releasePath(vgpath);
  1742     vgDestroyPath(vgpath);
  1769 
  1743 
  1770     vgSeti(VG_MASKING, VG_TRUE);
  1744     vgSeti(VG_MASKING, VG_TRUE);
  1771     d->maskValid = true;
  1745     d->maskValid = true;
  1772     d->maskIsSet = false;
  1746     d->maskIsSet = false;
  1773     d->scissorMask = false;
  1747     d->scissorMask = false;
  2080             vgRenderToMask(vgpath, VG_FILL_PATH, VG_INTERSECT_MASK);
  2054             vgRenderToMask(vgpath, VG_FILL_PATH, VG_INTERSECT_MASK);
  2081             break;
  2055             break;
  2082 
  2056 
  2083         default: break;
  2057         default: break;
  2084     }
  2058     }
  2085     d->releasePath(vgpath);
  2059     vgDestroyPath(vgpath);
  2086 
  2060 
  2087     vgSeti(VG_MASKING, VG_TRUE);
  2061     vgSeti(VG_MASKING, VG_TRUE);
  2088     d->maskValid = true;
  2062     d->maskValid = true;
  2089     d->maskIsSet = false;
  2063     d->maskIsSet = false;
  2090     d->scissorMask = false;
  2064     d->scissorMask = false;
  2094 }
  2068 }
  2095 
  2069 
  2096 void QVGPaintEnginePrivate::ensureMask
  2070 void QVGPaintEnginePrivate::ensureMask
  2097         (QVGPaintEngine *engine, int width, int height)
  2071         (QVGPaintEngine *engine, int width, int height)
  2098 {
  2072 {
  2099 	  scissorMask = false;
  2073     scissorMask = false;
  2100     if (maskIsSet) {
  2074     if (maskIsSet) {
  2101         vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, width, height);
  2075         vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, width, height);
  2102         maskRect = QRect();
  2076         maskRect = QRect();
  2103     } else {
  2077     } else {
  2104         vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height);
  2078         vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height);
  2520     if (d->simpleTransform) {
  2494     if (d->simpleTransform) {
  2521         QVGPainterState *s = state();
  2495         QVGPainterState *s = state();
  2522         VGPath vgpath = d->roundedRectPath(rect, xrad, yrad, mode);
  2496         VGPath vgpath = d->roundedRectPath(rect, xrad, yrad, mode);
  2523         d->draw(vgpath, s->pen, s->brush);
  2497         d->draw(vgpath, s->pen, s->brush);
  2524 #if defined(QVG_NO_MODIFY_PATH)
  2498 #if defined(QVG_NO_MODIFY_PATH)
  2525         d->releasePath(vgpath);
  2499         vgDestroyPath(vgpath);
  2526 #endif
  2500 #endif
  2527     } else {
  2501     } else {
  2528         QPaintEngineEx::drawRoundedRect(rect, xrad, yrad, mode);
  2502         QPaintEngineEx::drawRoundedRect(rect, xrad, yrad, mode);
  2529     }
  2503     }
  2530 }
  2504 }
  2669     // Based on the description of vguEllipse() in the OpenVG specification.
  2643     // Based on the description of vguEllipse() in the OpenVG specification.
  2670     // We don't use vguEllipse(), to avoid unnecessary library dependencies.
  2644     // We don't use vguEllipse(), to avoid unnecessary library dependencies.
  2671     Q_D(QVGPaintEngine);
  2645     Q_D(QVGPaintEngine);
  2672     if (d->simpleTransform) {
  2646     if (d->simpleTransform) {
  2673         QVGPainterState *s = state();
  2647         QVGPainterState *s = state();
  2674         VGPath path = d->reusablePath;
  2648         VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
       
  2649                                    VG_PATH_DATATYPE_F,
       
  2650                                    1.0f, // scale
       
  2651                                    0.0f, // bias
       
  2652                                    4,    // segmentCapacityHint
       
  2653                                    12,   // coordCapacityHint
       
  2654                                    VG_PATH_CAPABILITY_ALL);
  2675         static VGubyte segments[4] = {
  2655         static VGubyte segments[4] = {
  2676             VG_MOVE_TO_ABS,
  2656             VG_MOVE_TO_ABS,
  2677             VG_SCCWARC_TO_REL,
  2657             VG_SCCWARC_TO_REL,
  2678             VG_SCCWARC_TO_REL,
  2658             VG_SCCWARC_TO_REL,
  2679             VG_CLOSE_PATH
  2659             VG_CLOSE_PATH
  2693         coords[9]  = 0.0f;
  2673         coords[9]  = 0.0f;
  2694         coords[10] = r.width();
  2674         coords[10] = r.width();
  2695         coords[11] = 0.0f;
  2675         coords[11] = 0.0f;
  2696         vgAppendPathData(path, 4, segments, coords);
  2676         vgAppendPathData(path, 4, segments, coords);
  2697         d->draw(path, s->pen, s->brush);
  2677         d->draw(path, s->pen, s->brush);
  2698         d->releasePath(path);
  2678         vgDestroyPath(path);
  2699     } else {
  2679     } else {
  2700         // The projective transform version of an ellipse is difficult.
  2680         // The projective transform version of an ellipse is difficult.
  2701         // Generate a QVectorPath containing cubic curves and transform that.
  2681         // Generate a QVectorPath containing cubic curves and transform that.
  2702         QPaintEngineEx::drawEllipse(r);
  2682         QPaintEngineEx::drawEllipse(r);
  2703     }
  2683     }
  2717     VGPath vgpath = d->painterPathToVGPath(path);
  2697     VGPath vgpath = d->painterPathToVGPath(path);
  2718     if (path.fillRule() == Qt::OddEvenFill)
  2698     if (path.fillRule() == Qt::OddEvenFill)
  2719         d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD);
  2699         d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD);
  2720     else
  2700     else
  2721         d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO);
  2701         d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO);
  2722     d->releasePath(vgpath);
  2702     vgDestroyPath(vgpath);
  2723 }
  2703 }
  2724 
  2704 
  2725 void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount)
  2705 void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount)
  2726 {
  2706 {
  2727 #if !defined(QVG_NO_MODIFY_PATH)
  2707 #if !defined(QVG_NO_MODIFY_PATH)
  2792 
  2772 
  2793 void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
  2773 void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
  2794 {
  2774 {
  2795     Q_D(QVGPaintEngine);
  2775     Q_D(QVGPaintEngine);
  2796     QVGPainterState *s = state();
  2776     QVGPainterState *s = state();
  2797     VGPath path = d->reusablePath;
  2777     VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
       
  2778                                VG_PATH_DATATYPE_F,
       
  2779                                1.0f,             // scale
       
  2780                                0.0f,             // bias
       
  2781                                pointCount + 1,   // segmentCapacityHint
       
  2782                                pointCount * 2,   // coordCapacityHint
       
  2783                                VG_PATH_CAPABILITY_ALL);
  2798     QVarLengthArray<VGfloat, 16> coords;
  2784     QVarLengthArray<VGfloat, 16> coords;
  2799     QVarLengthArray<VGubyte, 10> segments;
  2785     QVarLengthArray<VGubyte, 10> segments;
  2800     for (int i = 0; i < pointCount; ++i, ++points) {
  2786     for (int i = 0; i < pointCount; ++i, ++points) {
  2801         if (d->simpleTransform) {
  2787         if (d->simpleTransform) {
  2802             coords.append(points->x());
  2788             coords.append(points->x());
  2826 
  2812 
  2827         default:
  2813         default:
  2828             d->draw(path, s->pen, s->brush, VG_EVEN_ODD);
  2814             d->draw(path, s->pen, s->brush, VG_EVEN_ODD);
  2829             break;
  2815             break;
  2830     }
  2816     }
  2831     d->releasePath(path);
  2817     vgDestroyPath(path);
  2832 }
  2818 }
  2833 
  2819 
  2834 void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
  2820 void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
  2835 {
  2821 {
  2836     Q_D(QVGPaintEngine);
  2822     Q_D(QVGPaintEngine);
  2837     QVGPainterState *s = state();
  2823     QVGPainterState *s = state();
  2838     VGPath path = d->reusablePath;
  2824     VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
       
  2825                                VG_PATH_DATATYPE_F,
       
  2826                                1.0f,             // scale
       
  2827                                0.0f,             // bias
       
  2828                                pointCount + 1,   // segmentCapacityHint
       
  2829                                pointCount * 2,   // coordCapacityHint
       
  2830                                VG_PATH_CAPABILITY_ALL);
  2839     QVarLengthArray<VGfloat, 16> coords;
  2831     QVarLengthArray<VGfloat, 16> coords;
  2840     QVarLengthArray<VGubyte, 10> segments;
  2832     QVarLengthArray<VGubyte, 10> segments;
  2841     for (int i = 0; i < pointCount; ++i, ++points) {
  2833     for (int i = 0; i < pointCount; ++i, ++points) {
  2842         if (d->simpleTransform) {
  2834         if (d->simpleTransform) {
  2843             coords.append(points->x());
  2835             coords.append(points->x());
  2867 
  2859 
  2868         default:
  2860         default:
  2869             d->draw(path, s->pen, s->brush, VG_EVEN_ODD);
  2861             d->draw(path, s->pen, s->brush, VG_EVEN_ODD);
  2870             break;
  2862             break;
  2871     }
  2863     }
  2872     d->releasePath(path);
  2864     vgDestroyPath(path);
  2873 }
  2865 }
  2874 
  2866 
  2875 void QVGPaintEnginePrivate::setImageOptions()
  2867 void QVGPaintEnginePrivate::setImageOptions()
  2876 {
  2868 {
  2877     if (opacity != 1.0f && simpleTransform) {
  2869     if (opacity != 1.0f && simpleTransform) {
  3266         // Calculate the path for the glyph and cache it.
  3258         // Calculate the path for the glyph and cache it.
  3267         QPainterPath path;
  3259         QPainterPath path;
  3268         ti.fontEngine->getUnscaledGlyph(glyph, &path, &metrics);
  3260         ti.fontEngine->getUnscaledGlyph(glyph, &path, &metrics);
  3269         VGPath vgPath;
  3261         VGPath vgPath;
  3270         if (!path.isEmpty()) {
  3262         if (!path.isEmpty()) {
  3271             vgPath = d->painterPathToVGPath(path, true);
  3263             vgPath = d->painterPathToVGPath(path);
  3272         } else {
  3264         } else {
  3273             // Probably a "space" character with no visible outline.
  3265             // Probably a "space" character with no visible outline.
  3274             vgPath = VG_INVALID_HANDLE;
  3266             vgPath = VG_INVALID_HANDLE;
  3275         }
  3267         }
  3276         origin[0] = 0;
  3268         origin[0] = 0;
  3326         QObject::connect(ti.fontEngine, SIGNAL(destroyed()),
  3318         QObject::connect(ti.fontEngine, SIGNAL(destroyed()),
  3327                          d->fontEngineCleaner, SLOT(fontEngineDestroyed()));
  3319                          d->fontEngineCleaner, SLOT(fontEngineDestroyed()));
  3328     }
  3320     }
  3329 
  3321 
  3330     // Set the transformation to use for drawing the current glyphs.
  3322     // Set the transformation to use for drawing the current glyphs.
  3331     QTransform glyphTransform(d->pathTransform);
  3323     QTransform glyphTransform(d->glyphTransform);
  3332     glyphTransform.translate(p.x(), p.y());
  3324     glyphTransform.translate(p.x(), p.y());
  3333 #if defined(QVG_NO_IMAGE_GLYPHS)
  3325 #if defined(QVG_NO_IMAGE_GLYPHS)
  3334     glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY);
  3326     glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY);
  3335 #endif
  3327 #endif
  3336     d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform);
  3328     d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform);
  3659             }
  3651             }
  3660         }
  3652         }
  3661 
  3653 
  3662     } else {
  3654     } else {
  3663         // Set the path transform to the default viewport transformation.
  3655         // Set the path transform to the default viewport transformation.
  3664         VGfloat devh = screenSize.height() - 1;
  3656         VGfloat devh = screenSize.height();
  3665         QTransform viewport(1.0f, 0.0f, 0.0f,
  3657         QTransform viewport(1.0f, 0.0f, 0.0f,
  3666                             0.0f, -1.0f, 0.0f,
  3658                             0.0f, -1.0f, 0.0f,
  3667                             -0.5f, devh + 0.5f, 1.0f);
  3659                             0.0f, devh, 1.0f);
  3668         d->setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, viewport);
  3660         d->setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, viewport);
  3669 
  3661 
  3670         // Set the brush to use to fill the background.
  3662         // Set the brush to use to fill the background.
  3671         d->ensureBrush(brush);
  3663         d->ensureBrush(brush);
  3672         d->setFillRule(VG_EVEN_ODD);
  3664         d->setFillRule(VG_EVEN_ODD);
  3698         if (vgpd->isValid())
  3690         if (vgpd->isValid())
  3699             vgImage = vgpd->toVGImage();
  3691             vgImage = vgpd->toVGImage();
  3700     }
  3692     }
  3701 
  3693 
  3702     // Set the image transformation and modes.
  3694     // Set the image transformation and modes.
  3703     VGfloat devh = screenSize.height() - 1;
  3695     VGfloat devh = screenSize.height();
  3704     QTransform transform(1.0f, 0.0f, 0.0f,
  3696     QTransform transform(1.0f, 0.0f, 0.0f,
  3705                          0.0f, -1.0f, 0.0f,
  3697                          0.0f, -1.0f, 0.0f,
  3706                          -0.5f, devh + 0.5f, 1.0f);
  3698                          0.0f, devh, 1.0f);
  3707     transform.translate(offset.x(), offset.y());
  3699     transform.translate(offset.x(), offset.y());
  3708     d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
  3700     d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
  3709     d->setImageMode(VG_DRAW_IMAGE_NORMAL);
  3701     d->setImageMode(VG_DRAW_IMAGE_NORMAL);
  3710 
  3702 
  3711     // Draw the VGImage.
  3703     // Draw the VGImage.