summaryrefslogtreecommitdiff
path: root/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'drawinglayer/source/primitive2d/svggradientprimitive2d.cxx')
-rw-r--r--drawinglayer/source/primitive2d/svggradientprimitive2d.cxx445
1 files changed, 236 insertions, 209 deletions
diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
index d3e32e22ea46..5784e8ec9e1b 100644
--- a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
@@ -20,17 +20,18 @@
#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
-#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <osl/diagnose.h>
#include <sal/log.hxx>
#include <cmath>
-
+#include <utility>
+#include <vcl/skia/SkiaHelper.hxx>
using namespace com::sun::star;
@@ -61,45 +62,46 @@ namespace
namespace drawinglayer::primitive2d
{
- void SvgGradientHelper::createSingleGradientEntryFill(Primitive2DContainer& rContainer) const
+ Primitive2DReference SvgGradientHelper::createSingleGradientEntryFill() const
{
- const SvgGradientEntryVector& rEntries = getGradientEntries();
+ const SvgGradientEntryVector& rEntries(getGradientEntries());
const sal_uInt32 nCount(rEntries.size());
- if(nCount)
+ if(0 == nCount)
{
- const SvgGradientEntry& rSingleEntry = rEntries[nCount - 1];
- const double fOpacity(rSingleEntry.getOpacity());
-
- if(fOpacity > 0.0)
- {
- Primitive2DReference xRef(
- new PolyPolygonColorPrimitive2D(
- getPolyPolygon(),
- rSingleEntry.getColor()));
-
- if(fOpacity < 1.0)
- {
- const Primitive2DContainer aContent { xRef };
+ // no entries, done
+ OSL_ENSURE(false, "Single gradient entry construction without entry (!)");
+ return nullptr;
+ }
- xRef = Primitive2DReference(
- new UnifiedTransparencePrimitive2D(
- aContent,
- 1.0 - fOpacity));
- }
+ const SvgGradientEntry& rSingleEntry(rEntries[nCount - 1]);
+ const double fOpacity(rSingleEntry.getOpacity());
- rContainer.push_back(xRef);
- }
+ if (fOpacity <= 0.0 || basegfx::fTools::equalZero(fOpacity))
+ {
+ // completely opaque, done
+ return nullptr;
}
- else
+
+ if (basegfx::fTools::moreOrEqual(fOpacity, 1.0))
{
- OSL_ENSURE(false, "Single gradient entry construction without entry (!)");
+ // no opacity
+ return Primitive2DReference {
+ new PolyPolygonColorPrimitive2D(
+ getPolyPolygon(),
+ rSingleEntry.getColor()) };
}
+
+ // if transparent, use PolyPolygonRGBAPrimitive2D
+ return Primitive2DReference {
+ new PolyPolygonRGBAPrimitive2D(
+ getPolyPolygon(),
+ rSingleEntry.getColor(),
+ 1.0 - fOpacity) };
}
void SvgGradientHelper::checkPreconditions()
{
- mbPreconditionsChecked = true;
const SvgGradientEntryVector& rEntries = getGradientEntries();
if(rEntries.empty())
@@ -186,7 +188,7 @@ namespace drawinglayer::primitive2d
const bool bMirror(SpreadMethod::Reflect == getSpreadMethod() && 0 != rInt % 2);
const SvgGradientEntryVector& rCurrent(bMirror ? getMirroredGradientEntries() : getGradientEntries());
- for(SvgGradientEntryVector::const_reverse_iterator aIter(rCurrent.rbegin()); aIter != rCurrent.rend(); aIter++)
+ for(SvgGradientEntryVector::const_reverse_iterator aIter(rCurrent.rbegin()); aIter != rCurrent.rend(); ++aIter)
{
if(basegfx::fTools::lessOrEqual(aIter->getOffset(), fFrac))
{
@@ -208,7 +210,7 @@ namespace drawinglayer::primitive2d
const bool bMirror(SpreadMethod::Reflect == getSpreadMethod() && 0 != rInt % 2);
const SvgGradientEntryVector& rCurrent(bMirror ? getMirroredGradientEntries() : getGradientEntries());
- for(SvgGradientEntryVector::const_iterator aIter(rCurrent.begin()); aIter != rCurrent.end(); aIter++)
+ for(SvgGradientEntryVector::const_iterator aIter(rCurrent.begin()); aIter != rCurrent.end(); ++aIter)
{
if(basegfx::fTools::more(aIter->getOffset(), fFrac))
{
@@ -303,26 +305,25 @@ namespace drawinglayer::primitive2d
}
}
- void SvgGradientHelper::createResult(
- Primitive2DContainer& rContainer,
- const Primitive2DContainer& rTargetColor,
- const Primitive2DContainer& rTargetOpacity,
+ Primitive2DReference SvgGradientHelper::createResult(
+ Primitive2DContainer aTargetColor,
+ Primitive2DContainer aTargetOpacity,
const basegfx::B2DHomMatrix& rUnitGradientToObject,
bool bInvert) const
{
- const Primitive2DContainer aTargetColorEntries(rTargetColor.maybeInvert(bInvert));
- const Primitive2DContainer aTargetOpacityEntries(rTargetOpacity.maybeInvert(bInvert));
+ Primitive2DContainer aTargetColorEntries(aTargetColor.maybeInvert(bInvert));
+ Primitive2DContainer aTargetOpacityEntries(aTargetOpacity.maybeInvert(bInvert));
if(aTargetColorEntries.empty())
- return;
+ return nullptr;
Primitive2DReference xRefContent;
if(!aTargetOpacityEntries.empty())
{
const Primitive2DReference xRefOpacity = new TransparencePrimitive2D(
- aTargetColorEntries,
- aTargetOpacityEntries);
+ std::move(aTargetColorEntries),
+ std::move(aTargetOpacityEntries));
xRefContent = new TransformPrimitive2D(
rUnitGradientToObject,
@@ -332,28 +333,26 @@ namespace drawinglayer::primitive2d
{
xRefContent = new TransformPrimitive2D(
rUnitGradientToObject,
- aTargetColorEntries);
+ std::move(aTargetColorEntries));
}
- rContainer.push_back(new MaskPrimitive2D(
+ return new MaskPrimitive2D(
getPolyPolygon(),
- Primitive2DContainer { xRefContent }));
+ Primitive2DContainer { xRefContent });
}
SvgGradientHelper::SvgGradientHelper(
- const basegfx::B2DHomMatrix& rGradientTransform,
- const basegfx::B2DPolyPolygon& rPolyPolygon,
- const SvgGradientEntryVector& rGradientEntries,
+ basegfx::B2DHomMatrix aGradientTransform,
+ basegfx::B2DPolyPolygon aPolyPolygon,
+ SvgGradientEntryVector&& rGradientEntries,
const basegfx::B2DPoint& rStart,
bool bUseUnitCoordinates,
SpreadMethod aSpreadMethod)
- : maGradientTransform(rGradientTransform),
- maPolyPolygon(rPolyPolygon),
- maGradientEntries(rGradientEntries),
- maMirroredGradientEntries(),
+ : maGradientTransform(std::move(aGradientTransform)),
+ maPolyPolygon(std::move(aPolyPolygon)),
+ maGradientEntries(std::move(rGradientEntries)),
maStart(rStart),
maSpreadMethod(aSpreadMethod),
- mbPreconditionsChecked(false),
mbCreatesContent(false),
mbSingleEntry(false),
mbFullyOpaque(true),
@@ -377,7 +376,7 @@ namespace drawinglayer::primitive2d
void SvgGradientHelper::createMirroredGradientEntries()
{
- if(!(maMirroredGradientEntries.empty() && !getGradientEntries().empty()))
+ if(!maMirroredGradientEntries.empty() || getGradientEntries().empty())
return;
const sal_uInt32 nCount(getGradientEntries().size());
@@ -465,64 +464,66 @@ namespace drawinglayer::primitive2d
}
}
- void SvgLinearGradientPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ basegfx::B2DHomMatrix SvgLinearGradientPrimitive2D::createUnitGradientToObjectTransformation() const
{
- if(!getPreconditionsChecked())
+ const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+
+ // create ObjectTransform based on polygon range
+ const basegfx::B2DHomMatrix aObjectTransform(
+ basegfx::utils::createScaleTranslateB2DHomMatrix(
+ fPolyWidth, fPolyHeight,
+ aPolyRange.getMinX(), aPolyRange.getMinY()));
+ basegfx::B2DHomMatrix aUnitGradientToObject;
+
+ if(getUseUnitCoordinates())
{
- const_cast< SvgLinearGradientPrimitive2D* >(this)->checkPreconditions();
+ // interpret in unit coordinate system -> object aspect ratio will scale result
+ // create unit transform from unit vector [0.0 .. 1.0] along the X-Axis to given
+ // gradient vector defined by Start,End
+ const basegfx::B2DVector aVector(getEnd() - getStart());
+ const double fVectorLength(aVector.getLength());
+
+ aUnitGradientToObject.scale(fVectorLength, 1.0);
+ aUnitGradientToObject.rotate(atan2(aVector.getY(), aVector.getX()));
+ aUnitGradientToObject.translate(getStart().getX(), getStart().getY());
+
+ aUnitGradientToObject *= getGradientTransform();
+
+ // create full transform from unit gradient coordinates to object coordinates
+ // including the SvgGradient transformation
+ aUnitGradientToObject *= aObjectTransform;
}
+ else
+ {
+ // interpret in object coordinate system -> object aspect ratio will not scale result
+ const basegfx::B2DPoint aStart(aObjectTransform * getStart());
+ const basegfx::B2DPoint aEnd(aObjectTransform * getEnd());
+ const basegfx::B2DVector aVector(aEnd - aStart);
+
+ aUnitGradientToObject.scale(aVector.getLength(), 1.0);
+ aUnitGradientToObject.rotate(atan2(aVector.getY(), aVector.getX()));
+ aUnitGradientToObject.translate(aStart.getX(), aStart.getY());
+
+ aUnitGradientToObject *= getGradientTransform();
+ }
+
+ return aUnitGradientToObject;
+ }
+ Primitive2DReference SvgLinearGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
if(getSingleEntry())
{
// fill with last existing color
- createSingleGradientEntryFill(rContainer);
+ return createSingleGradientEntryFill();
}
else if(getCreatesContent())
{
// at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely
// invisible, width and height to fill are not empty
- const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
- const double fPolyWidth(aPolyRange.getWidth());
- const double fPolyHeight(aPolyRange.getHeight());
-
- // create ObjectTransform based on polygon range
- const basegfx::B2DHomMatrix aObjectTransform(
- basegfx::utils::createScaleTranslateB2DHomMatrix(
- fPolyWidth, fPolyHeight,
- aPolyRange.getMinX(), aPolyRange.getMinY()));
- basegfx::B2DHomMatrix aUnitGradientToObject;
-
- if(getUseUnitCoordinates())
- {
- // interpret in unit coordinate system -> object aspect ratio will scale result
- // create unit transform from unit vector [0.0 .. 1.0] along the X-Axis to given
- // gradient vector defined by Start,End
- const basegfx::B2DVector aVector(getEnd() - getStart());
- const double fVectorLength(aVector.getLength());
-
- aUnitGradientToObject.scale(fVectorLength, 1.0);
- aUnitGradientToObject.rotate(atan2(aVector.getY(), aVector.getX()));
- aUnitGradientToObject.translate(getStart().getX(), getStart().getY());
-
- aUnitGradientToObject *= getGradientTransform();
-
- // create full transform from unit gradient coordinates to object coordinates
- // including the SvgGradient transformation
- aUnitGradientToObject *= aObjectTransform;
- }
- else
- {
- // interpret in object coordinate system -> object aspect ratio will not scale result
- const basegfx::B2DPoint aStart(aObjectTransform * getStart());
- const basegfx::B2DPoint aEnd(aObjectTransform * getEnd());
- const basegfx::B2DVector aVector(aEnd - aStart);
-
- aUnitGradientToObject.scale(aVector.getLength(), 1.0);
- aUnitGradientToObject.rotate(atan2(aVector.getY(), aVector.getX()));
- aUnitGradientToObject.translate(aStart.getX(), aStart.getY());
-
- aUnitGradientToObject *= getGradientTransform();
- }
+ basegfx::B2DHomMatrix aUnitGradientToObject(createUnitGradientToObjectTransformation());
// create inverse from it
basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject);
@@ -538,7 +539,7 @@ namespace drawinglayer::primitive2d
Primitive2DContainer aTargetColor;
Primitive2DContainer aTargetOpacity;
- if(basegfx::fTools::more(aUnitRange.getWidth(), 0.0))
+ if(aUnitRange.getWidth() > 0.0)
{
// add a pre-multiply to aUnitGradientToObject to allow
// multiplication of the polygon(xl, 0.0, xr, 1.0)
@@ -555,22 +556,24 @@ namespace drawinglayer::primitive2d
aUnitRange.getMaxX());
}
- createResult(rContainer, aTargetColor, aTargetOpacity, aUnitGradientToObject);
+ return createResult(std::move(aTargetColor), std::move(aTargetOpacity), aUnitGradientToObject);
}
+ return nullptr;
}
SvgLinearGradientPrimitive2D::SvgLinearGradientPrimitive2D(
const basegfx::B2DHomMatrix& rGradientTransform,
const basegfx::B2DPolyPolygon& rPolyPolygon,
- const SvgGradientEntryVector& rGradientEntries,
+ SvgGradientEntryVector&& rGradientEntries,
const basegfx::B2DPoint& rStart,
const basegfx::B2DPoint& rEnd,
bool bUseUnitCoordinates,
SpreadMethod aSpreadMethod)
- : BufferedDecompositionPrimitive2D(),
- SvgGradientHelper(rGradientTransform, rPolyPolygon, rGradientEntries, rStart, bUseUnitCoordinates, aSpreadMethod),
+ : SvgGradientHelper(rGradientTransform, rPolyPolygon, std::move(rGradientEntries), rStart, bUseUnitCoordinates, aSpreadMethod),
maEnd(rEnd)
{
+ // ensure Preconditions are checked
+ checkPreconditions();
}
SvgLinearGradientPrimitive2D::~SvgLinearGradientPrimitive2D()
@@ -598,7 +601,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(SvgLinearGradientPrimitive2D, PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D)
+ sal_uInt32 SvgLinearGradientPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D;
+ }
} // end of namespace drawinglayer::primitive2d
@@ -641,8 +647,9 @@ namespace drawinglayer::primitive2d
if(isFocalSet())
{
- const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
- const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+ const basegfx::B2DVector aFocalVector(getFocal() - getStart());
+ const basegfx::B2DVector aTranslateFrom(aFocalVector * (maFocalLength - fScaleFrom));
+ const basegfx::B2DVector aTranslateTo(aFocalVector * (maFocalLength - fScaleTo));
rTargetColor.push_back(
new SvgRadialAtomPrimitive2D(
@@ -666,8 +673,9 @@ namespace drawinglayer::primitive2d
if(isFocalSet())
{
- const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
- const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+ const basegfx::B2DVector aFocalVector(getFocal() - getStart());
+ const basegfx::B2DVector aTranslateFrom(aFocalVector * (maFocalLength - fScaleFrom));
+ const basegfx::B2DVector aTranslateTo(aFocalVector * (maFocalLength - fScaleTo));
rTargetOpacity.push_back(
new SvgRadialAtomPrimitive2D(
@@ -685,62 +693,64 @@ namespace drawinglayer::primitive2d
}
}
- void SvgRadialGradientPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ basegfx::B2DHomMatrix SvgRadialGradientPrimitive2D::createUnitGradientToObjectTransformation() const
{
- if(!getPreconditionsChecked())
+ const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+
+ // create ObjectTransform based on polygon range
+ const basegfx::B2DHomMatrix aObjectTransform(
+ basegfx::utils::createScaleTranslateB2DHomMatrix(
+ fPolyWidth, fPolyHeight,
+ aPolyRange.getMinX(), aPolyRange.getMinY()));
+ basegfx::B2DHomMatrix aUnitGradientToObject;
+
+ if(getUseUnitCoordinates())
+ {
+ // interpret in unit coordinate system -> object aspect ratio will scale result
+ // create unit transform from unit vector to given linear gradient vector
+ aUnitGradientToObject.scale(getRadius(), getRadius());
+ aUnitGradientToObject.translate(getStart().getX(), getStart().getY());
+
+ if(!getGradientTransform().isIdentity())
+ {
+ aUnitGradientToObject = getGradientTransform() * aUnitGradientToObject;
+ }
+
+ // create full transform from unit gradient coordinates to object coordinates
+ // including the SvgGradient transformation
+ aUnitGradientToObject = aObjectTransform * aUnitGradientToObject;
+ }
+ else
{
- const_cast< SvgRadialGradientPrimitive2D* >(this)->checkPreconditions();
+ // interpret in object coordinate system -> object aspect ratio will not scale result
+ // use X-Axis with radius, it was already made relative to object width when coming from
+ // SVG import
+ const double fRadius((aObjectTransform * basegfx::B2DVector(getRadius(), 0.0)).getLength());
+ const basegfx::B2DPoint aStart(aObjectTransform * getStart());
+
+ aUnitGradientToObject.scale(fRadius, fRadius);
+ aUnitGradientToObject.translate(aStart.getX(), aStart.getY());
+
+ aUnitGradientToObject *= getGradientTransform();
}
+ return aUnitGradientToObject;
+ }
+
+ Primitive2DReference SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
if(getSingleEntry())
{
// fill with last existing color
- createSingleGradientEntryFill(rContainer);
+ return createSingleGradientEntryFill();
}
else if(getCreatesContent())
{
// at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely
// invisible, width and height to fill are not empty
- const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
- const double fPolyWidth(aPolyRange.getWidth());
- const double fPolyHeight(aPolyRange.getHeight());
-
- // create ObjectTransform based on polygon range
- const basegfx::B2DHomMatrix aObjectTransform(
- basegfx::utils::createScaleTranslateB2DHomMatrix(
- fPolyWidth, fPolyHeight,
- aPolyRange.getMinX(), aPolyRange.getMinY()));
- basegfx::B2DHomMatrix aUnitGradientToObject;
-
- if(getUseUnitCoordinates())
- {
- // interpret in unit coordinate system -> object aspect ratio will scale result
- // create unit transform from unit vector to given linear gradient vector
- aUnitGradientToObject.scale(getRadius(), getRadius());
- aUnitGradientToObject.translate(getStart().getX(), getStart().getY());
-
- if(!getGradientTransform().isIdentity())
- {
- aUnitGradientToObject = getGradientTransform() * aUnitGradientToObject;
- }
-
- // create full transform from unit gradient coordinates to object coordinates
- // including the SvgGradient transformation
- aUnitGradientToObject = aObjectTransform * aUnitGradientToObject;
- }
- else
- {
- // interpret in object coordinate system -> object aspect ratio will not scale result
- // use X-Axis with radius, it was already made relative to object width when coming from
- // SVG import
- const double fRadius((aObjectTransform * basegfx::B2DVector(getRadius(), 0.0)).getLength());
- const basegfx::B2DPoint aStart(aObjectTransform * getStart());
-
- aUnitGradientToObject.scale(fRadius, fRadius);
- aUnitGradientToObject.translate(aStart.getX(), aStart.getY());
-
- aUnitGradientToObject *= getGradientTransform();
- }
+ basegfx::B2DHomMatrix aUnitGradientToObject(createUnitGradientToObjectTransformation());
// create inverse from it
basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject);
@@ -779,33 +789,32 @@ namespace drawinglayer::primitive2d
fMax);
}
- createResult(rContainer, aTargetColor, aTargetOpacity, aUnitGradientToObject, true);
+ return createResult(std::move(aTargetColor), std::move(aTargetOpacity), aUnitGradientToObject, true);
}
+ return nullptr;
}
SvgRadialGradientPrimitive2D::SvgRadialGradientPrimitive2D(
const basegfx::B2DHomMatrix& rGradientTransform,
const basegfx::B2DPolyPolygon& rPolyPolygon,
- const SvgGradientEntryVector& rGradientEntries,
+ SvgGradientEntryVector&& rGradientEntries,
const basegfx::B2DPoint& rStart,
double fRadius,
bool bUseUnitCoordinates,
SpreadMethod aSpreadMethod,
const basegfx::B2DPoint* pFocal)
- : BufferedDecompositionPrimitive2D(),
- SvgGradientHelper(rGradientTransform, rPolyPolygon, rGradientEntries, rStart, bUseUnitCoordinates, aSpreadMethod),
+ : SvgGradientHelper(rGradientTransform, rPolyPolygon, std::move(rGradientEntries), rStart, bUseUnitCoordinates, aSpreadMethod),
mfRadius(fRadius),
maFocal(rStart),
- maFocalVector(0.0, 0.0),
- maFocalLength(0.0),
- mbFocalSet(false)
+ maFocalLength(0.0)
{
if(pFocal && !pFocal->equal(getStart()))
{
maFocal = *pFocal;
- maFocalVector = maFocal - getStart();
- mbFocalSet = true;
}
+
+ // ensure Preconditions are checked
+ checkPreconditions();
}
SvgRadialGradientPrimitive2D::~SvgRadialGradientPrimitive2D()
@@ -816,22 +825,22 @@ namespace drawinglayer::primitive2d
{
const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive);
- if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper))
- {
- const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive);
+ if(!pSvgGradientHelper || !SvgGradientHelper::operator==(*pSvgGradientHelper))
+ return false;
+
+ const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive);
- if(getRadius() == rCompare.getRadius())
+ if(getRadius() == rCompare.getRadius())
+ {
+ if(isFocalSet() == rCompare.isFocalSet())
{
- if(isFocalSet() == rCompare.isFocalSet())
+ if(isFocalSet())
{
- if(isFocalSet())
- {
- return getFocal() == rCompare.getFocal();
- }
- else
- {
- return true;
- }
+ return getFocal() == rCompare.getFocal();
+ }
+ else
+ {
+ return true;
}
}
}
@@ -846,7 +855,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(SvgRadialGradientPrimitive2D, PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D)
+ sal_uInt32 SvgRadialGradientPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D;
+ }
} // end of namespace drawinglayer::primitive2d
@@ -855,12 +867,12 @@ namespace drawinglayer::primitive2d
namespace drawinglayer::primitive2d
{
- void SvgLinearAtomPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference SvgLinearAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const double fDelta(getOffsetB() - getOffsetA());
if(basegfx::fTools::equalZero(fDelta))
- return;
+ return nullptr;
// use one discrete unit for overlap (one pixel)
const double fDiscreteUnit(getDiscreteUnit());
@@ -868,6 +880,12 @@ namespace drawinglayer::primitive2d
// use color distance and discrete lengths to calculate step count
const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDelta, fDiscreteUnit));
+ // HACK: Splitting a gradient into adjacent polygons with gradually changing color is silly.
+ // If antialiasing is used to draw them, the AA-ed adjacent edges won't line up perfectly
+ // because of the AA (see SkiaSalGraphicsImpl::mergePolyPolygonToPrevious()).
+ // Make the polygons a bit wider, so they the partial overlap "fixes" this.
+ const double fixup = SkiaHelper::isVCLSkiaEnabled() ? fDiscreteUnit / 2 : 0;
+
// tdf#117949 Use a small amount of discrete overlap at the edges. Usually this
// should be exactly 0.0 and 1.0, but there were cases when this gets clipped
// against the mask polygon which got numerically problematic.
@@ -881,29 +899,31 @@ namespace drawinglayer::primitive2d
basegfx::B2DRange(
getOffsetA() - fDiscreteUnit,
-0.0001, // TTTT -> should be 0.0, see comment above
- getOffsetA() + (fDelta / nSteps) + fDiscreteUnit,
+ getOffsetA() + (fDelta / nSteps) + fDiscreteUnit + fixup,
1.0001))); // TTTT -> should be 1.0, see comment above
// prepare loop (inside to outside, [0.0 .. 1.0[)
double fUnitScale(0.0);
const double fUnitStep(1.0 / nSteps);
+ Primitive2DContainer aContainer;
+ aContainer.resize(nSteps);
for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep)
{
basegfx::B2DPolygon aNew(aPolygon);
- aNew.transform(basegfx::utils::createTranslateB2DHomMatrix(fDelta * fUnitScale, 0.0));
- rContainer.push_back(new PolyPolygonColorPrimitive2D(
+ aNew.translate(fDelta * fUnitScale, 0.0);
+ aContainer[a] = new PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(aNew),
- basegfx::interpolate(getColorA(), getColorB(), fUnitScale)));
+ basegfx::interpolate(getColorA(), getColorB(), fUnitScale));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
SvgLinearAtomPrimitive2D::SvgLinearAtomPrimitive2D(
const basegfx::BColor& aColorA, double fOffsetA,
const basegfx::BColor& aColorB, double fOffsetB)
- : DiscreteMetricDependentPrimitive2D(),
- maColorA(aColorA),
+ : maColorA(aColorA),
maColorB(aColorB),
mfOffsetA(fOffsetA),
mfOffsetB(fOffsetB)
@@ -931,7 +951,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(SvgLinearAtomPrimitive2D, PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D)
+ sal_uInt32 SvgLinearAtomPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D;
+ }
} // end of namespace drawinglayer::primitive2d
@@ -940,12 +963,12 @@ namespace drawinglayer::primitive2d
namespace drawinglayer::primitive2d
{
- void SvgRadialAtomPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ Primitive2DReference SvgRadialAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
const double fDeltaScale(getScaleB() - getScaleA());
if(basegfx::fTools::equalZero(fDeltaScale))
- return;
+ return nullptr;
// use one discrete unit for overlap (one pixel)
const double fDiscreteUnit(getDiscreteUnit());
@@ -957,6 +980,8 @@ namespace drawinglayer::primitive2d
double fUnitScale(0.0);
const double fUnitStep(1.0 / nSteps);
+ Primitive2DContainer aContainer;
+ aContainer.resize(nSteps);
for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep)
{
basegfx::B2DHomMatrix aTransform;
@@ -986,17 +1011,17 @@ namespace drawinglayer::primitive2d
basegfx::B2DPolygon aNew(basegfx::utils::createPolygonFromUnitCircle());
aNew.transform(aTransform);
- rContainer.push_back(new PolyPolygonColorPrimitive2D(
+ aContainer[a] = new PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(aNew),
- basegfx::interpolate(getColorB(), getColorA(), fUnitScale)));
+ basegfx::interpolate(getColorB(), getColorA(), fUnitScale));
}
+ return new GroupPrimitive2D(std::move(aContainer));
}
SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D(
const basegfx::BColor& aColorA, double fScaleA, const basegfx::B2DVector& rTranslateA,
const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB)
- : DiscreteMetricDependentPrimitive2D(),
- maColorA(aColorA),
+ : maColorA(aColorA),
maColorB(aColorB),
mfScaleA(fScaleA),
mfScaleB(fScaleB)
@@ -1027,8 +1052,7 @@ namespace drawinglayer::primitive2d
SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D(
const basegfx::BColor& aColorA, double fScaleA,
const basegfx::BColor& aColorB, double fScaleB)
- : DiscreteMetricDependentPrimitive2D(),
- maColorA(aColorA),
+ : maColorA(aColorA),
maColorB(aColorB),
mfScaleA(fScaleA),
mfScaleB(fScaleB)
@@ -1051,24 +1075,24 @@ namespace drawinglayer::primitive2d
bool SvgRadialAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
- if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
- {
- const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive);
+ if(!DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ return false;
- if(getColorA() == rCompare.getColorA()
- && getColorB() == rCompare.getColorB()
- && getScaleA() == rCompare.getScaleA()
- && getScaleB() == rCompare.getScaleB())
+ const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive);
+
+ if(getColorA() == rCompare.getColorA()
+ && getColorB() == rCompare.getColorB()
+ && getScaleA() == rCompare.getScaleA()
+ && getScaleB() == rCompare.getScaleB())
+ {
+ if(isTranslateSet() && rCompare.isTranslateSet())
{
- if(isTranslateSet() && rCompare.isTranslateSet())
- {
- return (getTranslateA() == rCompare.getTranslateA()
- && getTranslateB() == rCompare.getTranslateB());
- }
- else if(!isTranslateSet() && !rCompare.isTranslateSet())
- {
- return true;
- }
+ return (getTranslateA() == rCompare.getTranslateA()
+ && getTranslateB() == rCompare.getTranslateB());
+ }
+ else if(!isTranslateSet() && !rCompare.isTranslateSet())
+ {
+ return true;
}
}
@@ -1076,7 +1100,10 @@ namespace drawinglayer::primitive2d
}
// provide unique ID
- ImplPrimitive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D)
+ sal_uInt32 SvgRadialAtomPrimitive2D::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D;
+ }
} // end of namespace