1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _BGFX_TOOLS_GRADIENTTOOLS_HXX
25 #define _BGFX_TOOLS_GRADIENTTOOLS_HXX
26 
27 #include <basegfx/point/b2dpoint.hxx>
28 #include <basegfx/range/b2drange.hxx>
29 #include <basegfx/vector/b2dvector.hxx>
30 #include <basegfx/matrix/b2dhommatrix.hxx>
31 #include <basegfx/numeric/ftools.hxx>
32 
33 #include <vector>
34 #include <algorithm>
35 
36 namespace basegfx
37 {
38     /** Gradient definition as used in ODF 1.2
39 
40         This struct collects all data necessary for rendering ODF
41         1.2-compatible gradients. Use the createXXXODFGradientInfo()
42         methods below for initializing from ODF attributes.
43      */
44     class ODFGradientInfo
45     {
46     private:
47         /** transformation mapping from [0,1]^2 texture coordinate
48            space to [0,1]^2 shape coordinate space
49          */
50         B2DHomMatrix    maTextureTransform;
51 
52         /** transformation mapping from [0,1]^2 shape coordinate space
53            to [0,1]^2 texture coordinate space. This is the
54            transformation commonly used to create gradients from a
55            scanline rasterizer (put shape u/v coordinates into it, get
56            texture s/t coordinates out of it)
57          */
58         B2DHomMatrix    maBackTextureTransform;
59 
60         /** Aspect ratio of the gradient. Only used in drawinglayer
61            for generating nested gradient polygons currently. Already
62            catered for in the transformations above.
63          */
64         double          mfAspectRatio;
65 
66         /** Requested gradient steps to render. See the
67            implementations of the getXXXGradientAlpha() methods below,
68            the semantic differs slightly for the different gradient
69            types.
70          */
71         sal_uInt32      mnSteps;
72 
73     public:
ODFGradientInfo()74         ODFGradientInfo()
75         :   maTextureTransform(),
76             maBackTextureTransform(),
77             mfAspectRatio(1.0),
78             mnSteps(0)
79         {
80         }
81 
ODFGradientInfo(const B2DHomMatrix & rTextureTransform,double fAspectRatio,sal_uInt32 nSteps)82         ODFGradientInfo(
83             const B2DHomMatrix& rTextureTransform,
84             double fAspectRatio,
85             sal_uInt32 nSteps)
86         :   maTextureTransform(rTextureTransform),
87             maBackTextureTransform(),
88             mfAspectRatio(fAspectRatio),
89             mnSteps(nSteps)
90         {
91         }
92 
ODFGradientInfo(const ODFGradientInfo & rODFGradientInfo)93         ODFGradientInfo(const ODFGradientInfo& rODFGradientInfo)
94         :   maTextureTransform(rODFGradientInfo.getTextureTransform()),
95             maBackTextureTransform(rODFGradientInfo.maBackTextureTransform),
96             mfAspectRatio(rODFGradientInfo.getAspectRatio()),
97             mnSteps(rODFGradientInfo.getSteps())
98         {
99         }
100 
operator =(const ODFGradientInfo & rODFGradientInfo)101         ODFGradientInfo& operator=(const ODFGradientInfo& rODFGradientInfo)
102         {
103             maTextureTransform = rODFGradientInfo.getTextureTransform();
104             maBackTextureTransform = rODFGradientInfo.maBackTextureTransform;
105             mfAspectRatio = rODFGradientInfo.getAspectRatio();
106             mnSteps = rODFGradientInfo.getSteps();
107 
108             return *this;
109         }
110 
111         // compare operator
112         bool operator==(const ODFGradientInfo& rGeoTexSvx) const;
113 
getTextureTransform() const114         const B2DHomMatrix& getTextureTransform() const { return maTextureTransform; }
115         const B2DHomMatrix& getBackTextureTransform() const;
getAspectRatio() const116         double getAspectRatio() const { return mfAspectRatio; }
getSteps() const117         sal_uInt32 getSteps() const { return mnSteps; }
118 
setTextureTransform(const B2DHomMatrix & rNew)119         void setTextureTransform(const B2DHomMatrix& rNew)
120         {
121             maTextureTransform = rNew;
122             maBackTextureTransform.identity();
123         }
124     };
125 
126     namespace tools
127     {
128         /** Create matrix for ODF's linear gradient definition
129 
130             Note that odf linear gradients are varying in y direction.
131 
132             @param o_rGradientInfo
133             Receives the calculated texture transformation matrix (for
134             use with standard [0,1]x[0,1] texture coordinates)
135 
136             @param rTargetArea
137             Output area, needed for aspect ratio calculations and
138             texture transformation
139 
140             @param nSteps
141             Number of gradient steps (from ODF)
142 
143             @param fBorder
144             Width of gradient border (from ODF)
145 
146             @param fAngle
147             Gradient angle (from ODF)
148          */
149         ODFGradientInfo createLinearODFGradientInfo(
150             const B2DRange& rTargetArea,
151             sal_uInt32 nSteps,
152             double fBorder,
153             double fAngle);
154 
155         /** Calculate linear gradient blend value
156 
157             This method generates you the lerp alpha value for
158             blending linearly between gradient start and end color,
159             according to the formula (startCol*(1.0-alpha) + endCol*alpha)
160 
161             @param rUV
162             Current uv coordinate. Values outside [0,1] will be
163             clamped. Assumes gradient color varies along the y axis.
164 
165             @param rGradInfo
166             Gradient info, for transformation and number of steps
167          */
168         double getLinearGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo);
169 
170         /** Create matrix for ODF's axial gradient definition
171 
172             Note that odf axial gradients are varying in y
173             direction. Note further that you can map the axial
174             gradient to a linear gradient (in case you want or need to
175             avoid an extra gradient renderer), by using
176             createLinearODFGradientInfo() instead, shifting the
177             resulting texture transformation by 0.5 to the top and
178             appending the same stop colors again, but mirrored.
179 
180             @param o_rGradientInfo
181             Receives the calculated texture transformation matrix (for
182             use with standard [0,1]x[0,1] texture coordinates)
183 
184             @param rTargetArea
185             Output area, needed for aspect ratio calculations and
186             texture transformation
187 
188             @param nSteps
189             Number of gradient steps (from ODF)
190 
191             @param fBorder
192             Width of gradient border (from ODF)
193 
194             @param fAngle
195             Gradient angle (from ODF)
196          */
197         ODFGradientInfo createAxialODFGradientInfo(
198             const B2DRange& rTargetArea,
199             sal_uInt32 nSteps,
200             double fBorder,
201             double fAngle);
202 
203         /** Calculate axial gradient blend value
204 
205             This method generates you the lerp alpha value for
206             blending linearly between gradient start and end color,
207             according to the formula (startCol*(1.0-alpha) + endCol*alpha)
208 
209             @param rUV
210             Current uv coordinate. Values outside [0,1] will be
211             clamped. Assumes gradient color varies along the y axis.
212 
213             @param rGradInfo
214             Gradient info, for transformation and number of steps
215          */
216         double getAxialGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo);
217 
218         /** Create matrix for ODF's radial gradient definition
219 
220             @param o_rGradientInfo
221             Receives the calculated texture transformation matrix (for
222             use with standard [0,1]x[0,1] texture coordinates)
223 
224             @param rTargetArea
225             Output area, needed for aspect ratio calculations and
226             texture transformation
227 
228             @param rOffset
229             Gradient offset value (from ODF)
230 
231             @param nSteps
232             Number of gradient steps (from ODF)
233 
234             @param fBorder
235             Width of gradient border (from ODF)
236 
237             @param fAngle
238             Gradient angle (from ODF)
239          */
240         ODFGradientInfo createRadialODFGradientInfo(
241             const B2DRange& rTargetArea,
242             const B2DVector& rOffset,
243             sal_uInt32 nSteps,
244             double fBorder);
245 
246         /** Calculate radial gradient blend value
247 
248             This method generates you the lerp alpha value for
249             blending linearly between gradient start and end color,
250             according to the formula (startCol*(1.0-alpha) + endCol*alpha)
251 
252             @param rUV
253             Current uv coordinate. Values outside [0,1] will be
254             clamped.
255 
256             @param rGradInfo
257             Gradient info, for transformation and number of steps
258          */
259         double getRadialGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo);
260 
261         /** Create matrix for ODF's elliptical gradient definition
262 
263             @param o_rGradientInfo
264             Receives the calculated texture transformation matrix (for
265             use with standard [0,1]x[0,1] texture coordinates)
266 
267             @param rTargetArea
268             Output area, needed for aspect ratio calculations and
269             texture transformation
270 
271             @param rOffset
272             Gradient offset value (from ODF)
273 
274             @param nSteps
275             Number of gradient steps (from ODF)
276 
277             @param fBorder
278             Width of gradient border (from ODF)
279 
280             @param fAngle
281             Gradient angle (from ODF)
282          */
283         ODFGradientInfo createEllipticalODFGradientInfo(
284             const B2DRange& rTargetArea,
285             const B2DVector& rOffset,
286             sal_uInt32 nSteps,
287             double fBorder,
288             double fAngle);
289 
290         /** Calculate elliptical gradient blend value
291 
292             This method generates you the lerp alpha value for
293             blending linearly between gradient start and end color,
294             according to the formula (startCol*(1.0-alpha) + endCol*alpha)
295 
296             @param rUV
297             Current uv coordinate. Values outside [0,1] will be
298             clamped.
299 
300             @param rGradInfo
301             Gradient info, for transformation and number of steps
302          */
303         double getEllipticalGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo);
304 
305         /** Create matrix for ODF's square gradient definition
306 
307             @param o_rGradientInfo
308             Receives the calculated texture transformation matrix (for
309             use with standard [0,1]x[0,1] texture coordinates)
310 
311             @param rTargetArea
312             Output area, needed for aspect ratio calculations and
313             texture transformation
314 
315             @param rOffset
316             Gradient offset value (from ODF)
317 
318             @param nSteps
319             Number of gradient steps (from ODF)
320 
321             @param fBorder
322             Width of gradient border (from ODF)
323 
324             @param fAngle
325             Gradient angle (from ODF)
326          */
327         ODFGradientInfo createSquareODFGradientInfo(
328             const B2DRange& rTargetArea,
329             const B2DVector& rOffset,
330             sal_uInt32 nSteps,
331             double fBorder,
332             double fAngle);
333 
334         /** Calculate square gradient blend value
335 
336             This method generates you the lerp alpha value for
337             blending linearly between gradient start and end color,
338             according to the formula (startCol*(1.0-alpha) + endCol*alpha)
339 
340             @param rUV
341             Current uv coordinate. Values outside [0,1] will be
342             clamped.
343 
344             @param rGradInfo
345             Gradient info, for transformation and number of steps
346          */
347         double getSquareGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo);
348 
349         /** Create matrix for ODF's rectangular gradient definition
350 
351             @param o_rGradientInfo
352             Receives the calculated texture transformation matrix (for
353             use with standard [0,1]x[0,1] texture coordinates)
354 
355             @param rTargetArea
356             Output area, needed for aspect ratio calculations and
357             texture transformation
358 
359             @param rOffset
360             Gradient offset value (from ODF)
361 
362             @param nSteps
363             Number of gradient steps (from ODF)
364 
365             @param fBorder
366             Width of gradient border (from ODF)
367 
368             @param fAngle
369             Gradient angle (from ODF)
370          */
371         ODFGradientInfo createRectangularODFGradientInfo(
372             const B2DRange& rTargetArea,
373             const B2DVector& rOffset,
374             sal_uInt32 nSteps,
375             double fBorder,
376             double fAngle);
377 
378         /** Calculate rectangular gradient blend value
379 
380             This method generates you the lerp alpha value for
381             blending linearly between gradient start and end color,
382             according to the formula (startCol*(1.0-alpha) + endCol*alpha)
383 
384             @param rUV
385             Current uv coordinate. Values outside [0,1] will be
386             clamped.
387 
388             @param rGradInfo
389             Gradient info, for transformation and number of steps
390          */
391         double getRectangularGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo);
392     }
393 }
394 
395 #endif
396 
397 // eof
398