File indexing completed on 2024-05-12 15:56:41

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2008 Jan Hambrecht <jaham@gmx.net>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "KoGradientBackground.h"
0008 #include "KoFlake.h"
0009 #include <KoXmlNS.h>
0010 #include <KoShapeSavingContext.h>
0011 
0012 #include <FlakeDebug.h>
0013 
0014 #include <QSharedPointer>
0015 #include <QBrush>
0016 #include <QPainter>
0017 #include <QSharedData>
0018 #include <QPainterPath>
0019 
0020 class KoGradientBackground::Private : public QSharedData
0021 {
0022 public:
0023     Private()
0024         : QSharedData()
0025         , gradient(0)
0026     {}
0027 
0028     QGradient *gradient;
0029     QTransform matrix;
0030 };
0031 
0032 KoGradientBackground::KoGradientBackground(QGradient * gradient, const QTransform &matrix)
0033     : KoShapeBackground()
0034     , d(new Private)
0035 {
0036     d->gradient = gradient;
0037     d->matrix = matrix;
0038     Q_ASSERT(d->gradient);
0039 }
0040 
0041 KoGradientBackground::KoGradientBackground(const QGradient & gradient, const QTransform &matrix)
0042     : KoShapeBackground()
0043     , d(new Private)
0044 {
0045     d->gradient = KoFlake::cloneGradient(&gradient);
0046     d->matrix = matrix;
0047     Q_ASSERT(d->gradient);
0048 }
0049 
0050 KoGradientBackground::~KoGradientBackground()
0051 {
0052     delete d->gradient;
0053 }
0054 
0055 KoGradientBackground::KoGradientBackground(const KoGradientBackground &rhs)
0056     : d(new Private(*rhs.d))
0057 {
0058 }
0059 
0060 KoGradientBackground &KoGradientBackground::operator=(const KoGradientBackground &rhs)
0061 {
0062     d = rhs.d;
0063     return *this;
0064 }
0065 
0066 bool KoGradientBackground::compareTo(const KoShapeBackground *other) const
0067 {
0068     const KoGradientBackground *otherGradient = dynamic_cast<const KoGradientBackground*>(other);
0069 
0070     return otherGradient &&
0071         d->matrix == otherGradient->d->matrix &&
0072         *d->gradient == *otherGradient->d->gradient;
0073 }
0074 
0075 void KoGradientBackground::setTransform(const QTransform &matrix)
0076 {
0077     d->matrix = matrix;
0078 }
0079 
0080 QTransform KoGradientBackground::transform() const
0081 {
0082     return d->matrix;
0083 }
0084 
0085 void KoGradientBackground::setGradient(const QGradient &gradient)
0086 {
0087     delete d->gradient;
0088 
0089     d->gradient = KoFlake::cloneGradient(&gradient);
0090     Q_ASSERT(d->gradient);
0091 }
0092 
0093 const QGradient * KoGradientBackground::gradient() const
0094 {
0095     return d->gradient;
0096 }
0097 
0098 void KoGradientBackground::paint(QPainter &painter, const QPainterPath &fillPath) const
0099 {
0100     if (!d->gradient) return;
0101 
0102     if (d->gradient->coordinateMode() == QGradient::ObjectBoundingMode) {
0103 
0104         /**
0105          * NOTE: important hack!
0106          *
0107          * Qt has different notation of QBrush::setTransform() in comparison
0108          * to what SVG defines. SVG defines gradientToUser matrix to be postmultiplied
0109          * by QBrush::transform(), but Qt does exactly reverse!
0110          *
0111          * That most probably has beed caused by the fact that Qt uses transposed
0112          * matrices and someone just mistyped the stuff long ago :(
0113          *
0114          * So here we basically emulate this feature by converting the gradient into
0115          * QGradient::LogicalMode and doing transformations manually.
0116          */
0117 
0118         const QRectF boundingRect = fillPath.boundingRect();
0119         QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
0120                                   boundingRect.x(), boundingRect.y());
0121 
0122         // TODO: how about slicing the object?
0123         QGradient g = *d->gradient;
0124         g.setCoordinateMode(QGradient::LogicalMode);
0125 
0126         QBrush b(g);
0127         b.setTransform(d->matrix * gradientToUser);
0128         painter.setBrush(b);
0129     } else {
0130         QBrush b(*d->gradient);
0131         b.setTransform(d->matrix);
0132         painter.setBrush(b);
0133     }
0134 
0135     painter.drawPath(fillPath);
0136 }