File indexing completed on 2024-05-12 15:56:42
0001 /* 0002 * SPDX-License-Identifier: GPL-3.0-or-later 0003 */ 0004 0005 #include "KoMeshGradientBackground.h" 0006 #include <KoColorSpaceRegistry.h> 0007 #include <KoMixColorsOp.h> 0008 #include <kis_algebra_2d.h> 0009 0010 #include <QRegion> 0011 #include <QPainter> 0012 #include <QPainterPath> 0013 #include <QDebug> 0014 0015 #include "KoMeshPatchesRenderer.h" 0016 0017 class KoMeshGradientBackground::Private : public QSharedData 0018 { 0019 public: 0020 Private() 0021 : QSharedData() 0022 , gradient(0) 0023 , renderer(new KoMeshPatchesRenderer) 0024 {} 0025 0026 Private(const Private& other) 0027 : QSharedData() 0028 , gradient(new SvgMeshGradient(*other.gradient)) 0029 , matrix(other.matrix) 0030 , renderer(new KoMeshPatchesRenderer) 0031 { 0032 } 0033 0034 ~Private() { 0035 delete renderer; 0036 } 0037 0038 QScopedPointer<SvgMeshGradient> gradient; 0039 QTransform matrix; 0040 KoMeshPatchesRenderer *renderer; 0041 }; 0042 0043 KoMeshGradientBackground::KoMeshGradientBackground(const SvgMeshGradient *gradient, const QTransform &matrix) 0044 : KoShapeBackground() 0045 , d(new Private) 0046 { 0047 d->gradient.reset(new SvgMeshGradient(*gradient)); 0048 d->matrix = matrix; 0049 Q_ASSERT(d->gradient); 0050 } 0051 0052 KoMeshGradientBackground::~KoMeshGradientBackground() 0053 { 0054 } 0055 0056 KoMeshGradientBackground::KoMeshGradientBackground(const KoMeshGradientBackground &rhs) 0057 : d(new Private(*rhs.d)) 0058 { 0059 } 0060 KoMeshGradientBackground &KoMeshGradientBackground::operator=(const KoMeshGradientBackground &rhs) 0061 { 0062 d = rhs.d; 0063 return *this; 0064 } 0065 0066 void KoMeshGradientBackground::paint(QPainter &painter, 0067 const QPainterPath &fillPath) const 0068 { 0069 if (!d->gradient || !d->gradient->isValid()) return; 0070 painter.save(); 0071 0072 QScopedPointer<SvgMeshGradient> gradient(new SvgMeshGradient(*d->gradient)); 0073 0074 QRectF meshBoundingRect = gradient->boundingRect(); 0075 0076 if (gradient->gradientUnits() == KoFlake::ObjectBoundingBox) { 0077 const QTransform relativeToShape = KisAlgebra2D::mapToRect(fillPath.boundingRect()); 0078 gradient->setTransform(relativeToShape); 0079 meshBoundingRect = gradient->boundingRect(); 0080 } 0081 0082 if (d->renderer->patchImage()->isNull()) { 0083 0084 d->renderer->configure(meshBoundingRect, painter.transform()); 0085 SvgMeshArray *mesharray = gradient->getMeshArray().data(); 0086 0087 for (int row = 0; row < mesharray->numRows(); ++row) { 0088 for (int col = 0; col < mesharray->numColumns(); ++col) { 0089 SvgMeshPatch *patch = mesharray->getPatch(row, col); 0090 d->renderer->fillPatch(patch, gradient->type(), mesharray, row, col); 0091 } 0092 } 0093 // uncomment to debug 0094 // d->renderer->patchImage()->save("mesh-patch.png"); 0095 } 0096 0097 painter.setClipPath(fillPath); 0098 0099 // patch is to be drawn wrt. to "user" coordinates 0100 painter.drawImage(meshBoundingRect, *d->renderer->patchImage()); 0101 0102 painter.restore(); 0103 } 0104 0105 bool KoMeshGradientBackground::compareTo(const KoShapeBackground*) const 0106 { 0107 return false; 0108 } 0109 0110 SvgMeshGradient* KoMeshGradientBackground::gradient() 0111 { 0112 return d->gradient.data(); 0113 } 0114 0115 QTransform KoMeshGradientBackground::transform() 0116 { 0117 return d->matrix; 0118 }