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