LibreOffice Module basegfx (master) 1
bgradient.hxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 */
9
10#pragma once
11
12#include <config_options.h>
15#include <vector>
16#include <com/sun/star/awt/Gradient2.hpp>
17#include <com/sun/star/awt/GradientStyle.hpp>
18#include <tools/degree.hxx>
19#include <boost/property_tree/ptree_fwd.hpp>
20
21namespace com
22{
23namespace sun
24{
25namespace star
26{
27namespace uno
28{
29class Any;
30}
31}
32}
33}
34
35namespace basegfx
36{
37/* MCGR: Provide ColorStop definition
38
39 This is the needed combination of offset and color:
40
41 Offset is defined as:
42 - being in the range of [0.0 .. 1.0] (unit range)
43 - offsets outside are an error
44 - lowest/1st value equivalent to StartColor
45 - highest/last value equivalent to EndColor
46 - missing 0.0/1.0 entries are allowed
47 - at least one value (usually 0.0, StartColor) is required
48 - this allows to avoid massive testing in all places where
49 this data has to be accessed
50
51 Color is defined as:
52 - RGB with unit values [0.0 .. 1.0]
53
54 These definitions are packed in a std::vector<ColorStop> ColorStops,
55 see typedef below.
56 */
58{
59private:
60 // offset in the range of [0.0 .. 1.0]
62
63 // RGB color of ColorStop entry
65
66public:
67 // constructor - defaults are needed to have a default constructor
68 // e.g. for usage in std::vector::insert (even when only reducing)
69 // ensure [0.0 .. 1.0] range for mfStopOffset
70 BColorStop(double fStopOffset = 0.0, const BColor& rStopColor = BColor())
71 : mfStopOffset(fStopOffset)
72 , maStopColor(rStopColor)
73 {
74 // NOTE: I originally *corrected* mfStopOffset here by using
75 // mfStopOffset(std::max(0.0, std::min(fOffset, 1.0)))
76 // While that is formally correct, it moves an invalid
77 // entry to 0.0 or 1.0, thus creating additional wrong
78 // Start/EndColor entries. That may then 'overlay' the
79 // correct entry when corrections are applied to the
80 // vector of entries (see sortAndCorrectColorStops)
81 // which leads to getting the wanted Start/EndColor
82 // to be factically deleted, what is an error.
83 }
84
85 double getStopOffset() const { return mfStopOffset; }
86 const BColor& getStopColor() const { return maStopColor; }
87
88 // needed for std::sort
89 bool operator<(const BColorStop& rCandidate) const
90 {
91 return getStopOffset() < rCandidate.getStopOffset();
92 }
93
94 bool operator==(const BColorStop& rCandidate) const
95 {
96 return getStopOffset() == rCandidate.getStopOffset()
97 && getStopColor() == rCandidate.getStopColor();
98 }
99
100 bool operator!=(const BColorStop& rCandidate) const { return !(*this == rCandidate); }
101};
102
103/* MCGR: Provide ColorStops definition to the FillGradientAttribute
104
105 This array should be sorted ascending by offsets, from lowest to
106 highest. Since all the primitive data definition where it is used
107 is read-only, this can/will be guaranteed by forcing/checking this
108 in the constructor, see ::FillGradientAttribute
109 */
110class BASEGFX_DLLPUBLIC BColorStops final : public std::vector<BColorStop>
111{
112private:
113 void setColorStopSequence(const css::awt::ColorStopSequence& rColorStops);
114
115public:
116 explicit BColorStops()
117 : vector()
118 {
119 }
121 : vector(other)
122 {
123 }
124 BColorStops(BColorStops&& other) noexcept
125 : vector(std::move(other))
126 {
127 }
128 BColorStops(std::initializer_list<BColorStop> init)
129 : vector(init)
130 {
131 }
132 BColorStops(const_iterator first, const_iterator last)
133 : vector(first, last)
134 {
135 }
136 BColorStops(const css::awt::ColorStopSequence& rColorStops);
137
138 // needs true == rVal.has<css::awt::ColorStopSequence>()
139 BColorStops(const css::uno::Any& rVal);
140
141 // constructor with two colors to explicitly create a
142 // BColorStops for StartColor @0.0 & EndColor @1.0
143 BColorStops(const BColor& rStart, const BColor& rEnd);
144
146 {
147 vector::operator=(r);
148 return *this;
149 }
151 {
152 vector::operator=(std::move(r));
153 return *this;
154 }
155
156 // helper data struct to support buffering entries in
157 // gradient texture mapping, see usages for more info
159 {
164
166 : maColorStart()
167 , maColorEnd()
168 , mfOffsetStart(0.0)
169 , mfOffsetEnd(0.0)
170 {
171 }
172 };
173
174 /* Helper to grep the correct ColorStop out of
175 ColorStops and interpolate as needed for given
176 relative value in fPosition in the range of [0.0 .. 1.0].
177 It also takes care of evtl. given RequestedSteps.
178 */
179 BColor getInterpolatedBColor(double fPosition, sal_uInt32 nRequestedSteps,
180 BColorStopRange& rLastColorStopRange) const;
181
182 /* Tooling method that allows to replace the StartColor in a
183 vector of ColorStops. A vector in 'ordered state' is expected,
184 so you may use/have used sortAndCorrect.
185 This method is for convenience & backwards compatibility, please
186 think about handling multi-colored gradients directly.
187 */
188 void replaceStartColor(const BColor& rStart);
189
190 /* Tooling method that allows to replace the EndColor in a
191 vector of ColorStops. A vector in 'ordered state' is expected,
192 so you may use/have used sortAndCorrect.
193 This method is for convenience & backwards compatibility, please
194 think about handling multi-colored gradients directly.
195 */
196 void replaceEndColor(const BColor& rEnd);
197
198 /* Tooling method to linearly blend the Colors contained in
199 a given ColorStop vector against a given Color using the
200 given intensity values.
201 The intensity values fStartIntensity, fEndIntensity are
202 in the range of [0.0 .. 1.0] and describe how much the
203 blend is supposed to be done at the start color position
204 and the end color position respectively, where 0.0 means
205 to fully use the given BlendColor, 1.0 means to not change
206 the existing color in the ColorStop.
207 Every color entry in the given ColorStop is blended
208 relative to it's StopPosition, interpolating the
209 given intensities with the range [0.0 .. 1.0] to do so.
210 */
211 void blendToIntensity(double fStartIntensity, double fEndIntensity, const BColor& rBlendColor);
212
213 /* Tooling method to guarantee sort and correctness for
214 the given ColorStops vector.
215 A vector fulfilling these conditions is called to be
216 in 'ordered state'.
217
218 At return, the following conditions are guaranteed:
219 - contains no ColorStops with offset < 0.0 (will
220 be removed)
221 - contains no ColorStops with offset > 1.0 (will
222 be removed)
223 - ColorStops with identical offsets are now allowed
224 - will be sorted from lowest offset to highest
225
226 Some more notes:
227 - It can happen that the result is empty
228 - It is allowed to have consecutive entries with
229 the same color, this represents single-color
230 regions inside the gradient
231 - A entry with 0.0 is not required or forced, so
232 no 'StartColor' is technically required
233 - A entry with 1.0 is not required or forced, so
234 no 'EndColor' is technically required
235
236 All this is done in one run (sort + O(N)) without
237 creating a copy of the data in any form
238 */
239 void sortAndCorrect();
240
241 // check if we need last-ColorStop-correction. This returns true if the last
242 // two ColorStops have the same offset but different Colors. In that case the
243 // tessellation for gradients does have to create an extra ending/closing entry
244 bool checkPenultimate() const;
245
246 /* Tooling method to fill a awt::ColorStopSequence with
247 the data from the given ColorStops. This is used in
248 UNO API implementations.
249 */
250 css::awt::ColorStopSequence getAsColorStopSequence() const;
251
252 /* Tooling method to check if a ColorStop vector is defined
253 by a single color. It returns true if this is the case.
254 If true is returned, rSingleColor contains that single
255 color for convenience.
256 NOTE: If no ColorStop is defined, a fallback to BColor-default
257 (which is black) and true will be returned
258 */
259 bool isSingleColor(BColor& rSingleColor) const;
260
261 /* Tooling method to reverse ColorStops, including offsets.
262 When also mirroring offsets a valid sort keeps valid.
263 */
264 void reverseColorStops();
265
266 // createSpaceAtStart creates fOffset space at start by
267 // translating/scaling all entries to the right
268 void createSpaceAtStart(double fOffset);
269
270 // removeSpaceAtStart removes fOffset space from start by
271 // translating/scaling entries more or equal to fOffset
272 // to the left. Entries less than fOffset will be removed
273 void removeSpaceAtStart(double fOffset);
274
275 // try to detect if an empty/no-color-change area exists
276 // at the start and return offset to it. Returns 0.0 if not.
277 double detectPossibleOffsetAtStart() const;
278
279 // returns true if the color stops are symmetrical in color and offset, otherwise false.
280 bool isSymmetrical() const;
281 // assume that the color stops represent an Axial gradient
282 // and replace with gradient stops to represent the same
283 // gradient as linear gradient
284 void doApplyAxial();
285
286 // apply Steps as 'hard' color stops
287 void doApplySteps(sal_uInt16 nStepCount);
288};
289
291{
292private:
293 css::awt::GradientStyle eStyle;
294
295 // MCGS: ColorStops in the range [0.0 .. 1.0], including StartColor/EndColor
297
299 sal_uInt16 nBorder;
300 sal_uInt16 nOfsX;
301 sal_uInt16 nOfsY;
302 sal_uInt16 nIntensStart;
303 sal_uInt16 nIntensEnd;
304 sal_uInt16 nStepCount;
305
306 static std::string GradientStyleToString(css::awt::GradientStyle eStyle);
307 void setGradient2(const css::awt::Gradient2& rGradient2);
308
309public:
310 BGradient();
311 BGradient(const basegfx::BColorStops& rColorStops,
312 css::awt::GradientStyle eStyle = css::awt::GradientStyle_LINEAR,
313 Degree10 nAngle = 0_deg10, sal_uInt16 nXOfs = 50, sal_uInt16 nYOfs = 50,
314 sal_uInt16 nBorder = 0, sal_uInt16 nStartIntens = 100, sal_uInt16 nEndIntens = 100,
315 sal_uInt16 nSteps = 0);
316 BGradient(const css::awt::Gradient2& rGradient2);
317
318 // needs true == (rVal.has<css::awt::Gradient>() || rVal.has<css::awt::Gradient2>())
319 BGradient(const css::uno::Any& rVal);
320
321 bool operator==(const BGradient& rGradient) const;
322
323 void SetGradientStyle(css::awt::GradientStyle eNewStyle) { eStyle = eNewStyle; }
324 void SetColorStops(const basegfx::BColorStops& rSteps);
325 void SetAngle(Degree10 nNewAngle) { nAngle = nNewAngle; }
326 void SetBorder(sal_uInt16 nNewBorder) { nBorder = nNewBorder; }
327 void SetXOffset(sal_uInt16 nNewOffset) { nOfsX = nNewOffset; }
328 void SetYOffset(sal_uInt16 nNewOffset) { nOfsY = nNewOffset; }
329 void SetStartIntens(sal_uInt16 nNewIntens) { nIntensStart = nNewIntens; }
330 void SetEndIntens(sal_uInt16 nNewIntens) { nIntensEnd = nNewIntens; }
331 void SetSteps(sal_uInt16 nSteps) { nStepCount = nSteps; }
332
333 css::awt::GradientStyle GetGradientStyle() const { return eStyle; }
334 const basegfx::BColorStops& GetColorStops() const { return aColorStops; }
335 Degree10 GetAngle() const { return nAngle; }
336 sal_uInt16 GetBorder() const { return nBorder; }
337 sal_uInt16 GetXOffset() const { return nOfsX; }
338 sal_uInt16 GetYOffset() const { return nOfsY; }
339 sal_uInt16 GetStartIntens() const { return nIntensStart; }
340 sal_uInt16 GetEndIntens() const { return nIntensEnd; }
341 sal_uInt16 GetSteps() const { return nStepCount; }
342
343 boost::property_tree::ptree dumpAsJSON() const;
344 static BGradient fromJSON(std::u16string_view rJSON);
345
347 css::awt::Gradient2 getAsGradient2() const;
348
349 // Tooling to handle
350 // - border correction/integration
351 // - apply StartStopIntensity to color stops
352 // - convert type from 'axial' to linear
353 // - apply Steps as 'hard' color stops
354 void tryToRecreateBorder(basegfx::BColorStops* pAssociatedTransparencyStops = nullptr);
355 void tryToApplyBorder();
356 void tryToApplyStartEndIntensity();
357
358 // If a linear gradient is symmetrical it is converted to an axial gradient.
359 // Does nothing in other cases and for other gradient types.
360 void tryToConvertToAxial();
361 void tryToApplyAxial();
362 void tryToApplySteps();
363};
364}
365
366/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define BASEGFX_DLLPUBLIC
Definition: basegfxdllapi.h:35
FILE * init(int, char **)
bool operator<(const BColorStop &rCandidate) const
Definition: bgradient.hxx:89
BColorStop(double fStopOffset=0.0, const BColor &rStopColor=BColor())
Definition: bgradient.hxx:70
bool operator==(const BColorStop &rCandidate) const
Definition: bgradient.hxx:94
const BColor & getStopColor() const
Definition: bgradient.hxx:86
double getStopOffset() const
Definition: bgradient.hxx:85
bool operator!=(const BColorStop &rCandidate) const
Definition: bgradient.hxx:100
BColorStops(std::initializer_list< BColorStop > init)
Definition: bgradient.hxx:128
BColorStops(const BColorStops &other)
Definition: bgradient.hxx:120
BColorStops(BColorStops &&other) noexcept
Definition: bgradient.hxx:124
BColorStops & operator=(const BColorStops &r)
Definition: bgradient.hxx:145
BColorStops(const_iterator first, const_iterator last)
Definition: bgradient.hxx:132
BColorStops & operator=(BColorStops &&r) noexcept
Definition: bgradient.hxx:150
Base Color class with three double values.
Definition: bcolor.hxx:41
sal_uInt16 nStepCount
Definition: bgradient.hxx:304
sal_uInt16 GetBorder() const
Definition: bgradient.hxx:336
void SetGradientStyle(css::awt::GradientStyle eNewStyle)
Definition: bgradient.hxx:323
sal_uInt16 GetStartIntens() const
Definition: bgradient.hxx:339
sal_uInt16 nIntensStart
Definition: bgradient.hxx:302
sal_uInt16 GetSteps() const
Definition: bgradient.hxx:341
void SetEndIntens(sal_uInt16 nNewIntens)
Definition: bgradient.hxx:330
void SetYOffset(sal_uInt16 nNewOffset)
Definition: bgradient.hxx:328
void SetXOffset(sal_uInt16 nNewOffset)
Definition: bgradient.hxx:327
basegfx::BColorStops aColorStops
Definition: bgradient.hxx:296
sal_uInt16 GetXOffset() const
Definition: bgradient.hxx:337
sal_uInt16 nIntensEnd
Definition: bgradient.hxx:303
void SetSteps(sal_uInt16 nSteps)
Definition: bgradient.hxx:331
void SetBorder(sal_uInt16 nNewBorder)
Definition: bgradient.hxx:326
const basegfx::BColorStops & GetColorStops() const
Definition: bgradient.hxx:334
sal_uInt16 GetEndIntens() const
Definition: bgradient.hxx:340
Degree10 GetAngle() const
Definition: bgradient.hxx:335
sal_uInt16 nOfsY
Definition: bgradient.hxx:301
css::awt::GradientStyle eStyle
Definition: bgradient.hxx:293
css::awt::GradientStyle GetGradientStyle() const
Definition: bgradient.hxx:333
sal_uInt16 nBorder
Definition: bgradient.hxx:299
void SetStartIntens(sal_uInt16 nNewIntens)
Definition: bgradient.hxx:329
void SetAngle(Degree10 nNewAngle)
Definition: bgradient.hxx:325
sal_uInt16 GetYOffset() const
Definition: bgradient.hxx:338
sal_uInt16 nOfsX
Definition: bgradient.hxx:300
tools::Long const nBorder
constexpr OUStringLiteral first
constexpr OUStringLiteral last
bool operator==(const XclFontData &rLeft, const XclFontData &rRight)