File indexing completed on 2024-05-12 15:56:38
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KOBAKEDSHAPERENDERER_H 0008 #define KOBAKEDSHAPERENDERER_H 0009 0010 #include <QImage> 0011 #include <QPainter> 0012 #include <QPainterPath> 0013 #include <QTransform> 0014 0015 #include <kis_debug.h> 0016 #include <kis_algebra_2d.h> 0017 0018 0019 struct KoBakedShapeRenderer { 0020 KoBakedShapeRenderer(const QPainterPath &dstShapeOutline, const QTransform &dstShapeTransform, 0021 const QTransform &bakedTransform, 0022 const QRectF &referenceRect, 0023 bool contentIsObb, const QRectF &bakedShapeBoundingRect, 0024 bool referenceIsObb, 0025 const QTransform &patternTransform) 0026 : m_dstShapeOutline(dstShapeOutline), 0027 m_dstShapeTransform(dstShapeTransform), 0028 m_contentIsObb(contentIsObb), 0029 m_patternTransform(patternTransform) 0030 { 0031 KIS_SAFE_ASSERT_RECOVER_NOOP(!contentIsObb || !bakedShapeBoundingRect.isEmpty()); 0032 0033 const QRectF dstShapeBoundingRect = dstShapeOutline.boundingRect(); 0034 0035 QTransform relativeToBakedShape; 0036 0037 if (referenceIsObb || contentIsObb) { 0038 m_relativeToShape = KisAlgebra2D::mapToRect(dstShapeBoundingRect); 0039 relativeToBakedShape = KisAlgebra2D::mapToRect(bakedShapeBoundingRect); 0040 } 0041 0042 0043 m_referenceRectUser = 0044 referenceIsObb ? 0045 m_relativeToShape.mapRect(referenceRect).toAlignedRect() : 0046 referenceRect.toAlignedRect(); 0047 0048 m_patch = QImage(m_referenceRectUser.size(), QImage::Format_ARGB32); 0049 m_patch.fill(0); 0050 m_patchPainter.begin(&m_patch); 0051 0052 m_patchPainter.translate(-m_referenceRectUser.topLeft()); 0053 m_patchPainter.setClipRect(m_referenceRectUser); 0054 0055 if (contentIsObb) { 0056 m_patchPainter.setTransform(m_relativeToShape, true); 0057 m_patchPainter.setTransform(relativeToBakedShape.inverted(), true); 0058 } 0059 0060 m_patchPainter.setTransform(bakedTransform.inverted(), true); 0061 } 0062 0063 QPainter* bakeShapePainter() { 0064 return &m_patchPainter; 0065 } 0066 0067 void renderShape(QPainter &painter) { 0068 painter.save(); 0069 0070 painter.setTransform(m_dstShapeTransform, true); 0071 painter.setClipPath(m_dstShapeOutline); 0072 0073 QTransform brushTransform; 0074 0075 QPointF patternOffset = m_referenceRectUser.topLeft(); 0076 0077 brushTransform = 0078 brushTransform * 0079 QTransform::fromTranslate(patternOffset.x(), patternOffset.y()); 0080 0081 if (m_contentIsObb) { 0082 brushTransform = brushTransform * m_relativeToShape.inverted(); 0083 } 0084 0085 brushTransform = brushTransform * m_patternTransform; 0086 0087 if (m_contentIsObb) { 0088 brushTransform = brushTransform * m_relativeToShape; 0089 } 0090 0091 QBrush brush(m_patch); 0092 brush.setTransform(brushTransform); 0093 0094 painter.setBrush(brush); 0095 painter.drawPath(m_dstShapeOutline); 0096 0097 painter.restore(); 0098 } 0099 0100 QImage patchImage() const { 0101 return m_patch; 0102 } 0103 0104 0105 private: 0106 QPainterPath m_dstShapeOutline; 0107 QTransform m_dstShapeTransform; 0108 0109 bool m_contentIsObb; 0110 const QTransform &m_patternTransform; 0111 0112 QImage m_patch; 0113 QPainter m_patchPainter; 0114 0115 QTransform m_relativeToShape; 0116 QRect m_referenceRectUser; 0117 }; 0118 0119 #endif // KOBAKEDSHAPERENDERER_H