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  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_SVGGRADIENTPRIMITIVE2D_HXX
21 #define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_SVGGRADIENTPRIMITIVE2D_HXX
22 
23 #include <drawinglayer/drawinglayerdllapi.h>
24 #include <drawinglayer/primitive2d/baseprimitive2d.hxx>
25 #include <basegfx/color/bcolor.hxx>
26 #include <basegfx/polygon/b2dpolypolygon.hxx>
27 #include <basegfx/matrix/b2dhommatrix.hxx>
28 #include <drawinglayer/primitive2d/primitivetools2d.hxx>
29 #include <vector>
30 
31 
32 // SvgGradientEntry class
33 
34 namespace drawinglayer
35 {
36     namespace primitive2d
37     {
38         /// a single GradientStop defining a color and opacity at a distance
39         class SvgGradientEntry
40         {
41         private:
42             double              mfOffset;
43             basegfx::BColor     maColor;
44             double              mfOpacity;
45 
46         public:
SvgGradientEntry(double fOffset,const basegfx::BColor & rColor,double fOpacity)47             SvgGradientEntry(double fOffset, const basegfx::BColor& rColor, double fOpacity)
48             :   mfOffset(fOffset),
49                 maColor(rColor),
50                 mfOpacity(fOpacity)
51             {
52             }
53 
getOffset() const54             double getOffset() const { return mfOffset; }
getColor() const55             const basegfx::BColor& getColor() const { return maColor; }
getOpacity() const56             double getOpacity() const { return mfOpacity; }
57 
operator ==(const SvgGradientEntry & rCompare) const58             bool operator==(const SvgGradientEntry& rCompare) const
59             {
60                 return (getOffset() == rCompare.getOffset()
61                     && getColor() == rCompare.getColor()
62                     && getOpacity() == rCompare.getOpacity());
63             }
64 
operator <(const SvgGradientEntry & rCompare) const65             bool operator<(const SvgGradientEntry& rCompare) const
66             {
67                 return getOffset() < rCompare.getOffset();
68             }
69         };
70 
71         typedef ::std::vector< SvgGradientEntry > SvgGradientEntryVector;
72 
73     } // end of namespace primitive2d
74 } // end of namespace drawinglayer
75 
76 
77 // SvgGradientHelper class
78 
79 namespace drawinglayer
80 {
81     namespace primitive2d
82     {
83         enum class SpreadMethod
84         {
85             Pad,
86             Reflect,
87             Repeat
88         };
89 
90         /*  helper for linear and radial gradient, both get derived from this
91             to share common definitions and functionality
92          **/
93         class SvgGradientHelper
94         {
95         private:
96             /// the extra gradient transform
97             basegfx::B2DHomMatrix       maGradientTransform;
98 
99             /// geometric definition, the geometry to be filled
100             basegfx::B2DPolyPolygon     maPolyPolygon;
101 
102             /// the gradient definition
103             SvgGradientEntryVector      maGradientEntries;
104 
105             /// start and/or center point
106             basegfx::B2DPoint           maStart;
107 
108             /// how to spread
109             SpreadMethod                maSpreadMethod;
110 
111             bool                        mbPreconditionsChecked : 1;
112             bool                        mbCreatesContent : 1;
113             bool                        mbSingleEntry : 1;
114             bool                        mbFullyOpaque : 1;
115 
116             // true = interpret in unit coordinate system -> object aspect ratio will scale result
117             // false = interpret in object coordinate system -> object aspect ratio will not scale result
118             // (related to SVG's gradientUnits (userSpaceOnUse|objectBoundingBox)
119             bool                        mbUseUnitCoordinates : 1;
120 
121         protected:
122             /// local helpers
123             void createSingleGradientEntryFill(Primitive2DContainer& rContainer) const;
124             virtual void createAtom(
125                 Primitive2DContainer& rTargetColor,
126                 Primitive2DContainer& rTargetOpacity,
127                 const SvgGradientEntry& rFrom,
128                 const SvgGradientEntry& rTo,
129                 sal_Int32 nOffset) const = 0;
130             double createRun(
131                 Primitive2DContainer& rTargetColor,
132                 Primitive2DContainer& rTargetOpacity,
133                 double fPos,
134                 double fMax,
135                 const SvgGradientEntryVector& rEntries,
136                 sal_Int32 nOffset) const;
137             virtual void checkPreconditions();
138             void createResult(
139                 Primitive2DContainer& rContainer,
140                 const Primitive2DContainer& rTargetColor,
141                 const Primitive2DContainer& rTargetOpacity,
142                 const basegfx::B2DHomMatrix& rUnitGradientToObject,
143                 bool bInvert = false) const;
getCreatesContent() const144             bool getCreatesContent() const { return mbCreatesContent; }
getSingleEntry() const145             bool getSingleEntry() const { return mbSingleEntry; }
setSingleEntry()146             void setSingleEntry() { mbSingleEntry = true; }
getPreconditionsChecked() const147             bool getPreconditionsChecked() const { return mbPreconditionsChecked; }
getFullyOpaque() const148             bool getFullyOpaque() const { return mbFullyOpaque; }
149 
150         public:
151             /// constructor
152             SvgGradientHelper(
153                 const basegfx::B2DHomMatrix& rGradientTransform,
154                 const basegfx::B2DPolyPolygon& rPolyPolygon,
155                 const SvgGradientEntryVector& rGradientEntries,
156                 const basegfx::B2DPoint& rStart,
157                 bool bUseUnitCoordinates,
158                 SpreadMethod aSpreadMethod);
159             virtual ~SvgGradientHelper();
160 
161             /// data read access
getGradientTransform() const162             const basegfx::B2DHomMatrix& getGradientTransform() const { return maGradientTransform; }
getPolyPolygon() const163             const basegfx::B2DPolyPolygon& getPolyPolygon() const { return maPolyPolygon; }
getGradientEntries() const164             const SvgGradientEntryVector& getGradientEntries() const { return maGradientEntries; }
getStart() const165             const basegfx::B2DPoint& getStart() const { return maStart; }
getUseUnitCoordinates() const166             bool getUseUnitCoordinates() const { return mbUseUnitCoordinates; }
getSpreadMethod() const167             SpreadMethod getSpreadMethod() const { return maSpreadMethod; }
168 
169             /// compare operator
170             bool operator==(const SvgGradientHelper& rSvgGradientHelper) const;
171         };
172     } // end of namespace primitive2d
173 } // end of namespace drawinglayer
174 
175 
176 // SvgLinearGradientPrimitive2D class
177 
178 namespace drawinglayer
179 {
180     namespace primitive2d
181     {
182         /// the basic linear gradient primitive
183         class DRAWINGLAYER_DLLPUBLIC SvgLinearGradientPrimitive2D final : public BufferedDecompositionPrimitive2D, public SvgGradientHelper
184         {
185         private:
186             /// the end point for linear gradient
187             basegfx::B2DPoint                       maEnd;
188 
189             /// local helpers
190             virtual void createAtom(
191                 Primitive2DContainer& rTargetColor,
192                 Primitive2DContainer& rTargetOpacity,
193                 const SvgGradientEntry& rFrom,
194                 const SvgGradientEntry& rTo,
195                 sal_Int32 nOffset) const override;
196             virtual void checkPreconditions() override;
197 
198             /// local decomposition.
199             virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
200 
201         public:
202             /// constructor
203             SvgLinearGradientPrimitive2D(
204                 const basegfx::B2DHomMatrix& rGradientTransform,
205                 const basegfx::B2DPolyPolygon& rPolyPolygon,
206                 const SvgGradientEntryVector& rGradientEntries,
207                 const basegfx::B2DPoint& rStart,
208                 const basegfx::B2DPoint& rEnd,
209                 bool bUseUnitCoordinates,
210                 SpreadMethod aSpreadMethod);
211             virtual ~SvgLinearGradientPrimitive2D() override;
212 
213             /// data read access
getEnd() const214             const basegfx::B2DPoint& getEnd() const { return maEnd; }
215 
216             /// compare operator
217             virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
218 
219             /// get range
220             virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override;
221 
222             /// provide unique ID
223             DeclPrimitive2DIDBlock()
224         };
225     } // end of namespace primitive2d
226 } // end of namespace drawinglayer
227 
228 
229 // SvgRadialGradientPrimitive2D class
230 
231 namespace drawinglayer
232 {
233     namespace primitive2d
234     {
235         /// the basic radial gradient primitive
236         class DRAWINGLAYER_DLLPUBLIC SvgRadialGradientPrimitive2D final : public BufferedDecompositionPrimitive2D, public SvgGradientHelper
237         {
238         private:
239             /// the geometric definition
240             double                                  mfRadius;
241 
242             /// Focal only used when focal is set at all, see constructors
243             basegfx::B2DPoint                       maFocal;
244             basegfx::B2DVector                      maFocalVector;
245             double                                  maFocalLength;
246 
247             // internal helper for case SpreadMethod::Reflect
248             SvgGradientEntryVector                  maMirroredGradientEntries;
249 
250             bool                                    mbFocalSet : 1;
251 
252             /// local helpers
253             const SvgGradientEntryVector& getMirroredGradientEntries() const;
254             void createMirroredGradientEntries();
255 
256             /// local helpers
257             virtual void createAtom(
258                 Primitive2DContainer& rTargetColor,
259                 Primitive2DContainer& rTargetOpacity,
260                 const SvgGradientEntry& rFrom,
261                 const SvgGradientEntry& rTo,
262                 sal_Int32 nOffset) const override;
263             virtual void checkPreconditions() override;
264 
265             /// local decomposition.
266             virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
267 
268         public:
269             /// constructor
270             SvgRadialGradientPrimitive2D(
271                 const basegfx::B2DHomMatrix& rGradientTransform,
272                 const basegfx::B2DPolyPolygon& rPolyPolygon,
273                 const SvgGradientEntryVector& rGradientEntries,
274                 const basegfx::B2DPoint& rStart,
275                 double fRadius,
276                 bool bUseUnitCoordinates,
277                 SpreadMethod aSpreadMethod,
278                 const basegfx::B2DPoint* pFocal);
279             virtual ~SvgRadialGradientPrimitive2D() override;
280 
281             /// data read access
getRadius() const282             double getRadius() const { return mfRadius; }
getFocal() const283             const basegfx::B2DPoint& getFocal() const { return maFocal; }
isFocalSet() const284             bool isFocalSet() const { return mbFocalSet; }
285 
286             /// compare operator
287             virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
288 
289             /// get range
290             virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override;
291 
292             /// provide unique ID
293             DeclPrimitive2DIDBlock()
294         };
295     } // end of namespace primitive2d
296 } // end of namespace drawinglayer
297 
298 
299 // SvgLinearAtomPrimitive2D class
300 
301 namespace drawinglayer
302 {
303     namespace primitive2d
304     {
305         /*  basic primitive for a single linear GradientRun in unit coordinates.
306             It's derived from DiscreteMetricDependentPrimitive2D to allow view-dependent
307             decompositions allowing reduced color steps
308          **/
309         class DRAWINGLAYER_DLLPUBLIC SvgLinearAtomPrimitive2D final : public DiscreteMetricDependentPrimitive2D
310         {
311         private:
312             /// the geometric definition in unit coordinates
313             basegfx::BColor             maColorA;
314             basegfx::BColor             maColorB;
315             double                      mfOffsetA;
316             double                      mfOffsetB;
317 
318             /// local decomposition.
319             virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
320 
321         public:
322             /// constructor
323             SvgLinearAtomPrimitive2D(
324                 const basegfx::BColor& aColorA, double fOffsetA,
325                 const basegfx::BColor& aColorB, double fOffsetB);
326 
327             /// data read access
getColorA() const328             const basegfx::BColor& getColorA() const { return maColorA; }
getColorB() const329             const basegfx::BColor& getColorB() const { return maColorB; }
getOffsetA() const330             double getOffsetA() const { return mfOffsetA; }
getOffsetB() const331             double getOffsetB() const { return mfOffsetB; }
332 
333             /// compare operator
334             virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
335 
336             /// provide unique ID
337             DeclPrimitive2DIDBlock()
338         };
339     } // end of namespace primitive2d
340 } // end of namespace drawinglayer
341 
342 
343 // SvgRadialAtomPrimitive2D class
344 
345 namespace drawinglayer
346 {
347     namespace primitive2d
348     {
349         /*  basic primitive for a single radial GradientRun in unit coordinates.
350             It's derived from DiscreteMetricDependentPrimitive2D to allow view-dependent
351             decompositions allowing reduced color steps
352          **/
353         class DRAWINGLAYER_DLLPUBLIC SvgRadialAtomPrimitive2D final : public DiscreteMetricDependentPrimitive2D
354         {
355         private:
356             /// the geometric definition in unit coordinates
357             basegfx::BColor             maColorA;
358             basegfx::BColor             maColorB;
359             double                      mfScaleA;
360             double                      mfScaleB;
361 
362             // helper to hold translation vectors when given (for focal)
363             struct VectorPair
364             {
365                 basegfx::B2DVector          maTranslateA;
366                 basegfx::B2DVector          maTranslateB;
367 
VectorPairdrawinglayer::primitive2d::SvgRadialAtomPrimitive2D::VectorPair368                 VectorPair(const basegfx::B2DVector& rTranslateA, const basegfx::B2DVector& rTranslateB)
369                 :   maTranslateA(rTranslateA),
370                     maTranslateB(rTranslateB)
371                 {
372                 }
373             };
374 
375             /// Only used when focal is set
376             std::unique_ptr<VectorPair> mpTranslate;
377 
378             /// local decomposition.
379             virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
380 
381         public:
382             /// constructor
383             SvgRadialAtomPrimitive2D(
384                 const basegfx::BColor& aColorA, double fScaleA, const basegfx::B2DVector& rTranslateA,
385                 const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB);
386             SvgRadialAtomPrimitive2D(
387                 const basegfx::BColor& aColorA, double fScaleA,
388                 const basegfx::BColor& aColorB, double fScaleB);
389             virtual ~SvgRadialAtomPrimitive2D() override;
390 
391             /// data read access
getColorA() const392             const basegfx::BColor& getColorA() const { return maColorA; }
getColorB() const393             const basegfx::BColor& getColorB() const { return maColorB; }
getScaleA() const394             double getScaleA() const { return mfScaleA; }
getScaleB() const395             double getScaleB() const { return mfScaleB; }
isTranslateSet() const396             bool isTranslateSet() const { return (nullptr != mpTranslate); }
getTranslateA() const397             basegfx::B2DVector getTranslateA() const { if(mpTranslate) return mpTranslate->maTranslateA; return basegfx::B2DVector(); }
getTranslateB() const398             basegfx::B2DVector getTranslateB() const { if(mpTranslate) return mpTranslate->maTranslateB; return basegfx::B2DVector(); }
399 
400             /// compare operator
401             virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
402 
403             /// provide unique ID
404             DeclPrimitive2DIDBlock()
405         };
406     } // end of namespace primitive2d
407 } // end of namespace drawinglayer
408 
409 
410 #endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_SVGGRADIENTPRIMITIVE2D_HXX
411 
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
413