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. |
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 } |
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) { |
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 } |
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 } |
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); |
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(); |
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 |