diff options
4 files changed, 351 insertions, 107 deletions
diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx index 69881695a22b..4b8a5cb4ab86 100644 --- a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx @@ -104,7 +104,6 @@ namespace drawinglayer::primitive2d void SvgGradientHelper::checkPreconditions() { - mbPreconditionsChecked = true; const SvgGradientEntryVector& rEntries = getGradientEntries(); if(rEntries.empty()) @@ -356,7 +355,6 @@ namespace drawinglayer::primitive2d maGradientEntries(std::move(rGradientEntries)), maStart(rStart), maSpreadMethod(aSpreadMethod), - mbPreconditionsChecked(false), mbCreatesContent(false), mbSingleEntry(false), mbFullyOpaque(true), @@ -468,13 +466,56 @@ namespace drawinglayer::primitive2d } } - Primitive2DReference SvgLinearGradientPrimitive2D::create2DDecomposition(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 @@ -484,48 +525,7 @@ namespace drawinglayer::primitive2d { // 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); @@ -574,6 +574,8 @@ namespace drawinglayer::primitive2d : SvgGradientHelper(rGradientTransform, rPolyPolygon, std::move(rGradientEntries), rStart, bUseUnitCoordinates, aSpreadMethod), maEnd(rEnd) { + // ensure Preconditions are checked + checkPreconditions(); } SvgLinearGradientPrimitive2D::~SvgLinearGradientPrimitive2D() @@ -647,8 +649,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( @@ -672,8 +675,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( @@ -691,13 +695,54 @@ namespace drawinglayer::primitive2d } } - Primitive2DReference SvgRadialGradientPrimitive2D::create2DDecomposition(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()) { - const_cast< SvgRadialGradientPrimitive2D* >(this)->checkPreconditions(); + // 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(); + } + + return aUnitGradientToObject; + } + Primitive2DReference SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { if(getSingleEntry()) { // fill with last existing color @@ -707,46 +752,7 @@ namespace drawinglayer::primitive2d { // 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); @@ -802,16 +808,15 @@ namespace drawinglayer::primitive2d : 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() diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index c3a1c74e764a..4fbddc3cf9ca 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -43,6 +43,7 @@ #include <drawinglayer/primitive2d/textprimitive2d.hxx> #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> #include <drawinglayer/primitive2d/shadowprimitive2d.hxx> +#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx> #include <drawinglayer/converters.hxx> #include <drawinglayer/primitive2d/textlayoutdevice.hxx> #include <basegfx/curve/b2dcubicbezier.hxx> @@ -3213,6 +3214,216 @@ void CairoPixelProcessor2D::renderTextSimpleOrDecoratedPortionPrimitive2D( } } +bool CairoPixelProcessor2D::handleSvgGradientHelper( + const primitive2d::SvgGradientHelper& rCandidate) +{ + // check PolyPolygon to be filled + const basegfx::B2DPolyPolygon& rPolyPolygon(rCandidate.getPolyPolygon()); + + if (!rPolyPolygon.count()) + { + // no PolyPolygon, done + return true; + } + + // calculate visible range + basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.getB2DRange()); + aPolyPolygonRange.transform(getViewInformation2D().getObjectToViewTransformation()); + if (!getDiscreteViewRange(mpRT).overlaps(aPolyPolygonRange)) + { + // not visible, done + return true; + } + + if (!rCandidate.getCreatesContent()) + { + // creates no content, done + return true; + } + + if (rCandidate.getSingleEntry()) + { + // only one color entry, fill with last existing color, done + primitive2d::SvgGradientEntryVector::const_reference aEntry( + rCandidate.getGradientEntries().back()); + paintPolyPoylgonRGBA(rCandidate.getPolyPolygon(), aEntry.getColor(), + 1.0 - aEntry.getOpacity()); + + return true; + } + + return false; +} + +void CairoPixelProcessor2D::processSvgLinearGradientPrimitive2D( + const primitive2d::SvgLinearGradientPrimitive2D& rCandidate) +{ + // check for simple cases, returns if all necesary is already done + if (handleSvgGradientHelper(rCandidate)) + { + // simple case, handled, done + return; + } + + cairo_save(mpRT); + + // set ObjectToView as regular transformation at CairoContext + const basegfx::B2DHomMatrix aTrans(getViewInformation2D().getObjectToViewTransformation()); + cairo_matrix_t aMatrix; + cairo_matrix_init(&aMatrix, aTrans.a(), aTrans.b(), aTrans.c(), aTrans.d(), aTrans.e(), + aTrans.f()); + cairo_set_matrix(mpRT, &aMatrix); + + // create pattern using unit coordinates. Unit coordinates here means that + // the transformation provided by the primitive maps the linear gradient + // to (0,0) -> (1,0) at the unified object coordinates, along the unified + // X-Axis + cairo_pattern_t* pPattern(cairo_pattern_create_linear(0, 0, 1, 0)); + + // get pre-defined UnitGradientToObject transformation from primitive + // and invert to get ObjectToUnitGradient transform + basegfx::B2DHomMatrix aObjectToUnitGradient( + rCandidate.createUnitGradientToObjectTransformation()); + aObjectToUnitGradient.invert(); + + // set ObjectToUnitGradient as transformation at gradient - patterns + // need the inverted transformation, see cairo documentation + cairo_matrix_init(&aMatrix, aObjectToUnitGradient.a(), aObjectToUnitGradient.b(), + aObjectToUnitGradient.c(), aObjectToUnitGradient.d(), + aObjectToUnitGradient.e(), aObjectToUnitGradient.f()); + cairo_pattern_set_matrix(pPattern, &aMatrix); + + // add color stops + const primitive2d::SvgGradientEntryVector& rGradientEntries(rCandidate.getGradientEntries()); + + for (const auto& entry : rGradientEntries) + { + const basegfx::BColor& rColor(entry.getColor()); + cairo_pattern_add_color_stop_rgba(pPattern, entry.getOffset(), rColor.getRed(), + rColor.getGreen(), rColor.getBlue(), entry.getOpacity()); + } + + // set SpreadMethod. Note that we have no SpreadMethod::None because the + // source is SVG and SVG does also not have that (checked that) + switch (rCandidate.getSpreadMethod()) + { + case primitive2d::SpreadMethod::Pad: + cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_PAD); + break; + case primitive2d::SpreadMethod::Reflect: + cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_REFLECT); + break; + case primitive2d::SpreadMethod::Repeat: + cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_REPEAT); + break; + } + + // get PathGeometry & paint it filed with gradient + cairo_new_path(mpRT); + getOrCreateFillGeometry(mpRT, rCandidate.getPolyPolygon()); + cairo_set_source(mpRT, pPattern); + cairo_fill(mpRT); + + // cleanup + cairo_pattern_destroy(pPattern); + cairo_restore(mpRT); +} + +void CairoPixelProcessor2D::processSvgRadialGradientPrimitive2D( + const primitive2d::SvgRadialGradientPrimitive2D& rCandidate) +{ + // check for simple cases, returns if all necesary is already done + if (handleSvgGradientHelper(rCandidate)) + { + // simple case, handled, done + return; + } + + cairo_save(mpRT); + + // set ObjectToView as regular transformation at CairoContext + const basegfx::B2DHomMatrix aTrans(getViewInformation2D().getObjectToViewTransformation()); + cairo_matrix_t aMatrix; + cairo_matrix_init(&aMatrix, aTrans.a(), aTrans.b(), aTrans.c(), aTrans.d(), aTrans.e(), + aTrans.f()); + cairo_set_matrix(mpRT, &aMatrix); + + // get pre-defined UnitGradientToObject transformation from primitive + // and invert to get ObjectToUnitGradient transform + basegfx::B2DHomMatrix aObjectToUnitGradient( + rCandidate.createUnitGradientToObjectTransformation()); + aObjectToUnitGradient.invert(); + + // prepare empty FocalVector + basegfx::B2DVector aFocalVector(0.0, 0.0); + + if (rCandidate.isFocalSet()) + { + // FocalPoint is used, create ObjectTransform based on polygon range + const basegfx::B2DRange aPolyRange(rCandidate.getPolyPolygon().getB2DRange()); + const double fPolyWidth(aPolyRange.getWidth()); + const double fPolyHeight(aPolyRange.getHeight()); + const basegfx::B2DHomMatrix aObjectTransform( + basegfx::utils::createScaleTranslateB2DHomMatrix( + fPolyWidth, fPolyHeight, aPolyRange.getMinX(), aPolyRange.getMinY())); + + // get vector, then transform to object coordinates, then to + // UnitGradient coordinates to be in the needed coordinate system + aFocalVector = basegfx::B2DVector(rCandidate.getStart() - rCandidate.getFocal()); + aFocalVector *= aObjectTransform; + aFocalVector *= aObjectToUnitGradient; + } + + // create pattern using unit coordinates. Unit coordinates here means that + // the transformation provided by the primitive maps the radial gradient + // to (0,0) as center, 1.0 as radius - which is the unit circle. The + // FocalPoint (if used) has to be relative to that, so - since unified + // center is at (0, 0), handling as vector is sufficient + cairo_pattern_t* pPattern( + cairo_pattern_create_radial(0, 0, 0, aFocalVector.getX(), aFocalVector.getY(), 1)); + + // set ObjectToUnitGradient as transformation at gradient - patterns + // need the inverted transformation, see cairo documentation + cairo_matrix_init(&aMatrix, aObjectToUnitGradient.a(), aObjectToUnitGradient.b(), + aObjectToUnitGradient.c(), aObjectToUnitGradient.d(), + aObjectToUnitGradient.e(), aObjectToUnitGradient.f()); + cairo_pattern_set_matrix(pPattern, &aMatrix); + + // add color stops + const primitive2d::SvgGradientEntryVector& rGradientEntries(rCandidate.getGradientEntries()); + + for (const auto& entry : rGradientEntries) + { + const basegfx::BColor& rColor(entry.getColor()); + cairo_pattern_add_color_stop_rgba(pPattern, entry.getOffset(), rColor.getRed(), + rColor.getGreen(), rColor.getBlue(), entry.getOpacity()); + } + + // set SpreadMethod + switch (rCandidate.getSpreadMethod()) + { + case primitive2d::SpreadMethod::Pad: + cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_PAD); + break; + case primitive2d::SpreadMethod::Reflect: + cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_REFLECT); + break; + case primitive2d::SpreadMethod::Repeat: + cairo_pattern_set_extend(pPattern, CAIRO_EXTEND_REPEAT); + break; + } + + // get PathGeometry & paint it filed with gradient + cairo_new_path(mpRT); + getOrCreateFillGeometry(mpRT, rCandidate.getPolyPolygon()); + cairo_set_source(mpRT, pPattern); + cairo_fill(mpRT); + + // cleanup + cairo_pattern_destroy(pPattern); + cairo_restore(mpRT); +} + void CairoPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { switch (rCandidate.getPrimitive2DID()) @@ -3359,6 +3570,18 @@ void CairoPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimit static_cast<const primitive2d::TextDecoratedPortionPrimitive2D&>(rCandidate)); break; } + case PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D: + { + processSvgLinearGradientPrimitive2D( + static_cast<const primitive2d::SvgLinearGradientPrimitive2D&>(rCandidate)); + break; + } + case PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D: + { + processSvgRadialGradientPrimitive2D( + static_cast<const primitive2d::SvgRadialGradientPrimitive2D&>(rCandidate)); + break; + } // continue with decompose default: diff --git a/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx b/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx index e63e1df96507..ff5ae8df2eac 100644 --- a/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/svggradientprimitive2d.hxx @@ -100,7 +100,6 @@ namespace drawinglayer::primitive2d /// how to spread SpreadMethod maSpreadMethod; - bool mbPreconditionsChecked : 1; bool mbCreatesContent : 1; bool mbSingleEntry : 1; bool mbFullyOpaque : 1; @@ -137,13 +136,14 @@ namespace drawinglayer::primitive2d Primitive2DContainer aTargetOpacity, const basegfx::B2DHomMatrix& rUnitGradientToObject, bool bInvert = false) const; - bool getCreatesContent() const { return mbCreatesContent; } - bool getSingleEntry() const { return mbSingleEntry; } + void setSingleEntry() { mbSingleEntry = true; } - bool getPreconditionsChecked() const { return mbPreconditionsChecked; } bool getFullyOpaque() const { return mbFullyOpaque; } public: + bool getCreatesContent() const { return mbCreatesContent; } + bool getSingleEntry() const { return mbSingleEntry; } + /// constructor SvgGradientHelper( basegfx::B2DHomMatrix aGradientTransform, @@ -164,6 +164,9 @@ namespace drawinglayer::primitive2d /// compare operator bool operator==(const SvgGradientHelper& rSvgGradientHelper) const; + + /// create transformation from UnitGrandient to ObjectTransform + virtual basegfx::B2DHomMatrix createUnitGradientToObjectTransformation() const = 0; }; /// the basic linear gradient primitive @@ -209,6 +212,9 @@ namespace drawinglayer::primitive2d /// provide unique ID virtual sal_uInt32 getPrimitive2DID() const override; + + /// create transformation from UnitGrandient to ObjectTransform + virtual basegfx::B2DHomMatrix createUnitGradientToObjectTransformation() const override; }; /// the basic radial gradient primitive @@ -220,11 +226,8 @@ namespace drawinglayer::primitive2d /// Focal only used when focal is set at all, see constructors basegfx::B2DPoint maFocal; - basegfx::B2DVector maFocalVector; double maFocalLength; - bool mbFocalSet : 1; - /// local helpers virtual void createAtom( Primitive2DContainer& rTargetColor, @@ -254,7 +257,7 @@ namespace drawinglayer::primitive2d /// data read access double getRadius() const { return mfRadius; } const basegfx::B2DPoint& getFocal() const { return maFocal; } - bool isFocalSet() const { return mbFocalSet; } + bool isFocalSet() const { return !maFocal.equal(getStart()); } /// compare operator virtual bool operator==(const BasePrimitive2D& rPrimitive) const override; @@ -264,6 +267,9 @@ namespace drawinglayer::primitive2d /// provide unique ID virtual sal_uInt32 getPrimitive2DID() const override; + + /// create transformation from UnitGrandient to ObjectTransform + virtual basegfx::B2DHomMatrix createUnitGradientToObjectTransformation() const override; }; // SvgLinearAtomPrimitive2D class diff --git a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx index 56281bd0cd32..02a49842c512 100644 --- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx +++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx @@ -43,6 +43,9 @@ class BitmapAlphaPrimitive2D; class TextSimplePortionPrimitive2D; class TextDecoratedPortionPrimitive2D; class TextLayouterDevice; +class SvgLinearGradientPrimitive2D; +class SvgRadialGradientPrimitive2D; +class SvgGradientHelper; } namespace basegfx @@ -138,6 +141,13 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub const basegfx::B2DHomMatrix* pOptionalObjectTransform = nullptr, const basegfx::BColor* pReplacementColor = nullptr); + // support for SVG gradients + void processSvgLinearGradientPrimitive2D( + const primitive2d::SvgLinearGradientPrimitive2D& rCandidate); + void processSvgRadialGradientPrimitive2D( + const primitive2d::SvgRadialGradientPrimitive2D& rCandidate); + bool handleSvgGradientHelper(const primitive2d::SvgGradientHelper& rCandidate); + /* the local processor for BasePrimitive2D-Implementation based primitives, called from the common process()-implementation */ |