merged tag ooo/OOO330_m14
[LibreOffice.git] / basegfx / source / tools / gradienttools.cxx
blob857b668da68eaa19071991e4274f6372e3cc51cd
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basegfx.hxx"
31 #include <basegfx/tools/gradienttools.hxx>
32 #include <basegfx/point/b2dpoint.hxx>
33 #include <basegfx/range/b2drange.hxx>
34 #include <basegfx/matrix/b2dhommatrixtools.hxx>
36 namespace basegfx
38 /** Most of the setup for linear & axial gradient is the same, except
39 for the border treatment. Factored out here.
41 static void init1DGradientInfo(ODFGradientInfo& o_rGradientInfo,
42 const B2DRange& rTargetRange,
43 sal_uInt32 nSteps,
44 double fBorder,
45 double fAngle,
46 bool bAxial)
48 o_rGradientInfo.maTextureTransform.identity();
49 o_rGradientInfo.maBackTextureTransform.identity();
50 o_rGradientInfo.mnSteps = nSteps;
52 fAngle = -fAngle;
54 double fTargetSizeX(rTargetRange.getWidth());
55 double fTargetSizeY(rTargetRange.getHeight());
56 double fTargetOffsetX(rTargetRange.getMinX());
57 double fTargetOffsetY(rTargetRange.getMinY());
59 // add object expansion
60 if(0.0 != fAngle)
62 const double fAbsCos(fabs(cos(fAngle)));
63 const double fAbsSin(fabs(sin(fAngle)));
64 const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
65 const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
66 fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
67 fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
68 fTargetSizeX = fNewX;
69 fTargetSizeY = fNewY;
72 const double fSizeWithoutBorder=1.0 - fBorder;
73 if( bAxial )
75 o_rGradientInfo.maTextureTransform.scale(1.0, fSizeWithoutBorder * .5);
76 o_rGradientInfo.maTextureTransform.translate(0.0, 0.5);
78 else
80 if(!fTools::equal(fSizeWithoutBorder, 1.0))
82 o_rGradientInfo.maTextureTransform.scale(1.0, fSizeWithoutBorder);
83 o_rGradientInfo.maTextureTransform.translate(0.0, fBorder);
87 o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
89 // add texture rotate after scale to keep perpendicular angles
90 if(0.0 != fAngle)
92 const B2DPoint aCenter(0.5*fTargetSizeX,
93 0.5*fTargetSizeY);
94 o_rGradientInfo.maTextureTransform *=
95 basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
98 // add object translate
99 o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
101 // prepare aspect for texture
102 o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
104 // build transform from u,v to [0.0 .. 1.0].
105 o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
106 o_rGradientInfo.maBackTextureTransform.invert();
109 /** Most of the setup for radial & ellipsoidal gradient is the same,
110 except for the border treatment. Factored out here.
112 static void initEllipticalGradientInfo(ODFGradientInfo& o_rGradientInfo,
113 const B2DRange& rTargetRange,
114 const B2DVector& rOffset,
115 sal_uInt32 nSteps,
116 double fBorder,
117 double fAngle,
118 bool bCircular)
120 o_rGradientInfo.maTextureTransform.identity();
121 o_rGradientInfo.maBackTextureTransform.identity();
122 o_rGradientInfo.mnSteps = nSteps;
124 fAngle = -fAngle;
126 double fTargetSizeX(rTargetRange.getWidth());
127 double fTargetSizeY(rTargetRange.getHeight());
128 double fTargetOffsetX(rTargetRange.getMinX());
129 double fTargetOffsetY(rTargetRange.getMinY());
131 // add object expansion
132 if( bCircular )
134 const double fOriginalDiag(sqrt((fTargetSizeX * fTargetSizeX) + (fTargetSizeY * fTargetSizeY)));
135 fTargetOffsetX -= (fOriginalDiag - fTargetSizeX) / 2.0;
136 fTargetOffsetY -= (fOriginalDiag - fTargetSizeY) / 2.0;
137 fTargetSizeX = fOriginalDiag;
138 fTargetSizeY = fOriginalDiag;
140 else
142 fTargetOffsetX -= (0.4142 / 2.0 ) * fTargetSizeX;
143 fTargetOffsetY -= (0.4142 / 2.0 ) * fTargetSizeY;
144 fTargetSizeX = 1.4142 * fTargetSizeX;
145 fTargetSizeY = 1.4142 * fTargetSizeY;
148 const double fHalfBorder((1.0 - fBorder) * 0.5);
149 o_rGradientInfo.maTextureTransform.scale(fHalfBorder, fHalfBorder);
151 o_rGradientInfo.maTextureTransform.translate(0.5, 0.5);
152 o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
154 // add texture rotate after scale to keep perpendicular angles
155 if( !bCircular && 0.0 != fAngle)
157 const B2DPoint aCenter(0.5*fTargetSizeX,
158 0.5*fTargetSizeY);
159 o_rGradientInfo.maTextureTransform *=
160 basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
163 // add defined offsets after rotation
164 if(0.5 != rOffset.getX() || 0.5 != rOffset.getY())
166 // use original target size
167 fTargetOffsetX += (rOffset.getX() - 0.5) * rTargetRange.getWidth();
168 fTargetOffsetY += (rOffset.getY() - 0.5) * rTargetRange.getHeight();
171 // add object translate
172 o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
174 // prepare aspect for texture
175 o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
177 // build transform from u,v to [0.0 .. 1.0].
178 o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
179 o_rGradientInfo.maBackTextureTransform.invert();
182 /** Setup for rect & square gradient is exactly the same. Factored out
183 here.
185 static void initRectGradientInfo(ODFGradientInfo& o_rGradientInfo,
186 const B2DRange& rTargetRange,
187 const B2DVector& rOffset,
188 sal_uInt32 nSteps,
189 double fBorder,
190 double fAngle)
192 o_rGradientInfo.maTextureTransform.identity();
193 o_rGradientInfo.maBackTextureTransform.identity();
194 o_rGradientInfo.mnSteps = nSteps;
196 fAngle = -fAngle;
198 double fTargetSizeX(rTargetRange.getWidth());
199 double fTargetSizeY(rTargetRange.getHeight());
200 double fTargetOffsetX(rTargetRange.getMinX());
201 double fTargetOffsetY(rTargetRange.getMinY());
203 // add object expansion
204 if(0.0 != fAngle)
206 const double fAbsCos(fabs(cos(fAngle)));
207 const double fAbsSin(fabs(sin(fAngle)));
208 const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
209 const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
210 fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
211 fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
212 fTargetSizeX = fNewX;
213 fTargetSizeY = fNewY;
216 const double fHalfBorder((1.0 - fBorder) * 0.5);
217 o_rGradientInfo.maTextureTransform.scale(fHalfBorder, fHalfBorder);
219 o_rGradientInfo.maTextureTransform.translate(0.5, 0.5);
220 o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
222 // add texture rotate after scale to keep perpendicular angles
223 if(0.0 != fAngle)
225 const B2DPoint aCenter(0.5*fTargetSizeX,
226 0.5*fTargetSizeY);
227 o_rGradientInfo.maTextureTransform *=
228 basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
231 // add defined offsets after rotation
232 if(0.5 != rOffset.getX() || 0.5 != rOffset.getY())
234 // use scaled target size
235 fTargetOffsetX += (rOffset.getX() - 0.5) * fTargetSizeX;
236 fTargetOffsetY += (rOffset.getY() - 0.5) * fTargetSizeY;
239 // add object translate
240 o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
242 // prepare aspect for texture
243 o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
245 // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform
246 o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
247 o_rGradientInfo.maBackTextureTransform.invert();
250 namespace tools
252 ODFGradientInfo& createLinearODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
253 const B2DRange& rTargetArea,
254 sal_uInt32 nSteps,
255 double fBorder,
256 double fAngle)
258 init1DGradientInfo(o_rGradientInfo,
259 rTargetArea,
260 nSteps,
261 fBorder,
262 fAngle,
263 false);
264 return o_rGradientInfo;
267 ODFGradientInfo& createAxialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
268 const B2DRange& rTargetArea,
269 sal_uInt32 nSteps,
270 double fBorder,
271 double fAngle)
273 init1DGradientInfo(o_rGradientInfo,
274 rTargetArea,
275 nSteps,
276 fBorder,
277 fAngle,
278 true);
279 return o_rGradientInfo;
282 ODFGradientInfo& createRadialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
283 const B2DRange& rTargetArea,
284 const B2DVector& rOffset,
285 sal_uInt32 nSteps,
286 double fBorder)
288 initEllipticalGradientInfo(o_rGradientInfo,
289 rTargetArea,
290 rOffset,
291 nSteps,
292 fBorder,
293 0.0,
294 true);
295 return o_rGradientInfo;
298 ODFGradientInfo& createEllipticalODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
299 const B2DRange& rTargetArea,
300 const B2DVector& rOffset,
301 sal_uInt32 nSteps,
302 double fBorder,
303 double fAngle)
305 initEllipticalGradientInfo(o_rGradientInfo,
306 rTargetArea,
307 rOffset,
308 nSteps,
309 fBorder,
310 fAngle,
311 false);
312 return o_rGradientInfo;
315 ODFGradientInfo& createSquareODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
316 const B2DRange& rTargetArea,
317 const B2DVector& rOffset,
318 sal_uInt32 nSteps,
319 double fBorder,
320 double fAngle)
322 initRectGradientInfo(o_rGradientInfo,
323 rTargetArea,
324 rOffset,
325 nSteps,
326 fBorder,
327 fAngle);
328 return o_rGradientInfo;
331 ODFGradientInfo& createRectangularODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
332 const B2DRange& rTargetArea,
333 const B2DVector& rOffset,
334 sal_uInt32 nSteps,
335 double fBorder,
336 double fAngle)
338 initRectGradientInfo(o_rGradientInfo,
339 rTargetArea,
340 rOffset,
341 nSteps,
342 fBorder,
343 fAngle);
344 return o_rGradientInfo;
347 } // namespace tools
349 } // namespace basegfx