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>
29 #include <basegfx/utils/bgradient.hxx>
30 #include <osl/endian.h>
32 namespace basegfx
{ class B2DRange
; }
36 /* Internal helper to convert ::Color from tools::color.hxx to BColor
37 without the need to link against tools library. Be on the
38 safe side by using the same union
40 struct ColorToBColorConverter
59 ColorToBColorConverter
GetRGBColor() const
64 ColorToBColorConverter(sal_uInt32 nColor
)
68 constexpr ColorToBColorConverter(sal_uInt8 nRed
, sal_uInt8 nGreen
, sal_uInt8 nBlue
)
69 : mValue(sal_uInt32(nBlue
) | (sal_uInt32(nGreen
) << 8) | (sal_uInt32(nRed
) << 16))
72 explicit ColorToBColorConverter(const basegfx::BColor
& rBColor
)
73 : ColorToBColorConverter(
74 sal_uInt8(std::lround(rBColor
.getRed() * 255.0)),
75 sal_uInt8(std::lround(rBColor
.getGreen() * 255.0)),
76 sal_uInt8(std::lround(rBColor
.getBlue() * 255.0)))
79 basegfx::BColor
getBColor() const
81 return basegfx::BColor(R
/ 255.0, G
/ 255.0, B
/ 255.0);
84 constexpr explicit operator sal_Int32() const
86 return sal_Int32(mValue
);
89 constexpr explicit operator sal_uInt32() const
98 /** Gradient definition as used in ODF 1.2
100 This struct collects all data necessary for rendering ODF
101 1.2-compatible gradients. Use the createXXXODFGradientInfo()
102 methods below for initializing from ODF attributes.
104 class UNLESS_MERGELIBS(BASEGFX_DLLPUBLIC
) ODFGradientInfo
107 /** transformation mapping from [0,1]^2 texture coordinate
108 space to [0,1]^2 shape coordinate space
110 B2DHomMatrix maTextureTransform
;
112 /** transformation mapping from [0,1]^2 shape coordinate space
113 to [0,1]^2 texture coordinate space. This is the
114 transformation commonly used to create gradients from a
115 scanline rasterizer (put shape u/v coordinates into it, get
116 texture s/t coordinates out of it)
118 B2DHomMatrix maBackTextureTransform
;
120 /** Aspect ratio of the gradient. Only used in drawinglayer
121 for generating nested gradient polygons currently. Already
122 catered for in the transformations above.
124 double mfAspectRatio
;
126 /** Requested gradient steps to render. See the
127 implementations of the getXXXGradientAlpha() methods below,
128 the semantic differs slightly for the different gradient
131 sal_uInt32 mnRequestedSteps
;
135 : mfAspectRatio(1.0),
141 B2DHomMatrix aTextureTransform
,
143 sal_uInt32 nRequestedSteps
)
144 : maTextureTransform(std::move(aTextureTransform
)),
145 mfAspectRatio(fAspectRatio
),
146 mnRequestedSteps(nRequestedSteps
)
150 ODFGradientInfo(const ODFGradientInfo
& rODFGradientInfo
)
151 : maTextureTransform(rODFGradientInfo
.getTextureTransform()),
152 maBackTextureTransform(rODFGradientInfo
.maBackTextureTransform
),
153 mfAspectRatio(rODFGradientInfo
.getAspectRatio()),
154 mnRequestedSteps(rODFGradientInfo
.getRequestedSteps())
158 ODFGradientInfo
& operator=(const ODFGradientInfo
& rODFGradientInfo
)
160 maTextureTransform
= rODFGradientInfo
.getTextureTransform();
161 maBackTextureTransform
= rODFGradientInfo
.maBackTextureTransform
;
162 mfAspectRatio
= rODFGradientInfo
.getAspectRatio();
163 mnRequestedSteps
= rODFGradientInfo
.getRequestedSteps();
169 bool operator==(const ODFGradientInfo
& rGeoTexSvx
) const;
171 const B2DHomMatrix
& getTextureTransform() const { return maTextureTransform
; }
172 const B2DHomMatrix
& getBackTextureTransform() const;
173 double getAspectRatio() const { return mfAspectRatio
; }
174 sal_uInt32
getRequestedSteps() const { return mnRequestedSteps
; }
176 void setTextureTransform(const B2DHomMatrix
& rNew
)
178 maTextureTransform
= rNew
;
179 maBackTextureTransform
.identity();
185 /* Tooling method to extract data from given BGradient
186 to ColorStops, doing some corrections, partially based
187 on given SingleColor.
188 This is used for export preparations in case these exports
189 do neither support Start/EndIntensity nor Border settings,
190 both will be eliminated if possible (see below).
191 The BGradient rGradient and BColorStops& rColorStops
192 are both return parameters and may be changed.
193 This will do quite some preparations for the gradient
195 - It will check for single color (resetting rSingleColor when
196 this is the case) and return with empty ColorStops
197 - It will blend ColorStops to Intensity if StartIntensity/
198 EndIntensity != 100 is set in BGradient, so applying
199 that value(s) to the gradient directly
200 - It will adapt to Border if Border != 0 is set at the
201 given BGradient, so applying that value to the gradient
204 BASEGFX_DLLPUBLIC
void prepareColorStops(
205 const basegfx::BGradient
& rGradient
,
206 BColorStops
& rColorStops
,
207 BColor
& rSingleColor
);
209 /* Tooling method to synchronize the given ColorStops.
210 The intention is that a color GradientStops and an
211 alpha/transparence GradientStops gets synchronized
213 For the corrections the single values for color and
214 alpha may be used, e.g. when ColorStops is given
215 and not empty, but AlphaStops is empty, it will get
216 synchronized so that it will have the same number and
217 offsets in AlphaStops as in ColorStops, but with
218 the given SingleAlpha as value.
219 At return it guarantees that both have the same
220 number of entries with the same StopOffsets, so
221 that synchronized pair of ColorStops can e.g. be used
222 to export a Gradient with defined/adapted alpha
223 being 'coupled' indirectly using the
224 'FillTransparenceGradient' method (at import time).
226 BASEGFX_DLLPUBLIC
void synchronizeColorStops(
227 BColorStops
& rColorStops
,
228 BColorStops
& rAlphaStops
,
229 const BColor
& rSingleColor
,
230 const BColor
& rSingleAlpha
);
232 /* Helper to calculate numberOfSteps needed to represent
233 gradient for the given two colors:
234 - to define only based on color distance, give 0 == nRequestedSteps
235 as wanted value, so color distance will be used
236 - if a wanted value of nRequestedSteps is given, it gets synched
237 against the maximum number of steps defined by the color
238 distance of the two colors
239 - a minimum result of 1 is returned which means a single
240 step -> no real gradient
242 BASEGFX_DLLPUBLIC sal_uInt32
calculateNumberOfSteps(
243 sal_uInt32 nRequestedSteps
,
244 const BColor
& rStart
,
247 /** Create matrix for ODF's linear gradient definition
249 Note that odf linear gradients are varying in y direction.
251 @param o_rGradientInfo
252 Receives the calculated texture transformation matrix (for
253 use with standard [0,1]x[0,1] texture coordinates)
256 Output area, needed for aspect ratio calculations and
257 texture transformation
259 @param nRequestedSteps
260 Number of gradient steps (from ODF)
263 Width of gradient border (from ODF)
266 Gradient angle (from ODF)
268 BASEGFX_DLLPUBLIC ODFGradientInfo
createLinearODFGradientInfo(
269 const B2DRange
& rTargetArea
,
270 sal_uInt32 nRequestedSteps
,
275 /** Calculate linear gradient blend value
277 This method generates you the lerp alpha value for
278 blending linearly between gradient start and end color,
279 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
282 Current uv coordinate. Values outside [0,1] will be
283 clamped. Assumes gradient color varies along the y axis.
286 Gradient info, for transformation and number of steps
288 BASEGFX_DLLPUBLIC
double getLinearGradientAlpha(const B2DPoint
& rUV
,
289 const ODFGradientInfo
& rGradInfo
);
291 /** Create matrix for ODF's axial gradient definition
293 Note that odf axial gradients are varying in y
294 direction. Note further that you can map the axial
295 gradient to a linear gradient (in case you want or need to
296 avoid an extra gradient renderer), by using
297 createLinearODFGradientInfo() instead, shifting the
298 resulting texture transformation by 0.5 to the top and
299 appending the same stop colors again, but mirrored.
301 @param o_rGradientInfo
302 Receives the calculated texture transformation matrix (for
303 use with standard [0,1]x[0,1] texture coordinates)
306 Output area, needed for aspect ratio calculations and
307 texture transformation
309 @param nRequestedSteps
310 Number of gradient steps (from ODF)
313 Width of gradient border (from ODF)
316 Gradient angle (from ODF)
318 BASEGFX_DLLPUBLIC ODFGradientInfo
createAxialODFGradientInfo(
319 const B2DRange
& rTargetArea
,
320 sal_uInt32 nRequestedSteps
,
325 /** Calculate axial gradient blend value
327 This method generates you the lerp alpha value for
328 blending linearly between gradient start and end color,
329 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
332 Current uv coordinate. Values outside [0,1] will be
333 clamped. Assumes gradient color varies along the y axis.
336 Gradient info, for transformation and number of steps
338 BASEGFX_DLLPUBLIC
double getAxialGradientAlpha(const B2DPoint
& rUV
,
339 const ODFGradientInfo
& rGradInfo
);
341 /** Create matrix for ODF's radial gradient definition
343 @param o_rGradientInfo
344 Receives the calculated texture transformation matrix (for
345 use with standard [0,1]x[0,1] texture coordinates)
348 Output area, needed for aspect ratio calculations and
349 texture transformation
352 Gradient offset value (from ODF)
354 @param nRequestedSteps
355 Number of gradient steps (from ODF)
358 Width of gradient border (from ODF)
361 Gradient angle (from ODF)
363 BASEGFX_DLLPUBLIC ODFGradientInfo
createRadialODFGradientInfo(
364 const B2DRange
& rTargetArea
,
365 const B2DVector
& rOffset
,
366 sal_uInt32 nRequestedSteps
,
370 /** Calculate radial gradient blend value
372 This method generates you the lerp alpha value for
373 blending linearly between gradient start and end color,
374 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
377 Current uv coordinate. Values outside [0,1] will be
381 Gradient info, for transformation and number of steps
383 BASEGFX_DLLPUBLIC
double getRadialGradientAlpha(const B2DPoint
& rUV
,
384 const ODFGradientInfo
& rGradInfo
);
386 /** Create matrix for ODF's elliptical gradient definition
388 @param o_rGradientInfo
389 Receives the calculated texture transformation matrix (for
390 use with standard [0,1]x[0,1] texture coordinates)
393 Output area, needed for aspect ratio calculations and
394 texture transformation
397 Gradient offset value (from ODF)
399 @param nRequestedSteps
400 Number of gradient steps (from ODF)
403 Width of gradient border (from ODF)
406 Gradient angle (from ODF)
408 BASEGFX_DLLPUBLIC ODFGradientInfo
createEllipticalODFGradientInfo(
409 const B2DRange
& rTargetArea
,
410 const B2DVector
& rOffset
,
411 sal_uInt32 nRequestedSteps
,
416 /** Calculate elliptical gradient blend value
418 This method generates you the lerp alpha value for
419 blending linearly between gradient start and end color,
420 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
423 Current uv coordinate. Values outside [0,1] will be
427 Gradient info, for transformation and number of steps
429 BASEGFX_DLLPUBLIC
double getEllipticalGradientAlpha(const B2DPoint
& rUV
,
430 const ODFGradientInfo
& rGradInfo
);
432 /** Create matrix for ODF's square gradient definition
434 @param o_rGradientInfo
435 Receives the calculated texture transformation matrix (for
436 use with standard [0,1]x[0,1] texture coordinates)
439 Output area, needed for aspect ratio calculations and
440 texture transformation
443 Gradient offset value (from ODF)
445 @param nRequestedSteps
446 Number of gradient steps (from ODF)
449 Width of gradient border (from ODF)
452 Gradient angle (from ODF)
454 BASEGFX_DLLPUBLIC ODFGradientInfo
createSquareODFGradientInfo(
455 const B2DRange
& rTargetArea
,
456 const B2DVector
& rOffset
,
457 sal_uInt32 nRequestedSteps
,
462 /** Calculate square gradient blend value
464 This method generates you the lerp alpha value for
465 blending linearly between gradient start and end color,
466 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
469 Current uv coordinate. Values outside [0,1] will be
473 Gradient info, for transformation and number of steps
475 BASEGFX_DLLPUBLIC
double getSquareGradientAlpha(const B2DPoint
& rUV
,
476 const ODFGradientInfo
& rGradInfo
);
478 /** Create matrix for ODF's rectangular gradient definition
480 @param o_rGradientInfo
481 Receives the calculated texture transformation matrix (for
482 use with standard [0,1]x[0,1] texture coordinates)
485 Output area, needed for aspect ratio calculations and
486 texture transformation
489 Gradient offset value (from ODF)
491 @param nRequestedSteps
492 Number of gradient steps (from ODF)
495 Width of gradient border (from ODF)
498 Gradient angle (from ODF)
500 BASEGFX_DLLPUBLIC ODFGradientInfo
createRectangularODFGradientInfo(
501 const B2DRange
& rTargetArea
,
502 const B2DVector
& rOffset
,
503 sal_uInt32 nRequestedSteps
,
508 /** Calculate rectangular gradient blend value
510 This method generates you the lerp alpha value for
511 blending linearly between gradient start and end color,
512 according to the formula (startCol*(1.0-alpha) + endCol*alpha)
515 Current uv coordinate. Values outside [0,1] will be
519 Gradient info, for transformation and number of steps
521 BASEGFX_DLLPUBLIC
double getRectangularGradientAlpha(const B2DPoint
& rUV
,
522 const ODFGradientInfo
& rGradInfo
);
526 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */