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>
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
,
48 o_rGradientInfo
.maTextureTransform
.identity();
49 o_rGradientInfo
.maBackTextureTransform
.identity();
50 o_rGradientInfo
.mnSteps
= nSteps
;
54 double fTargetSizeX(rTargetRange
.getWidth());
55 double fTargetSizeY(rTargetRange
.getHeight());
56 double fTargetOffsetX(rTargetRange
.getMinX());
57 double fTargetOffsetY(rTargetRange
.getMinY());
59 // add object expansion
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;
72 const double fSizeWithoutBorder
=1.0 - fBorder
;
75 o_rGradientInfo
.maTextureTransform
.scale(1.0, fSizeWithoutBorder
* .5);
76 o_rGradientInfo
.maTextureTransform
.translate(0.0, 0.5);
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
92 const B2DPoint
aCenter(0.5*fTargetSizeX
,
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
,
120 o_rGradientInfo
.maTextureTransform
.identity();
121 o_rGradientInfo
.maBackTextureTransform
.identity();
122 o_rGradientInfo
.mnSteps
= nSteps
;
126 double fTargetSizeX(rTargetRange
.getWidth());
127 double fTargetSizeY(rTargetRange
.getHeight());
128 double fTargetOffsetX(rTargetRange
.getMinX());
129 double fTargetOffsetY(rTargetRange
.getMinY());
131 // add object expansion
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
;
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
,
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
185 static void initRectGradientInfo(ODFGradientInfo
& o_rGradientInfo
,
186 const B2DRange
& rTargetRange
,
187 const B2DVector
& rOffset
,
192 o_rGradientInfo
.maTextureTransform
.identity();
193 o_rGradientInfo
.maBackTextureTransform
.identity();
194 o_rGradientInfo
.mnSteps
= nSteps
;
198 double fTargetSizeX(rTargetRange
.getWidth());
199 double fTargetSizeY(rTargetRange
.getHeight());
200 double fTargetOffsetX(rTargetRange
.getMinX());
201 double fTargetOffsetY(rTargetRange
.getMinY());
203 // add object expansion
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
225 const B2DPoint
aCenter(0.5*fTargetSizeX
,
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();
252 ODFGradientInfo
& createLinearODFGradientInfo(ODFGradientInfo
& o_rGradientInfo
,
253 const B2DRange
& rTargetArea
,
258 init1DGradientInfo(o_rGradientInfo
,
264 return o_rGradientInfo
;
267 ODFGradientInfo
& createAxialODFGradientInfo(ODFGradientInfo
& o_rGradientInfo
,
268 const B2DRange
& rTargetArea
,
273 init1DGradientInfo(o_rGradientInfo
,
279 return o_rGradientInfo
;
282 ODFGradientInfo
& createRadialODFGradientInfo(ODFGradientInfo
& o_rGradientInfo
,
283 const B2DRange
& rTargetArea
,
284 const B2DVector
& rOffset
,
288 initEllipticalGradientInfo(o_rGradientInfo
,
295 return o_rGradientInfo
;
298 ODFGradientInfo
& createEllipticalODFGradientInfo(ODFGradientInfo
& o_rGradientInfo
,
299 const B2DRange
& rTargetArea
,
300 const B2DVector
& rOffset
,
305 initEllipticalGradientInfo(o_rGradientInfo
,
312 return o_rGradientInfo
;
315 ODFGradientInfo
& createSquareODFGradientInfo(ODFGradientInfo
& o_rGradientInfo
,
316 const B2DRange
& rTargetArea
,
317 const B2DVector
& rOffset
,
322 initRectGradientInfo(o_rGradientInfo
,
328 return o_rGradientInfo
;
331 ODFGradientInfo
& createRectangularODFGradientInfo(ODFGradientInfo
& o_rGradientInfo
,
332 const B2DRange
& rTargetArea
,
333 const B2DVector
& rOffset
,
338 initRectGradientInfo(o_rGradientInfo
,
344 return o_rGradientInfo
;
349 } // namespace basegfx