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 : : #ifndef _BGFX_TOOLS_GRADIENTTOOLS_HXX
30 : : #define _BGFX_TOOLS_GRADIENTTOOLS_HXX
31 : :
32 : : #include <basegfx/point/b2dpoint.hxx>
33 : : #include <basegfx/range/b2drange.hxx>
34 : : #include <basegfx/vector/b2dvector.hxx>
35 : : #include <basegfx/matrix/b2dhommatrix.hxx>
36 : : #include <basegfx/numeric/ftools.hxx>
37 : : #include <basegfx/basegfxdllapi.h>
38 : :
39 : : #include <vector>
40 : : #include <algorithm>
41 : :
42 : : namespace basegfx
43 : : {
44 : : /** Gradient definition as used in ODF 1.2
45 : :
46 : : This struct collects all data necessary for rendering ODF
47 : : 1.2-compatible gradients. Use the createXXXODFGradientInfo()
48 : : methods below for initializing from ODF attributes.
49 : : */
50 [ + - ][ + - ]: 3170 : struct BASEGFX_DLLPUBLIC ODFGradientInfo
51 : : {
52 : : /** transformation mapping from [0,1]^2 texture coordinate
53 : : space to [0,1]^2 shape coordinate space
54 : : */
55 : : B2DHomMatrix maTextureTransform;
56 : :
57 : : /** transformation mapping from [0,1]^2 shape coordinate space
58 : : to [0,1]^2 texture coordinate space. This is the
59 : : transformation commonly used to create gradients from a
60 : : scanline rasterizer (put shape u/v coordinates into it, get
61 : : texture s/t coordinates out of it)
62 : : */
63 : : B2DHomMatrix maBackTextureTransform;
64 : :
65 : : /** Aspect ratio of the gradient. Only used in drawinglayer
66 : : for generating nested gradient polygons currently. Already
67 : : catered for in the transformations above.
68 : : */
69 : : double mfAspectRatio;
70 : :
71 : : /** Requested gradient steps to render. See the
72 : : implementations of the getXXXGradientAlpha() methods below,
73 : : the semantic differs slightly for the different gradient
74 : : types.
75 : : */
76 : : sal_uInt32 mnSteps;
77 : : };
78 : :
79 : : namespace tools
80 : : {
81 : : /** Create matrix for ODF's linear gradient definition
82 : :
83 : : Note that odf linear gradients are varying in y direction.
84 : :
85 : : @param o_rGradientInfo
86 : : Receives the calculated texture transformation matrix (for
87 : : use with standard [0,1]x[0,1] texture coordinates)
88 : :
89 : : @param rTargetArea
90 : : Output area, needed for aspect ratio calculations and
91 : : texture transformation
92 : :
93 : : @param nSteps
94 : : Number of gradient steps (from ODF)
95 : :
96 : : @param fBorder
97 : : Width of gradient border (from ODF)
98 : :
99 : : @param fAngle
100 : : Gradient angle (from ODF)
101 : : */
102 : : BASEGFX_DLLPUBLIC ODFGradientInfo& createLinearODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
103 : : const B2DRange& rTargetArea,
104 : : sal_uInt32 nSteps,
105 : : double fBorder,
106 : : double fAngle);
107 : :
108 : : /** Calculate linear gradient blend value
109 : :
110 : : This method generates you the lerp alpha value for
111 : : blending linearly between gradient start and end color,
112 : : according to the formula (startCol*(1.0-alpha) + endCol*alpha)
113 : :
114 : : @param rUV
115 : : Current uv coordinate. Values outside [0,1] will be
116 : : clamped. Assumes gradient color varies along the y axis.
117 : :
118 : : @param rGradInfo
119 : : Gradient info, for transformation and number of steps
120 : : */
121 : 68762 : inline double getLinearGradientAlpha(const B2DPoint& rUV,
122 : : const ODFGradientInfo& rGradInfo )
123 : : {
124 [ + - ]: 68762 : const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV);
125 : 68762 : const double t(clamp(aCoor.getY(), 0.0, 1.0));
126 : 68762 : const sal_uInt32 nSteps(rGradInfo.mnSteps);
127 : :
128 [ - + ][ + - ]: 68762 : if(nSteps > 2L && nSteps < 128L)
129 : 0 : return floor(t * nSteps) / double(nSteps + 1L);
130 : :
131 : 68762 : return t;
132 : : }
133 : :
134 : : /** Create matrix for ODF's axial gradient definition
135 : :
136 : : Note that odf axial gradients are varying in y
137 : : direction. Note further that you can map the axial
138 : : gradient to a linear gradient (in case you want or need to
139 : : avoid an extra gradient renderer), by using
140 : : createLinearODFGradientInfo() instead, shifting the
141 : : resulting texture transformation by 0.5 to the top and
142 : : appending the same stop colors again, but mirrored.
143 : :
144 : : @param o_rGradientInfo
145 : : Receives the calculated texture transformation matrix (for
146 : : use with standard [0,1]x[0,1] texture coordinates)
147 : :
148 : : @param rTargetArea
149 : : Output area, needed for aspect ratio calculations and
150 : : texture transformation
151 : :
152 : : @param nSteps
153 : : Number of gradient steps (from ODF)
154 : :
155 : : @param fBorder
156 : : Width of gradient border (from ODF)
157 : :
158 : : @param fAngle
159 : : Gradient angle (from ODF)
160 : : */
161 : : BASEGFX_DLLPUBLIC ODFGradientInfo& createAxialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
162 : : const B2DRange& rTargetArea,
163 : : sal_uInt32 nSteps,
164 : : double fBorder,
165 : : double fAngle);
166 : :
167 : : /** Calculate axial gradient blend value
168 : :
169 : : This method generates you the lerp alpha value for
170 : : blending linearly between gradient start and end color,
171 : : according to the formula (startCol*(1.0-alpha) + endCol*alpha)
172 : :
173 : : @param rUV
174 : : Current uv coordinate. Values outside [0,1] will be
175 : : clamped. Assumes gradient color varies along the y axis.
176 : :
177 : : @param rGradInfo
178 : : Gradient info, for transformation and number of steps
179 : : */
180 : 67774 : inline double getAxialGradientAlpha(const B2DPoint& rUV,
181 : : const ODFGradientInfo& rGradInfo )
182 : : {
183 [ + - ]: 67774 : const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV);
184 : 67774 : const double t(clamp(fabs(aCoor.getY()), 0.0, 1.0));
185 : 67774 : const sal_uInt32 nSteps(rGradInfo.mnSteps);
186 : 67774 : const double fInternalSteps((nSteps * 2L) - 1L);
187 : :
188 [ - + ][ + - ]: 67774 : if(nSteps > 2L && nSteps < 128L)
189 : 0 : return floor(((t * fInternalSteps) + 1.0) / 2.0) / double(nSteps - 1L);
190 : :
191 : 67774 : return t;
192 : : }
193 : :
194 : : /** Create matrix for ODF's radial gradient definition
195 : :
196 : : @param o_rGradientInfo
197 : : Receives the calculated texture transformation matrix (for
198 : : use with standard [0,1]x[0,1] texture coordinates)
199 : :
200 : : @param rTargetArea
201 : : Output area, needed for aspect ratio calculations and
202 : : texture transformation
203 : :
204 : : @param rOffset
205 : : Gradient offset value (from ODF)
206 : :
207 : : @param nSteps
208 : : Number of gradient steps (from ODF)
209 : :
210 : : @param fBorder
211 : : Width of gradient border (from ODF)
212 : :
213 : : @param fAngle
214 : : Gradient angle (from ODF)
215 : : */
216 : : BASEGFX_DLLPUBLIC ODFGradientInfo& createRadialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
217 : : const B2DRange& rTargetArea,
218 : : const B2DVector& rOffset,
219 : : sal_uInt32 nSteps,
220 : : double fBorder);
221 : :
222 : : /** Calculate radial gradient blend value
223 : :
224 : : This method generates you the lerp alpha value for
225 : : blending linearly between gradient start and end color,
226 : : according to the formula (startCol*(1.0-alpha) + endCol*alpha)
227 : :
228 : : @param rUV
229 : : Current uv coordinate. Values outside [0,1] will be
230 : : clamped.
231 : :
232 : : @param rGradInfo
233 : : Gradient info, for transformation and number of steps
234 : : */
235 : 0 : inline double getRadialGradientAlpha(const B2DPoint& rUV,
236 : : const ODFGradientInfo& rGradInfo )
237 : : {
238 [ # # ]: 0 : const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV);
239 : : const double fDist(
240 : 0 : clamp(aCoor.getX() * aCoor.getX() + aCoor.getY() * aCoor.getY(),
241 : : 0.0,
242 : 0 : 1.0));
243 : :
244 : 0 : const double t(1.0 - sqrt(fDist));
245 : 0 : const sal_uInt32 nSteps(rGradInfo.mnSteps);
246 : :
247 [ # # ][ # # ]: 0 : if(nSteps > 2L && nSteps < 128L)
248 : 0 : return floor(t * nSteps) / double(nSteps - 1L);
249 : :
250 : 0 : return t;
251 : : }
252 : :
253 : : /** Create matrix for ODF's elliptical gradient definition
254 : :
255 : : @param o_rGradientInfo
256 : : Receives the calculated texture transformation matrix (for
257 : : use with standard [0,1]x[0,1] texture coordinates)
258 : :
259 : : @param rTargetArea
260 : : Output area, needed for aspect ratio calculations and
261 : : texture transformation
262 : :
263 : : @param rOffset
264 : : Gradient offset value (from ODF)
265 : :
266 : : @param nSteps
267 : : Number of gradient steps (from ODF)
268 : :
269 : : @param fBorder
270 : : Width of gradient border (from ODF)
271 : :
272 : : @param fAngle
273 : : Gradient angle (from ODF)
274 : : */
275 : : BASEGFX_DLLPUBLIC ODFGradientInfo& createEllipticalODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
276 : : const B2DRange& rTargetArea,
277 : : const B2DVector& rOffset,
278 : : sal_uInt32 nSteps,
279 : : double fBorder,
280 : : double fAngle);
281 : :
282 : : /** Calculate elliptical gradient blend value
283 : :
284 : : This method generates you the lerp alpha value for
285 : : blending linearly between gradient start and end color,
286 : : according to the formula (startCol*(1.0-alpha) + endCol*alpha)
287 : :
288 : : @param rUV
289 : : Current uv coordinate. Values outside [0,1] will be
290 : : clamped.
291 : :
292 : : @param rGradInfo
293 : : Gradient info, for transformation and number of steps
294 : : */
295 : 0 : inline double getEllipticalGradientAlpha(const B2DPoint& rUV,
296 : : const ODFGradientInfo& rGradInfo )
297 : : {
298 : 0 : return getRadialGradientAlpha(rUV,rGradInfo); // only matrix setup differs
299 : : }
300 : :
301 : : /** Create matrix for ODF's square gradient definition
302 : :
303 : : @param o_rGradientInfo
304 : : Receives the calculated texture transformation matrix (for
305 : : use with standard [0,1]x[0,1] texture coordinates)
306 : :
307 : : @param rTargetArea
308 : : Output area, needed for aspect ratio calculations and
309 : : texture transformation
310 : :
311 : : @param rOffset
312 : : Gradient offset value (from ODF)
313 : :
314 : : @param nSteps
315 : : Number of gradient steps (from ODF)
316 : :
317 : : @param fBorder
318 : : Width of gradient border (from ODF)
319 : :
320 : : @param fAngle
321 : : Gradient angle (from ODF)
322 : : */
323 : : BASEGFX_DLLPUBLIC ODFGradientInfo& createSquareODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
324 : : const B2DRange& rTargetArea,
325 : : const B2DVector& rOffset,
326 : : sal_uInt32 nSteps,
327 : : double fBorder,
328 : : double fAngle);
329 : :
330 : : /** Calculate square gradient blend value
331 : :
332 : : This method generates you the lerp alpha value for
333 : : blending linearly between gradient start and end color,
334 : : according to the formula (startCol*(1.0-alpha) + endCol*alpha)
335 : :
336 : : @param rUV
337 : : Current uv coordinate. Values outside [0,1] will be
338 : : clamped.
339 : :
340 : : @param rGradInfo
341 : : Gradient info, for transformation and number of steps
342 : : */
343 : 0 : inline double getSquareGradientAlpha(const B2DPoint& rUV,
344 : : const ODFGradientInfo& rGradInfo )
345 : : {
346 [ # # ]: 0 : const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV);
347 : 0 : const double fAbsX(fabs(aCoor.getX()));
348 : 0 : const double fAbsY(fabs(aCoor.getY()));
349 : :
350 [ # # ][ # # ]: 0 : if(fTools::moreOrEqual(fAbsX, 1.0) || fTools::moreOrEqual(fAbsY, 1.0))
[ # # ][ # # ]
[ # # ]
351 : 0 : return 0.0;
352 : :
353 [ # # ]: 0 : const double t(1.0 - (fAbsX > fAbsY ? fAbsX : fAbsY));
354 : 0 : const sal_uInt32 nSteps(rGradInfo.mnSteps);
355 : :
356 [ # # ][ # # ]: 0 : if(nSteps > 2L && nSteps < 128L)
357 : 0 : return floor(t * nSteps) / double(nSteps - 1L);
358 : :
359 : 0 : return t;
360 : : }
361 : :
362 : : /** Create matrix for ODF's rectangular gradient definition
363 : :
364 : : @param o_rGradientInfo
365 : : Receives the calculated texture transformation matrix (for
366 : : use with standard [0,1]x[0,1] texture coordinates)
367 : :
368 : : @param rTargetArea
369 : : Output area, needed for aspect ratio calculations and
370 : : texture transformation
371 : :
372 : : @param rOffset
373 : : Gradient offset value (from ODF)
374 : :
375 : : @param nSteps
376 : : Number of gradient steps (from ODF)
377 : :
378 : : @param fBorder
379 : : Width of gradient border (from ODF)
380 : :
381 : : @param fAngle
382 : : Gradient angle (from ODF)
383 : : */
384 : : BASEGFX_DLLPUBLIC ODFGradientInfo& createRectangularODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
385 : : const B2DRange& rTargetArea,
386 : : const B2DVector& rOffset,
387 : : sal_uInt32 nSteps,
388 : : double fBorder,
389 : : double fAngle);
390 : :
391 : : /** Calculate rectangular gradient blend value
392 : :
393 : : This method generates you the lerp alpha value for
394 : : blending linearly between gradient start and end color,
395 : : according to the formula (startCol*(1.0-alpha) + endCol*alpha)
396 : :
397 : : @param rUV
398 : : Current uv coordinate. Values outside [0,1] will be
399 : : clamped.
400 : :
401 : : @param rGradInfo
402 : : Gradient info, for transformation and number of steps
403 : : */
404 : 0 : inline double getRectangularGradientAlpha(const B2DPoint& rUV,
405 : : const ODFGradientInfo& rGradInfo )
406 : : {
407 : 0 : return getSquareGradientAlpha(rUV, rGradInfo); // only matrix setup differs
408 : : }
409 : : }
410 : : }
411 : :
412 : : #endif
413 : :
414 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|