| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the tools applications of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** This file may be used under the terms of the GNU Lesser General Public |
| ** License version 2.1 as published by the Free Software Foundation and |
| ** appearing in the file LICENSE.LGPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU Lesser |
| ** General Public License version 2.1 requirements will be met: |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qtgradientutils.h" |
| #include "qtgradientmanager.h" |
| #include <QtGui/QLinearGradient> |
| #include <QtGui/QRadialGradient> |
| #include <QtGui/QConicalGradient> |
| #include <QtXml/QDomDocument> |
| #include <QtCore/QDebug> |
| |
| QT_BEGIN_NAMESPACE |
| |
| static QString gradientTypeToString(QGradient::Type type) |
| { |
| if (type == QGradient::LinearGradient) |
| return QLatin1String("LinearGradient"); |
| if (type == QGradient::RadialGradient) |
| return QLatin1String("RadialGradient"); |
| if (type == QGradient::ConicalGradient) |
| return QLatin1String("ConicalGradient"); |
| return QLatin1String("NoGradient"); |
| } |
| |
| static QGradient::Type stringToGradientType(const QString &name) |
| { |
| if (name == QLatin1String("LinearGradient")) |
| return QGradient::LinearGradient; |
| if (name == QLatin1String("RadialGradient")) |
| return QGradient::RadialGradient; |
| if (name == QLatin1String("ConicalGradient")) |
| return QGradient::ConicalGradient; |
| return QGradient::NoGradient; |
| } |
| |
| static QString gradientSpreadToString(QGradient::Spread spread) |
| { |
| if (spread == QGradient::PadSpread) |
| return QLatin1String("PadSpread"); |
| if (spread == QGradient::RepeatSpread) |
| return QLatin1String("RepeatSpread"); |
| if (spread == QGradient::ReflectSpread) |
| return QLatin1String("ReflectSpread"); |
| return QLatin1String("PadSpread"); |
| } |
| |
| static QGradient::Spread stringToGradientSpread(const QString &name) |
| { |
| if (name == QLatin1String("PadSpread")) |
| return QGradient::PadSpread; |
| if (name == QLatin1String("RepeatSpread")) |
| return QGradient::RepeatSpread; |
| if (name == QLatin1String("ReflectSpread")) |
| return QGradient::ReflectSpread; |
| return QGradient::PadSpread; |
| } |
| |
| static QString gradientCoordinateModeToString(QGradient::CoordinateMode mode) |
| { |
| if (mode == QGradient::LogicalMode) |
| return QLatin1String("LogicalMode"); |
| if (mode == QGradient::StretchToDeviceMode) |
| return QLatin1String("StretchToDeviceMode"); |
| if (mode == QGradient::ObjectBoundingMode) |
| return QLatin1String("ObjectBoundingMode"); |
| return QLatin1String("StretchToDeviceMode"); |
| } |
| |
| static QGradient::CoordinateMode stringToGradientCoordinateMode(const QString &name) |
| { |
| if (name == QLatin1String("LogicalMode")) |
| return QGradient::LogicalMode; |
| if (name == QLatin1String("StretchToDeviceMode")) |
| return QGradient::StretchToDeviceMode; |
| if (name == QLatin1String("ObjectBoundingMode")) |
| return QGradient::ObjectBoundingMode; |
| return QGradient::StretchToDeviceMode; |
| } |
| |
| static QDomElement saveColor(QDomDocument &doc, const QColor &color) |
| { |
| QDomElement colorElem = doc.createElement(QLatin1String("colorData")); |
| |
| colorElem.setAttribute(QLatin1String("r"), QString::number(color.red())); |
| colorElem.setAttribute(QLatin1String("g"), QString::number(color.green())); |
| colorElem.setAttribute(QLatin1String("b"), QString::number(color.blue())); |
| colorElem.setAttribute(QLatin1String("a"), QString::number(color.alpha())); |
| |
| return colorElem; |
| } |
| |
| static QDomElement saveGradientStop(QDomDocument &doc, const QGradientStop &stop) |
| { |
| QDomElement stopElem = doc.createElement(QLatin1String("stopData")); |
| |
| stopElem.setAttribute(QLatin1String("position"), QString::number(stop.first)); |
| |
| const QDomElement colorElem = saveColor(doc, stop.second); |
| stopElem.appendChild(colorElem); |
| |
| return stopElem; |
| } |
| |
| static QDomElement saveGradient(QDomDocument &doc, const QGradient &gradient) |
| { |
| QDomElement gradElem = doc.createElement(QLatin1String("gradientData")); |
| |
| const QGradient::Type type = gradient.type(); |
| gradElem.setAttribute(QLatin1String("type"), gradientTypeToString(type)); |
| gradElem.setAttribute(QLatin1String("spread"), gradientSpreadToString(gradient.spread())); |
| gradElem.setAttribute(QLatin1String("coordinateMode"), gradientCoordinateModeToString(gradient.coordinateMode())); |
| |
| QGradientStops stops = gradient.stops(); |
| QVectorIterator<QGradientStop > it(stops); |
| while (it.hasNext()) |
| gradElem.appendChild(saveGradientStop(doc, it.next())); |
| |
| if (type == QGradient::LinearGradient) { |
| const QLinearGradient &g = *static_cast<const QLinearGradient *>(&gradient); |
| gradElem.setAttribute(QLatin1String("startX"), QString::number(g.start().x())); |
| gradElem.setAttribute(QLatin1String("startY"), QString::number(g.start().y())); |
| gradElem.setAttribute(QLatin1String("endX"), QString::number(g.finalStop().x())); |
| gradElem.setAttribute(QLatin1String("endY"), QString::number(g.finalStop().y())); |
| } else if (type == QGradient::RadialGradient) { |
| const QRadialGradient &g = *static_cast<const QRadialGradient *>(&gradient); |
| gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x())); |
| gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y())); |
| gradElem.setAttribute(QLatin1String("focalX"), QString::number(g.focalPoint().x())); |
| gradElem.setAttribute(QLatin1String("focalY"), QString::number(g.focalPoint().y())); |
| gradElem.setAttribute(QLatin1String("radius"), QString::number(g.radius())); |
| } else if (type == QGradient::ConicalGradient) { |
| const QConicalGradient &g = *static_cast<const QConicalGradient*>(&gradient); |
| gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x())); |
| gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y())); |
| gradElem.setAttribute(QLatin1String("angle"), QString::number(g.angle())); |
| } |
| |
| return gradElem; |
| } |
| |
| static QColor loadColor(const QDomElement &elem) |
| { |
| if (elem.tagName() != QLatin1String("colorData")) |
| return QColor(); |
| |
| return QColor(elem.attribute(QLatin1String("r")).toInt(), |
| elem.attribute(QLatin1String("g")).toInt(), |
| elem.attribute(QLatin1String("b")).toInt(), |
| elem.attribute(QLatin1String("a")).toInt()); |
| } |
| |
| static QGradientStop loadGradientStop(const QDomElement &elem) |
| { |
| if (elem.tagName() != QLatin1String("stopData")) |
| return QGradientStop(); |
| |
| const qreal pos = static_cast<qreal>(elem.attribute(QLatin1String("position")).toDouble()); |
| return qMakePair(pos, loadColor(elem.firstChild().toElement())); |
| } |
| |
| static QGradient loadGradient(const QDomElement &elem) |
| { |
| if (elem.tagName() != QLatin1String("gradientData")) |
| return QLinearGradient(); |
| |
| const QGradient::Type type = stringToGradientType(elem.attribute(QLatin1String("type"))); |
| const QGradient::Spread spread = stringToGradientSpread(elem.attribute(QLatin1String("spread"))); |
| const QGradient::CoordinateMode mode = stringToGradientCoordinateMode(elem.attribute(QLatin1String("coordinateMode"))); |
| |
| QGradient gradient = QLinearGradient(); |
| |
| if (type == QGradient::LinearGradient) { |
| QLinearGradient g; |
| g.setStart(elem.attribute(QLatin1String("startX")).toDouble(), elem.attribute(QLatin1String("startY")).toDouble()); |
| g.setFinalStop(elem.attribute(QLatin1String("endX")).toDouble(), elem.attribute(QLatin1String("endY")).toDouble()); |
| gradient = g; |
| } else if (type == QGradient::RadialGradient) { |
| QRadialGradient g; |
| g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble()); |
| g.setFocalPoint(elem.attribute(QLatin1String("focalX")).toDouble(), elem.attribute(QLatin1String("focalY")).toDouble()); |
| g.setRadius(elem.attribute(QLatin1String("radius")).toDouble()); |
| gradient = g; |
| } else if (type == QGradient::ConicalGradient) { |
| QConicalGradient g; |
| g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble()); |
| g.setAngle(elem.attribute(QLatin1String("angle")).toDouble()); |
| gradient = g; |
| } |
| |
| QDomElement stopElem = elem.firstChildElement(); |
| while (!stopElem.isNull()) { |
| QGradientStop stop = loadGradientStop(stopElem); |
| |
| gradient.setColorAt(stop.first, stop.second); |
| |
| stopElem = stopElem.nextSiblingElement(); |
| } |
| |
| gradient.setSpread(spread); |
| gradient.setCoordinateMode(mode); |
| |
| return gradient; |
| } |
| |
| QString QtGradientUtils::saveState(const QtGradientManager *manager) |
| { |
| QDomDocument doc; |
| |
| QDomElement rootElem = doc.createElement(QLatin1String("gradients")); |
| |
| QMap<QString, QGradient> grads = manager->gradients(); |
| QMapIterator<QString, QGradient> itGrad(grads); |
| while (itGrad.hasNext()) { |
| itGrad.next(); |
| QDomElement idElem = doc.createElement(QLatin1String("gradient")); |
| idElem.setAttribute(QLatin1String("name"), itGrad.key()); |
| QDomElement gradElem = saveGradient(doc, itGrad.value()); |
| idElem.appendChild(gradElem); |
| |
| rootElem.appendChild(idElem); |
| } |
| |
| doc.appendChild(rootElem); |
| |
| return doc.toString(); |
| } |
| |
| void QtGradientUtils::restoreState(QtGradientManager *manager, const QString &state) |
| { |
| manager->clear(); |
| |
| QDomDocument doc; |
| doc.setContent(state); |
| |
| QDomElement rootElem = doc.documentElement(); |
| |
| QDomElement gradElem = rootElem.firstChildElement(); |
| while (!gradElem.isNull()) { |
| const QString name = gradElem.attribute(QLatin1String("name")); |
| const QGradient gradient = loadGradient(gradElem.firstChildElement()); |
| |
| manager->addGradient(name, gradient); |
| gradElem = gradElem.nextSiblingElement(); |
| } |
| } |
| |
| QPixmap QtGradientUtils::gradientPixmap(const QGradient &gradient, const QSize &size, bool checkeredBackground) |
| { |
| QImage image(size, QImage::Format_ARGB32); |
| QPainter p(&image); |
| p.setCompositionMode(QPainter::CompositionMode_Source); |
| |
| if (checkeredBackground) { |
| int pixSize = 20; |
| QPixmap pm(2 * pixSize, 2 * pixSize); |
| |
| QPainter pmp(&pm); |
| pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray); |
| pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray); |
| pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray); |
| pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray); |
| |
| p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2); |
| p.fillRect(0, 0, size.width(), size.height(), pm); |
| p.setBrushOrigin(0, 0); |
| p.setCompositionMode(QPainter::CompositionMode_SourceOver); |
| } |
| |
| const qreal scaleFactor = 0.999999; |
| p.scale(scaleFactor, scaleFactor); |
| QGradient grad = gradient; |
| grad.setCoordinateMode(QGradient::StretchToDeviceMode); |
| p.fillRect(QRect(0, 0, size.width(), size.height()), grad); |
| p.drawRect(QRect(0, 0, size.width() - 1, size.height() - 1)); |
| |
| return QPixmap::fromImage(image); |
| } |
| |
| static QString styleSheetFillName(const QGradient &gradient) |
| { |
| QString result; |
| |
| switch (gradient.type()) { |
| case QGradient::LinearGradient: |
| result += QLatin1String("qlineargradient"); |
| break; |
| case QGradient::RadialGradient: |
| result += QLatin1String("qradialgradient"); |
| break; |
| case QGradient::ConicalGradient: |
| result += QLatin1String("qconicalgradient"); |
| break; |
| default: |
| qWarning() << "QtGradientUtils::styleSheetFillName(): gradient type" << gradient.type() << "not supported!"; |
| break; |
| } |
| |
| return result; |
| } |
| |
| static QStringList styleSheetParameters(const QGradient &gradient) |
| { |
| QStringList result; |
| |
| if (gradient.type() != QGradient::ConicalGradient) { |
| QString spread; |
| switch (gradient.spread()) { |
| case QGradient::PadSpread: |
| spread = QLatin1String("pad"); |
| break; |
| case QGradient::ReflectSpread: |
| spread = QLatin1String("reflect"); |
| break; |
| case QGradient::RepeatSpread: |
| spread = QLatin1String("repeat"); |
| break; |
| default: |
| qWarning() << "QtGradientUtils::styleSheetParameters(): gradient spread" << gradient.spread() << "not supported!"; |
| break; |
| } |
| result << QLatin1String("spread:") + spread; |
| } |
| |
| switch (gradient.type()) { |
| case QGradient::LinearGradient: { |
| const QLinearGradient *linearGradient = static_cast<const QLinearGradient*>(&gradient); |
| result << QLatin1String("x1:") + QString::number(linearGradient->start().x()) |
| << QLatin1String("y1:") + QString::number(linearGradient->start().y()) |
| << QLatin1String("x2:") + QString::number(linearGradient->finalStop().x()) |
| << QLatin1String("y2:") + QString::number(linearGradient->finalStop().y()); |
| break; |
| } |
| case QGradient::RadialGradient: { |
| const QRadialGradient *radialGradient = static_cast<const QRadialGradient*>(&gradient); |
| result << QLatin1String("cx:") + QString::number(radialGradient->center().x()) |
| << QLatin1String("cy:") + QString::number(radialGradient->center().y()) |
| << QLatin1String("radius:") + QString::number(radialGradient->radius()) |
| << QLatin1String("fx:") + QString::number(radialGradient->focalPoint().x()) |
| << QLatin1String("fy:") + QString::number(radialGradient->focalPoint().y()); |
| break; |
| } |
| case QGradient::ConicalGradient: { |
| const QConicalGradient *conicalGradient = static_cast<const QConicalGradient*>(&gradient); |
| result << QLatin1String("cx:") + QString::number(conicalGradient->center().x()) |
| << QLatin1String("cy:") + QString::number(conicalGradient->center().y()) |
| << QLatin1String("angle:") + QString::number(conicalGradient->angle()); |
| break; |
| } |
| default: |
| qWarning() << "QtGradientUtils::styleSheetParameters(): gradient type" << gradient.type() << "not supported!"; |
| break; |
| } |
| |
| return result; |
| } |
| |
| static QStringList styleSheetStops(const QGradient &gradient) |
| { |
| QStringList result; |
| foreach (const QGradientStop &stop, gradient.stops()) { |
| const QColor color = stop.second; |
| |
| const QString stopDescription = QLatin1String("stop:") + QString::number(stop.first) + QLatin1String(" rgba(") |
| + QString::number(color.red()) + QLatin1String(", ") |
| + QString::number(color.green()) + QLatin1String(", ") |
| + QString::number(color.blue()) + QLatin1String(", ") |
| + QString::number(color.alpha()) + QLatin1Char(')'); |
| result << stopDescription; |
| } |
| |
| return result; |
| } |
| |
| QString QtGradientUtils::styleSheetCode(const QGradient &gradient) |
| { |
| QStringList gradientParameters; |
| gradientParameters << styleSheetParameters(gradient) << styleSheetStops(gradient); |
| |
| return styleSheetFillName(gradient) + QLatin1Char('(') + gradientParameters.join(QLatin1String(", ")) + QLatin1Char(')'); |
| } |
| |
| QT_END_NAMESPACE |