1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <config_options.h>
23 #include <basegfx/point/b2dpoint.hxx>
24 #include <basegfx/vector/b2dvector.hxx>
25 #include <basegfx/matrix/b2dhommatrix.hxx>
26 #include <basegfx/color/bcolor.hxx>
28 #include <basegfx/basegfxdllapi.h>
30 #include <com/sun/star/awt/ColorStopSequence.hdl>
31 #include <basegfx/utils/bgradient.hxx>
32 #include <osl/endian.h>
34 namespace com
{ namespace sun
{ namespace star
{ namespace uno
{ class Any
; } } } }
35 namespace com
{ namespace sun
{ namespace star
{ namespace awt
{ struct Gradient2
; } } } }
36 namespace basegfx
{ class B2DRange
; }
40 /* Internal helper to convert ::Color from tools::color.hxx to BColor
41 without the need to link against tools library. Be on the
42 safe side by using the same union
44 struct ColorToBColorConverter
63 ColorToBColorConverter
GetRGBColor() const
68 ColorToBColorConverter(sal_uInt32 nColor
)
72 constexpr ColorToBColorConverter(sal_uInt8 nRed
, sal_uInt8 nGreen
, sal_uInt8 nBlue
)
73 : mValue(sal_uInt32(nBlue
) | (sal_uInt32(nGreen
) << 8) | (sal_uInt32(nRed
) << 16))
76 explicit ColorToBColorConverter(const basegfx::BColor
& rBColor
)
77 : ColorToBColorConverter(
78 sal_uInt8(std::lround(rBColor
.getRed() * 255.0)),
79 sal_uInt8(std::lround(rBColor
.getGreen() * 255.0)),
80 sal_uInt8(std::lround(rBColor
.getBlue() * 255.0)))
83 basegfx::BColor
getBColor() const
85 return basegfx::BColor(R
/ 255.0, G
/ 255.0, B
/ 255.0);
88 constexpr explicit operator sal_Int32() const
90 return sal_Int32(mValue
);
93 constexpr explicit operator sal_uInt32() const
102 /** Gradient definition as used in ODF 1.2
104 This struct collects all data necessary for rendering ODF
105 1.2-compatible gradients. Use the createXXXODFGradientInfo()
106 methods below for initializing from ODF attributes.
108 class UNLESS_MERGELIBS(BASEGFX_DLLPUBLIC
) ODFGradientInfo
111 /** transformation mapping from [0,1]^2 texture coordinate
112 space to [0,1]^2 shape coordinate space
114 B2DHomMatrix maTextureTransform
;
116 /** transformation mapping from [0,1]^2 shape coordinate space
117 to [0,1]^2 texture coordinate space. This is the
118 transformation commonly used to create gradients from a
119 scanline rasterizer (put shape u/v coordinates into it, get
120 texture s/t coordinates out of it)
122 B2DHomMatrix maBackTextureTransform
;
124 /** Aspect ratio of the gradient. Only used in drawinglayer
125 for generating nested gradient polygons currently. Already
126 catered for in the transformations above.
128 double mfAspectRatio
;
130 /** Requested gradient steps to render. See the
131 implementations of the getXXXGradientAlpha() methods below,
132 the semantic differs slightly for the different gradient
135 sal_uInt32 mnRequestedSteps
;
139 : mfAspectRatio(1.0),
145 B2DHomMatrix aTextureTransform
,
147 sal_uInt32 nRequestedSteps
)
148 : maTextureTransform(std::move(aTextureTransform
)),
149 mfAspectRatio(fAspectRatio
),
150 mnRequestedSteps(nRequestedSteps
)
154 ODFGradientInfo(const ODFGradientInfo
& rODFGradientInfo
)
155 : maTextureTransform(rODFGradientInfo
.getTextureTransform()),
156 maBackTextureTransform(rODFGradientInfo
.maBackTextureTransform
),
157 mfAspectRatio(rODFGradientInfo
.getAspectRatio()),
158 mnRequestedSteps(rODFGradientInfo
.getRequestedSteps())
162 ODFGradientInfo
& operator=(const ODFGradientInfo
& rODFGradientInfo
)
164 maTextureTransform
= rODFGradientInfo
.getTextureTransform();
165 maBackTextureTransform
= rODFGradientInfo
.maBackTextureTransform
;
166 mfAspectRatio
= rODFGradientInfo
.getAspectRatio();
167 mnRequestedSteps
= rODFGradientInfo
.getRequestedSteps();
173 bool operator==(const ODFGradientInfo
& rGeoTexSvx
) const;
175 const B2DHomMatrix
& getTextureTransform() const { return maTextureTransform
; }
176 const B2DHomMatrix
& getBackTextureTransform() const;
177 double getAspectRatio() const { return mfAspectRatio
; }
178 sal_uInt32
getRequestedSteps() const { return mnRequestedSteps
; }
180 void setTextureTransform(const B2DHomMatrix
& rNew
)
182 maTextureTransform
= rNew
;
183 maBackTextureTransform
.identity();
189 /* Tooling method to extract data from given BGradient
190 to ColorStops, doing some corrections, partially based
191 on given SingleColor.
192 This is used for export preparations in case these exports
193 do neither support Start/EndIntensity nor Border settings,
194 both will be eliminated if possible (see below).
195 The BGradient rGradient and BColorStops& rColorStops
196 are both return parameters and may be changed.
197 This will do quite some preparations for the gradient
199 - It will check for single color (resetting rSingleColor when
200 this is the case) and return with empty ColorStops
201 - It will blend ColorStops to Intensity if StartIntensity/
202 EndIntensity != 100 is set in BGradient, so applying
203 that value(s) to the gradient directly
204 - It will adapt to Border if Border != 0 is set at the
205 given BGradient, so applying that value to the gradient
208 BASEGFX_DLLPUBLIC
void prepareColorStops(
209 const basegfx::BGradient
& rGradient
,
210 BColorStops
& rColorStops
,
211 BColor
& rSingleColor
);
213 /* Tooling method to synchronize the given ColorStops.
214 The intention is that a color GradientStops and an
215 alpha/transparence GradientStops gets synchronized
217 For the corrections the single values for color and
218 alpha may be used, e.g. when ColorStops is given
219 and not empty, but AlphaStops is empty, it will get
220 synchronized so that it will have the same number and
221 offsets in AlphaStops as in ColorStops, but with
222 the given SingleAlpha as value.
223 At return it guarantees that both have the same
224 number of entries with the same StopOffsets, so
225 that synchronized pair of ColorStops can e.g. be used
226 to export a Gradient with defined/adapted alpha
227 being 'coupled' indirectly using the
228 'FillTransparenceGradient' method (at import time).
230 BASEGFX_DLLPUBLIC
void synchronizeColorStops(
231 BColorStops
& rColorStops
,
232 BColorStops
& rAlphaStops
,
233 const BColor
& rSingleColor
,
234 const BColor
& rSingleAlpha
);
236 /* Helper to calculate numberOfSteps needed to represent
237 gradient for the given two colors:
238 - to define only based on color distance, give 0 == nRequestedSteps
239 as wanted value, so color distance will be used
240 - if a wanted value of nRequestedSteps is given, it gets synched
241 against the maximum number of steps defined by the color
242 distance of the two colors
243 - a minimum result of 1 is returned which means a single
244 step -> no real gradient
246 BASEGFX_DLLPUBLIC sal_uInt32
calculateNumberOfSteps(
247 sal_uInt32 nRequestedSteps
,
248 const BColor
& rStart
,
251 /** Create matrix for ODF's linear gradient definition
253 Note that odf linear gradients are varying in y direction.
255 @param o_rGradientInfo
256 Receives the calculated texture transformation matrix (for
257 use with standard [0,1]x[0,1] texture coordinates)
260 Output area, needed for aspect ratio calculations and
261 texture transformation
263 @param nRequestedSteps
264 Number of gradient steps (from ODF)
267 Width of gradient border (from ODF)
270 Gradient angle (from ODF)
272 BASEGFX_DLLPUBLIC ODFGradientInfo
createLinearODFGradientInfo(
273 const B2DRange
& rTargetArea
,
274 sal_uInt32 nRequestedSteps
,
279 /** Calculate linear gradient blend value
281 This method generates you the lerp alpha value for
282 blending linearly between gradient start and end color,
283 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
286 Current uv coordinate. Values outside [0,1] will be
287 clamped. Assumes gradient color varies along the y axis.
290 Gradient info, for transformation and number of steps
292 BASEGFX_DLLPUBLIC
double getLinearGradientAlpha(const B2DPoint
& rUV
,
293 const ODFGradientInfo
& rGradInfo
);
295 /** Create matrix for ODF's axial gradient definition
297 Note that odf axial gradients are varying in y
298 direction. Note further that you can map the axial
299 gradient to a linear gradient (in case you want or need to
300 avoid an extra gradient renderer), by using
301 createLinearODFGradientInfo() instead, shifting the
302 resulting texture transformation by 0.5 to the top and
303 appending the same stop colors again, but mirrored.
305 @param o_rGradientInfo
306 Receives the calculated texture transformation matrix (for
307 use with standard [0,1]x[0,1] texture coordinates)
310 Output area, needed for aspect ratio calculations and
311 texture transformation
313 @param nRequestedSteps
314 Number of gradient steps (from ODF)
317 Width of gradient border (from ODF)
320 Gradient angle (from ODF)
322 BASEGFX_DLLPUBLIC ODFGradientInfo
createAxialODFGradientInfo(
323 const B2DRange
& rTargetArea
,
324 sal_uInt32 nRequestedSteps
,
329 /** Calculate axial gradient blend value
331 This method generates you the lerp alpha value for
332 blending linearly between gradient start and end color,
333 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
336 Current uv coordinate. Values outside [0,1] will be
337 clamped. Assumes gradient color varies along the y axis.
340 Gradient info, for transformation and number of steps
342 BASEGFX_DLLPUBLIC
double getAxialGradientAlpha(const B2DPoint
& rUV
,
343 const ODFGradientInfo
& rGradInfo
);
345 /** Create matrix for ODF's radial gradient definition
347 @param o_rGradientInfo
348 Receives the calculated texture transformation matrix (for
349 use with standard [0,1]x[0,1] texture coordinates)
352 Output area, needed for aspect ratio calculations and
353 texture transformation
356 Gradient offset value (from ODF)
358 @param nRequestedSteps
359 Number of gradient steps (from ODF)
362 Width of gradient border (from ODF)
365 Gradient angle (from ODF)
367 BASEGFX_DLLPUBLIC ODFGradientInfo
createRadialODFGradientInfo(
368 const B2DRange
& rTargetArea
,
369 const B2DVector
& rOffset
,
370 sal_uInt32 nRequestedSteps
,
374 /** Calculate radial gradient blend value
376 This method generates you the lerp alpha value for
377 blending linearly between gradient start and end color,
378 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
381 Current uv coordinate. Values outside [0,1] will be
385 Gradient info, for transformation and number of steps
387 BASEGFX_DLLPUBLIC
double getRadialGradientAlpha(const B2DPoint
& rUV
,
388 const ODFGradientInfo
& rGradInfo
);
390 /** Create matrix for ODF's elliptical gradient definition
392 @param o_rGradientInfo
393 Receives the calculated texture transformation matrix (for
394 use with standard [0,1]x[0,1] texture coordinates)
397 Output area, needed for aspect ratio calculations and
398 texture transformation
401 Gradient offset value (from ODF)
403 @param nRequestedSteps
404 Number of gradient steps (from ODF)
407 Width of gradient border (from ODF)
410 Gradient angle (from ODF)
412 BASEGFX_DLLPUBLIC ODFGradientInfo
createEllipticalODFGradientInfo(
413 const B2DRange
& rTargetArea
,
414 const B2DVector
& rOffset
,
415 sal_uInt32 nRequestedSteps
,
420 /** Calculate elliptical gradient blend value
422 This method generates you the lerp alpha value for
423 blending linearly between gradient start and end color,
424 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
427 Current uv coordinate. Values outside [0,1] will be
431 Gradient info, for transformation and number of steps
433 BASEGFX_DLLPUBLIC
double getEllipticalGradientAlpha(const B2DPoint
& rUV
,
434 const ODFGradientInfo
& rGradInfo
);
436 /** Create matrix for ODF's square gradient definition
438 @param o_rGradientInfo
439 Receives the calculated texture transformation matrix (for
440 use with standard [0,1]x[0,1] texture coordinates)
443 Output area, needed for aspect ratio calculations and
444 texture transformation
447 Gradient offset value (from ODF)
449 @param nRequestedSteps
450 Number of gradient steps (from ODF)
453 Width of gradient border (from ODF)
456 Gradient angle (from ODF)
458 BASEGFX_DLLPUBLIC ODFGradientInfo
createSquareODFGradientInfo(
459 const B2DRange
& rTargetArea
,
460 const B2DVector
& rOffset
,
461 sal_uInt32 nRequestedSteps
,
466 /** Calculate square gradient blend value
468 This method generates you the lerp alpha value for
469 blending linearly between gradient start and end color,
470 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
473 Current uv coordinate. Values outside [0,1] will be
477 Gradient info, for transformation and number of steps
479 BASEGFX_DLLPUBLIC
double getSquareGradientAlpha(const B2DPoint
& rUV
,
480 const ODFGradientInfo
& rGradInfo
);
482 /** Create matrix for ODF's rectangular gradient definition
484 @param o_rGradientInfo
485 Receives the calculated texture transformation matrix (for
486 use with standard [0,1]x[0,1] texture coordinates)
489 Output area, needed for aspect ratio calculations and
490 texture transformation
493 Gradient offset value (from ODF)
495 @param nRequestedSteps
496 Number of gradient steps (from ODF)
499 Width of gradient border (from ODF)
502 Gradient angle (from ODF)
504 BASEGFX_DLLPUBLIC ODFGradientInfo
createRectangularODFGradientInfo(
505 const B2DRange
& rTargetArea
,
506 const B2DVector
& rOffset
,
507 sal_uInt32 nRequestedSteps
,
512 /** Calculate rectangular gradient blend value
514 This method generates you the lerp alpha value for
515 blending linearly between gradient start and end color,
516 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
519 Current uv coordinate. Values outside [0,1] will be
523 Gradient info, for transformation and number of steps
525 BASEGFX_DLLPUBLIC
double getRectangularGradientAlpha(const B2DPoint
& rUV
,
526 const ODFGradientInfo
& rGradInfo
);
530 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */