1 /* This file is part of the KDE project
2  * Copyright (C) 2008 Jan Hambrecht <jaham@gmx.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #include "KoGradientBackground.h"
21 #include "KoShapeBackground_p.h"
22 #include "KoFlake.h"
23 #include <KoStyleStack.h>
24 #include <KoXmlNS.h>
25 #include <KoOdfLoadingContext.h>
26 #include <KoOdfGraphicStyles.h>
27 #include <KoShapeSavingContext.h>
28 
29 #include <FlakeDebug.h>
30 
31 #include <QSharedPointer>
32 #include <QBrush>
33 #include <QPainter>
34 
35 class KoGradientBackgroundPrivate : public KoShapeBackgroundPrivate
36 {
37 public:
KoGradientBackgroundPrivate()38     KoGradientBackgroundPrivate()
39         : gradient(0)
40     {}
41 
42     QGradient *gradient;
43     QTransform matrix;
44 };
45 
KoGradientBackground(QGradient * gradient,const QTransform & matrix)46 KoGradientBackground::KoGradientBackground(QGradient * gradient, const QTransform &matrix)
47     : KoShapeBackground(*(new KoGradientBackgroundPrivate()))
48 {
49     Q_D(KoGradientBackground);
50     d->gradient = gradient;
51     d->matrix = matrix;
52     Q_ASSERT(d->gradient);
53     Q_ASSERT(d->gradient->coordinateMode() == QGradient::ObjectBoundingMode);
54 }
55 
KoGradientBackground(const QGradient & gradient,const QTransform & matrix)56 KoGradientBackground::KoGradientBackground(const QGradient & gradient, const QTransform &matrix)
57     : KoShapeBackground(*(new KoGradientBackgroundPrivate()))
58 {
59     Q_D(KoGradientBackground);
60     d->gradient = KoFlake::cloneGradient(&gradient);
61     d->matrix = matrix;
62     Q_ASSERT(d->gradient);
63     Q_ASSERT(d->gradient->coordinateMode() == QGradient::ObjectBoundingMode);
64 }
65 
~KoGradientBackground()66 KoGradientBackground::~KoGradientBackground()
67 {
68     Q_D(KoGradientBackground);
69     delete d->gradient;
70 }
71 
setTransform(const QTransform & matrix)72 void KoGradientBackground::setTransform(const QTransform &matrix)
73 {
74     Q_D(KoGradientBackground);
75     d->matrix = matrix;
76 }
77 
transform() const78 QTransform KoGradientBackground::transform() const
79 {
80     Q_D(const KoGradientBackground);
81     return d->matrix;
82 }
83 
setGradient(const QGradient & gradient)84 void KoGradientBackground::setGradient(const QGradient &gradient)
85 {
86     Q_D(KoGradientBackground);
87     delete d->gradient;
88 
89     d->gradient = KoFlake::cloneGradient(&gradient);
90     Q_ASSERT(d->gradient);
91     Q_ASSERT(d->gradient->coordinateMode() == QGradient::ObjectBoundingMode);
92 }
93 
gradient() const94 const QGradient * KoGradientBackground::gradient() const
95 {
96     Q_D(const KoGradientBackground);
97     return d->gradient;
98 }
99 
paint(QPainter & painter,const KoViewConverter &,KoShapePaintingContext &,const QPainterPath & fillPath) const100 void KoGradientBackground::paint(QPainter &painter, const KoViewConverter &/*converter*/, KoShapePaintingContext &/*context*/, const QPainterPath &fillPath) const
101 {
102     Q_D(const KoGradientBackground);
103     if (!d->gradient) return;
104     QBrush brush(*d->gradient);
105     brush.setTransform(d->matrix);
106 
107     painter.setBrush(brush);
108     painter.drawPath(fillPath);
109 }
110 
fillStyle(KoGenStyle & style,KoShapeSavingContext & context)111 void KoGradientBackground::fillStyle(KoGenStyle &style, KoShapeSavingContext &context)
112 {
113     Q_D(KoGradientBackground);
114     if (!d->gradient) return;
115     QBrush brush(*d->gradient);
116     brush.setTransform(d->matrix);
117     KoOdfGraphicStyles::saveOdfFillStyle(style, context.mainStyles(), brush);
118 }
119 
loadStyle(KoOdfLoadingContext & context,const QSizeF & shapeSize)120 bool KoGradientBackground::loadStyle(KoOdfLoadingContext &context, const QSizeF &shapeSize)
121 {
122     Q_D(KoGradientBackground);
123     KoStyleStack &styleStack = context.styleStack();
124     if (! styleStack.hasProperty(KoXmlNS::draw, "fill"))
125         return false;
126 
127     QString fillStyle = styleStack.property(KoXmlNS::draw, "fill");
128     if (fillStyle == "gradient") {
129         QBrush brush = KoOdfGraphicStyles::loadOdfGradientStyle(styleStack, context.stylesReader(), shapeSize);
130         const QGradient * gradient = brush.gradient();
131         if (gradient) {
132             d->gradient = KoFlake::cloneGradient(gradient);
133             d->matrix = brush.transform();
134 
135             //Gopalakrishna Bhat: If the brush has transparency then we ignore the draw:opacity property and use the brush transparency.
136             // Brush will have transparency if the svg:linearGradient stop point has stop-opacity property otherwise it is opaque
137             if (brush.isOpaque() && styleStack.hasProperty(KoXmlNS::draw, "opacity")) {
138                 QString opacityPercent = styleStack.property(KoXmlNS::draw, "opacity");
139                 if (! opacityPercent.isEmpty() && opacityPercent.right(1) == "%") {
140                     float opacity = qMin(opacityPercent.leftRef(opacityPercent.length() - 1).toDouble(), 100.0) / 100;
141                     QGradientStops stops;
142                     foreach(QGradientStop stop, d->gradient->stops()) {
143                         stop.second.setAlphaF(opacity);
144                         stops << stop;
145                     }
146                     d->gradient->setStops(stops);
147                 }
148             }
149 
150             return true;
151         }
152     }
153     return false;
154 }
155