src/openvg/qpaintengine_vg.cpp
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtOpenVG module of the Qt Toolkit.
     7 ** This file is part of the QtOpenVG module of the Qt Toolkit.
     8 **
     8 **
   186     QTransform imageTransform; // Calculated VG image transformation.
   186     QTransform imageTransform; // Calculated VG image transformation.
   187     bool pathTransformSet;  // True if path transform set in the VG context.
   187     bool pathTransformSet;  // True if path transform set in the VG context.
   188 
   188 
   189     bool maskValid;         // True if vgMask() contains valid data.
   189     bool maskValid;         // True if vgMask() contains valid data.
   190     bool maskIsSet;         // True if mask would be fully set if it was valid.
   190     bool maskIsSet;         // True if mask would be fully set if it was valid.
       
   191     bool scissorMask;       // True if scissor is used in place of the mask.
   191     bool rawVG;             // True if processing a raw VG escape.
   192     bool rawVG;             // True if processing a raw VG escape.
   192 
   193 
   193     QRect maskRect;         // Rectangle version of mask if it is simple.
   194     QRect maskRect;         // Rectangle version of mask if it is simple.
   194 
   195 
   195     QTransform penTransform;   // Transform for the pen.
   196     QTransform penTransform;   // Transform for the pen.
   198     VGMatrixMode matrixMode;    // Last matrix mode that was set.
   199     VGMatrixMode matrixMode;    // Last matrix mode that was set.
   199     VGImageMode imageMode;      // Last image mode that was set.
   200     VGImageMode imageMode;      // Last image mode that was set.
   200 
   201 
   201     QRegion scissorRegion;  // Currently active scissor region.
   202     QRegion scissorRegion;  // Currently active scissor region.
   202     bool scissorActive;     // True if scissor region is active.
   203     bool scissorActive;     // True if scissor region is active.
       
   204     bool scissorDirty;      // True if scissor is dirty after native painting.
   203 
   205 
   204     QPaintEngine::DirtyFlags dirty;
   206     QPaintEngine::DirtyFlags dirty;
   205 
   207 
   206     QColor clearColor;      // Last clear color that was set.
   208     QColor clearColor;      // Last clear color that was set.
   207     VGfloat clearOpacity;   // Opacity during the last clear.
   209     VGfloat clearOpacity;   // Opacity during the last clear.
   352     pathTransformSet = false;
   354     pathTransformSet = false;
   353     penScale = 1.0;
   355     penScale = 1.0;
   354 
   356 
   355     maskValid = false;
   357     maskValid = false;
   356     maskIsSet = false;
   358     maskIsSet = false;
       
   359     scissorMask = false;
   357     rawVG = false;
   360     rawVG = false;
   358 
   361 
   359     scissorActive = false;
   362     scissorActive = false;
       
   363     scissorDirty = false;
   360 
   364 
   361     dirty = 0;
   365     dirty = 0;
   362 
   366 
   363     clearOpacity = 1.0f;
   367     clearOpacity = 1.0f;
   364 
   368 
   510     //      3. Flip the co-ordinate system upside down.
   514     //      3. Flip the co-ordinate system upside down.
   511     QTransform viewport(1.0f, 0.0f, 0.0f,
   515     QTransform viewport(1.0f, 0.0f, 0.0f,
   512                         0.0f, -1.0f, 0.0f,
   516                         0.0f, -1.0f, 0.0f,
   513                         0.5f, devh + 0.5f, 1.0f);
   517                         0.5f, devh + 0.5f, 1.0f);
   514 
   518 
   515     // The image transform is always the full transformation,
   519     // Compute the path transform and determine if it is projective.
   516     // because it can be projective.
   520     pathTransform = transform * viewport;
   517     imageTransform = transform * viewport;
   521     bool projective = (pathTransform.m13() != 0.0f ||
   518 
   522                        pathTransform.m23() != 0.0f ||
   519     // Determine if the transformation is projective.
   523                        pathTransform.m33() != 1.0f);
   520     bool projective = (imageTransform.m13() != 0.0f ||
       
   521                        imageTransform.m23() != 0.0f ||
       
   522                        imageTransform.m33() != 1.0f);
       
   523     if (projective) {
   524     if (projective) {
   524         // The engine cannot do projective path transforms for us,
   525         // The engine cannot do projective path transforms for us,
   525         // so we will have to convert the co-ordinates ourselves.
   526         // so we will have to convert the co-ordinates ourselves.
   526         // Change the matrix to just the viewport transformation.
   527         // Change the matrix to just the viewport transformation.
   527         pathTransform = viewport;
   528         pathTransform = viewport;
   528         simpleTransform = false;
   529         simpleTransform = false;
   529     } else {
   530     } else {
   530         pathTransform = imageTransform;
       
   531         simpleTransform = true;
   531         simpleTransform = true;
   532     }
   532     }
   533     pathTransformSet = false;
   533     pathTransformSet = false;
       
   534 
       
   535     // The image transform is always the full transformation,
       
   536     // because it can be projective.  It also does not need the
       
   537     // (0.5, -0.5) translation because vgDrawImage() implicitly
       
   538     // adds 0.5 to each co-ordinate.
       
   539     QTransform viewport2(1.0f, 0.0f, 0.0f,
       
   540                          0.0f, -1.0f, 0.0f,
       
   541                          0.0f, devh + 1, 1.0f);
       
   542     imageTransform = transform * viewport2;
   534 
   543 
   535     // Calculate the scaling factor to use for turning cosmetic pens
   544     // Calculate the scaling factor to use for turning cosmetic pens
   536     // into ordinary non-cosmetic pens.
   545     // into ordinary non-cosmetic pens.
   537     qt_scaleForTransform(transform, &penScale);
   546     qt_scaleForTransform(transform, &penScale);
   538 }
   547 }
   981         for (int x=0; x < width; ++x)
   990         for (int x=0; x < width; ++x)
   982             target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg;
   991             target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg;
   983     }
   992     }
   984     return dest;
   993     return dest;
   985 }
   994 }
       
   995 
       
   996 // defined in qpixmapdata_vg.cpp.
       
   997 const uchar *qt_vg_imageBits(const QImage& image);
   986 
   998 
   987 static VGImage toVGImage
   999 static VGImage toVGImage
   988     (const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor)
  1000     (const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor)
   989 {
  1001 {
   990     QImage img(image);
  1002     QImage img(image);
  1015         img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
  1027         img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
  1016         format = VG_sARGB_8888_PRE;
  1028         format = VG_sARGB_8888_PRE;
  1017         break;
  1029         break;
  1018     }
  1030     }
  1019 
  1031 
  1020     const uchar *pixels = img.bits();
  1032     const uchar *pixels = qt_vg_imageBits(img);
  1021 
  1033 
  1022     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1034     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1023         (format, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1035         (format, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1024     vgImageSubData
  1036     vgImageSubData
  1025         (vgImg, pixels, img.bytesPerLine(), format, 0, 0,
  1037         (vgImg, pixels, img.bytesPerLine(), format, 0, 0,
  1059         img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
  1071         img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
  1060         format = VG_sARGB_8888_PRE;
  1072         format = VG_sARGB_8888_PRE;
  1061         break;
  1073         break;
  1062     }
  1074     }
  1063 
  1075 
  1064     const uchar *pixels = img.bits() + bpp * sr.x() +
  1076     const uchar *pixels = qt_vg_imageBits(img) + bpp * sr.x() +
  1065                           img.bytesPerLine() * sr.y();
  1077                           img.bytesPerLine() * sr.y();
  1066 
  1078 
  1067     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1079     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1068         (format, sr.width(), sr.height(), VG_IMAGE_QUALITY_FASTER);
  1080         (format, sr.width(), sr.height(), VG_IMAGE_QUALITY_FASTER);
  1069     vgImageSubData
  1081     vgImageSubData
  1081     painter.begin(&img);
  1093     painter.begin(&img);
  1082     painter.setOpacity(opacity);
  1094     painter.setOpacity(opacity);
  1083     painter.drawImage(0, 0, image);
  1095     painter.drawImage(0, 0, image);
  1084     painter.end();
  1096     painter.end();
  1085 
  1097 
  1086     const uchar *pixels = img.bits();
  1098     const uchar *pixels = qt_vg_imageBits(img);
  1087 
  1099 
  1088     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1100     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1089         (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1101         (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1090     vgImageSubData
  1102     vgImageSubData
  1091         (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
  1103         (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
  1103     painter.begin(&img);
  1115     painter.begin(&img);
  1104     painter.setOpacity(opacity);
  1116     painter.setOpacity(opacity);
  1105     painter.drawImage(QPoint(0, 0), image, sr);
  1117     painter.drawImage(QPoint(0, 0), image, sr);
  1106     painter.end();
  1118     painter.end();
  1107 
  1119 
  1108     const uchar *pixels = img.bits();
  1120     const uchar *pixels = qt_vg_imageBits(img);
  1109 
  1121 
  1110     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1122     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1111         (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1123         (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1112     vgImageSubData
  1124     vgImageSubData
  1113         (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
  1125         (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
  1535 // rectangle-based clipping with vgMask().  Simple transforms most
  1547 // rectangle-based clipping with vgMask().  Simple transforms most
  1536 // often result from origin translations.
  1548 // often result from origin translations.
  1537 static inline bool clipTransformIsSimple(const QTransform& transform)
  1549 static inline bool clipTransformIsSimple(const QTransform& transform)
  1538 {
  1550 {
  1539     QTransform::TransformationType type = transform.type();
  1551     QTransform::TransformationType type = transform.type();
  1540     return (type == QTransform::TxNone || type == QTransform::TxTranslate);
  1552     if (type == QTransform::TxNone || type == QTransform::TxTranslate)
       
  1553         return true;
       
  1554     if (type == QTransform::TxRotate) {
       
  1555         // Check for 0, 90, 180, and 270 degree rotations.
       
  1556         // (0 might happen after 4 rotations of 90 degrees).
       
  1557         qreal m11 = transform.m11();
       
  1558         qreal m12 = transform.m12();
       
  1559         qreal m21 = transform.m21();
       
  1560         qreal m22 = transform.m22();
       
  1561         if (m11 == 0.0f && m22 == 0.0f) {
       
  1562             if (m12 == 1.0f && m21 == -1.0f)
       
  1563                 return true;    // 90 degrees.
       
  1564             else if (m12 == -1.0f && m21 == 1.0f)
       
  1565                 return true;    // 270 degrees.
       
  1566         } else if (m12 == 0.0f && m21 == 0.0f) {
       
  1567             if (m11 == -1.0f && m22 == -1.0f)
       
  1568                 return true;    // 180 degrees.
       
  1569             else if (m11 == 1.0f && m22 == 1.0f)
       
  1570                 return true;    // 0 degrees.
       
  1571         }
       
  1572     }
       
  1573     return false;
  1541 }
  1574 }
  1542 
  1575 
  1543 #if defined(QVG_SCISSOR_CLIP)
  1576 #if defined(QVG_SCISSOR_CLIP)
  1544 
  1577 
  1545 void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
  1578 void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
  1657     d->dirty |= QPaintEngine::DirtyClipRegion;
  1690     d->dirty |= QPaintEngine::DirtyClipRegion;
  1658 
  1691 
  1659     if (op == Qt::NoClip) {
  1692     if (op == Qt::NoClip) {
  1660         d->maskValid = false;
  1693         d->maskValid = false;
  1661         d->maskIsSet = true;
  1694         d->maskIsSet = true;
       
  1695         d->scissorMask = false;
  1662         d->maskRect = QRect();
  1696         d->maskRect = QRect();
  1663         vgSeti(VG_MASKING, VG_FALSE);
  1697         vgSeti(VG_MASKING, VG_FALSE);
  1664         return;
  1698         return;
  1665     }
  1699     }
  1666 
  1700 
  1667 #if defined(QVG_NO_RENDER_TO_MASK)
       
  1668     // We don't have vgRenderToMask(), so handle simple QRectF's only.
  1701     // We don't have vgRenderToMask(), so handle simple QRectF's only.
  1669     if (path.shape() == QVectorPath::RectangleHint &&
  1702     if (path.shape() == QVectorPath::RectangleHint &&
  1670             path.elementCount() == 4 && clipTransformIsSimple(d->transform)) {
  1703             path.elementCount() == 4 && clipTransformIsSimple(d->transform)) {
  1671         // Clipping region that resulted from QPainter::setClipRect(QRectF).
  1704         // Clipping region that resulted from QPainter::setClipRect(QRectF).
  1672         // Convert it into a QRect and apply.
  1705         // Convert it into a QRect and apply.
  1673         const qreal *points = path.points();
  1706         const qreal *points = path.points();
  1674         QRectF rect(points[0], points[1], points[2] - points[0],
  1707         QRectF rect(points[0], points[1], points[2] - points[0],
  1675                     points[5] - points[1]);
  1708                     points[5] - points[1]);
  1676         clip(rect.toRect(), op);
  1709         clip(rect.toRect(), op);
  1677     }
  1710         return;
  1678 #else
  1711     }
       
  1712 
       
  1713 #if !defined(QVG_NO_RENDER_TO_MASK)
  1679     QPaintDevice *pdev = paintDevice();
  1714     QPaintDevice *pdev = paintDevice();
  1680     int width = pdev->width();
  1715     int width = pdev->width();
  1681     int height = pdev->height();
  1716     int height = pdev->height();
  1682 
  1717 
  1683     if (op == Qt::ReplaceClip) {
  1718     if (op == Qt::ReplaceClip) {
  1704     vgDestroyPath(vgpath);
  1739     vgDestroyPath(vgpath);
  1705 
  1740 
  1706     vgSeti(VG_MASKING, VG_TRUE);
  1741     vgSeti(VG_MASKING, VG_TRUE);
  1707     d->maskValid = true;
  1742     d->maskValid = true;
  1708     d->maskIsSet = false;
  1743     d->maskIsSet = false;
       
  1744     d->scissorMask = false;
  1709 #endif
  1745 #endif
  1710 }
  1746 }
  1711 
  1747 
  1712 void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
  1748 void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
  1713 {
  1749 {
  1724     switch (op) {
  1760     switch (op) {
  1725         case Qt::NoClip:
  1761         case Qt::NoClip:
  1726         {
  1762         {
  1727             d->maskValid = false;
  1763             d->maskValid = false;
  1728             d->maskIsSet = true;
  1764             d->maskIsSet = true;
       
  1765             d->scissorMask = false;
  1729             d->maskRect = QRect();
  1766             d->maskRect = QRect();
  1730             vgSeti(VG_MASKING, VG_FALSE);
  1767             vgSeti(VG_MASKING, VG_FALSE);
  1731         }
  1768         }
  1732         break;
  1769         break;
  1733 
  1770 
  1739                 // same as turning off clipping.
  1776                 // same as turning off clipping.
  1740                 if (d->maskValid)
  1777                 if (d->maskValid)
  1741                     vgSeti(VG_MASKING, VG_FALSE);
  1778                     vgSeti(VG_MASKING, VG_FALSE);
  1742                 d->maskValid = false;
  1779                 d->maskValid = false;
  1743                 d->maskIsSet = true;
  1780                 d->maskIsSet = true;
       
  1781                 d->scissorMask = false;
  1744                 d->maskRect = QRect();
  1782                 d->maskRect = QRect();
  1745             } else {
  1783             } else {
  1746                 // Special case: if the intersection of the system
  1784                 // Special case: if the intersection of the system
  1747                 // clip and "r" is a single rectangle, then use the
  1785                 // clip and "r" is a single rectangle, then use the
  1748                 // scissor for clipping.  We try to avoid allocating a
  1786                 // scissor for clipping.  We try to avoid allocating a
  1756                 } else {
  1794                 } else {
  1757                     clip = clip.intersect(r);
  1795                     clip = clip.intersect(r);
  1758                     if (clip.rectCount() != 1) {
  1796                     if (clip.rectCount() != 1) {
  1759                         d->maskValid = false;
  1797                         d->maskValid = false;
  1760                         d->maskIsSet = false;
  1798                         d->maskIsSet = false;
       
  1799                         d->scissorMask = false;
  1761                         d->maskRect = QRect();
  1800                         d->maskRect = QRect();
  1762                         d->modifyMask(this, VG_FILL_MASK, r);
  1801                         d->modifyMask(this, VG_FILL_MASK, r);
  1763                         break;
  1802                         break;
  1764                     }
  1803                     }
  1765                     clipRect = clip.boundingRect();
  1804                     clipRect = clip.boundingRect();
  1766                 }
  1805                 }
  1767                 d->maskValid = false;
  1806                 d->maskValid = false;
  1768                 d->maskIsSet = false;
  1807                 d->maskIsSet = false;
       
  1808                 d->scissorMask = true;
  1769                 d->maskRect = clipRect;
  1809                 d->maskRect = clipRect;
  1770                 vgSeti(VG_MASKING, VG_FALSE);
  1810                 vgSeti(VG_MASKING, VG_FALSE);
  1771                 updateScissor();
  1811                 updateScissor();
  1772             }
  1812             }
  1773         }
  1813         }
  1774         break;
  1814         break;
  1775 
  1815 
  1776         case Qt::IntersectClip:
  1816         case Qt::IntersectClip:
  1777         {
  1817         {
  1778             QRect r = d->transform.mapRect(rect);
  1818             QRect r = d->transform.mapRect(rect);
  1779             if (d->maskIsSet && isDefaultClipRect(r)) {
  1819             if (!d->maskValid) {
       
  1820                 // Mask has not been used yet, so intersect with
       
  1821                 // the previous scissor-based region in maskRect.
       
  1822                 if (d->scissorMask)
       
  1823                     r = r.intersect(d->maskRect);
       
  1824                 if (isDefaultClipRect(r)) {
       
  1825                     // The clip is the full window, so turn off clipping.
       
  1826                     d->maskIsSet = true;
       
  1827                     d->maskRect = QRect();
       
  1828                 } else {
       
  1829                     // Activate the scissor on a smaller maskRect.
       
  1830                     d->maskIsSet = false;
       
  1831                     d->maskRect = r;
       
  1832                 }
       
  1833                 d->scissorMask = true;
       
  1834                 updateScissor();
       
  1835             } else if (d->maskIsSet && isDefaultClipRect(r)) {
  1780                 // Intersecting a full-window clip with a full-window
  1836                 // Intersecting a full-window clip with a full-window
  1781                 // region is the same as turning off clipping.
  1837                 // region is the same as turning off clipping.
  1782                 if (d->maskValid)
  1838                 if (d->maskValid)
  1783                     vgSeti(VG_MASKING, VG_FALSE);
  1839                     vgSeti(VG_MASKING, VG_FALSE);
  1784                 d->maskValid = false;
  1840                 d->maskValid = false;
  1785                 d->maskIsSet = true;
  1841                 d->maskIsSet = true;
       
  1842                 d->scissorMask = false;
  1786                 d->maskRect = QRect();
  1843                 d->maskRect = QRect();
  1787             } else {
  1844             } else {
  1788                 d->modifyMask(this, VG_INTERSECT_MASK, r);
  1845                 d->modifyMask(this, VG_INTERSECT_MASK, r);
  1789             }
  1846             }
  1790         }
  1847         }
  1822     switch (op) {
  1879     switch (op) {
  1823         case Qt::NoClip:
  1880         case Qt::NoClip:
  1824         {
  1881         {
  1825             d->maskValid = false;
  1882             d->maskValid = false;
  1826             d->maskIsSet = true;
  1883             d->maskIsSet = true;
       
  1884             d->scissorMask = false;
  1827             d->maskRect = QRect();
  1885             d->maskRect = QRect();
  1828             vgSeti(VG_MASKING, VG_FALSE);
  1886             vgSeti(VG_MASKING, VG_FALSE);
  1829         }
  1887         }
  1830         break;
  1888         break;
  1831 
  1889 
  1837                 // same as turning off clipping.
  1895                 // same as turning off clipping.
  1838                 if (d->maskValid)
  1896                 if (d->maskValid)
  1839                     vgSeti(VG_MASKING, VG_FALSE);
  1897                     vgSeti(VG_MASKING, VG_FALSE);
  1840                 d->maskValid = false;
  1898                 d->maskValid = false;
  1841                 d->maskIsSet = true;
  1899                 d->maskIsSet = true;
       
  1900                 d->scissorMask = false;
  1842                 d->maskRect = QRect();
  1901                 d->maskRect = QRect();
  1843             } else {
  1902             } else {
  1844                 // Special case: if the intersection of the system
  1903                 // Special case: if the intersection of the system
  1845                 // clip and the region is a single rectangle, then
  1904                 // clip and the region is a single rectangle, then
  1846                 // use the scissor for clipping.
  1905                 // use the scissor for clipping.
  1850                 else
  1909                 else
  1851                     clip = clip.intersect(r);
  1910                     clip = clip.intersect(r);
  1852                 if (clip.rectCount() == 1) {
  1911                 if (clip.rectCount() == 1) {
  1853                     d->maskValid = false;
  1912                     d->maskValid = false;
  1854                     d->maskIsSet = false;
  1913                     d->maskIsSet = false;
       
  1914                     d->scissorMask = true;
  1855                     d->maskRect = clip.boundingRect();
  1915                     d->maskRect = clip.boundingRect();
  1856                     vgSeti(VG_MASKING, VG_FALSE);
  1916                     vgSeti(VG_MASKING, VG_FALSE);
  1857                     updateScissor();
  1917                     updateScissor();
  1858                 } else {
  1918                 } else {
  1859                     d->maskValid = false;
  1919                     d->maskValid = false;
  1860                     d->maskIsSet = false;
  1920                     d->maskIsSet = false;
       
  1921                     d->scissorMask = false;
  1861                     d->maskRect = QRect();
  1922                     d->maskRect = QRect();
  1862                     d->modifyMask(this, VG_FILL_MASK, r);
  1923                     d->modifyMask(this, VG_FILL_MASK, r);
  1863                 }
  1924                 }
  1864             }
  1925             }
  1865         }
  1926         }
  1880                 // region is the same as turning off clipping.
  1941                 // region is the same as turning off clipping.
  1881                 if (d->maskValid)
  1942                 if (d->maskValid)
  1882                     vgSeti(VG_MASKING, VG_FALSE);
  1943                     vgSeti(VG_MASKING, VG_FALSE);
  1883                 d->maskValid = false;
  1944                 d->maskValid = false;
  1884                 d->maskIsSet = true;
  1945                 d->maskIsSet = true;
       
  1946                 d->scissorMask = false;
  1885                 d->maskRect = QRect();
  1947                 d->maskRect = QRect();
  1886             } else {
  1948             } else {
  1887                 d->modifyMask(this, VG_INTERSECT_MASK, r);
  1949                 d->modifyMask(this, VG_INTERSECT_MASK, r);
  1888             }
  1950             }
  1889         }
  1951         }
  1958     d->dirty |= QPaintEngine::DirtyClipRegion;
  2020     d->dirty |= QPaintEngine::DirtyClipRegion;
  1959 
  2021 
  1960     if (op == Qt::NoClip) {
  2022     if (op == Qt::NoClip) {
  1961         d->maskValid = false;
  2023         d->maskValid = false;
  1962         d->maskIsSet = true;
  2024         d->maskIsSet = true;
       
  2025         d->scissorMask = false;
  1963         d->maskRect = QRect();
  2026         d->maskRect = QRect();
  1964         vgSeti(VG_MASKING, VG_FALSE);
  2027         vgSeti(VG_MASKING, VG_FALSE);
  1965         return;
  2028         return;
  1966     }
  2029     }
  1967 
  2030 
  1993     vgDestroyPath(vgpath);
  2056     vgDestroyPath(vgpath);
  1994 
  2057 
  1995     vgSeti(VG_MASKING, VG_TRUE);
  2058     vgSeti(VG_MASKING, VG_TRUE);
  1996     d->maskValid = true;
  2059     d->maskValid = true;
  1997     d->maskIsSet = false;
  2060     d->maskIsSet = false;
       
  2061     d->scissorMask = false;
  1998 #else
  2062 #else
  1999     QPaintEngineEx::clip(path, op);
  2063     QPaintEngineEx::clip(path, op);
  2000 #endif
  2064 #endif
  2001 }
  2065 }
  2002 
  2066 
  2003 void QVGPaintEnginePrivate::ensureMask
  2067 void QVGPaintEnginePrivate::ensureMask
  2004         (QVGPaintEngine *engine, int width, int height)
  2068         (QVGPaintEngine *engine, int width, int height)
  2005 {
  2069 {
       
  2070     scissorMask = false;
  2006     if (maskIsSet) {
  2071     if (maskIsSet) {
  2007         vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, width, height);
  2072         vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, width, height);
  2008         maskRect = QRect();
  2073         maskRect = QRect();
  2009     } else {
  2074     } else {
  2010         vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height);
  2075         vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height);
  2036     }
  2101     }
  2037 
  2102 
  2038     vgSeti(VG_MASKING, VG_TRUE);
  2103     vgSeti(VG_MASKING, VG_TRUE);
  2039     maskValid = true;
  2104     maskValid = true;
  2040     maskIsSet = false;
  2105     maskIsSet = false;
       
  2106     scissorMask = false;
  2041 }
  2107 }
  2042 
  2108 
  2043 void QVGPaintEnginePrivate::modifyMask
  2109 void QVGPaintEnginePrivate::modifyMask
  2044         (QVGPaintEngine *engine, VGMaskOperation op, const QRect& rect)
  2110         (QVGPaintEngine *engine, VGMaskOperation op, const QRect& rect)
  2045 {
  2111 {
  2057     }
  2123     }
  2058 
  2124 
  2059     vgSeti(VG_MASKING, VG_TRUE);
  2125     vgSeti(VG_MASKING, VG_TRUE);
  2060     maskValid = true;
  2126     maskValid = true;
  2061     maskIsSet = false;
  2127     maskIsSet = false;
       
  2128     scissorMask = false;
  2062 }
  2129 }
  2063 
  2130 
  2064 #endif // !QVG_SCISSOR_CLIP
  2131 #endif // !QVG_SCISSOR_CLIP
  2065 
  2132 
  2066 void QVGPaintEngine::updateScissor()
  2133 void QVGPaintEngine::updateScissor()
  2081         if (isDefaultClipRegion(region)) {
  2148         if (isDefaultClipRegion(region)) {
  2082             // The scissor region is the entire drawing surface,
  2149             // The scissor region is the entire drawing surface,
  2083             // so there is no point doing any scissoring.
  2150             // so there is no point doing any scissoring.
  2084             vgSeti(VG_SCISSORING, VG_FALSE);
  2151             vgSeti(VG_SCISSORING, VG_FALSE);
  2085             d->scissorActive = false;
  2152             d->scissorActive = false;
       
  2153             d->scissorDirty = false;
  2086             return;
  2154             return;
  2087         }
  2155         }
  2088     } else
  2156     } else
  2089 #endif
  2157 #endif
  2090     {
  2158     {
  2091 #if !defined(QVG_SCISSOR_CLIP)
  2159 #if !defined(QVG_SCISSOR_CLIP)
  2092         // Combine the system clip with the simple mask rectangle.
  2160         // Combine the system clip with the simple mask rectangle.
  2093         if (!d->maskRect.isNull()) {
  2161         if (d->scissorMask) {
  2094             if (region.isEmpty())
  2162             if (region.isEmpty())
  2095                 region = d->maskRect;
  2163                 region = d->maskRect;
  2096             else
  2164             else
  2097                 region = region.intersect(d->maskRect);
  2165                 region = region.intersect(d->maskRect);
  2098             if (isDefaultClipRegion(region)) {
  2166             if (isDefaultClipRegion(region)) {
  2099                 // The scissor region is the entire drawing surface,
  2167                 // The scissor region is the entire drawing surface,
  2100                 // so there is no point doing any scissoring.
  2168                 // so there is no point doing any scissoring.
  2101                 vgSeti(VG_SCISSORING, VG_FALSE);
  2169                 vgSeti(VG_SCISSORING, VG_FALSE);
  2102                 d->scissorActive = false;
  2170                 d->scissorActive = false;
       
  2171                 d->scissorDirty = false;
  2103                 return;
  2172                 return;
  2104             }
  2173             }
  2105         } else
  2174         } else
  2106 #endif
  2175 #endif
  2107 
  2176 
  2108         // Disable the scissor completely if the system clip is empty.
  2177         // Disable the scissor completely if the system clip is empty.
  2109         if (region.isEmpty()) {
  2178         if (region.isEmpty()) {
  2110             vgSeti(VG_SCISSORING, VG_FALSE);
  2179             vgSeti(VG_SCISSORING, VG_FALSE);
  2111             d->scissorActive = false;
  2180             d->scissorActive = false;
       
  2181             d->scissorDirty = false;
  2112             return;
  2182             return;
  2113         }
  2183         }
  2114     }
  2184     }
  2115 
  2185 
  2116     if (d->scissorActive && region == d->scissorRegion)
  2186     if (d->scissorActive && region == d->scissorRegion && !d->scissorDirty)
  2117         return;
  2187         return;
  2118 
  2188 
  2119     QVector<QRect> rects = region.rects();
  2189     QVector<QRect> rects = region.rects();
  2120     int count = rects.count();
  2190     int count = rects.count();
  2121     if (count > d->maxScissorRects)
  2191     if (count > d->maxScissorRects)
  2129         params[i * 4 + 3] = rects[i].height();
  2199         params[i * 4 + 3] = rects[i].height();
  2130     }
  2200     }
  2131 
  2201 
  2132     vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data());
  2202     vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data());
  2133     vgSeti(VG_SCISSORING, VG_TRUE);
  2203     vgSeti(VG_SCISSORING, VG_TRUE);
       
  2204     d->scissorDirty = false;
  2134     d->scissorActive = true;
  2205     d->scissorActive = true;
  2135     d->scissorRegion = region;
  2206     d->scissorRegion = region;
  2136 }
  2207 }
  2137 
  2208 
  2138 QRegion QVGPaintEngine::defaultClipRegion()
  2209 QRegion QVGPaintEngine::defaultClipRegion()
  2176     d->dirty |= QPaintEngine::DirtyClipEnabled;
  2247     d->dirty |= QPaintEngine::DirtyClipEnabled;
  2177     if (s->clipEnabled && s->clipOperation != Qt::NoClip) {
  2248     if (s->clipEnabled && s->clipOperation != Qt::NoClip) {
  2178         // Replay the entire clip stack to put the mask into the right state.
  2249         // Replay the entire clip stack to put the mask into the right state.
  2179         d->maskValid = false;
  2250         d->maskValid = false;
  2180         d->maskIsSet = true;
  2251         d->maskIsSet = true;
       
  2252         d->scissorMask = false;
  2181         d->maskRect = QRect();
  2253         d->maskRect = QRect();
  2182         s->clipRegion = defaultClipRegion();
  2254         s->clipRegion = defaultClipRegion();
  2183         d->replayClipOperations();
  2255         d->replayClipOperations();
  2184         d->transform = s->transform();
  2256         d->transform = s->transform();
  2185         d->updateTransform(paintDevice());
  2257         d->updateTransform(paintDevice());
  2186     } else {
  2258     } else {
  2187         vgSeti(VG_MASKING, VG_FALSE);
  2259         vgSeti(VG_MASKING, VG_FALSE);
  2188         d->maskValid = false;
  2260         d->maskValid = false;
  2189         d->maskIsSet = false;
  2261         d->maskIsSet = false;
       
  2262         d->scissorMask = false;
  2190         d->maskRect = QRect();
  2263         d->maskRect = QRect();
  2191     }
  2264     }
  2192 #endif
  2265 #endif
  2193 }
  2266 }
  2194 
  2267 
  2303 bool QVGPaintEngine::clearRect(const QRectF &rect, const QColor &color)
  2376 bool QVGPaintEngine::clearRect(const QRectF &rect, const QColor &color)
  2304 {
  2377 {
  2305     Q_D(QVGPaintEngine);
  2378     Q_D(QVGPaintEngine);
  2306     QVGPainterState *s = state();
  2379     QVGPainterState *s = state();
  2307     if (!s->clipEnabled || s->clipOperation == Qt::NoClip) {
  2380     if (!s->clipEnabled || s->clipOperation == Qt::NoClip) {
  2308         // The transform will either be identity or a simple translation,
  2381         QRect r = d->transform.mapRect(rect).toRect();
  2309         // so do a simpler version of "r = d->transform.map(rect).toRect()".
       
  2310         QRect r = QRect(qRound(rect.x() + d->transform.dx()),
       
  2311                         qRound(rect.y() + d->transform.dy()),
       
  2312                         qRound(rect.width()),
       
  2313                         qRound(rect.height()));
       
  2314         int height = paintDevice()->height();
  2382         int height = paintDevice()->height();
  2315         if (d->clearColor != color || d->clearOpacity != s->opacity) {
  2383         if (d->clearColor != color || d->clearOpacity != s->opacity) {
  2316             VGfloat values[4];
  2384             VGfloat values[4];
  2317             values[0] = color.redF();
  2385             values[0] = color.redF();
  2318             values[1] = color.greenF();
  2386             values[1] = color.greenF();
  2335 
  2403 
  2336     if (brush.style() == Qt::NoBrush)
  2404     if (brush.style() == Qt::NoBrush)
  2337         return;
  2405         return;
  2338 
  2406 
  2339     // Check to see if we can use vgClear() for faster filling.
  2407     // Check to see if we can use vgClear() for faster filling.
  2340     if (brush.style() == Qt::SolidPattern &&
  2408     if (brush.style() == Qt::SolidPattern && brush.isOpaque() &&
  2341             clipTransformIsSimple(d->transform) && d->opacity == 1.0f &&
  2409             clipTransformIsSimple(d->transform) && d->opacity == 1.0f &&
  2342             clearRect(rect, brush.color())) {
  2410             clearRect(rect, brush.color())) {
  2343         return;
  2411         return;
  2344     }
  2412     }
  2345 
  2413 
  2378 void QVGPaintEngine::fillRect(const QRectF &rect, const QColor &color)
  2446 void QVGPaintEngine::fillRect(const QRectF &rect, const QColor &color)
  2379 {
  2447 {
  2380     Q_D(QVGPaintEngine);
  2448     Q_D(QVGPaintEngine);
  2381 
  2449 
  2382     // Check to see if we can use vgClear() for faster filling.
  2450     // Check to see if we can use vgClear() for faster filling.
  2383     if (clipTransformIsSimple(d->transform) && d->opacity == 1.0f &&
  2451     if (clipTransformIsSimple(d->transform) && d->opacity == 1.0f && color.alpha() == 255 &&
  2384             clearRect(rect, color)) {
  2452             clearRect(rect, color)) {
  2385         return;
  2453         return;
  2386     }
  2454     }
  2387 
  2455 
  2388 #if !defined(QVG_NO_MODIFY_PATH)
  2456 #if !defined(QVG_NO_MODIFY_PATH)
  3164         VGImage vgImage = VG_INVALID_HANDLE;
  3232         VGImage vgImage = VG_INVALID_HANDLE;
  3165         metrics = ti.fontEngine->boundingBox(glyph);
  3233         metrics = ti.fontEngine->boundingBox(glyph);
  3166         if (!scaledImage.isNull()) {  // Not a space character
  3234         if (!scaledImage.isNull()) {  // Not a space character
  3167             if (scaledImage.format() == QImage::Format_Indexed8) {
  3235             if (scaledImage.format() == QImage::Format_Indexed8) {
  3168                 vgImage = vgCreateImage(VG_A_8, scaledImage.width(), scaledImage.height(), VG_IMAGE_QUALITY_FASTER);
  3236                 vgImage = vgCreateImage(VG_A_8, scaledImage.width(), scaledImage.height(), VG_IMAGE_QUALITY_FASTER);
  3169                 vgImageSubData(vgImage, scaledImage.bits(), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
  3237                 vgImageSubData(vgImage, qt_vg_imageBits(scaledImage), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
  3170             } else if (scaledImage.format() == QImage::Format_Mono) {
  3238             } else if (scaledImage.format() == QImage::Format_Mono) {
  3171                 QImage img = scaledImage.convertToFormat(QImage::Format_Indexed8);
  3239                 QImage img = scaledImage.convertToFormat(QImage::Format_Indexed8);
  3172                 vgImage = vgCreateImage(VG_A_8, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  3240                 vgImage = vgCreateImage(VG_A_8, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  3173                 vgImageSubData(vgImage, img.bits(), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
  3241                 vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
  3174             } else {
  3242             } else {
  3175                 QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
  3243                 QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
  3176                 vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  3244                 vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  3177                 vgImageSubData(vgImage, img.bits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
  3245                 vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
  3178             }
  3246             }
  3179         }
  3247         }
  3180         origin[0] = -metrics.x.toReal() + 0.5f;
  3248         origin[0] = -metrics.x.toReal() + 0.5f;
  3181         origin[1] = -metrics.y.toReal() + 0.5f;
  3249         origin[1] = -metrics.y.toReal() + 0.5f;
  3182         escapement[0] = metrics.xoff.toReal();
  3250         escapement[0] = metrics.xoff.toReal();
  3331     d->forceBrushChange = true;
  3399     d->forceBrushChange = true;
  3332     d->penType = (VGPaintType)0;
  3400     d->penType = (VGPaintType)0;
  3333     d->brushType = (VGPaintType)0;
  3401     d->brushType = (VGPaintType)0;
  3334     d->clearColor = QColor();
  3402     d->clearColor = QColor();
  3335     d->fillPaint = d->brushPaint;
  3403     d->fillPaint = d->brushPaint;
       
  3404     d->scissorDirty = true;
  3336     restoreState(QPaintEngine::AllDirty);
  3405     restoreState(QPaintEngine::AllDirty);
  3337     d->dirty = dirty;
  3406     d->dirty = dirty;
  3338     d->rawVG = false;
  3407     d->rawVG = false;
  3339     vgSetPaint(d->penPaint, VG_STROKE_PATH);
  3408     vgSetPaint(d->penPaint, VG_STROKE_PATH);
  3340     vgSetPaint(d->brushPaint, VG_FILL_PATH);
  3409     vgSetPaint(d->brushPaint, VG_FILL_PATH);
  3386     if ((dirty & (QPaintEngine::DirtyClipRegion |
  3455     if ((dirty & (QPaintEngine::DirtyClipRegion |
  3387                   QPaintEngine::DirtyClipPath |
  3456                   QPaintEngine::DirtyClipPath |
  3388                   QPaintEngine::DirtyClipEnabled)) != 0) {
  3457                   QPaintEngine::DirtyClipEnabled)) != 0) {
  3389         d->maskValid = false;
  3458         d->maskValid = false;
  3390         d->maskIsSet = false;
  3459         d->maskIsSet = false;
       
  3460         d->scissorMask = false;
  3391         d->maskRect = QRect();
  3461         d->maskRect = QRect();
  3392         clipEnabledChanged();
  3462         clipEnabledChanged();
  3393     }
  3463     }
  3394 
  3464 
  3395 #if defined(QVG_SCISSOR_CLIP)
  3465 #if defined(QVG_SCISSOR_CLIP)
  3638             (VG_sARGB_8888_PRE, img.width(), img.height(),
  3708             (VG_sARGB_8888_PRE, img.width(), img.height(),
  3639              VG_IMAGE_QUALITY_FASTER);
  3709              VG_IMAGE_QUALITY_FASTER);
  3640         if (vgImage == VG_INVALID_HANDLE)
  3710         if (vgImage == VG_INVALID_HANDLE)
  3641             return;
  3711             return;
  3642         vgImageSubData
  3712         vgImageSubData
  3643             (vgImage, img.bits() + img.bytesPerLine() * (img.height() - 1),
  3713             (vgImage, qt_vg_imageBits(img) + img.bytesPerLine() * (img.height() - 1),
  3644              -(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0,
  3714              -(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0,
  3645              img.width(), img.height());
  3715              img.width(), img.height());
  3646 
  3716 
  3647         vgDrawImage(vgImage);
  3717         vgDrawImage(vgImage);
  3648         vgDestroyImage(vgImage);
  3718         vgDestroyImage(vgImage);
  3664         params[i * 4 + 3] = rects[i].height();
  3734         params[i * 4 + 3] = rects[i].height();
  3665     }
  3735     }
  3666 
  3736 
  3667     vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data());
  3737     vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data());
  3668     vgSeti(VG_SCISSORING, VG_TRUE);
  3738     vgSeti(VG_SCISSORING, VG_TRUE);
       
  3739     d->scissorDirty = false;
  3669     d->scissorActive = true;
  3740     d->scissorActive = true;
  3670     d->scissorRegion = region;
  3741     d->scissorRegion = region;
  3671 }
  3742 }
  3672 
  3743 
  3673 void QVGCompositionHelper::clearScissor()
  3744 void QVGCompositionHelper::clearScissor()
  3674 {
  3745 {
  3675     if (d->scissorActive) {
  3746     if (d->scissorActive || d->scissorDirty) {
  3676         vgSeti(VG_SCISSORING, VG_FALSE);
  3747         vgSeti(VG_SCISSORING, VG_FALSE);
  3677         d->scissorActive = false;
  3748         d->scissorActive = false;
       
  3749         d->scissorDirty = false;
  3678     }
  3750     }
  3679 }
  3751 }
  3680 
  3752 
  3681 #endif // !QVG_NO_SINGLE_CONTEXT && !QT_NO_EGL
  3753 #endif // !QVG_NO_SINGLE_CONTEXT && !QT_NO_EGL
  3682 
  3754