Warning, file /office/calligra/libs/flake/KoGradientHelper.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2008 Jan Hambrecht <jaham@gmx.net>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Library General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Library General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Library General Public License
0015  * along with this library; see the file COPYING.LIB.  If not, write to
0016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018  */
0019 
0020 #include "KoGradientHelper.h"
0021 
0022 #include <QGradient>
0023 #include <math.h>
0024 
0025 QGradient* KoGradientHelper::defaultGradient(QGradient::Type type, QGradient::Spread spread, const QGradientStops &stops)
0026 {
0027     QGradient *gradient = 0;
0028     switch (type) {
0029     case QGradient::LinearGradient:
0030         gradient = new QLinearGradient(QPointF(0.0, 0.5), QPointF(1, 0.5));
0031         break;
0032     case QGradient::RadialGradient:
0033         gradient = new QRadialGradient(QPointF(0.5, 0.5), sqrt(0.5));
0034         break;
0035     case QGradient::ConicalGradient:
0036         gradient = new QConicalGradient(QPointF(0.5, 0.5), 0.0);
0037         break;
0038     default:
0039         return 0;
0040     }
0041     gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
0042     gradient->setSpread(spread);
0043     gradient->setStops(stops);
0044 
0045     return gradient;
0046 }
0047 
0048 QGradient* KoGradientHelper::convertGradient(const QGradient * gradient, QGradient::Type newType)
0049 {
0050     QPointF start, stop;
0051     // try to preserve gradient positions
0052     switch (gradient->type()) {
0053     case QGradient::LinearGradient: {
0054         const QLinearGradient *g = static_cast<const QLinearGradient*>(gradient);
0055         start = g->start();
0056         stop = g->finalStop();
0057         break;
0058     }
0059     case QGradient::RadialGradient: {
0060         const QRadialGradient *g = static_cast<const QRadialGradient*>(gradient);
0061         start = g->center();
0062         stop = QPointF(g->radius(), 0.0);
0063         break;
0064     }
0065     case QGradient::ConicalGradient: {
0066         const QConicalGradient *g = static_cast<const QConicalGradient*>(gradient);
0067         start = g->center();
0068         qreal radAngle = g->angle() * M_PI / 180.0;
0069         stop = QPointF(0.5 * cos(radAngle), 0.5 * sin(radAngle));
0070         break;
0071     }
0072     default:
0073         start = QPointF(0.0, 0.0);
0074         stop = QPointF(0.5, 0.5);
0075     }
0076 
0077     QGradient *newGradient = 0;
0078     switch (newType) {
0079     case QGradient::LinearGradient:
0080         newGradient = new QLinearGradient(start, stop);
0081         break;
0082     case QGradient::RadialGradient: {
0083         QPointF diff(stop - start);
0084         qreal radius = sqrt(diff.x()*diff.x() + diff.y()*diff.y());
0085         newGradient = new QRadialGradient(start, radius, start);
0086         break;
0087     }
0088     case QGradient::ConicalGradient: {
0089         QPointF diff(stop - start);
0090         qreal angle = atan2(diff.y(), diff.x());
0091         if (angle < 0.0)
0092             angle += 2 * M_PI;
0093         newGradient = new QConicalGradient(start, angle * 180/M_PI);
0094         break;
0095     }
0096     default:
0097         return 0;
0098     }
0099     newGradient->setCoordinateMode(QGradient::ObjectBoundingMode);
0100     newGradient->setSpread(gradient->spread());
0101     newGradient->setStops(gradient->stops());
0102 
0103     return newGradient;
0104 }
0105 
0106 QColor KoGradientHelper::colorAt(qreal position, const QGradientStops &stops)
0107 {
0108     if (! stops.count())
0109         return QColor();
0110 
0111     if (stops.count() == 1)
0112         return stops.first().second;
0113 
0114     QGradientStop prevStop(-1.0, QColor());
0115     QGradientStop nextStop(2.0, QColor());
0116     // find framing gradient stops
0117     foreach(const QGradientStop & stop, stops) {
0118         if (stop.first > prevStop.first && stop.first < position)
0119             prevStop = stop;
0120         if (stop.first < nextStop.first && stop.first > position)
0121             nextStop = stop;
0122     }
0123 
0124     QColor theColor;
0125 
0126     if (prevStop.first < 0.0) {
0127         // new stop is before the first stop
0128         theColor = nextStop.second;
0129     } else if (nextStop.first > 1.0) {
0130         // new stop is after the last stop
0131         theColor = prevStop.second;
0132     } else {
0133         // linear interpolate colors between framing stops
0134         QColor prevColor = prevStop.second, nextColor = nextStop.second;
0135         qreal colorScale = (position - prevStop.first) / (nextStop.first - prevStop.first);
0136         theColor.setRedF(prevColor.redF() + colorScale *(nextColor.redF() - prevColor.redF()));
0137         theColor.setGreenF(prevColor.greenF() + colorScale *(nextColor.greenF() - prevColor.greenF()));
0138         theColor.setBlueF(prevColor.blueF() + colorScale *(nextColor.blueF() - prevColor.blueF()));
0139         theColor.setAlphaF(prevColor.alphaF() + colorScale *(nextColor.alphaF() - prevColor.alphaF()));
0140     }
0141     return theColor;
0142 }