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 }