1 /* This file is part of the KDE project
2 * Copyright (C) 2007,2009 Jan Hambrecht <jaham@gmx.net>
3 * Copyright (C) 2010 Thorsten Zachmann <zachmann@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "SvgGradientHelper.h"
22
23 #include <QConicalGradient>
24 #include <QLinearGradient>
25 #include <QRadialGradient>
26
27 #include <cmath>
28 #include <KoFlake.h>
29
SvgGradientHelper()30 SvgGradientHelper::SvgGradientHelper()
31 : m_gradient(0), m_gradientUnits(ObjectBoundingBox)
32 {
33 }
34
~SvgGradientHelper()35 SvgGradientHelper::~SvgGradientHelper()
36 {
37 delete m_gradient;
38 }
39
SvgGradientHelper(const SvgGradientHelper & other)40 SvgGradientHelper::SvgGradientHelper(const SvgGradientHelper &other)
41 : m_gradient(0), m_gradientUnits(ObjectBoundingBox)
42 {
43 m_gradientUnits = other.m_gradientUnits;
44 m_gradientTransform = other.m_gradientTransform;
45 copyGradient(other.m_gradient);
46 }
47
operator =(const SvgGradientHelper & rhs)48 SvgGradientHelper & SvgGradientHelper::operator = (const SvgGradientHelper & rhs)
49 {
50 if (this == &rhs)
51 return *this;
52
53 m_gradientUnits = rhs.m_gradientUnits;
54 m_gradientTransform = rhs.m_gradientTransform;
55 copyGradient(rhs.m_gradient);
56
57 return *this;
58 }
59
setGradientUnits(Units units)60 void SvgGradientHelper::setGradientUnits(Units units)
61 {
62 m_gradientUnits = units;
63 }
64
gradientUnits() const65 SvgGradientHelper::Units SvgGradientHelper::gradientUnits() const
66 {
67 return m_gradientUnits;
68 }
69
gradient()70 QGradient * SvgGradientHelper::gradient()
71 {
72 return m_gradient;
73 }
74
setGradient(QGradient * g)75 void SvgGradientHelper::setGradient(QGradient * g)
76 {
77 delete m_gradient;
78 m_gradient = g;
79 }
80
copyGradient(QGradient * other)81 void SvgGradientHelper::copyGradient(QGradient * other)
82 {
83 delete m_gradient;
84 m_gradient = duplicateGradient(other, QTransform());
85 }
86
adjustedFill(const QRectF & bound)87 QBrush SvgGradientHelper::adjustedFill(const QRectF &bound)
88 {
89 QBrush brush;
90
91 QGradient * g = adjustedGradient(bound);
92 if (g) {
93 brush = QBrush(*g);
94 delete g;
95 }
96
97 return brush;
98 }
99
transform() const100 QTransform SvgGradientHelper::transform() const
101 {
102 return m_gradientTransform;
103 }
104
setTransform(const QTransform & transform)105 void SvgGradientHelper::setTransform(const QTransform &transform)
106 {
107 m_gradientTransform = transform;
108 }
109
adjustedGradient(const QRectF & bound) const110 QGradient * SvgGradientHelper::adjustedGradient(const QRectF &bound) const
111 {
112 QTransform matrix;
113 matrix.scale(0.01 * bound.width(), 0.01 * bound.height());
114
115 return duplicateGradient(m_gradient, matrix);
116 }
117
duplicateGradient(const QGradient * originalGradient,const QTransform & transform)118 QGradient * SvgGradientHelper::duplicateGradient(const QGradient * originalGradient, const QTransform &transform)
119 {
120 if (! originalGradient)
121 return 0;
122
123 QGradient * duplicatedGradient = 0;
124
125 switch (originalGradient->type()) {
126 case QGradient::ConicalGradient: {
127 const QConicalGradient * o = static_cast<const QConicalGradient*>(originalGradient);
128 QConicalGradient * g = new QConicalGradient();
129 g->setAngle(o->angle());
130 g->setCenter(transform.map(o->center()));
131 duplicatedGradient = g;
132 }
133 break;
134 case QGradient::LinearGradient: {
135 const QLinearGradient * o = static_cast<const QLinearGradient*>(originalGradient);
136 QLinearGradient * g = new QLinearGradient();
137 g->setStart(transform.map(o->start()));
138 g->setFinalStop(transform.map(o->finalStop()));
139 duplicatedGradient = g;
140 }
141 break;
142 case QGradient::RadialGradient: {
143 const QRadialGradient * o = static_cast<const QRadialGradient*>(originalGradient);
144 QRadialGradient * g = new QRadialGradient();
145 g->setCenter(transform.map(o->center()));
146 g->setFocalPoint(transform.map(o->focalPoint()));
147 g->setRadius(transform.map(QPointF(o->radius(), 0.0)).x());
148 duplicatedGradient = g;
149 }
150 break;
151 default:
152 return 0;
153 }
154
155 duplicatedGradient->setCoordinateMode(originalGradient->coordinateMode());
156 duplicatedGradient->setStops(originalGradient->stops());
157 duplicatedGradient->setSpread(originalGradient->spread());
158
159 return duplicatedGradient;
160 }
161
convertGradient(const QGradient * originalGradient,const QSizeF & size)162 QGradient *SvgGradientHelper::convertGradient(const QGradient *originalGradient, const QSizeF &size)
163 {
164 if (! originalGradient)
165 return 0;
166
167 if (originalGradient->coordinateMode() != QGradient::LogicalMode) {
168 return duplicateGradient(originalGradient, QTransform());
169 }
170
171 QGradient *duplicatedGradient = 0;
172
173 switch (originalGradient->type()) {
174 case QGradient::ConicalGradient:
175 {
176 const QConicalGradient *o = static_cast<const QConicalGradient*>(originalGradient);
177 QConicalGradient *g = new QConicalGradient();
178 g->setAngle(o->angle());
179 g->setCenter(KoFlake::toRelative(o->center(),size));
180 duplicatedGradient = g;
181 }
182 break;
183 case QGradient::LinearGradient:
184 {
185 const QLinearGradient *o = static_cast<const QLinearGradient*>(originalGradient);
186 QLinearGradient *g = new QLinearGradient();
187 g->setStart(KoFlake::toRelative(o->start(),size));
188 g->setFinalStop(KoFlake::toRelative(o->finalStop(),size));
189 duplicatedGradient = g;
190 }
191 break;
192 case QGradient::RadialGradient:
193 {
194 const QRadialGradient *o = static_cast<const QRadialGradient*>(originalGradient);
195 QRadialGradient *g = new QRadialGradient();
196 g->setCenter(KoFlake::toRelative(o->center(),size));
197 g->setFocalPoint(KoFlake::toRelative(o->focalPoint(),size));
198 g->setRadius(KoFlake::toRelative(QPointF(o->radius(), 0.0),
199 QSizeF(sqrt(size.width() * size.width() + size.height() * size.height()), 0.0)).x());
200 duplicatedGradient = g;
201 }
202 break;
203 default:
204 return 0;
205 }
206
207 duplicatedGradient->setCoordinateMode(QGradient::ObjectBoundingMode);
208 duplicatedGradient->setStops(originalGradient->stops());
209 duplicatedGradient->setSpread(originalGradient->spread());
210
211 return duplicatedGradient;
212 }
213
214