Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <vclhelpergradient.hxx>
30 : : #include <basegfx/range/b2drange.hxx>
31 : : #include <vcl/outdev.hxx>
32 : : #include <basegfx/polygon/b2dpolygon.hxx>
33 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
34 : : #include <basegfx/polygon/b2dpolygontools.hxx>
35 : : #include <drawinglayer/texture/texture.hxx>
36 : :
37 : : //////////////////////////////////////////////////////////////////////////////
38 : : // support methods for vcl direct gradient renderering
39 : :
40 : : namespace drawinglayer
41 : : {
42 : : namespace
43 : : {
44 : 235 : sal_uInt32 impCalcGradientSteps(OutputDevice& rOutDev, sal_uInt32 nSteps, const basegfx::B2DRange& rRange, sal_uInt32 nMaxDist)
45 : : {
46 [ + - ]: 235 : if(nSteps == 0L)
47 : : {
48 [ + - ][ + - ]: 235 : const Size aSize(rOutDev.LogicToPixel(Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight()))));
[ + - ]
49 : 235 : nSteps = (aSize.getWidth() + aSize.getHeight()) >> 3L;
50 : : }
51 : :
52 [ - + ]: 235 : if(nSteps < 2L)
53 : : {
54 : 0 : nSteps = 2L;
55 : : }
56 : :
57 [ + + ]: 235 : if(nSteps > nMaxDist)
58 : : {
59 : 19 : nSteps = nMaxDist;
60 : : }
61 : :
62 : 235 : return nSteps;
63 : : }
64 : :
65 : 0 : void impDrawGradientToOutDevSimple(
66 : : OutputDevice& rOutDev,
67 : : const basegfx::B2DPolyPolygon& rTargetForm,
68 : : const ::std::vector< basegfx::B2DHomMatrix >& rMatrices,
69 : : const ::std::vector< basegfx::BColor >& rColors,
70 : : const basegfx::B2DPolygon& rUnitPolygon)
71 : : {
72 : 0 : rOutDev.SetLineColor();
73 : :
74 [ # # ]: 0 : for(sal_uInt32 a(0L); a < rColors.size(); a++)
75 : : {
76 : : // set correct color
77 [ # # ]: 0 : const basegfx::BColor aFillColor(rColors[a]);
78 [ # # ]: 0 : rOutDev.SetFillColor(Color(aFillColor));
79 : :
80 [ # # ]: 0 : if(a)
81 : : {
82 [ # # ]: 0 : if(a - 1L < static_cast< sal_uInt32 >(rMatrices.size()))
83 : : {
84 [ # # ]: 0 : basegfx::B2DPolygon aNewPoly(rUnitPolygon);
85 [ # # ][ # # ]: 0 : aNewPoly.transform(rMatrices[a - 1L]);
86 [ # # ][ # # ]: 0 : rOutDev.DrawPolygon(aNewPoly);
87 : : }
88 : : }
89 : : else
90 : : {
91 [ # # ]: 0 : rOutDev.DrawPolyPolygon(rTargetForm);
92 : : }
93 : 0 : }
94 : 0 : }
95 : :
96 : 235 : void impDrawGradientToOutDevComplex(
97 : : OutputDevice& rOutDev,
98 : : const basegfx::B2DPolyPolygon& rTargetForm,
99 : : const ::std::vector< basegfx::B2DHomMatrix >& rMatrices,
100 : : const ::std::vector< basegfx::BColor >& rColors,
101 : : const basegfx::B2DPolygon& rUnitPolygon)
102 : : {
103 [ + - ]: 235 : PolyPolygon aVclTargetForm(rTargetForm);
104 [ + - ]: 235 : ::std::vector< Polygon > aVclPolygons;
105 : : sal_uInt32 a;
106 : :
107 : : // remember and set to XOR
108 [ + - ]: 235 : rOutDev.SetLineColor();
109 [ + - ]: 235 : rOutDev.Push(PUSH_RASTEROP);
110 [ + - ]: 235 : rOutDev.SetRasterOp(ROP_XOR);
111 : :
112 : : // draw gradient PolyPolygons
113 [ + + ]: 12480 : for(a = 0L; a < rMatrices.size(); a++)
114 : : {
115 : : // create polygon and remember
116 [ + - ]: 12245 : basegfx::B2DPolygon aNewPoly(rUnitPolygon);
117 [ + - ][ + - ]: 12245 : aNewPoly.transform(rMatrices[a]);
118 [ + - ][ + - ]: 12245 : aVclPolygons.push_back(Polygon(aNewPoly));
[ + - ]
119 : :
120 : : // set correct color
121 [ + - ]: 12245 : if(rColors.size() > a)
122 : : {
123 [ + - ]: 12245 : const basegfx::BColor aFillColor(rColors[a]);
124 [ + - ]: 12245 : rOutDev.SetFillColor(Color(aFillColor));
125 : : }
126 : :
127 : : // create vcl PolyPolygon and draw it
128 [ + + ]: 12245 : if(a)
129 : : {
130 [ + - ][ + - ]: 12010 : PolyPolygon aVclPolyPoly(aVclPolygons[a - 1L]);
131 [ + - ][ + - ]: 12010 : aVclPolyPoly.Insert(aVclPolygons[a]);
132 [ + - ][ + - ]: 12010 : rOutDev.DrawPolyPolygon(aVclPolyPoly);
133 : : }
134 : : else
135 : : {
136 [ + - ]: 235 : PolyPolygon aVclPolyPoly(aVclTargetForm);
137 [ + - ][ + - ]: 235 : aVclPolyPoly.Insert(aVclPolygons[0L]);
138 [ + - ][ + - ]: 235 : rOutDev.DrawPolyPolygon(aVclPolyPoly);
139 : : }
140 [ + - ]: 12245 : }
141 : :
142 : : // draw last poly in last color
143 [ + - ]: 235 : if(!rColors.empty())
144 : : {
145 [ + - ]: 235 : const basegfx::BColor aFillColor(rColors[rColors.size() - 1L]);
146 [ + - ]: 235 : rOutDev.SetFillColor(Color(aFillColor));
147 [ + - ][ + - ]: 235 : rOutDev.DrawPolygon(aVclPolygons[aVclPolygons.size() - 1L]);
148 : : }
149 : :
150 : : // draw object form in black and go back to XOR
151 [ + - ]: 235 : rOutDev.SetFillColor(COL_BLACK);
152 [ + - ]: 235 : rOutDev.SetRasterOp(ROP_0);
153 [ + - ]: 235 : rOutDev.DrawPolyPolygon(aVclTargetForm);
154 [ + - ]: 235 : rOutDev.SetRasterOp(ROP_XOR);
155 : :
156 : : // draw gradient PolyPolygons again
157 [ + + ]: 12480 : for(a = 0L; a < rMatrices.size(); a++)
158 : : {
159 : : // set correct color
160 [ + - ]: 12245 : if(rColors.size() > a)
161 : : {
162 [ + - ]: 12245 : const basegfx::BColor aFillColor(rColors[a]);
163 [ + - ]: 12245 : rOutDev.SetFillColor(Color(aFillColor));
164 : : }
165 : :
166 : : // create vcl PolyPolygon and draw it
167 [ + + ]: 12245 : if(a)
168 : : {
169 [ + - ][ + - ]: 12010 : PolyPolygon aVclPolyPoly(aVclPolygons[a - 1L]);
170 [ + - ][ + - ]: 12010 : aVclPolyPoly.Insert(aVclPolygons[a]);
171 [ + - ][ + - ]: 12010 : rOutDev.DrawPolyPolygon(aVclPolyPoly);
172 : : }
173 : : else
174 : : {
175 [ + - ]: 235 : PolyPolygon aVclPolyPoly(aVclTargetForm);
176 [ + - ][ + - ]: 235 : aVclPolyPoly.Insert(aVclPolygons[0L]);
177 [ + - ][ + - ]: 235 : rOutDev.DrawPolyPolygon(aVclPolyPoly);
178 : : }
179 : : }
180 : :
181 : : // draw last poly in last color
182 [ + - ]: 235 : if(!rColors.empty())
183 : : {
184 [ + - ]: 235 : const basegfx::BColor aFillColor(rColors[rColors.size() - 1L]);
185 [ + - ]: 235 : rOutDev.SetFillColor(Color(aFillColor));
186 [ + - ][ + - ]: 235 : rOutDev.DrawPolygon(aVclPolygons[aVclPolygons.size() - 1L]);
187 : : }
188 : :
189 : : // reset drawmode
190 [ + - ][ + - ]: 235 : rOutDev.Pop();
191 : 235 : }
192 : : } // end of anonymous namespace
193 : : } // end of namespace drawinglayer
194 : :
195 : : namespace drawinglayer
196 : : {
197 : 235 : void impDrawGradientToOutDev(
198 : : OutputDevice& rOutDev,
199 : : const basegfx::B2DPolyPolygon& rTargetForm,
200 : : attribute::GradientStyle eGradientStyle,
201 : : sal_uInt32 nSteps,
202 : : const basegfx::BColor& rStart,
203 : : const basegfx::BColor& rEnd,
204 : : double fBorder, double fAngle, double fOffsetX, double fOffsetY, bool bSimple)
205 : : {
206 [ + - ]: 235 : const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(rTargetForm));
207 [ + - ]: 235 : ::std::vector< basegfx::B2DHomMatrix > aMatrices;
208 [ + - ]: 235 : ::std::vector< basegfx::BColor > aColors;
209 [ + - ]: 235 : basegfx::B2DPolygon aUnitPolygon;
210 : :
211 : : // make sure steps is not too high/low
212 [ + - ]: 235 : nSteps = impCalcGradientSteps(rOutDev, nSteps, aOutlineRange, sal_uInt32((rStart.getMaximumDistance(rEnd) * 127.5) + 0.5));
213 : :
214 : : // create geometries
215 [ + + - - : 235 : switch(eGradientStyle)
- - - ]
216 : : {
217 : : case attribute::GRADIENTSTYLE_LINEAR:
218 : : {
219 [ + - ]: 230 : texture::GeoTexSvxGradientLinear aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
220 [ + - ]: 230 : aGradient.appendTransformations(aMatrices);
221 [ + - ]: 230 : aGradient.appendColors(aColors);
222 [ + - ][ + - ]: 230 : aUnitPolygon = basegfx::tools::createUnitPolygon();
[ + - ]
223 [ + - ]: 230 : break;
224 : : }
225 : : case attribute::GRADIENTSTYLE_AXIAL:
226 : : {
227 [ + - ]: 5 : texture::GeoTexSvxGradientAxial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
228 [ + - ]: 5 : aGradient.appendTransformations(aMatrices);
229 [ + - ]: 5 : aGradient.appendColors(aColors);
230 [ + - ][ + - ]: 5 : aUnitPolygon = basegfx::tools::createPolygonFromRect(basegfx::B2DRange(-1, -1, 1, 1));
[ + - ][ + - ]
231 [ + - ]: 5 : break;
232 : : }
233 : : case attribute::GRADIENTSTYLE_RADIAL:
234 : : {
235 [ # # ]: 0 : texture::GeoTexSvxGradientRadial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetY);
236 [ # # ]: 0 : aGradient.appendTransformations(aMatrices);
237 [ # # ]: 0 : aGradient.appendColors(aColors);
238 [ # # ][ # # ]: 0 : aUnitPolygon = basegfx::tools::createPolygonFromCircle(basegfx::B2DPoint(0,0), 1);
[ # # ]
239 [ # # ]: 0 : break;
240 : : }
241 : : case attribute::GRADIENTSTYLE_ELLIPTICAL:
242 : : {
243 [ # # ]: 0 : texture::GeoTexSvxGradientElliptical aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
244 [ # # ]: 0 : aGradient.appendTransformations(aMatrices);
245 [ # # ]: 0 : aGradient.appendColors(aColors);
246 [ # # ][ # # ]: 0 : aUnitPolygon = basegfx::tools::createPolygonFromCircle(basegfx::B2DPoint(0,0), 1);
[ # # ]
247 [ # # ]: 0 : break;
248 : : }
249 : : case attribute::GRADIENTSTYLE_SQUARE:
250 : : {
251 [ # # ]: 0 : texture::GeoTexSvxGradientSquare aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
252 [ # # ]: 0 : aGradient.appendTransformations(aMatrices);
253 [ # # ]: 0 : aGradient.appendColors(aColors);
254 [ # # ][ # # ]: 0 : aUnitPolygon = basegfx::tools::createPolygonFromRect(basegfx::B2DRange(-1, -1, 1, 1));
[ # # ][ # # ]
255 [ # # ]: 0 : break;
256 : : }
257 : : case attribute::GRADIENTSTYLE_RECT:
258 : : {
259 [ # # ]: 0 : texture::GeoTexSvxGradientRect aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
260 [ # # ]: 0 : aGradient.appendTransformations(aMatrices);
261 [ # # ]: 0 : aGradient.appendColors(aColors);
262 [ # # ][ # # ]: 0 : aUnitPolygon = basegfx::tools::createPolygonFromRect(basegfx::B2DRange(-1, -1, 1, 1));
[ # # ][ # # ]
263 [ # # ]: 0 : break;
264 : : }
265 : : }
266 : :
267 : : // paint them with mask using the XOR method
268 [ + - ]: 235 : if(!aMatrices.empty())
269 : : {
270 [ - + ]: 235 : if(bSimple)
271 : : {
272 [ # # ]: 0 : impDrawGradientToOutDevSimple(rOutDev, rTargetForm, aMatrices, aColors, aUnitPolygon);
273 : : }
274 : : else
275 : : {
276 [ + - ]: 235 : impDrawGradientToOutDevComplex(rOutDev, rTargetForm, aMatrices, aColors, aUnitPolygon);
277 : : }
278 [ + - ]: 235 : }
279 : 235 : }
280 : : } // end of namespace drawinglayer
281 : :
282 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|