source: trunk/tools/shared/qtgradienteditor/qtgradientutils.cpp@ 158

Last change on this file since 158 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 16.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtgradientutils.h"
43#include "qtgradientmanager.h"
44#include <QtGui/QLinearGradient>
45#include <QtGui/QRadialGradient>
46#include <QtGui/QConicalGradient>
47#include <QtXml/QDomDocument>
48#include <QtCore/QDebug>
49
50QT_BEGIN_NAMESPACE
51
52static QString gradientTypeToString(QGradient::Type type)
53{
54 if (type == QGradient::LinearGradient)
55 return QLatin1String("LinearGradient");
56 if (type == QGradient::RadialGradient)
57 return QLatin1String("RadialGradient");
58 if (type == QGradient::ConicalGradient)
59 return QLatin1String("ConicalGradient");
60 return QLatin1String("NoGradient");
61}
62
63static QGradient::Type stringToGradientType(const QString &name)
64{
65 if (name == QLatin1String("LinearGradient"))
66 return QGradient::LinearGradient;
67 if (name == QLatin1String("RadialGradient"))
68 return QGradient::RadialGradient;
69 if (name == QLatin1String("ConicalGradient"))
70 return QGradient::ConicalGradient;
71 return QGradient::NoGradient;
72}
73
74static QString gradientSpreadToString(QGradient::Spread spread)
75{
76 if (spread == QGradient::PadSpread)
77 return QLatin1String("PadSpread");
78 if (spread == QGradient::RepeatSpread)
79 return QLatin1String("RepeatSpread");
80 if (spread == QGradient::ReflectSpread)
81 return QLatin1String("ReflectSpread");
82 return QLatin1String("PadSpread");
83}
84
85static QGradient::Spread stringToGradientSpread(const QString &name)
86{
87 if (name == QLatin1String("PadSpread"))
88 return QGradient::PadSpread;
89 if (name == QLatin1String("RepeatSpread"))
90 return QGradient::RepeatSpread;
91 if (name == QLatin1String("ReflectSpread"))
92 return QGradient::ReflectSpread;
93 return QGradient::PadSpread;
94}
95
96static QString gradientCoordinateModeToString(QGradient::CoordinateMode mode)
97{
98 if (mode == QGradient::LogicalMode)
99 return QLatin1String("LogicalMode");
100 if (mode == QGradient::StretchToDeviceMode)
101 return QLatin1String("StretchToDeviceMode");
102 if (mode == QGradient::ObjectBoundingMode)
103 return QLatin1String("ObjectBoundingMode");
104 return QLatin1String("StretchToDeviceMode");
105}
106
107static QGradient::CoordinateMode stringToGradientCoordinateMode(const QString &name)
108{
109 if (name == QLatin1String("LogicalMode"))
110 return QGradient::LogicalMode;
111 if (name == QLatin1String("StretchToDeviceMode"))
112 return QGradient::StretchToDeviceMode;
113 if (name == QLatin1String("ObjectBoundingMode"))
114 return QGradient::ObjectBoundingMode;
115 return QGradient::StretchToDeviceMode;
116}
117
118static QDomElement saveColor(QDomDocument &doc, const QColor &color)
119{
120 QDomElement colorElem = doc.createElement(QLatin1String("colorData"));
121
122 colorElem.setAttribute(QLatin1String("r"), QString::number(color.red()));
123 colorElem.setAttribute(QLatin1String("g"), QString::number(color.green()));
124 colorElem.setAttribute(QLatin1String("b"), QString::number(color.blue()));
125 colorElem.setAttribute(QLatin1String("a"), QString::number(color.alpha()));
126
127 return colorElem;
128}
129
130static QDomElement saveGradientStop(QDomDocument &doc, const QGradientStop &stop)
131{
132 QDomElement stopElem = doc.createElement(QLatin1String("stopData"));
133
134 stopElem.setAttribute(QLatin1String("position"), QString::number(stop.first));
135
136 const QDomElement colorElem = saveColor(doc, stop.second);
137 stopElem.appendChild(colorElem);
138
139 return stopElem;
140}
141
142static QDomElement saveGradient(QDomDocument &doc, const QGradient &gradient)
143{
144 QDomElement gradElem = doc.createElement(QLatin1String("gradientData"));
145
146 const QGradient::Type type = gradient.type();
147 gradElem.setAttribute(QLatin1String("type"), gradientTypeToString(type));
148 gradElem.setAttribute(QLatin1String("spread"), gradientSpreadToString(gradient.spread()));
149 gradElem.setAttribute(QLatin1String("coordinateMode"), gradientCoordinateModeToString(gradient.coordinateMode()));
150
151 QGradientStops stops = gradient.stops();
152 QVectorIterator<QGradientStop > it(stops);
153 while (it.hasNext())
154 gradElem.appendChild(saveGradientStop(doc, it.next()));
155
156 if (type == QGradient::LinearGradient) {
157 const QLinearGradient &g = *static_cast<const QLinearGradient *>(&gradient);
158 gradElem.setAttribute(QLatin1String("startX"), QString::number(g.start().x()));
159 gradElem.setAttribute(QLatin1String("startY"), QString::number(g.start().y()));
160 gradElem.setAttribute(QLatin1String("endX"), QString::number(g.finalStop().x()));
161 gradElem.setAttribute(QLatin1String("endY"), QString::number(g.finalStop().y()));
162 } else if (type == QGradient::RadialGradient) {
163 const QRadialGradient &g = *static_cast<const QRadialGradient *>(&gradient);
164 gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x()));
165 gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y()));
166 gradElem.setAttribute(QLatin1String("focalX"), QString::number(g.focalPoint().x()));
167 gradElem.setAttribute(QLatin1String("focalY"), QString::number(g.focalPoint().y()));
168 gradElem.setAttribute(QLatin1String("radius"), QString::number(g.radius()));
169 } else if (type == QGradient::ConicalGradient) {
170 const QConicalGradient &g = *static_cast<const QConicalGradient*>(&gradient);
171 gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x()));
172 gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y()));
173 gradElem.setAttribute(QLatin1String("angle"), QString::number(g.angle()));
174 }
175
176 return gradElem;
177}
178
179static QColor loadColor(const QDomElement &elem)
180{
181 if (elem.tagName() != QLatin1String("colorData"))
182 return QColor();
183
184 return QColor(elem.attribute(QLatin1String("r")).toInt(),
185 elem.attribute(QLatin1String("g")).toInt(),
186 elem.attribute(QLatin1String("b")).toInt(),
187 elem.attribute(QLatin1String("a")).toInt());
188}
189
190static QGradientStop loadGradientStop(const QDomElement &elem)
191{
192 if (elem.tagName() != QLatin1String("stopData"))
193 return QGradientStop();
194
195 const qreal pos = static_cast<qreal>(elem.attribute(QLatin1String("position")).toDouble());
196 return qMakePair(pos, loadColor(elem.firstChild().toElement()));
197}
198
199static QGradient loadGradient(const QDomElement &elem)
200{
201 if (elem.tagName() != QLatin1String("gradientData"))
202 return QLinearGradient();
203
204 const QGradient::Type type = stringToGradientType(elem.attribute(QLatin1String("type")));
205 const QGradient::Spread spread = stringToGradientSpread(elem.attribute(QLatin1String("spread")));
206 const QGradient::CoordinateMode mode = stringToGradientCoordinateMode(elem.attribute(QLatin1String("coordinateMode")));
207
208 QGradient gradient = QLinearGradient();
209
210 if (type == QGradient::LinearGradient) {
211 QLinearGradient g;
212 g.setStart(elem.attribute(QLatin1String("startX")).toDouble(), elem.attribute(QLatin1String("startY")).toDouble());
213 g.setFinalStop(elem.attribute(QLatin1String("endX")).toDouble(), elem.attribute(QLatin1String("endY")).toDouble());
214 gradient = g;
215 } else if (type == QGradient::RadialGradient) {
216 QRadialGradient g;
217 g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble());
218 g.setFocalPoint(elem.attribute(QLatin1String("focalX")).toDouble(), elem.attribute(QLatin1String("focalY")).toDouble());
219 g.setRadius(elem.attribute(QLatin1String("radius")).toDouble());
220 gradient = g;
221 } else if (type == QGradient::ConicalGradient) {
222 QConicalGradient g;
223 g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble());
224 g.setAngle(elem.attribute(QLatin1String("angle")).toDouble());
225 gradient = g;
226 }
227
228 QDomElement stopElem = elem.firstChildElement();
229 while (!stopElem.isNull()) {
230 QGradientStop stop = loadGradientStop(stopElem);
231
232 gradient.setColorAt(stop.first, stop.second);
233
234 stopElem = stopElem.nextSiblingElement();
235 }
236
237 gradient.setSpread(spread);
238 gradient.setCoordinateMode(mode);
239
240 return gradient;
241}
242
243QString QtGradientUtils::saveState(const QtGradientManager *manager)
244{
245 QDomDocument doc;
246
247 QDomElement rootElem = doc.createElement(QLatin1String("gradients"));
248
249 QMap<QString, QGradient> grads = manager->gradients();
250 QMapIterator<QString, QGradient> itGrad(grads);
251 while (itGrad.hasNext()) {
252 itGrad.next();
253 QDomElement idElem = doc.createElement(QLatin1String("gradient"));
254 idElem.setAttribute(QLatin1String("name"), itGrad.key());
255 QDomElement gradElem = saveGradient(doc, itGrad.value());
256 idElem.appendChild(gradElem);
257
258 rootElem.appendChild(idElem);
259 }
260
261 doc.appendChild(rootElem);
262
263 return doc.toString();
264}
265
266void QtGradientUtils::restoreState(QtGradientManager *manager, const QString &state)
267{
268 manager->clear();
269
270 QDomDocument doc;
271 doc.setContent(state);
272
273 QDomElement rootElem = doc.documentElement();
274
275 QDomElement gradElem = rootElem.firstChildElement();
276 while (!gradElem.isNull()) {
277 const QString name = gradElem.attribute(QLatin1String("name"));
278 const QGradient gradient = loadGradient(gradElem.firstChildElement());
279
280 manager->addGradient(name, gradient);
281 gradElem = gradElem.nextSiblingElement();
282 }
283}
284
285QPixmap QtGradientUtils::gradientPixmap(const QGradient &gradient, const QSize &size, bool checkeredBackground)
286{
287 QImage image(size, QImage::Format_ARGB32);
288 QPainter p(&image);
289 p.setCompositionMode(QPainter::CompositionMode_Source);
290
291 if (checkeredBackground) {
292 int pixSize = 20;
293 QPixmap pm(2 * pixSize, 2 * pixSize);
294
295 QPainter pmp(&pm);
296 pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray);
297 pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray);
298 pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray);
299 pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray);
300
301 p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2);
302 p.fillRect(0, 0, size.width(), size.height(), pm);
303 p.setBrushOrigin(0, 0);
304 p.setCompositionMode(QPainter::CompositionMode_SourceOver);
305 }
306
307 const qreal scaleFactor = 0.999999;
308 p.scale(scaleFactor, scaleFactor);
309 QGradient grad = gradient;
310 grad.setCoordinateMode(QGradient::StretchToDeviceMode);
311 p.fillRect(QRect(0, 0, size.width(), size.height()), grad);
312 p.drawRect(QRect(0, 0, size.width() - 1, size.height() - 1));
313
314 return QPixmap::fromImage(image);
315}
316
317static QString styleSheetFillName(const QGradient &gradient)
318{
319 QString result;
320
321 switch (gradient.type()) {
322 case QGradient::LinearGradient:
323 result += QLatin1String("qlineargradient");
324 break;
325 case QGradient::RadialGradient:
326 result += QLatin1String("qradialgradient");
327 break;
328 case QGradient::ConicalGradient:
329 result += QLatin1String("qconicalgradient");
330 break;
331 default:
332 qWarning() << "QtGradientUtils::styleSheetFillName(): gradient type" << gradient.type() << "not supported!";
333 break;
334 }
335
336 return result;
337}
338
339static QStringList styleSheetParameters(const QGradient &gradient)
340{
341 QStringList result;
342
343 if (gradient.type() != QGradient::ConicalGradient) {
344 QString spread;
345 switch (gradient.spread()) {
346 case QGradient::PadSpread:
347 spread = QLatin1String("pad");
348 break;
349 case QGradient::ReflectSpread:
350 spread = QLatin1String("reflect");
351 break;
352 case QGradient::RepeatSpread:
353 spread = QLatin1String("repeat");
354 break;
355 default:
356 qWarning() << "QtGradientUtils::styleSheetParameters(): gradient spread" << gradient.spread() << "not supported!";
357 break;
358 }
359 result << QLatin1String("spread:") + spread;
360 }
361
362 switch (gradient.type()) {
363 case QGradient::LinearGradient: {
364 const QLinearGradient *linearGradient = static_cast<const QLinearGradient*>(&gradient);
365 result << QLatin1String("x1:") + QString::number(linearGradient->start().x())
366 << QLatin1String("y1:") + QString::number(linearGradient->start().y())
367 << QLatin1String("x2:") + QString::number(linearGradient->finalStop().x())
368 << QLatin1String("y2:") + QString::number(linearGradient->finalStop().y());
369 break;
370 }
371 case QGradient::RadialGradient: {
372 const QRadialGradient *radialGradient = static_cast<const QRadialGradient*>(&gradient);
373 result << QLatin1String("cx:") + QString::number(radialGradient->center().x())
374 << QLatin1String("cy:") + QString::number(radialGradient->center().y())
375 << QLatin1String("radius:") + QString::number(radialGradient->radius())
376 << QLatin1String("fx:") + QString::number(radialGradient->focalPoint().x())
377 << QLatin1String("fy:") + QString::number(radialGradient->focalPoint().y());
378 break;
379 }
380 case QGradient::ConicalGradient: {
381 const QConicalGradient *conicalGradient = static_cast<const QConicalGradient*>(&gradient);
382 result << QLatin1String("cx:") + QString::number(conicalGradient->center().x())
383 << QLatin1String("cy:") + QString::number(conicalGradient->center().y())
384 << QLatin1String("angle:") + QString::number(conicalGradient->angle());
385 break;
386 }
387 default:
388 qWarning() << "QtGradientUtils::styleSheetParameters(): gradient type" << gradient.type() << "not supported!";
389 break;
390 }
391
392 return result;
393}
394
395static QStringList styleSheetStops(const QGradient &gradient)
396{
397 QStringList result;
398 foreach (QGradientStop stop, gradient.stops()) {
399 const QColor color = stop.second;
400
401 const QString stopDescription = QLatin1String("stop:") + QString::number(stop.first) + QLatin1String(" rgba(")
402 + QString::number(color.red()) + QLatin1String(", ")
403 + QString::number(color.green()) + QLatin1String(", ")
404 + QString::number(color.blue()) + QLatin1String(", ")
405 + QString::number(color.alpha()) + QLatin1Char(')');
406 result << stopDescription;
407 }
408
409 return result;
410}
411
412QString QtGradientUtils::styleSheetCode(const QGradient &gradient)
413{
414 QStringList gradientParameters;
415 gradientParameters << styleSheetParameters(gradient) << styleSheetStops(gradient);
416
417 return styleSheetFillName(gradient) + QLatin1Char('(') + gradientParameters.join(QLatin1String(", ")) + QLatin1Char(')');
418}
419
420QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.