1 /*
2     Copyright (c) 2007 Sven Langkamp <sven.langkamp@gmail.com>
3     Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
4     Copyright (c) 2009 Jan Hambrecht <jaham@gmx.net>
5 
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10 
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Lesser General Public License for more details.
15 
16     You should have received a copy of the GNU Lesser General Public
17     License along with this library; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "KoAbstractGradient.h"
22 #include "KoColorSpaceRegistry.h"
23 
24 #include <KoColor.h>
25 
26 #include <QBuffer>
27 #include <QByteArray>
28 
29 #define PREVIEW_WIDTH 64
30 #define PREVIEW_HEIGHT 64
31 
32 
33 struct Q_DECL_HIDDEN KoAbstractGradient::Private {
34     const KoColorSpace* colorSpace;
35     QGradient::Spread spread;
36     QGradient::Type type;
37 };
38 
KoAbstractGradient(const QString & filename)39 KoAbstractGradient::KoAbstractGradient(const QString& filename)
40         : KoResource(filename)
41         , d(new Private)
42 {
43     d->colorSpace = KoColorSpaceRegistry::instance()->rgb8();
44     d->spread = QGradient::PadSpread;
45     d->type = QGradient::NoGradient;
46 }
47 
~KoAbstractGradient()48 KoAbstractGradient::~KoAbstractGradient()
49 {
50     delete d;
51 }
52 
KoAbstractGradient(const KoAbstractGradient & rhs)53 KoAbstractGradient::KoAbstractGradient(const KoAbstractGradient &rhs)
54     : KoResource(rhs)
55     , d(new Private(*rhs.d))
56 {
57 }
58 
colorAt(KoColor &,qreal t) const59 void KoAbstractGradient::colorAt(KoColor&, qreal t) const
60 {
61     Q_UNUSED(t);
62 }
63 
setColorSpace(KoColorSpace * colorSpace)64 void KoAbstractGradient::setColorSpace(KoColorSpace* colorSpace)
65 {
66     d->colorSpace = colorSpace;
67 }
68 
colorSpace() const69 const KoColorSpace* KoAbstractGradient::colorSpace() const
70 {
71     return d->colorSpace;
72 }
73 
setSpread(QGradient::Spread spreadMethod)74 void KoAbstractGradient::setSpread(QGradient::Spread spreadMethod)
75 {
76     d->spread = spreadMethod;
77 }
78 
spread() const79 QGradient::Spread KoAbstractGradient::spread() const
80 {
81     return d->spread;
82 }
83 
setType(QGradient::Type repeatType)84 void KoAbstractGradient::setType(QGradient::Type repeatType)
85 {
86     d->type = repeatType;
87 }
88 
type() const89 QGradient::Type KoAbstractGradient::type() const
90 {
91     return d->type;
92 }
93 
generatePreview(int width,int height) const94 QImage KoAbstractGradient::generatePreview(int width, int height) const
95 {
96     QImage image(width, height, QImage::Format_RGB32);
97 
98     const int checkerSize = 4;
99     const int checkerSize_2 = 2 * checkerSize;
100     const int darkBackground = 128;
101     const int lightBackground = 128 + 63;
102 
103     QRgb * lineA = reinterpret_cast<QRgb*>(image.scanLine(0));
104     QRgb * lineB = reinterpret_cast<QRgb*>(image.scanLine(checkerSize));
105 
106     KoColor c;
107     QColor color;
108     // first create the two reference lines
109     for (int x = 0; x < image.width(); ++x) {
110 
111         qreal t = static_cast<qreal>(x) / (image.width() - 1);
112         colorAt(c, t);
113         c.toQColor(&color);
114         const qreal alpha = color.alphaF();
115 
116         int darkR = static_cast<int>((1 - alpha) * darkBackground + alpha * color.red() + 0.5);
117         int darkG = static_cast<int>((1 - alpha) * darkBackground + alpha * color.green() + 0.5);
118         int darkB = static_cast<int>((1 - alpha) * darkBackground + alpha * color.blue() + 0.5);
119 
120         int lightR = static_cast<int>((1 - alpha) * lightBackground + alpha * color.red() + 0.5);
121         int lightG = static_cast<int>((1 - alpha) * lightBackground + alpha * color.green() + 0.5);
122         int lightB = static_cast<int>((1 - alpha) * lightBackground + alpha * color.blue() + 0.5);
123 
124         bool defColor = (x % checkerSize_2) < checkerSize;
125 
126         if (lineA)
127             lineA[x] = defColor ? qRgb(darkR, darkG, darkB) : qRgb(lightR, lightG, lightB);
128         if (lineB)
129             lineB[x] = defColor ? qRgb(lightR, lightG, lightB) : qRgb(darkR, darkG, darkB);
130     }
131 
132     int bytesPerLine = image.bytesPerLine();
133 
134     // now copy lines accordingly
135     for (int y = 0; y < image.height(); ++y) {
136         bool firstLine = (y % checkerSize_2) < checkerSize;
137         QRgb * line = reinterpret_cast<QRgb*>(image.scanLine(y));
138         if (line == lineA || line == lineB)
139             continue;
140 
141         memcpy(line, firstLine ? lineA : lineB, bytesPerLine);
142     }
143 
144     return image;
145 }
146 
updatePreview()147 void KoAbstractGradient::updatePreview()
148 {
149     setImage(generatePreview(PREVIEW_WIDTH, PREVIEW_HEIGHT));
150 }
151