summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@me.com>2020-03-11 14:06:53 +0100
committerArmin Le Grand <Armin.Le.Grand@me.com>2020-03-11 16:24:36 +0100
commitc3f0c527b31f5c88263ea63d3d0e332c4783917c (patch)
treebab3bd06413795688746dc95f9e92eca77203fc6
parent367431b6987b75e7a201499bfbd25a41c92a4a59 (diff)
tdf#124424 Enhanced SvgGradientHelper for EMF+
Added support for repeat modes in GDI+ support and saw that the SVG primitive gradient helpers are not capable to support these completely, so had to do some quite complex adaptions which OTOH will be useful for more complex gradients anyways Change-Id: Ib9a9e4a55115834a4fb00300b05abe17ae36d105 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90329 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
-rw-r--r--drawinglayer/source/primitive2d/svggradientprimitive2d.cxx461
-rw-r--r--drawinglayer/source/tools/emfphelperdata.cxx14
-rw-r--r--include/drawinglayer/primitive2d/svggradientprimitive2d.hxx33
3 files changed, 242 insertions, 266 deletions
diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
index b6b85390a711..4367d8e3eb1a 100644
--- a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
@@ -28,6 +28,8 @@
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <sal/log.hxx>
+#include <cmath>
using namespace com::sun::star;
@@ -102,131 +104,191 @@ namespace drawinglayer::primitive2d
if(rEntries.empty())
{
- // no fill at all
+ // no fill at all, done
+ return;
}
- else
- {
- const sal_uInt32 nCount(rEntries.size());
- if(1 == nCount)
+ // sort maGradientEntries by offset, small to big
+ std::sort(maGradientEntries.begin(), maGradientEntries.end());
+
+ // gradient with at least two colors
+ bool bAllInvisible(true);
+ bool bInvalidEntries(false);
+
+ for(const SvgGradientEntry& rCandidate : rEntries)
+ {
+ if(basegfx::fTools::equalZero(rCandidate.getOpacity()))
{
- // fill with single existing color
- setSingleEntry();
+ // invisible
+ mbFullyOpaque = false;
+ }
+ else if(basegfx::fTools::equal(rCandidate.getOpacity(), 1.0))
+ {
+ // completely opaque
+ bAllInvisible = false;
}
else
{
- // sort maGradientEntries when more than one
- std::sort(maGradientEntries.begin(), maGradientEntries.end());
+ // opacity
+ bAllInvisible = false;
+ mbFullyOpaque = false;
+ }
- // gradient with at least two colors
- bool bAllInvisible(true);
+ if(!basegfx::fTools::betweenOrEqualEither(rCandidate.getOffset(), 0.0, 1.0))
+ {
+ bInvalidEntries = true;
+ }
+ }
- for(sal_uInt32 a(0); a < nCount; a++)
- {
- const SvgGradientEntry& rCandidate = rEntries[a];
+ if(bAllInvisible)
+ {
+ // all invisible, nothing to do
+ return;
+ }
- if(basegfx::fTools::equalZero(rCandidate.getOpacity()))
- {
- // invisible
- mbFullyOpaque = false;
- }
- else if(basegfx::fTools::equal(rCandidate.getOpacity(), 1.0))
- {
- // completely opaque
- bAllInvisible = false;
- }
- else
- {
- // opacity
- bAllInvisible = false;
- mbFullyOpaque = false;
- }
- }
+ if(bInvalidEntries)
+ {
+ // invalid entries, do nothing
+ SAL_WARN("drawinglayer", "SvgGradientHelper got invalid SvgGradientEntries outside [0.0 .. 1.0]");
+ return;
+ }
- if(bAllInvisible)
- {
- // all invisible, nothing to do
- }
- else
- {
- const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
+ const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange());
- if(aPolyRange.isEmpty())
- {
- // no range to fill, nothing to do
- }
- else
- {
- const double fPolyWidth(aPolyRange.getWidth());
- const double fPolyHeight(aPolyRange.getHeight());
-
- if(basegfx::fTools::equalZero(fPolyWidth) || basegfx::fTools::equalZero(fPolyHeight))
- {
- // no width/height to fill, nothing to do
- }
- else
- {
- mbCreatesContent = true;
- }
- }
- }
- }
+ if(aPolyRange.isEmpty())
+ {
+ // no range to fill, nothing to do
+ return;
+ }
+
+ const double fPolyWidth(aPolyRange.getWidth());
+ const double fPolyHeight(aPolyRange.getHeight());
+
+ if(basegfx::fTools::equalZero(fPolyWidth) || basegfx::fTools::equalZero(fPolyHeight))
+ {
+ // no width/height to fill, nothing to do
+ return;
+ }
+
+ mbCreatesContent = true;
+
+ if(1 == rEntries.size())
+ {
+ // fill with single existing color
+ setSingleEntry();
}
}
- double SvgGradientHelper::createRun(
- Primitive2DContainer& rTargetColor,
- Primitive2DContainer& rTargetOpacity,
- double fPos,
- double fMax,
- const SvgGradientEntryVector& rEntries,
- sal_Int32 nOffset) const
+ const SvgGradientEntry& SvgGradientHelper::FindEntryLessOrEqual(
+ sal_Int32& rInt,
+ const double fFrac) const
{
- const sal_uInt32 nCount(rEntries.size());
+ const bool bMirror(SpreadMethod::Reflect == getSpreadMethod() && 0 != rInt % 2);
+ const SvgGradientEntryVector& rCurrent(bMirror ? getMirroredGradientEntries() : getGradientEntries());
- if(nCount)
+ for(SvgGradientEntryVector::const_reverse_iterator aIter(rCurrent.rbegin()); aIter != rCurrent.rend(); aIter++)
{
- const SvgGradientEntry& rStart = rEntries[0];
- const bool bCreateStartPad(fPos < 0.0 && SpreadMethod::Pad == getSpreadMethod());
- const bool bCreateStartFill(rStart.getOffset() > 0.0);
- sal_uInt32 nIndex(0);
+ if(basegfx::fTools::lessOrEqual(aIter->getOffset(), fFrac))
+ {
+ return *aIter;
+ }
+ }
- if(bCreateStartPad || bCreateStartFill)
- {
- const SvgGradientEntry aTemp(bCreateStartPad ? fPos : 0.0, rStart.getColor(), rStart.getOpacity());
+ // walk over gap to the left, be prepared for missing 0.0/1.0 entries
+ rInt--;
+ const bool bMirror2(SpreadMethod::Reflect == getSpreadMethod() && 0 != rInt % 2);
+ const SvgGradientEntryVector& rCurrent2(bMirror2 ? getMirroredGradientEntries() : getGradientEntries());
+ return rCurrent2.back();
+ }
- createAtom(rTargetColor, rTargetOpacity, aTemp, rStart, nOffset);
- fPos = rStart.getOffset();
- }
+ const SvgGradientEntry& SvgGradientHelper::FindEntryMore(
+ sal_Int32& rInt,
+ const double fFrac) const
+ {
+ 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++)
+ {
+ if(basegfx::fTools::more(aIter->getOffset(), fFrac))
+ {
+ return *aIter;
+ }
+ }
- while(fPos < 1.0 && nIndex + 1 < nCount)
+ // walk over gap to the right, be prepared for missing 0.0/1.0 entries
+ rInt++;
+ const bool bMirror2(SpreadMethod::Reflect == getSpreadMethod() && 0 != rInt % 2);
+ const SvgGradientEntryVector& rCurrent2(bMirror2 ? getMirroredGradientEntries() : getGradientEntries());
+ return rCurrent2.front();
+ }
+
+ // tdf#124424 Adapted creation of color runs to do in a single effort. Previous
+ // version tried to do this from [0.0 .. 1.0] and to re-use transformed versions
+ // in the caller if SpreadMethod was on some repeat mode, but had problems when
+ // e.g. like in the bugdoc from the task a negative-only fStart/fEnd run was
+ // requested in which case it did nothing. Even when reusing the spread might
+ // not have been a full one from [0.0 .. 1.0].
+ // This gets complicated due to mirrored runs, but also for gradient definitions
+ // with missing entries for 0.0 and 1.0 in which case these have to be guessed
+ // to be there with same parametrisation as their nearest existing entries. These
+ // *could* have been added at checkPreconditions() but would then create unnecessary
+ // spreads on zone overlaps.
+ void SvgGradientHelper::createRun(
+ Primitive2DContainer& rTargetColor,
+ Primitive2DContainer& rTargetOpacity,
+ double fStart,
+ double fEnd) const
+ {
+ if(SpreadMethod::Pad == getSpreadMethod())
+ {
+ if(fStart < 0.0)
{
- const SvgGradientEntry& rCandidateA = rEntries[nIndex++];
- const SvgGradientEntry& rCandidateB = rEntries[nIndex];
+ const SvgGradientEntry& rFront(getGradientEntries().front());
+ const SvgGradientEntry aTemp(fStart, rFront.getColor(), rFront.getOpacity());
+ createAtom(rTargetColor, rTargetOpacity, aTemp, rFront, 0, 0);
+ fStart = rFront.getOffset();
+ }
- createAtom(rTargetColor, rTargetOpacity, rCandidateA, rCandidateB, nOffset);
- fPos = rCandidateB.getOffset();
+ if(fEnd < 1.0)
+ {
+ const SvgGradientEntry& rBack(getGradientEntries().back());
+ const SvgGradientEntry aTemp(fEnd, rBack.getColor(), rBack.getOpacity());
+ createAtom(rTargetColor, rTargetOpacity, rBack, aTemp, 0, 0);
+ fEnd = rBack.getOffset();
}
+ }
- const SvgGradientEntry& rEnd = rEntries[nCount - 1];
- const bool bCreateEndPad(fPos < fMax && SpreadMethod::Pad == getSpreadMethod());
- const bool bCreateEndFill(rEnd.getOffset() < 1.0);
+ while(fStart < fEnd)
+ {
+ double fInt(0.0);
+ double fFrac(std::modf(fStart, &fInt));
- if(bCreateEndPad || bCreateEndFill)
+ if(fFrac < 0.0)
{
- fPos = bCreateEndPad ? fMax : 1.0;
- const SvgGradientEntry aTemp(fPos, rEnd.getColor(), rEnd.getOpacity());
+ fInt -= 1;
+ fFrac = 1.0 + fFrac;
+ }
+
+ sal_Int32 nIntLeft(static_cast<sal_Int32>(fInt));
+ sal_Int32 nIntRight(nIntLeft);
- createAtom(rTargetColor, rTargetOpacity, rEnd, aTemp, nOffset);
+ const SvgGradientEntry& rLeft(FindEntryLessOrEqual(nIntLeft, fFrac));
+ const SvgGradientEntry& rRight(FindEntryMore(nIntRight, fFrac));
+ createAtom(rTargetColor, rTargetOpacity, rLeft, rRight, nIntLeft, nIntRight);
+
+ const double fNextfStart(static_cast<double>(nIntRight) + rRight.getOffset());
+
+ if(basegfx::fTools::more(fNextfStart, fStart))
+ {
+ fStart = fNextfStart;
+ }
+ else
+ {
+ SAL_WARN("drawinglayer", "SvgGradientHelper spread error");
+ fStart += 1.0;
}
}
- else
- {
- OSL_ENSURE(false, "GradientAtom creation without ColorStops (!)");
- fPos = fMax;
- }
-
- return fPos;
}
void SvgGradientHelper::createResult(
@@ -276,6 +338,7 @@ namespace drawinglayer::primitive2d
: maGradientTransform(rGradientTransform),
maPolyPolygon(rPolyPolygon),
maGradientEntries(rGradientEntries),
+ maMirroredGradientEntries(),
maStart(rStart),
maSpreadMethod(aSpreadMethod),
mbPreconditionsChecked(false),
@@ -290,6 +353,36 @@ namespace drawinglayer::primitive2d
{
}
+ const SvgGradientEntryVector& SvgGradientHelper::getMirroredGradientEntries() const
+ {
+ if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
+ {
+ const_cast< SvgGradientHelper* >(this)->createMirroredGradientEntries();
+ }
+
+ return maMirroredGradientEntries;
+ }
+
+ void SvgGradientHelper::createMirroredGradientEntries()
+ {
+ if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
+ {
+ const sal_uInt32 nCount(getGradientEntries().size());
+ maMirroredGradientEntries.clear();
+ maMirroredGradientEntries.reserve(nCount);
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a];
+
+ maMirroredGradientEntries.emplace_back(
+ 1.0 - rCandidate.getOffset(),
+ rCandidate.getColor(),
+ rCandidate.getOpacity());
+ }
+ }
+ }
+
bool SvgGradientHelper::operator==(const SvgGradientHelper& rSvgGradientHelper) const
{
const SvgGradientHelper& rCompare = rSvgGradientHelper;
@@ -330,7 +423,8 @@ namespace drawinglayer::primitive2d
Primitive2DContainer& rTargetOpacity,
const SvgGradientEntry& rFrom,
const SvgGradientEntry& rTo,
- sal_Int32 nOffset) const
+ sal_Int32 nOffsetFrom,
+ sal_Int32 nOffsetTo) const
{
// create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset())
if(rFrom.getOffset() == rTo.getOffset())
@@ -341,8 +435,8 @@ namespace drawinglayer::primitive2d
{
rTargetColor.push_back(
new SvgLinearAtomPrimitive2D(
- rFrom.getColor(), rFrom.getOffset() + nOffset,
- rTo.getColor(), rTo.getOffset() + nOffset));
+ rFrom.getColor(), rFrom.getOffset() + nOffsetFrom,
+ rTo.getColor(), rTo.getOffset() + nOffsetTo));
if(!getFullyOpaque())
{
@@ -353,8 +447,8 @@ namespace drawinglayer::primitive2d
rTargetOpacity.push_back(
new SvgLinearAtomPrimitive2D(
- aColorFrom, rFrom.getOffset() + nOffset,
- aColorTo, rTo.getOffset() + nOffset));
+ aColorFrom, rFrom.getOffset() + nOffsetFrom,
+ aColorTo, rTo.getOffset() + nOffsetTo));
}
}
}
@@ -441,92 +535,12 @@ namespace drawinglayer::primitive2d
1.0, aUnitRange.getHeight(), 0.0, aUnitRange.getMinY()));
aUnitGradientToObject = aUnitGradientToObject * aPreMultiply;
- // create central run, may also already do all necessary when
- // SpreadMethod::Pad is set as SpreadMethod and/or the range is smaller
- double fPos(createRun(aTargetColor, aTargetOpacity, aUnitRange.getMinX(), aUnitRange.getMaxX(), getGradientEntries(), 0));
-
- if(fPos < aUnitRange.getMaxX())
- {
- // can only happen when SpreadMethod is SpreadMethod::Reflect or SpreadMethod::Repeat,
- // else the start and end pads are already created and fPos == aUnitRange.getMaxX().
- // Its possible to express the repeated linear gradient by adding the
- // transformed central run. Create it this way
- Primitive2DContainer aTargetColorEntries(aTargetColor.maybeInvert());
- Primitive2DContainer aTargetOpacityEntries(aTargetOpacity.maybeInvert());
- aTargetColor.clear();
- aTargetOpacity.clear();
-
- if(!aTargetColorEntries.empty())
- {
- // add original central run as group primitive
- aTargetColor.push_back(new GroupPrimitive2D(aTargetColorEntries));
-
- if(!aTargetOpacityEntries.empty())
- {
- aTargetOpacity.push_back(new GroupPrimitive2D(aTargetOpacityEntries));
- }
-
- // add negative runs
- fPos = 0.0;
- sal_Int32 nOffset(0);
-
- while(fPos > aUnitRange.getMinX())
- {
- fPos -= 1.0;
- nOffset++;
-
- basegfx::B2DHomMatrix aTransform;
- const bool bMirror(SpreadMethod::Reflect == getSpreadMethod() && (nOffset % 2));
-
- if(bMirror)
- {
- aTransform.scale(-1.0, 1.0);
- aTransform.translate(fPos + 1.0, 0.0);
- }
- else
- {
- aTransform.translate(fPos, 0.0);
- }
-
- aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries));
-
- if(!aTargetOpacityEntries.empty())
- {
- aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries));
- }
- }
-
- // add positive runs
- fPos = 1.0;
- nOffset = 1;
-
- while(fPos < aUnitRange.getMaxX())
- {
- basegfx::B2DHomMatrix aTransform;
- const bool bMirror(SpreadMethod::Reflect == getSpreadMethod() && (nOffset % 2));
-
- if(bMirror)
- {
- aTransform.scale(-1.0, 1.0);
- aTransform.translate(fPos + 1.0, 0.0);
- }
- else
- {
- aTransform.translate(fPos, 0.0);
- }
-
- aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries));
-
- if(!aTargetOpacityEntries.empty())
- {
- aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries));
- }
-
- fPos += 1.0;
- nOffset++;
- }
- }
- }
+ // create full color run, including all SpreadMethod variants
+ createRun(
+ aTargetColor,
+ aTargetOpacity,
+ aUnitRange.getMinX(),
+ aUnitRange.getMaxX());
}
createResult(rContainer, aTargetColor, aTargetOpacity, aUnitGradientToObject);
@@ -600,7 +614,8 @@ namespace drawinglayer::primitive2d
Primitive2DContainer& rTargetOpacity,
const SvgGradientEntry& rFrom,
const SvgGradientEntry& rTo,
- sal_Int32 nOffset) const
+ sal_Int32 nOffsetFrom,
+ sal_Int32 nOffsetTo) const
{
// create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset())
if(rFrom.getOffset() == rTo.getOffset())
@@ -609,8 +624,8 @@ namespace drawinglayer::primitive2d
}
else
{
- const double fScaleFrom(rFrom.getOffset() + nOffset);
- const double fScaleTo(rTo.getOffset() + nOffset);
+ const double fScaleFrom(rFrom.getOffset() + nOffsetFrom);
+ const double fScaleTo(rTo.getOffset() + nOffsetTo);
if(isFocalSet())
{
@@ -658,36 +673,6 @@ namespace drawinglayer::primitive2d
}
}
- const SvgGradientEntryVector& SvgRadialGradientPrimitive2D::getMirroredGradientEntries() const
- {
- if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
- {
- const_cast< SvgRadialGradientPrimitive2D* >(this)->createMirroredGradientEntries();
- }
-
- return maMirroredGradientEntries;
- }
-
- void SvgRadialGradientPrimitive2D::createMirroredGradientEntries()
- {
- if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
- {
- const sal_uInt32 nCount(getGradientEntries().size());
- maMirroredGradientEntries.clear();
- maMirroredGradientEntries.reserve(nCount);
-
- for(sal_uInt32 a(0); a < nCount; a++)
- {
- const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a];
-
- maMirroredGradientEntries.emplace_back(
- 1.0 - rCandidate.getOffset(),
- rCandidate.getColor(),
- rCandidate.getOpacity());
- }
- }
- }
-
void SvgRadialGradientPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
{
if(!getPreconditionsChecked())
@@ -774,35 +759,12 @@ namespace drawinglayer::primitive2d
const_cast< SvgRadialGradientPrimitive2D* >(this)->maFocalLength = fMax;
}
- // create central run, may also already do all necessary when
- // SpreadMethod::Pad is set as SpreadMethod and/or the range is smaller
- double fPos(createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), 0));
-
- if(fPos < fMax)
- {
- // can only happen when SpreadMethod is SpreadMethod::Reflect or SpreadMethod::Repeat,
- // else the start and end pads are already created and fPos == fMax.
- // For radial there is no way to transform the already created
- // central run, it needs to be created from 1.0 to fMax
- sal_Int32 nOffset(1);
-
- while(fPos < fMax)
- {
- const bool bMirror(SpreadMethod::Reflect == getSpreadMethod() && (nOffset % 2));
-
- if(bMirror)
- {
- createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getMirroredGradientEntries(), nOffset);
- }
- else
- {
- createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), nOffset);
- }
-
- nOffset++;
- fPos += 1.0;
- }
- }
+ // create full color run, including all SpreadMethod variants
+ createRun(
+ aTargetColor,
+ aTargetOpacity,
+ 0.0,
+ fMax);
}
createResult(rContainer, aTargetColor, aTargetOpacity, aUnitGradientToObject, true);
@@ -824,7 +786,6 @@ namespace drawinglayer::primitive2d
maFocal(rStart),
maFocalVector(0.0, 0.0),
maFocalLength(0.0),
- maMirroredGradientEntries(),
mbFocalSet(false)
{
if(pFocal && !pFocal->equal(getStart()))
diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx
index 936afec29364..9b16f6af51a3 100644
--- a/drawinglayer/source/tools/emfphelperdata.cxx
+++ b/drawinglayer/source/tools/emfphelperdata.cxx
@@ -877,11 +877,23 @@ namespace emfplushelper
if (brush->type == BrushTypeLinearGradient)
{
+ // support for public enum EmfPlusWrapMode
basegfx::B2DPoint aStartPoint = Map(brush->firstPointX, brush->firstPointY);
aStartPoint = aPolygonTransformation * aStartPoint;
basegfx::B2DPoint aEndPoint = Map(brush->firstPointX + brush->secondPointX, brush->firstPointY + brush->secondPointY);
aEndPoint = aPolygonTransformation * aEndPoint;
+ // support for public enum EmfPlusWrapMode
+ drawinglayer::primitive2d::SpreadMethod aSpreadMethod(drawinglayer::primitive2d::SpreadMethod::Pad);
+ switch(brush->wrapMode)
+ {
+ case 0 : aSpreadMethod = drawinglayer::primitive2d::SpreadMethod::Repeat; break;
+ case 1 :
+ case 2 :
+ case 3 : aSpreadMethod = drawinglayer::primitive2d::SpreadMethod::Reflect; break;
+ default: break;
+ }
+
// create the same one used for SVG
mrTargetHolders.Current().append(
std::make_unique<drawinglayer::primitive2d::SvgLinearGradientPrimitive2D>(
@@ -891,7 +903,7 @@ namespace emfplushelper
aStartPoint,
aEndPoint,
false, // do not use UnitCoordinates
- drawinglayer::primitive2d::SpreadMethod::Pad));
+ aSpreadMethod));
}
else // BrushTypePathGradient
{
diff --git a/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx b/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx
index c130368bf5b9..871a4aea822d 100644
--- a/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx
@@ -101,6 +101,9 @@ namespace drawinglayer
/// the gradient definition
SvgGradientEntryVector maGradientEntries;
+ // internal helper for case SpreadMethod::Reflect
+ SvgGradientEntryVector maMirroredGradientEntries;
+
/// start and/or center point
basegfx::B2DPoint maStart;
@@ -117,6 +120,12 @@ namespace drawinglayer
// (related to SVG's gradientUnits (userSpaceOnUse|objectBoundingBox)
bool mbUseUnitCoordinates : 1;
+ /// local helpers
+ const SvgGradientEntryVector& getMirroredGradientEntries() const;
+ void createMirroredGradientEntries();
+ const SvgGradientEntry& FindEntryLessOrEqual(sal_Int32& rInt, const double fFrac) const;
+ const SvgGradientEntry& FindEntryMore(sal_Int32& rInt,const double fFrac) const;
+
protected:
/// local helpers
void createSingleGradientEntryFill(Primitive2DContainer& rContainer) const;
@@ -125,14 +134,13 @@ namespace drawinglayer
Primitive2DContainer& rTargetOpacity,
const SvgGradientEntry& rFrom,
const SvgGradientEntry& rTo,
- sal_Int32 nOffset) const = 0;
- double createRun(
+ sal_Int32 nOffsetFrom,
+ sal_Int32 nOffsetTo) const = 0;
+ void createRun(
Primitive2DContainer& rTargetColor,
Primitive2DContainer& rTargetOpacity,
- double fPos,
- double fMax,
- const SvgGradientEntryVector& rEntries,
- sal_Int32 nOffset) const;
+ double fStart,
+ double fEnd) const;
virtual void checkPreconditions();
void createResult(
Primitive2DContainer& rContainer,
@@ -191,7 +199,8 @@ namespace drawinglayer
Primitive2DContainer& rTargetOpacity,
const SvgGradientEntry& rFrom,
const SvgGradientEntry& rTo,
- sal_Int32 nOffset) const override;
+ sal_Int32 nOffsetFrom,
+ sal_Int32 nOffsetTo) const override;
virtual void checkPreconditions() override;
/// local decomposition.
@@ -243,22 +252,16 @@ namespace drawinglayer
basegfx::B2DVector maFocalVector;
double maFocalLength;
- // internal helper for case SpreadMethod::Reflect
- SvgGradientEntryVector maMirroredGradientEntries;
-
bool mbFocalSet : 1;
/// local helpers
- const SvgGradientEntryVector& getMirroredGradientEntries() const;
- void createMirroredGradientEntries();
-
- /// local helpers
virtual void createAtom(
Primitive2DContainer& rTargetColor,
Primitive2DContainer& rTargetOpacity,
const SvgGradientEntry& rFrom,
const SvgGradientEntry& rTo,
- sal_Int32 nOffset) const override;
+ sal_Int32 nOffsetFrom,
+ sal_Int32 nOffsetTo) const override;
virtual void checkPreconditions() override;
/// local decomposition.