LCOV - code coverage report
Current view: top level - libreoffice/drawinglayer/source/primitive2d - svggradientprimitive2d.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 389 0.0 %
Date: 2012-12-27 Functions: 0 34 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
      21             : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
      22             : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
      23             : #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
      24             : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
      25             : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      26             : #include <basegfx/polygon/b2dpolygontools.hxx>
      27             : #include <basegfx/polygon/b2dpolygon.hxx>
      28             : #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
      29             : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
      30             : #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
      31             : #include <drawinglayer/geometry/viewinformation2d.hxx>
      32             : 
      33             : //////////////////////////////////////////////////////////////////////////////
      34             : 
      35             : using namespace com::sun::star;
      36             : 
      37             : //////////////////////////////////////////////////////////////////////////////
      38             : 
      39             : namespace
      40             : {
      41           0 :     sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA, const basegfx::BColor& rColorB, double fDelta, double fDiscreteUnit)
      42             :     {
      43             :         // use color distance, assume to do every color step (full quality)
      44           0 :         sal_uInt32 nSteps(basegfx::fround(rColorA.getDistance(rColorB) * 255.0));
      45             : 
      46           0 :         if(nSteps)
      47             :         {
      48             :             // calc discrete length to change color all 1.5 disctete units (pixels)
      49           0 :             const sal_uInt32 nDistSteps(basegfx::fround(fDelta / (fDiscreteUnit * 1.5)));
      50             : 
      51           0 :             nSteps = std::min(nSteps, nDistSteps);
      52             :         }
      53             : 
      54             :         // roughly cut when too big or too small
      55           0 :         nSteps = std::min(nSteps, sal_uInt32(255));
      56           0 :         nSteps = std::max(nSteps, sal_uInt32(1));
      57             : 
      58           0 :         return nSteps;
      59             :     }
      60             : } // end of anonymous namespace
      61             : 
      62             : //////////////////////////////////////////////////////////////////////////////
      63             : 
      64             : namespace drawinglayer
      65             : {
      66             :     namespace primitive2d
      67             :     {
      68           0 :         Primitive2DSequence SvgGradientHelper::createSingleGradientEntryFill() const
      69             :         {
      70           0 :             const SvgGradientEntryVector& rEntries = getGradientEntries();
      71           0 :             const sal_uInt32 nCount(rEntries.size());
      72           0 :             Primitive2DSequence xRetval;
      73             : 
      74           0 :             if(nCount)
      75             :             {
      76           0 :                 const SvgGradientEntry& rSingleEntry = rEntries[nCount - 1];
      77           0 :                 const double fOpacity(rSingleEntry.getOpacity());
      78             : 
      79           0 :                 if(fOpacity > 0.0)
      80             :                 {
      81             :                     Primitive2DReference xRef(
      82             :                         new PolyPolygonColorPrimitive2D(
      83             :                             getPolyPolygon(),
      84           0 :                             rSingleEntry.getColor()));
      85             : 
      86           0 :                     if(fOpacity < 1.0)
      87             :                     {
      88           0 :                         const Primitive2DSequence aContent(&xRef, 1);
      89             : 
      90             :                         xRef = Primitive2DReference(
      91             :                             new UnifiedTransparencePrimitive2D(
      92             :                                 aContent,
      93           0 :                                 1.0 - fOpacity));
      94             :                     }
      95             : 
      96           0 :                     xRetval = Primitive2DSequence(&xRef, 1);
      97             :                 }
      98             :             }
      99             :             else
     100             :             {
     101             :                 OSL_ENSURE(false, "Single gradient entry construction without entry (!)");
     102             :             }
     103             : 
     104           0 :             return xRetval;
     105             :         }
     106             : 
     107           0 :         void SvgGradientHelper::checkPreconditions()
     108             :         {
     109           0 :             mbPreconditionsChecked = true;
     110           0 :             const SvgGradientEntryVector& rEntries = getGradientEntries();
     111             : 
     112           0 :             if(rEntries.empty())
     113             :             {
     114             :                 // no fill at all
     115             :             }
     116             :             else
     117             :             {
     118           0 :                 const sal_uInt32 nCount(rEntries.size());
     119             : 
     120           0 :                 if(1 == nCount)
     121             :                 {
     122             :                     // fill with single existing color
     123           0 :                     setSingleEntry();
     124             :                 }
     125             :                 else
     126             :                 {
     127             :                     // sort maGradientEntries when more than one
     128           0 :                     std::sort(maGradientEntries.begin(), maGradientEntries.end());
     129             : 
     130             :                     // gradient with at least two colors
     131           0 :                     bool bAllInvisible(true);
     132             : 
     133           0 :                     for(sal_uInt32 a(0); a < nCount; a++)
     134             :                     {
     135           0 :                         const SvgGradientEntry& rCandidate = rEntries[a];
     136             : 
     137           0 :                         if(basegfx::fTools::equalZero(rCandidate.getOpacity()))
     138             :                         {
     139             :                             // invisible
     140           0 :                             mbFullyOpaque = false;
     141             :                         }
     142           0 :                         else if(basegfx::fTools::equal(rCandidate.getOpacity(), 1.0))
     143             :                         {
     144             :                             // completely opaque
     145           0 :                             bAllInvisible = false;
     146             :                         }
     147             :                         else
     148             :                         {
     149             :                             // opacity
     150           0 :                             bAllInvisible = false;
     151           0 :                             mbFullyOpaque = false;
     152             :                         }
     153             :                     }
     154             : 
     155           0 :                     if(bAllInvisible)
     156             :                     {
     157             :                         // all invisible, nothing to do
     158             :                     }
     159             :                     else
     160             :                     {
     161           0 :                         const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
     162             : 
     163           0 :                         if(aPolyRange.isEmpty())
     164             :                         {
     165             :                             // no range to fill, nothing to do
     166             :                         }
     167             :                         else
     168             :                         {
     169           0 :                             const double fPolyWidth(aPolyRange.getWidth());
     170           0 :                             const double fPolyHeight(aPolyRange.getHeight());
     171             : 
     172           0 :                             if(basegfx::fTools::equalZero(fPolyWidth) || basegfx::fTools::equalZero(fPolyHeight))
     173             :                             {
     174             :                                 // no width/height to fill, nothing to do
     175             :                             }
     176             :                             else
     177             :                             {
     178           0 :                                 mbCreatesContent = true;
     179             :                             }
     180             :                         }
     181             :                     }
     182             :                 }
     183             :             }
     184           0 :         }
     185             : 
     186           0 :         double SvgGradientHelper::createRun(
     187             :             Primitive2DVector& rTargetColor,
     188             :             Primitive2DVector& rTargetOpacity,
     189             :             double fPos,
     190             :             double fMax,
     191             :             const SvgGradientEntryVector& rEntries,
     192             :             sal_Int32 nOffset) const
     193             :         {
     194           0 :             const sal_uInt32 nCount(rEntries.size());
     195             : 
     196           0 :             if(nCount)
     197             :             {
     198           0 :                 const SvgGradientEntry& rStart = rEntries[0];
     199           0 :                 const bool bCreateStartPad(fPos < 0.0 && Spread_pad == getSpreadMethod());
     200           0 :                 const bool bCreateStartFill(rStart.getOffset() > 0.0);
     201           0 :                 sal_uInt32 nIndex(0);
     202             : 
     203           0 :                 if(bCreateStartPad || bCreateStartFill)
     204             :                 {
     205           0 :                     const SvgGradientEntry aTemp(bCreateStartPad ? fPos : 0.0, rStart.getColor(), rStart.getOpacity());
     206             : 
     207           0 :                     createAtom(rTargetColor, rTargetOpacity, aTemp, rStart, nOffset);
     208           0 :                     fPos = rStart.getOffset();
     209             :                 }
     210             : 
     211           0 :                 while(fPos < 1.0 && nIndex + 1 < nCount)
     212             :                 {
     213           0 :                     const SvgGradientEntry& rCandidateA = rEntries[nIndex++];
     214           0 :                     const SvgGradientEntry& rCandidateB = rEntries[nIndex];
     215             : 
     216           0 :                     createAtom(rTargetColor, rTargetOpacity, rCandidateA, rCandidateB, nOffset);
     217           0 :                     fPos = rCandidateB.getOffset();
     218             :                 }
     219             : 
     220           0 :                 const SvgGradientEntry& rEnd = rEntries[nCount - 1];
     221           0 :                 const bool bCreateEndPad(fPos < fMax && Spread_pad == getSpreadMethod());
     222           0 :                 const bool bCreateEndFill(rEnd.getOffset() < 1.0);
     223             : 
     224           0 :                 if(bCreateEndPad || bCreateEndFill)
     225             :                 {
     226           0 :                     fPos = bCreateEndPad ? fMax : 1.0;
     227           0 :                     const SvgGradientEntry aTemp(fPos, rEnd.getColor(), rEnd.getOpacity());
     228             : 
     229           0 :                     createAtom(rTargetColor, rTargetOpacity, rEnd, aTemp, nOffset);
     230             :                 }
     231             :             }
     232             :             else
     233             :             {
     234             :                 OSL_ENSURE(false, "GradientAtom creation without ColorStops (!)");
     235           0 :                 fPos = fMax;
     236             :             }
     237             : 
     238           0 :             return fPos;
     239             :         }
     240             : 
     241           0 :         Primitive2DSequence SvgGradientHelper::createResult(
     242             :             const Primitive2DVector& rTargetColor,
     243             :             const Primitive2DVector& rTargetOpacity,
     244             :             const basegfx::B2DHomMatrix& rUnitGradientToObject,
     245             :             bool bInvert) const
     246             :         {
     247           0 :             Primitive2DSequence xRetval;
     248           0 :             const Primitive2DSequence aTargetColorEntries(Primitive2DVectorToPrimitive2DSequence(rTargetColor, bInvert));
     249           0 :             const Primitive2DSequence aTargetOpacityEntries(Primitive2DVectorToPrimitive2DSequence(rTargetOpacity, bInvert));
     250             : 
     251           0 :             if(aTargetColorEntries.hasElements())
     252             :             {
     253           0 :                 Primitive2DReference xRefContent;
     254             : 
     255           0 :                 if(aTargetOpacityEntries.hasElements())
     256             :                 {
     257             :                     const Primitive2DReference xRefOpacity = new TransparencePrimitive2D(
     258             :                         aTargetColorEntries,
     259           0 :                         aTargetOpacityEntries);
     260             : 
     261             :                     xRefContent = new TransformPrimitive2D(
     262             :                         rUnitGradientToObject,
     263           0 :                         Primitive2DSequence(&xRefOpacity, 1));
     264             :                 }
     265             :                 else
     266             :                 {
     267             :                     xRefContent = new TransformPrimitive2D(
     268             :                         rUnitGradientToObject,
     269           0 :                         aTargetColorEntries);
     270             :                 }
     271             : 
     272             :                 xRefContent = new MaskPrimitive2D(
     273             :                     getPolyPolygon(),
     274           0 :                     Primitive2DSequence(&xRefContent, 1));
     275             : 
     276           0 :                 xRetval = Primitive2DSequence(&xRefContent, 1);
     277             :             }
     278             : 
     279           0 :             return xRetval;
     280             :         }
     281             : 
     282           0 :         SvgGradientHelper::SvgGradientHelper(
     283             :             const basegfx::B2DPolyPolygon& rPolyPolygon,
     284             :             const SvgGradientEntryVector& rGradientEntries,
     285             :             const basegfx::B2DPoint& rStart,
     286             :             SpreadMethod aSpreadMethod)
     287             :         :   maPolyPolygon(rPolyPolygon),
     288             :             maGradientEntries(rGradientEntries),
     289             :             maStart(rStart),
     290             :             maSpreadMethod(aSpreadMethod),
     291             :             mbPreconditionsChecked(false),
     292             :             mbCreatesContent(false),
     293             :             mbSingleEntry(false),
     294           0 :             mbFullyOpaque(true)
     295             :         {
     296           0 :         }
     297             : 
     298           0 :         bool SvgGradientHelper::equalTo(const SvgGradientHelper& rSvgGradientHelper) const
     299             :         {
     300           0 :             const SvgGradientHelper& rCompare = static_cast< const SvgGradientHelper& >(rSvgGradientHelper);
     301             : 
     302           0 :             return (getPolyPolygon() == rCompare.getPolyPolygon()
     303           0 :                 && getGradientEntries() == rCompare.getGradientEntries()
     304           0 :                 && getStart() == rCompare.getStart()
     305           0 :                 && getSpreadMethod() == rCompare.getSpreadMethod());
     306             :         }
     307             : 
     308             :     } // end of namespace primitive2d
     309             : } // end of namespace drawinglayer
     310             : 
     311             : //////////////////////////////////////////////////////////////////////////////
     312             : 
     313             : namespace drawinglayer
     314             : {
     315             :     namespace primitive2d
     316             :     {
     317           0 :         void SvgLinearGradientPrimitive2D::checkPreconditions()
     318             :         {
     319             :             // call parent
     320           0 :             SvgGradientHelper::checkPreconditions();
     321             : 
     322           0 :             if(getCreatesContent())
     323             :             {
     324             :                 // Check Vector
     325           0 :                 const basegfx::B2DVector aVector(getEnd() - getStart());
     326             : 
     327           0 :                 if(basegfx::fTools::equalZero(aVector.getX()) && basegfx::fTools::equalZero(aVector.getY()))
     328             :                 {
     329             :                     // fill with single color using last stop color
     330           0 :                     setSingleEntry();
     331           0 :                 }
     332             :             }
     333           0 :         }
     334             : 
     335           0 :         void SvgLinearGradientPrimitive2D::createAtom(
     336             :             Primitive2DVector& rTargetColor,
     337             :             Primitive2DVector& rTargetOpacity,
     338             :             const SvgGradientEntry& rFrom,
     339             :             const SvgGradientEntry& rTo,
     340             :             sal_Int32 nOffset) const
     341             :         {
     342             :             // create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset())
     343           0 :             if(rFrom.getOffset() == rTo.getOffset())
     344             :             {
     345             :                 OSL_ENSURE(false, "SvgGradient Atom creation with no step width (!)");
     346             :             }
     347             :             else
     348             :             {
     349             :                 rTargetColor.push_back(
     350             :                     new SvgLinearAtomPrimitive2D(
     351           0 :                         rFrom.getColor(), rFrom.getOffset() + nOffset,
     352           0 :                         rTo.getColor(), rTo.getOffset() + nOffset));
     353             : 
     354           0 :                 const double fTransFrom(1.0 - rFrom.getOpacity());
     355           0 :                 const double fTransTo(1.0 - rTo.getOpacity());
     356             : 
     357             :                 rTargetOpacity.push_back(
     358             :                     new SvgLinearAtomPrimitive2D(
     359           0 :                         basegfx::BColor(fTransFrom, fTransFrom, fTransFrom), rFrom.getOffset() + nOffset,
     360           0 :                         basegfx::BColor(fTransTo,fTransTo, fTransTo), rTo.getOffset() + nOffset));
     361             :             }
     362           0 :         }
     363             : 
     364           0 :         Primitive2DSequence SvgLinearGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
     365             :         {
     366           0 :             Primitive2DSequence xRetval;
     367             : 
     368           0 :             if(!getPreconditionsChecked())
     369             :             {
     370           0 :                 const_cast< SvgLinearGradientPrimitive2D* >(this)->checkPreconditions();
     371             :             }
     372             : 
     373           0 :             if(getSingleEntry())
     374             :             {
     375             :                 // fill with last existing color
     376           0 :                 xRetval = createSingleGradientEntryFill();
     377             :             }
     378           0 :             else if(getCreatesContent())
     379             :             {
     380             :                 // at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely
     381             :                 // invisible, width and height to fill are not empty
     382           0 :                 const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
     383           0 :                 const double fPolyWidth(aPolyRange.getWidth());
     384           0 :                 const double fPolyHeight(aPolyRange.getHeight());
     385             : 
     386             :                 // create ObjectTransform based on polygon range
     387             :                 const basegfx::B2DHomMatrix aObjectTransform(
     388             :                     basegfx::tools::createScaleTranslateB2DHomMatrix(
     389             :                         fPolyWidth, fPolyHeight,
     390           0 :                         aPolyRange.getMinX(), aPolyRange.getMinY()));
     391             : 
     392             :                 // create unit transform from unit vector [0.0 .. 1.0] along the X-Axis to given
     393             :                 // gradient vector defined by Start,End
     394           0 :                 const basegfx::B2DVector aVector(getEnd() - getStart());
     395           0 :                 const double fVectorLength(aVector.getLength());
     396           0 :                 basegfx::B2DHomMatrix aUnitGradientToGradient;
     397             : 
     398           0 :                 aUnitGradientToGradient.scale(fVectorLength, 1.0);
     399           0 :                 aUnitGradientToGradient.rotate(atan2(aVector.getY(), aVector.getX()));
     400           0 :                 aUnitGradientToGradient.translate(getStart().getX(), getStart().getY());
     401             : 
     402             :                 // create full transform from unit gradient coordinates to object coordinates
     403             :                 // including the SvgGradient transformation
     404           0 :                 basegfx::B2DHomMatrix aUnitGradientToObject(aObjectTransform * aUnitGradientToGradient);
     405             : 
     406             :                 // create inverse from it
     407           0 :                 basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject);
     408           0 :                 aObjectToUnitGradient.invert();
     409             : 
     410             :                 // back-transform polygon to unit gradient coordinates and get
     411             :                 // UnitRage. This is the range the gradient has to cover
     412           0 :                 basegfx::B2DPolyPolygon aUnitPoly(getPolyPolygon());
     413           0 :                 aUnitPoly.transform(aObjectToUnitGradient);
     414           0 :                 const basegfx::B2DRange aUnitRange(aUnitPoly.getB2DRange());
     415             : 
     416             :                 // prepare result vectors
     417           0 :                 Primitive2DVector aTargetColor;
     418           0 :                 Primitive2DVector aTargetOpacity;
     419             : 
     420           0 :                 if(basegfx::fTools::more(aUnitRange.getWidth(), 0.0))
     421             :                 {
     422             :                     // add a pre-multiply to aUnitGradientToObject to allow
     423             :                     // multiplication of the polygon(xl, 0.0, xr, 1.0)
     424             :                     const basegfx::B2DHomMatrix aPreMultiply(
     425             :                         basegfx::tools::createScaleTranslateB2DHomMatrix(
     426           0 :                             1.0, aUnitRange.getHeight(), 0.0, aUnitRange.getMinY()));
     427           0 :                     aUnitGradientToObject = aUnitGradientToObject * aPreMultiply;
     428             : 
     429             :                     // create central run, may also already do all necessary when
     430             :                     // Spread_pad is set as SpreadMethod and/or the range is smaller
     431           0 :                     double fPos(createRun(aTargetColor, aTargetOpacity, aUnitRange.getMinX(), aUnitRange.getMaxX(), getGradientEntries(), 0));
     432             : 
     433           0 :                     if(fPos < aUnitRange.getMaxX())
     434             :                     {
     435             :                         // can only happen when SpreadMethod is Spread_reflect or Spread_repeat,
     436             :                         // else the start and end pads are already created and fPos == aUnitRange.getMaxX().
     437             :                         // Its possible to express the repeated linear gradient by adding the
     438             :                         // transformed central run. Crete it this way
     439           0 :                         Primitive2DSequence aTargetColorEntries(Primitive2DVectorToPrimitive2DSequence(aTargetColor));
     440           0 :                         Primitive2DSequence aTargetOpacityEntries(Primitive2DVectorToPrimitive2DSequence(aTargetOpacity));
     441           0 :                         aTargetColor.clear();
     442           0 :                         aTargetOpacity.clear();
     443             : 
     444           0 :                         if(aTargetColorEntries.hasElements())
     445             :                         {
     446             :                             // add original central run as group primitive
     447           0 :                             aTargetColor.push_back(new GroupPrimitive2D(aTargetColorEntries));
     448             : 
     449           0 :                             if(aTargetOpacityEntries.hasElements())
     450             :                             {
     451           0 :                                 aTargetOpacity.push_back(new GroupPrimitive2D(aTargetOpacityEntries));
     452             :                             }
     453             : 
     454             :                             // add negative runs
     455           0 :                             fPos = 0.0;
     456           0 :                             sal_Int32 nOffset(0);
     457             : 
     458           0 :                             while(fPos > aUnitRange.getMinX())
     459             :                             {
     460           0 :                                 fPos -= 1.0;
     461           0 :                                 nOffset++;
     462             : 
     463           0 :                                 basegfx::B2DHomMatrix aTransform;
     464           0 :                                 const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2));
     465             : 
     466           0 :                                 if(bMirror)
     467             :                                 {
     468           0 :                                     aTransform.scale(-1.0, 1.0);
     469           0 :                                     aTransform.translate(fPos + 1.0, 0.0);
     470             :                                 }
     471             :                                 else
     472             :                                 {
     473           0 :                                     aTransform.translate(fPos, 0.0);
     474             :                                 }
     475             : 
     476           0 :                                 aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries));
     477             : 
     478           0 :                                 if(aTargetOpacityEntries.hasElements())
     479             :                                 {
     480           0 :                                     aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries));
     481             :                                 }
     482           0 :                             }
     483             : 
     484             :                             // add positive runs
     485           0 :                             fPos = 1.0;
     486           0 :                             nOffset = 1;
     487             : 
     488           0 :                             while(fPos < aUnitRange.getMaxX())
     489             :                             {
     490           0 :                                 basegfx::B2DHomMatrix aTransform;
     491           0 :                                 const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2));
     492             : 
     493           0 :                                 if(bMirror)
     494             :                                 {
     495           0 :                                     aTransform.scale(-1.0, 1.0);
     496           0 :                                     aTransform.translate(fPos + 1.0, 0.0);
     497             :                                 }
     498             :                                 else
     499             :                                 {
     500           0 :                                     aTransform.translate(fPos, 0.0);
     501             :                                 }
     502             : 
     503           0 :                                 aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries));
     504             : 
     505           0 :                                 if(aTargetOpacityEntries.hasElements())
     506             :                                 {
     507           0 :                                     aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries));
     508             :                                 }
     509             : 
     510           0 :                                 fPos += 1.0;
     511           0 :                                 nOffset++;
     512           0 :                             }
     513           0 :                         }
     514           0 :                     }
     515             :                 }
     516             : 
     517           0 :                 xRetval = createResult(aTargetColor, aTargetOpacity, aUnitGradientToObject);
     518             :             }
     519             : 
     520           0 :             return xRetval;
     521             :         }
     522             : 
     523           0 :         SvgLinearGradientPrimitive2D::SvgLinearGradientPrimitive2D(
     524             :             const basegfx::B2DPolyPolygon& rPolyPolygon,
     525             :             const SvgGradientEntryVector& rGradientEntries,
     526             :             const basegfx::B2DPoint& rStart,
     527             :             const basegfx::B2DPoint& rEnd,
     528             :             SpreadMethod aSpreadMethod)
     529             :         :   BufferedDecompositionPrimitive2D(),
     530             :             SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod),
     531           0 :             maEnd(rEnd)
     532             :         {
     533           0 :         }
     534             : 
     535           0 :         bool SvgLinearGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
     536             :         {
     537           0 :             const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive);
     538             : 
     539           0 :             if(pSvgGradientHelper && SvgGradientHelper::equalTo(*pSvgGradientHelper))
     540             :             {
     541           0 :                 const SvgLinearGradientPrimitive2D& rCompare = static_cast< const SvgLinearGradientPrimitive2D& >(rPrimitive);
     542             : 
     543           0 :                 return (getEnd() == rCompare.getEnd());
     544             :             }
     545             : 
     546           0 :             return false;
     547             :         }
     548             : 
     549           0 :         basegfx::B2DRange SvgLinearGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
     550             :         {
     551             :             // return ObjectRange
     552           0 :             return getPolyPolygon().getB2DRange();
     553             :         }
     554             : 
     555             :         // provide unique ID
     556           0 :         ImplPrimitrive2DIDBlock(SvgLinearGradientPrimitive2D, PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D)
     557             : 
     558             :     } // end of namespace primitive2d
     559             : } // end of namespace drawinglayer
     560             : 
     561             : //////////////////////////////////////////////////////////////////////////////
     562             : 
     563             : namespace drawinglayer
     564             : {
     565             :     namespace primitive2d
     566             :     {
     567           0 :         void SvgRadialGradientPrimitive2D::checkPreconditions()
     568             :         {
     569             :             // call parent
     570           0 :             SvgGradientHelper::checkPreconditions();
     571             : 
     572           0 :             if(getCreatesContent())
     573             :             {
     574             :                 // Check Radius
     575           0 :                 if(basegfx::fTools::equalZero(getRadius()))
     576             :                 {
     577             :                     // fill with single color using last stop color
     578           0 :                     setSingleEntry();
     579             :                 }
     580             :             }
     581           0 :         }
     582             : 
     583           0 :         void SvgRadialGradientPrimitive2D::createAtom(
     584             :             Primitive2DVector& rTargetColor,
     585             :             Primitive2DVector& rTargetOpacity,
     586             :             const SvgGradientEntry& rFrom,
     587             :             const SvgGradientEntry& rTo,
     588             :             sal_Int32 nOffset) const
     589             :         {
     590             :             // create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset())
     591           0 :             if(rFrom.getOffset() == rTo.getOffset())
     592             :             {
     593             :                 OSL_ENSURE(false, "SvgGradient Atom creation with no step width (!)");
     594             :             }
     595             :             else
     596             :             {
     597           0 :                 const double fScaleFrom(rFrom.getOffset() + nOffset);
     598           0 :                 const double fScaleTo(rTo.getOffset() + nOffset);
     599             : 
     600           0 :                 if(isFocalSet())
     601             :                 {
     602           0 :                     const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
     603           0 :                     const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
     604             : 
     605             :                     rTargetColor.push_back(
     606             :                         new SvgRadialAtomPrimitive2D(
     607             :                             rFrom.getColor(), fScaleFrom, aTranslateFrom,
     608           0 :                             rTo.getColor(), fScaleTo, aTranslateTo));
     609             :                 }
     610             :                 else
     611             :                 {
     612             :                     rTargetColor.push_back(
     613             :                         new SvgRadialAtomPrimitive2D(
     614             :                             rFrom.getColor(), fScaleFrom,
     615           0 :                             rTo.getColor(), fScaleTo));
     616             :                 }
     617             : 
     618           0 :                 const double fTransFrom(1.0 - rFrom.getOpacity());
     619           0 :                 const double fTransTo(1.0 - rTo.getOpacity());
     620           0 :                 const basegfx::BColor aColorFrom(fTransFrom, fTransFrom, fTransFrom);
     621           0 :                 const basegfx::BColor aColorTo(fTransTo, fTransTo, fTransTo);
     622             : 
     623           0 :                 if(isFocalSet())
     624             :                 {
     625           0 :                     const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
     626           0 :                     const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
     627             : 
     628             :                     rTargetOpacity.push_back(
     629             :                         new SvgRadialAtomPrimitive2D(
     630             :                             aColorFrom, fScaleFrom, aTranslateFrom,
     631           0 :                             aColorTo, fScaleTo, aTranslateTo));
     632             :                 }
     633             :                 else
     634             :                 {
     635             :                     rTargetOpacity.push_back(
     636             :                         new SvgRadialAtomPrimitive2D(
     637             :                             aColorFrom, fScaleFrom,
     638           0 :                             aColorTo, fScaleTo));
     639           0 :                 }
     640             :             }
     641           0 :         }
     642             : 
     643           0 :         const SvgGradientEntryVector& SvgRadialGradientPrimitive2D::getMirroredGradientEntries() const
     644             :         {
     645           0 :             if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
     646             :             {
     647           0 :                 const_cast< SvgRadialGradientPrimitive2D* >(this)->createMirroredGradientEntries();
     648             :             }
     649             : 
     650           0 :             return maMirroredGradientEntries;
     651             :         }
     652             : 
     653           0 :         void SvgRadialGradientPrimitive2D::createMirroredGradientEntries()
     654             :         {
     655           0 :             if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
     656             :             {
     657           0 :                 const sal_uInt32 nCount(getGradientEntries().size());
     658           0 :                 maMirroredGradientEntries.clear();
     659           0 :                 maMirroredGradientEntries.reserve(nCount);
     660             : 
     661           0 :                 for(sal_uInt32 a(0); a < nCount; a++)
     662             :                 {
     663           0 :                     const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a];
     664             : 
     665             :                     maMirroredGradientEntries.push_back(
     666             :                         SvgGradientEntry(
     667           0 :                             1.0 - rCandidate.getOffset(),
     668           0 :                             rCandidate.getColor(),
     669           0 :                             rCandidate.getOpacity()));
     670             :                 }
     671             :             }
     672           0 :         }
     673             : 
     674           0 :         Primitive2DSequence SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
     675             :         {
     676           0 :             Primitive2DSequence xRetval;
     677             : 
     678           0 :             if(!getPreconditionsChecked())
     679             :             {
     680           0 :                 const_cast< SvgRadialGradientPrimitive2D* >(this)->checkPreconditions();
     681             :             }
     682             : 
     683           0 :             if(getSingleEntry())
     684             :             {
     685             :                 // fill with last existing color
     686           0 :                 xRetval = createSingleGradientEntryFill();
     687             :             }
     688           0 :             else if(getCreatesContent())
     689             :             {
     690             :                 // at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely
     691             :                 // invisible, width and height to fill are not empty
     692           0 :                 const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
     693           0 :                 const double fPolyWidth(aPolyRange.getWidth());
     694           0 :                 const double fPolyHeight(aPolyRange.getHeight());
     695             : 
     696             :                 // create ObjectTransform based on polygon range
     697             :                 const basegfx::B2DHomMatrix aObjectTransform(
     698             :                     basegfx::tools::createScaleTranslateB2DHomMatrix(
     699             :                         fPolyWidth, fPolyHeight,
     700           0 :                         aPolyRange.getMinX(), aPolyRange.getMinY()));
     701             : 
     702             :                 // create unit transform from unit vector to given linear gradient vector
     703           0 :                 basegfx::B2DHomMatrix aUnitGradientToGradient;
     704             : 
     705           0 :                 aUnitGradientToGradient.scale(getRadius(), getRadius());
     706           0 :                 aUnitGradientToGradient.translate(getStart().getX(), getStart().getY());
     707             : 
     708             :                 // create full transform from unit gradient coordinates to object coordinates
     709             :                 // including the SvgGradient transformation
     710           0 :                 basegfx::B2DHomMatrix aUnitGradientToObject(aObjectTransform * aUnitGradientToGradient);
     711             : 
     712             :                 // create inverse from it
     713           0 :                 basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject);
     714           0 :                 aObjectToUnitGradient.invert();
     715             : 
     716             :                 // back-transform polygon to unit gradient coordinates and get
     717             :                 // UnitRage. This is the range the gradient has to cover
     718           0 :                 basegfx::B2DPolyPolygon aUnitPoly(getPolyPolygon());
     719           0 :                 aUnitPoly.transform(aObjectToUnitGradient);
     720           0 :                 const basegfx::B2DRange aUnitRange(aUnitPoly.getB2DRange());
     721             : 
     722             :                 // create range which the gradient has to cover to cover the whole given geometry.
     723             :                 // For circle, go from 0.0 to max radius in all directions (the corners)
     724           0 :                 double fMax(basegfx::B2DVector(aUnitRange.getMinimum()).getLength());
     725           0 :                 fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMaximum()).getLength());
     726           0 :                 fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMinX(), aUnitRange.getMaxY()).getLength());
     727           0 :                 fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMaxX(), aUnitRange.getMinY()).getLength());
     728             : 
     729             :                 // prepare result vectors
     730           0 :                 Primitive2DVector aTargetColor;
     731           0 :                 Primitive2DVector aTargetOpacity;
     732             : 
     733           0 :                 if(0.0 < fMax)
     734             :                 {
     735             :                     // prepare maFocalVector
     736           0 :                     if(isFocalSet())
     737             :                     {
     738           0 :                         const_cast< SvgRadialGradientPrimitive2D* >(this)->maFocalLength = fMax;
     739             :                     }
     740             : 
     741             :                     // create central run, may also already do all necessary when
     742             :                     // Spread_pad is set as SpreadMethod and/or the range is smaller
     743           0 :                     double fPos(createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), 0));
     744             : 
     745           0 :                     if(fPos < fMax)
     746             :                     {
     747             :                         // can only happen when SpreadMethod is Spread_reflect or Spread_repeat,
     748             :                         // else the start and end pads are already created and fPos == fMax.
     749             :                         // For radial there is no way to transform the already created
     750             :                         // central run, it needs to be created from 1.0 to fMax
     751           0 :                         sal_Int32 nOffset(1);
     752             : 
     753           0 :                         while(fPos < fMax)
     754             :                         {
     755           0 :                             const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2));
     756             : 
     757           0 :                             if(bMirror)
     758             :                             {
     759           0 :                                 createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getMirroredGradientEntries(), nOffset);
     760             :                             }
     761             :                             else
     762             :                             {
     763           0 :                                 createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), nOffset);
     764             :                             }
     765             : 
     766           0 :                             nOffset++;
     767           0 :                             fPos += 1.0;
     768             :                         }
     769             :                     }
     770             :                 }
     771             : 
     772           0 :                 xRetval = createResult(aTargetColor, aTargetOpacity, aUnitGradientToObject, true);
     773             :             }
     774             : 
     775           0 :             return xRetval;
     776             :         }
     777             : 
     778           0 :         SvgRadialGradientPrimitive2D::SvgRadialGradientPrimitive2D(
     779             :             const basegfx::B2DPolyPolygon& rPolyPolygon,
     780             :             const SvgGradientEntryVector& rGradientEntries,
     781             :             const basegfx::B2DPoint& rStart,
     782             :             double fRadius,
     783             :             SpreadMethod aSpreadMethod,
     784             :             const basegfx::B2DPoint* pFocal)
     785             :         :   BufferedDecompositionPrimitive2D(),
     786             :             SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod),
     787             :             mfRadius(fRadius),
     788             :             maFocal(rStart),
     789             :             maFocalVector(0.0, 0.0),
     790             :             maFocalLength(0.0),
     791             :             maMirroredGradientEntries(),
     792           0 :             mbFocalSet(false)
     793             :         {
     794           0 :             if(pFocal)
     795             :             {
     796           0 :                 maFocal = *pFocal;
     797           0 :                 maFocalVector = maFocal - getStart();
     798           0 :                 mbFocalSet = true;
     799             :             }
     800           0 :         }
     801             : 
     802           0 :         bool SvgRadialGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
     803             :         {
     804           0 :             const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive);
     805             : 
     806           0 :             if(pSvgGradientHelper && SvgGradientHelper::equalTo(*pSvgGradientHelper))
     807             :             {
     808           0 :                 const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive);
     809             : 
     810           0 :                 if(getRadius() == rCompare.getRadius())
     811             :                 {
     812           0 :                     if(isFocalSet() == rCompare.isFocalSet())
     813             :                     {
     814           0 :                         if(isFocalSet())
     815             :                         {
     816           0 :                             return getFocal() == rCompare.getFocal();
     817             :                         }
     818             :                         else
     819             :                         {
     820           0 :                             return true;
     821             :                         }
     822             :                     }
     823             :                 }
     824             :             }
     825             : 
     826           0 :             return false;
     827             :         }
     828             : 
     829           0 :         basegfx::B2DRange SvgRadialGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
     830             :         {
     831             :             // return ObjectRange
     832           0 :             return getPolyPolygon().getB2DRange();
     833             :         }
     834             : 
     835             :         // provide unique ID
     836           0 :         ImplPrimitrive2DIDBlock(SvgRadialGradientPrimitive2D, PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D)
     837             : 
     838             :     } // end of namespace primitive2d
     839             : } // end of namespace drawinglayer
     840             : 
     841             : //////////////////////////////////////////////////////////////////////////////
     842             : // SvgLinearAtomPrimitive2D class
     843             : 
     844             : namespace drawinglayer
     845             : {
     846             :     namespace primitive2d
     847             :     {
     848           0 :         Primitive2DSequence SvgLinearAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
     849             :         {
     850           0 :             Primitive2DSequence xRetval;
     851           0 :             const double fDelta(getOffsetB() - getOffsetA());
     852             : 
     853           0 :             if(!basegfx::fTools::equalZero(fDelta))
     854             :             {
     855             :                 // use one discrete unit for overlap (one pixel)
     856           0 :                 const double fDiscreteUnit(getDiscreteUnit());
     857             : 
     858             :                 // use color distance and discrete lengths to calculate step count
     859           0 :                 const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDelta, fDiscreteUnit));
     860             : 
     861             :                 // prepare loop and polygon (with overlap for linear gradients)
     862           0 :                 double fStart(0.0);
     863           0 :                 double fStep(fDelta / nSteps);
     864             :                 const basegfx::B2DPolygon aPolygon(
     865             :                     basegfx::tools::createPolygonFromRect(
     866             :                         basegfx::B2DRange(
     867           0 :                             getOffsetA() - fDiscreteUnit,
     868             :                             0.0,
     869           0 :                             getOffsetA() + fStep + fDiscreteUnit,
     870           0 :                             1.0)));
     871             : 
     872             :                 // loop and create primitives
     873           0 :                 xRetval.realloc(nSteps);
     874             : 
     875           0 :                 for(sal_uInt32 a(0); a < nSteps; a++, fStart += fStep)
     876             :                 {
     877           0 :                     basegfx::B2DPolygon aNew(aPolygon);
     878             : 
     879           0 :                     aNew.transform(basegfx::tools::createTranslateB2DHomMatrix(fStart, 0.0));
     880           0 :                     xRetval[a] = new PolyPolygonColorPrimitive2D(
     881             :                         basegfx::B2DPolyPolygon(aNew),
     882           0 :                         basegfx::interpolate(getColorA(), getColorB(), fStart/fDelta));
     883           0 :                 }
     884             :             }
     885             : 
     886           0 :             return xRetval;
     887             :         }
     888             : 
     889           0 :         SvgLinearAtomPrimitive2D::SvgLinearAtomPrimitive2D(
     890             :             const basegfx::BColor& aColorA, double fOffsetA,
     891             :             const basegfx::BColor& aColorB, double fOffsetB)
     892             :         :   DiscreteMetricDependentPrimitive2D(),
     893             :             maColorA(aColorA),
     894             :             maColorB(aColorB),
     895             :             mfOffsetA(fOffsetA),
     896           0 :             mfOffsetB(fOffsetB)
     897             :         {
     898           0 :             if(mfOffsetA > mfOffsetB)
     899             :             {
     900             :                 OSL_ENSURE(false, "Wrong offset order (!)");
     901           0 :                 ::std::swap(mfOffsetA, mfOffsetB);
     902             :             }
     903           0 :         }
     904             : 
     905           0 :         bool SvgLinearAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
     906             :         {
     907           0 :             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
     908             :             {
     909           0 :                 const SvgLinearAtomPrimitive2D& rCompare = static_cast< const SvgLinearAtomPrimitive2D& >(rPrimitive);
     910             : 
     911           0 :                 return (getColorA() == rCompare.getColorA()
     912           0 :                     && getColorB() == rCompare.getColorB()
     913           0 :                     && getOffsetA() == rCompare.getOffsetA()
     914           0 :                     && getOffsetB() == rCompare.getOffsetB());
     915             :             }
     916             : 
     917           0 :             return false;
     918             :         }
     919             : 
     920             :         // provide unique ID
     921           0 :         ImplPrimitrive2DIDBlock(SvgLinearAtomPrimitive2D, PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D)
     922             : 
     923             :     } // end of namespace primitive2d
     924             : } // end of namespace drawinglayer
     925             : 
     926             : //////////////////////////////////////////////////////////////////////////////
     927             : // SvgRadialAtomPrimitive2D class
     928             : 
     929             : namespace drawinglayer
     930             : {
     931             :     namespace primitive2d
     932             :     {
     933           0 :         Primitive2DSequence SvgRadialAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
     934             :         {
     935           0 :             Primitive2DSequence xRetval;
     936           0 :             const double fDeltaScale(getScaleB() - getScaleA());
     937             : 
     938           0 :             if(!basegfx::fTools::equalZero(fDeltaScale))
     939             :             {
     940             :                 // use one discrete unit for overlap (one pixel)
     941           0 :                 const double fDiscreteUnit(getDiscreteUnit());
     942             : 
     943             :                 // use color distance and discrete lengths to calculate step count
     944           0 :                 const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDeltaScale, fDiscreteUnit));
     945             : 
     946             :                 // prepare loop (outside to inside, full polygons, no polypolygons with holes)
     947           0 :                 double fEndScale(getScaleB());
     948           0 :                 double fStepScale(fDeltaScale / nSteps);
     949             : 
     950             :                 // loop and create primitives
     951           0 :                 xRetval.realloc(nSteps);
     952             : 
     953           0 :                 for(sal_uInt32 a(0); a < nSteps; a++, fEndScale -= fStepScale)
     954             :                 {
     955           0 :                     const double fUnitScale(fEndScale/fDeltaScale);
     956           0 :                     basegfx::B2DHomMatrix aTransform;
     957             : 
     958           0 :                     if(isTranslateSet())
     959             :                     {
     960             :                         const basegfx::B2DVector aTranslate(
     961             :                             basegfx::interpolate(
     962             :                                 getTranslateA(),
     963             :                                 getTranslateB(),
     964           0 :                                 fUnitScale));
     965             : 
     966             :                         aTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
     967             :                             fEndScale,
     968             :                             fEndScale,
     969             :                             aTranslate.getX(),
     970           0 :                             aTranslate.getY());
     971             :                     }
     972             :                     else
     973             :                     {
     974             :                         aTransform = basegfx::tools::createScaleB2DHomMatrix(
     975             :                             fEndScale,
     976           0 :                             fEndScale);
     977             :                     }
     978             : 
     979           0 :                     basegfx::B2DPolygon aNew(basegfx::tools::createPolygonFromUnitCircle());
     980             : 
     981           0 :                     aNew.transform(aTransform);
     982           0 :                     xRetval[a] = new PolyPolygonColorPrimitive2D(
     983             :                         basegfx::B2DPolyPolygon(aNew),
     984           0 :                         basegfx::interpolate(getColorA(), getColorB(), fUnitScale));
     985           0 :                 }
     986             :             }
     987             : 
     988           0 :             return xRetval;
     989             :         }
     990             : 
     991           0 :         SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D(
     992             :             const basegfx::BColor& aColorA, double fScaleA, const basegfx::B2DVector& rTranslateA,
     993             :             const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB)
     994             :         :   DiscreteMetricDependentPrimitive2D(),
     995             :             maColorA(aColorA),
     996             :             maColorB(aColorB),
     997             :             mfScaleA(fScaleA),
     998             :             mfScaleB(fScaleB),
     999           0 :             mpTranslate(0)
    1000             :         {
    1001             :             // check and evtl. set translations
    1002           0 :             if(!rTranslateA.equal(rTranslateB))
    1003             :             {
    1004           0 :                 mpTranslate = new VectorPair(rTranslateA, rTranslateB);
    1005             :             }
    1006             : 
    1007             :             // scale A and B have to be positive
    1008           0 :             mfScaleA = ::std::max(mfScaleA, 0.0);
    1009           0 :             mfScaleB = ::std::max(mfScaleB, 0.0);
    1010             : 
    1011             :             // scale B has to be bigger than scale A; swap if different
    1012           0 :             if(mfScaleA > mfScaleB)
    1013             :             {
    1014             :                 OSL_ENSURE(false, "Wrong offset order (!)");
    1015           0 :                 ::std::swap(mfScaleA, mfScaleB);
    1016             : 
    1017           0 :                 if(mpTranslate)
    1018             :                 {
    1019           0 :                     ::std::swap(mpTranslate->maTranslateA, mpTranslate->maTranslateB);
    1020             :                 }
    1021             :             }
    1022           0 :         }
    1023             : 
    1024           0 :         SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D(
    1025             :             const basegfx::BColor& aColorA, double fScaleA,
    1026             :             const basegfx::BColor& aColorB, double fScaleB)
    1027             :         :   DiscreteMetricDependentPrimitive2D(),
    1028             :             maColorA(aColorA),
    1029             :             maColorB(aColorB),
    1030             :             mfScaleA(fScaleA),
    1031             :             mfScaleB(fScaleB),
    1032           0 :             mpTranslate(0)
    1033             :         {
    1034             :             // scale A and B have to be positive
    1035           0 :             mfScaleA = ::std::max(mfScaleA, 0.0);
    1036           0 :             mfScaleB = ::std::max(mfScaleB, 0.0);
    1037             : 
    1038             :             // scale B has to be bigger than scale A; swap if different
    1039           0 :             if(mfScaleA > mfScaleB)
    1040             :             {
    1041             :                 OSL_ENSURE(false, "Wrong offset order (!)");
    1042           0 :                 ::std::swap(mfScaleA, mfScaleB);
    1043             :             }
    1044           0 :         }
    1045             : 
    1046           0 :         SvgRadialAtomPrimitive2D::~SvgRadialAtomPrimitive2D()
    1047             :         {
    1048           0 :             if(mpTranslate)
    1049             :             {
    1050           0 :                 delete mpTranslate;
    1051           0 :                 mpTranslate = 0;
    1052             :             }
    1053           0 :         }
    1054             : 
    1055           0 :         bool SvgRadialAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
    1056             :         {
    1057           0 :             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
    1058             :             {
    1059           0 :                 const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive);
    1060             : 
    1061           0 :                 if(getColorA() == rCompare.getColorA()
    1062           0 :                     && getColorB() == rCompare.getColorB()
    1063           0 :                     && getScaleA() == rCompare.getScaleA()
    1064           0 :                     && getScaleB() == rCompare.getScaleB())
    1065             :                 {
    1066           0 :                     if(isTranslateSet() && rCompare.isTranslateSet())
    1067             :                     {
    1068           0 :                         return (getTranslateA() == rCompare.getTranslateA()
    1069           0 :                             && getTranslateB() == rCompare.getTranslateB());
    1070             :                     }
    1071           0 :                     else if(!isTranslateSet() && !rCompare.isTranslateSet())
    1072             :                     {
    1073           0 :                         return true;
    1074             :                     }
    1075             :                 }
    1076             :             }
    1077             : 
    1078           0 :             return false;
    1079             :         }
    1080             : 
    1081             :         // provide unique ID
    1082           0 :         ImplPrimitrive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D)
    1083             : 
    1084             :     } // end of namespace primitive2d
    1085             : } // end of namespace drawinglayer
    1086             : 
    1087             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10