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 }