31#include <osl/diagnose.h>
50 const sal_uInt32 nDistSteps(
basegfx::fround(fDelta / (fDiscreteUnit * 1.5)));
52 nSteps = std::min(nSteps, nDistSteps);
56 nSteps = std::min(nSteps, sal_uInt32(255));
57 nSteps = std::max(nSteps, sal_uInt32(1));
66 void SvgGradientHelper::createSingleGradientEntryFill(Primitive2DContainer& rContainer)
const
69 const sal_uInt32
nCount(rEntries.size());
73 const SvgGradientEntry& rSingleEntry = rEntries[
nCount - 1];
74 const double fOpacity(rSingleEntry.getOpacity());
79 new PolyPolygonColorPrimitive2D(
81 rSingleEntry.getColor()));
85 Primitive2DContainer aContent { xRef };
88 new UnifiedTransparencePrimitive2D(
93 rContainer.push_back(xRef);
98 OSL_ENSURE(
false,
"Single gradient entry construction without entry (!)");
102 void SvgGradientHelper::checkPreconditions()
104 mbPreconditionsChecked =
true;
114 std::sort(maGradientEntries.begin(), maGradientEntries.end());
117 bool bAllInvisible(
true);
118 bool bInvalidEntries(
false);
120 for(
const SvgGradientEntry& rCandidate : rEntries)
125 mbFullyOpaque =
false;
130 bAllInvisible =
false;
135 bAllInvisible =
false;
136 mbFullyOpaque =
false;
141 bInvalidEntries =
true;
154 SAL_WARN(
"drawinglayer",
"SvgGradientHelper got invalid SvgGradientEntries outside [0.0 .. 1.0]");
160 if(aPolyRange.isEmpty())
166 const double fPolyWidth(aPolyRange.getWidth());
167 const double fPolyHeight(aPolyRange.getHeight());
175 mbCreatesContent =
true;
177 if(1 == rEntries.size())
184 const SvgGradientEntry& SvgGradientHelper::FindEntryLessOrEqual(
186 const double fFrac)
const
191 for(SvgGradientEntryVector::const_reverse_iterator aIter(rCurrent.rbegin()); aIter != rCurrent.rend(); ++aIter)
203 return rCurrent2.back();
206 const SvgGradientEntry& SvgGradientHelper::FindEntryMore(
208 const double fFrac)
const
213 for(SvgGradientEntryVector::const_iterator aIter(rCurrent.begin()); aIter != rCurrent.end(); ++aIter)
225 return rCurrent2.front();
239 void SvgGradientHelper::createRun(
240 Primitive2DContainer& rTargetColor,
241 Primitive2DContainer& rTargetOpacity,
253 fFrac = std::modf(fStart, &fInt);
254 const SvgGradientEntry& rFront(getGradientEntries().front());
255 const SvgGradientEntry aTemp(1.0 + fFrac, rFront.getColor(), rFront.getOpacity());
256 createAtom(rTargetColor, rTargetOpacity, aTemp, rFront,
static_cast<sal_Int32
>(fInt - 1), 0);
257 fStart = rFront.getOffset();
264 fEnd = getGradientEntries().back().getOffset();
270 fFrac = std::modf(fStart, &fInt);
278 sal_Int32 nIntLeft(
static_cast<sal_Int32
>(fInt));
279 sal_Int32 nIntRight(nIntLeft);
281 const SvgGradientEntry& rLeft(FindEntryLessOrEqual(nIntLeft, fFrac));
282 const SvgGradientEntry& rRight(FindEntryMore(nIntRight, fFrac));
283 createAtom(rTargetColor, rTargetOpacity, rLeft, rRight, nIntLeft, nIntRight);
285 const double fNextfStart(
static_cast<double>(nIntRight) + rRight.getOffset());
289 fStart = fNextfStart;
293 SAL_WARN(
"drawinglayer",
"SvgGradientHelper spread error");
301 fFrac = std::modf(fEnd2, &fInt);
302 const SvgGradientEntry& rBack(getGradientEntries().back());
303 const SvgGradientEntry aTemp(fFrac, rBack.getColor(), rBack.getOpacity());
304 createAtom(rTargetColor, rTargetOpacity, rBack, aTemp, 0,
static_cast<sal_Int32
>(fInt));
308 void SvgGradientHelper::createResult(
309 Primitive2DContainer& rContainer,
310 Primitive2DContainer aTargetColor,
311 Primitive2DContainer aTargetOpacity,
315 Primitive2DContainer aTargetColorEntries(aTargetColor.maybeInvert(bInvert));
316 Primitive2DContainer aTargetOpacityEntries(aTargetOpacity.maybeInvert(bInvert));
318 if(aTargetColorEntries.empty())
323 if(!aTargetOpacityEntries.empty())
326 std::move(aTargetColorEntries),
327 std::move(aTargetOpacityEntries));
329 xRefContent =
new TransformPrimitive2D(
330 rUnitGradientToObject,
331 Primitive2DContainer { xRefOpacity });
335 xRefContent =
new TransformPrimitive2D(
336 rUnitGradientToObject,
337 std::move(aTargetColorEntries));
340 rContainer.push_back(
new MaskPrimitive2D(
342 Primitive2DContainer { xRefContent }));
345 SvgGradientHelper::SvgGradientHelper(
350 bool bUseUnitCoordinates,
352 : maGradientTransform(
std::move(aGradientTransform)),
354 maGradientEntries(
std::move(rGradientEntries)),
356 maSpreadMethod(aSpreadMethod),
357 mbPreconditionsChecked(false),
358 mbCreatesContent(false),
359 mbSingleEntry(false),
361 mbUseUnitCoordinates(bUseUnitCoordinates)
365 SvgGradientHelper::~SvgGradientHelper()
371 if(maMirroredGradientEntries.empty() && !getGradientEntries().empty())
373 const_cast< SvgGradientHelper*
>(
this)->createMirroredGradientEntries();
376 return maMirroredGradientEntries;
379 void SvgGradientHelper::createMirroredGradientEntries()
381 if(!maMirroredGradientEntries.empty() || getGradientEntries().empty())
384 const sal_uInt32
nCount(getGradientEntries().
size());
385 maMirroredGradientEntries.clear();
386 maMirroredGradientEntries.reserve(nCount);
390 const SvgGradientEntry& rCandidate = getGradientEntries()[
nCount - 1 -
a];
392 maMirroredGradientEntries.emplace_back(
393 1.0 - rCandidate.getOffset(),
394 rCandidate.getColor(),
395 rCandidate.getOpacity());
399 bool SvgGradientHelper::operator==(
const SvgGradientHelper& rSvgGradientHelper)
const
401 const SvgGradientHelper& rCompare = rSvgGradientHelper;
403 return (getGradientTransform() == rCompare.getGradientTransform()
404 && getPolyPolygon() == rCompare.getPolyPolygon()
405 && getGradientEntries() == rCompare.getGradientEntries()
406 && getStart() == rCompare.getStart()
407 && getUseUnitCoordinates() == rCompare.getUseUnitCoordinates()
408 && getSpreadMethod() == rCompare.getSpreadMethod());
419 SvgGradientHelper::checkPreconditions();
421 if(getCreatesContent())
439 sal_Int32 nOffsetFrom,
440 sal_Int32 nOffsetTo)
const
445 OSL_ENSURE(
false,
"SvgGradient Atom creation with no step width (!)");
449 rTargetColor.push_back(
454 if(!getFullyOpaque())
456 const double fTransFrom(1.0 - rFrom.
getOpacity());
457 const double fTransTo(1.0 - rTo.
getOpacity());
461 rTargetOpacity.push_back(
463 aColorFrom, rFrom.
getOffset() + nOffsetFrom,
471 if(!getPreconditionsChecked())
479 createSingleGradientEntryFill(rContainer);
481 else if(getCreatesContent())
486 const double fPolyWidth(aPolyRange.
getWidth());
487 const double fPolyHeight(aPolyRange.
getHeight());
492 fPolyWidth, fPolyHeight,
496 if(getUseUnitCoordinates())
502 const double fVectorLength(aVector.
getLength());
504 aUnitGradientToObject.
scale(fVectorLength, 1.0);
505 aUnitGradientToObject.
rotate(atan2(aVector.
getY(), aVector.
getX()));
506 aUnitGradientToObject.
translate(getStart().getX(), getStart().getY());
508 aUnitGradientToObject *= getGradientTransform();
512 aUnitGradientToObject *= aObjectTransform;
522 aUnitGradientToObject.
rotate(atan2(aVector.
getY(), aVector.
getX()));
525 aUnitGradientToObject *= getGradientTransform();
530 aObjectToUnitGradient.
invert();
535 aUnitPoly.
transform(aObjectToUnitGradient);
549 aUnitGradientToObject = aUnitGradientToObject * aPreMultiply;
559 createResult(rContainer, std::move(aTargetColor), std::move(aTargetOpacity), aUnitGradientToObject);
569 bool bUseUnitCoordinates,
571 : SvgGradientHelper(rGradientTransform, rPolyPolygon,
std::move(rGradientEntries), rStart, bUseUnitCoordinates, aSpreadMethod),
582 const SvgGradientHelper* pSvgGradientHelper =
dynamic_cast< const SvgGradientHelper*
>(&rPrimitive);
584 if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper))
597 return getPolyPolygon().getB2DRange();
614 SvgGradientHelper::checkPreconditions();
616 if(getCreatesContent())
632 sal_Int32 nOffsetFrom,
633 sal_Int32 nOffsetTo)
const
638 OSL_ENSURE(
false,
"SvgGradient Atom creation with no step width (!)");
642 const double fScaleFrom(rFrom.
getOffset() + nOffsetFrom);
643 const double fScaleTo(rTo.
getOffset() + nOffsetTo);
650 rTargetColor.push_back(
652 rFrom.
getColor(), fScaleFrom, aTranslateFrom,
653 rTo.
getColor(), fScaleTo, aTranslateTo));
657 rTargetColor.push_back(
663 if(!getFullyOpaque())
665 const double fTransFrom(1.0 - rFrom.
getOpacity());
666 const double fTransTo(1.0 - rTo.
getOpacity());
675 rTargetOpacity.push_back(
677 aColorFrom, fScaleFrom, aTranslateFrom,
678 aColorTo, fScaleTo, aTranslateTo));
682 rTargetOpacity.push_back(
684 aColorFrom, fScaleFrom,
685 aColorTo, fScaleTo));
693 if(!getPreconditionsChecked())
701 createSingleGradientEntryFill(rContainer);
703 else if(getCreatesContent())
708 const double fPolyWidth(aPolyRange.
getWidth());
709 const double fPolyHeight(aPolyRange.
getHeight());
714 fPolyWidth, fPolyHeight,
718 if(getUseUnitCoordinates())
723 aUnitGradientToObject.
translate(getStart().getX(), getStart().getY());
725 if(!getGradientTransform().isIdentity())
727 aUnitGradientToObject = getGradientTransform() * aUnitGradientToObject;
732 aUnitGradientToObject = aObjectTransform * aUnitGradientToObject;
742 aUnitGradientToObject.
scale(fRadius, fRadius);
745 aUnitGradientToObject *= getGradientTransform();
750 aObjectToUnitGradient.
invert();
755 aUnitPoly.
transform(aObjectToUnitGradient);
785 createResult(rContainer, std::move(aTargetColor), std::move(aTargetOpacity), aUnitGradientToObject,
true);
795 bool bUseUnitCoordinates,
798 : SvgGradientHelper(rGradientTransform, rPolyPolygon,
std::move(rGradientEntries), rStart, bUseUnitCoordinates, aSpreadMethod),
801 maFocalVector(0.0, 0.0),
805 if(pFocal && !pFocal->
equal(getStart()))
819 const SvgGradientHelper* pSvgGradientHelper =
dynamic_cast< const SvgGradientHelper*
>(&rPrimitive);
821 if(!pSvgGradientHelper || !SvgGradientHelper::operator==(*pSvgGradientHelper))
847 return getPolyPolygon().getB2DRange();
874 const sal_uInt32 nSteps(calculateStepsForSvgGradient(
getColorA(),
getColorB(), fDelta, fDiscreteUnit));
895 getOffsetA() + (fDelta / nSteps) + fDiscreteUnit + fixup,
899 double fUnitScale(0.0);
900 const double fUnitStep(1.0 / nSteps);
902 for(sal_uInt32
a(0);
a < nSteps;
a++, fUnitScale += fUnitStep)
923 OSL_ENSURE(
false,
"Wrong offset order (!)");
930 if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
967 const sal_uInt32 nSteps(calculateStepsForSvgGradient(
getColorA(),
getColorB(), fDeltaScale, fDiscreteUnit));
970 double fUnitScale(0.0);
971 const double fUnitStep(1.0 / nSteps);
973 for(sal_uInt32
a(0);
a < nSteps;
a++, fUnitScale += fUnitStep)
976 const double fEndScale(
getScaleB() - (fDeltaScale * fUnitScale));
1011 : maColorA(aColorA),
1017 if(!rTranslateA.
equal(rTranslateB))
1029 OSL_ENSURE(
false,
"Wrong offset order (!)");
1042 : maColorA(aColorA),
1054 OSL_ENSURE(
false,
"Wrong offset order (!)");
1065 if(!DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
void rotate(double fRadiant)
void translate(double fX, double fY)
void scale(double fX, double fY)
void transform(const basegfx::B2DHomMatrix &rMatrix)
B2DRange getB2DRange() const
void transform(const basegfx::B2DHomMatrix &rMatrix)
B2DPoint getMaximum() const
B2DPoint getMinimum() const
double getDistance(const BColor &rColor) const
bool equal(const Tuple2D< TYPE > &rTup) const
double getDiscreteUnit() const
data read access
PolyPolygonColorPrimitive2D class.
a single GradientStop defining a color and opacity at a distance
const basegfx::BColor & getColor() const
double getOpacity() const
virtual void create2DDecomposition(Primitive2DContainer &rContainer, const geometry::ViewInformation2D &rViewInformation) const override
local decomposition.
const basegfx::BColor & getColorA() const
data read access
double getOffsetA() const
double getOffsetB() const
SvgLinearAtomPrimitive2D(const basegfx::BColor &aColorA, double fOffsetA, const basegfx::BColor &aColorB, double fOffsetB)
constructor
virtual bool operator==(const BasePrimitive2D &rPrimitive) const override
compare operator
const basegfx::BColor & getColorB() const
virtual sal_uInt32 getPrimitive2DID() const override
provide unique ID
the basic linear gradient primitive
virtual void createAtom(Primitive2DContainer &rTargetColor, Primitive2DContainer &rTargetOpacity, const SvgGradientEntry &rFrom, const SvgGradientEntry &rTo, sal_Int32 nOffsetFrom, sal_Int32 nOffsetTo) const override
local helpers
SvgLinearGradientPrimitive2D(const basegfx::B2DHomMatrix &rGradientTransform, const basegfx::B2DPolyPolygon &rPolyPolygon, SvgGradientEntryVector &&rGradientEntries, const basegfx::B2DPoint &rStart, const basegfx::B2DPoint &rEnd, bool bUseUnitCoordinates, SpreadMethod aSpreadMethod)
constructor
virtual bool operator==(const BasePrimitive2D &rPrimitive) const override
compare operator
virtual void create2DDecomposition(Primitive2DContainer &rContainer, const geometry::ViewInformation2D &rViewInformation) const override
local decomposition.
virtual void checkPreconditions() override
virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D &rViewInformation) const override
get range
virtual sal_uInt32 getPrimitive2DID() const override
provide unique ID
const basegfx::B2DPoint & getEnd() const
data read access
virtual ~SvgLinearGradientPrimitive2D() override
virtual bool operator==(const BasePrimitive2D &rPrimitive) const override
compare operator
std::unique_ptr< VectorPair > mpTranslate
Only used when focal is set.
virtual sal_uInt32 getPrimitive2DID() const override
provide unique ID
basegfx::B2DVector getTranslateB() const
basegfx::B2DVector getTranslateA() const
virtual void create2DDecomposition(Primitive2DContainer &rContainer, const geometry::ViewInformation2D &rViewInformation) const override
local decomposition.
const basegfx::BColor & getColorA() const
data read access
const basegfx::BColor & getColorB() const
virtual ~SvgRadialAtomPrimitive2D() override
SvgRadialAtomPrimitive2D(const basegfx::BColor &aColorA, double fScaleA, const basegfx::B2DVector &rTranslateA, const basegfx::BColor &aColorB, double fScaleB, const basegfx::B2DVector &rTranslateB)
constructor
bool isTranslateSet() const
the basic radial gradient primitive
virtual ~SvgRadialGradientPrimitive2D() override
virtual sal_uInt32 getPrimitive2DID() const override
provide unique ID
SvgRadialGradientPrimitive2D(const basegfx::B2DHomMatrix &rGradientTransform, const basegfx::B2DPolyPolygon &rPolyPolygon, SvgGradientEntryVector &&rGradientEntries, const basegfx::B2DPoint &rStart, double fRadius, bool bUseUnitCoordinates, SpreadMethod aSpreadMethod, const basegfx::B2DPoint *pFocal)
constructor
virtual bool operator==(const BasePrimitive2D &rPrimitive) const override
compare operator
const basegfx::B2DPoint & getFocal() const
basegfx::B2DVector maFocalVector
virtual void create2DDecomposition(Primitive2DContainer &rContainer, const geometry::ViewInformation2D &rViewInformation) const override
local decomposition.
double getRadius() const
data read access
virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D &rViewInformation) const override
get range
virtual void checkPreconditions() override
virtual void createAtom(Primitive2DContainer &rTargetColor, Primitive2DContainer &rTargetOpacity, const SvgGradientEntry &rFrom, const SvgGradientEntry &rTo, sal_Int32 nOffsetFrom, sal_Int32 nOffsetTo) const override
local helpers
basegfx::B2DPoint maFocal
Focal only used when focal is set at all, see constructors.
#define PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D
#define PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D
#define PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D
#define PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D
#define SAL_WARN(area, stream)
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
double getLength(const B2DPolygon &rCandidate)
B2DHomMatrix createScaleTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fTranslateX, double fTranslateY)
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
B2DPolygon const & createPolygonFromUnitCircle(sal_uInt32 nStartQuadrant=0)
B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY)
B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
B2DTuple interpolate(const B2DTuple &rOld1, const B2DTuple &rOld2, double t)
B2IRange fround(const B2DRange &rRange)
rtl::Reference< BasePrimitive2D > Primitive2DReference
::std::vector< SvgGradientEntry > SvgGradientEntryVector