basegfx/source/color/bcolormodifier.cxx          |   74 +++++++++++++++++++++++
 drawinglayer/source/tools/primitive2dxmldump.cxx |   12 ++-
 include/basegfx/color/bcolormodifier.hxx         |   40 ++++++++++++
 svgio/inc/svgfecolormatrixnode.hxx               |    6 +
 svgio/inc/svgtoken.hxx                           |    1 
 svgio/qa/cppunit/SvgImportTest.cxx               |   21 +++++-
 svgio/qa/cppunit/data/filterSaturate.svg         |   11 +++
 svgio/source/svgreader/svgfecolormatrixnode.cxx  |   29 ++++++++-
 svgio/source/svgreader/svgtoken.cxx              |    2 
 9 files changed, 183 insertions(+), 13 deletions(-)

New commits:
commit 41bf4139cab36984cff514bfdd6b1b13576746a3
Author:     Xisco Fauli <[email protected]>
AuthorDate: Wed Jun 14 12:39:06 2023 +0200
Commit:     Xisco Fauli <[email protected]>
CommitDate: Wed Jun 14 21:08:17 2023 +0200

    tdf#155735: Add support for saturate type
    
    Add getModifierName to BColorModifier class so when
    can assert which modifier is being used
    
    Change-Id: I2bc2a36470a449df4dc84a8440f232149c1f8278
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153048
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/basegfx/source/color/bcolormodifier.cxx 
b/basegfx/source/color/bcolormodifier.cxx
index f27ffcc9aaf0..2067257015b4 100644
--- a/basegfx/source/color/bcolormodifier.cxx
+++ b/basegfx/source/color/bcolormodifier.cxx
@@ -45,6 +45,11 @@ namespace basegfx
         return ::basegfx::BColor(fLuminance, fLuminance, fLuminance);
     }
 
+    OUString BColorModifier_gray::getModifierName() const
+    {
+        return "gray";
+    }
+
     BColorModifier_invert::~BColorModifier_invert()
     {
     }
@@ -59,6 +64,11 @@ namespace basegfx
         return ::basegfx::BColor(1.0 - aSourceColor.getRed(), 1.0 - 
aSourceColor.getGreen(), 1.0 - aSourceColor.getBlue());
     }
 
+    OUString BColorModifier_invert::getModifierName() const
+    {
+        return "invert";
+    }
+
     BColorModifier_luminance_to_alpha::~BColorModifier_luminance_to_alpha()
     {
     }
@@ -75,6 +85,11 @@ namespace basegfx
         return ::basegfx::BColor(fAlpha, fAlpha, fAlpha);
     }
 
+    OUString BColorModifier_luminance_to_alpha::getModifierName() const
+    {
+        return "luminance_to_alpha";
+    }
+
     BColorModifier_replace::~BColorModifier_replace()
     {
     }
@@ -96,6 +111,11 @@ namespace basegfx
         return maBColor;
     }
 
+    OUString BColorModifier_replace::getModifierName() const
+    {
+        return "replace";
+    }
+
     BColorModifier_interpolate::~BColorModifier_interpolate()
     {
     }
@@ -117,6 +137,40 @@ namespace basegfx
         return interpolate(maBColor, aSourceColor, mfValue);
     }
 
+    OUString BColorModifier_interpolate::getModifierName() const
+    {
+        return "interpolate";
+    }
+
+    BColorModifier_saturate::~BColorModifier_saturate()
+    {
+    }
+
+    bool BColorModifier_saturate::operator==(const BColorModifier& rCompare) 
const
+    {
+        const BColorModifier_saturate* pCompare = dynamic_cast< const 
BColorModifier_saturate* >(&rCompare);
+
+        if(!pCompare)
+        {
+            return false;
+        }
+
+        return mfValue == pCompare->mfValue;
+    }
+
+    ::basegfx::BColor BColorModifier_saturate::getModifiedColor(const 
::basegfx::BColor& aSourceColor) const
+    {
+        return basegfx::BColor(
+            (0.213 + 0.787 * mfValue) * aSourceColor.getRed() + (0.715 - 0.715 
* mfValue) * aSourceColor.getGreen() + (0.072 - 0.072 * mfValue) * 
aSourceColor.getBlue(),
+            (0.213 - 0.213 * mfValue) * aSourceColor.getRed() + (0.715 + 0.285 
* mfValue) * aSourceColor.getGreen() + (0.072 - 0.072 * mfValue) * 
aSourceColor.getBlue(),
+            (0.213 - 0.213 * mfValue) * aSourceColor.getRed() + (0.715 - 0.715 
* mfValue) * aSourceColor.getGreen() + (0.072 + 0.928 * mfValue) * 
aSourceColor.getBlue());
+    }
+
+    OUString BColorModifier_saturate::getModifierName() const
+    {
+        return "saturate";
+    }
+
     BColorModifier_black_and_white::~BColorModifier_black_and_white()
     {
     }
@@ -147,6 +201,11 @@ namespace basegfx
         }
     }
 
+    OUString BColorModifier_black_and_white::getModifierName() const
+    {
+        return "black_and_white";
+    }
+
     BColorModifier_gamma::BColorModifier_gamma(double fValue)
     :   mfValue(fValue),
         mfInvValue(fValue),
@@ -193,6 +252,11 @@ namespace basegfx
         }
     }
 
+    OUString BColorModifier_gamma::getModifierName() const
+    {
+        return "gamma";
+    }
+
     
BColorModifier_RGBLuminanceContrast::BColorModifier_RGBLuminanceContrast(double 
fRed, double fGreen, double fBlue, double fLuminance, double fContrast)
     :   mfRed(std::clamp(fRed, -1.0, 1.0)),
         mfGreen(std::clamp(fGreen, -1.0, 1.0)),
@@ -270,6 +334,11 @@ namespace basegfx
         }
     }
 
+    OUString BColorModifier_RGBLuminanceContrast::getModifierName() const
+    {
+        return "RGBLuminanceContrast";
+    }
+
     BColorModifier_randomize::BColorModifier_randomize(double fRandomPart)
     : mfRandomPart(fRandomPart)
     {
@@ -321,6 +390,11 @@ namespace basegfx
                 comphelper::rng::uniform_real_distribution(0.0, 
nextafter(mfRandomPart, DBL_MAX)));
     }
 
+    OUString BColorModifier_randomize::getModifierName() const
+    {
+        return "randomize";
+    }
+
     ::basegfx::BColor BColorModifierStack::getModifiedColor(const 
::basegfx::BColor& rSource) const
     {
         if(maBColorModifiers.empty())
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx 
b/drawinglayer/source/tools/primitive2dxmldump.cxx
index 7edb5bce5c89..37ea828a6fbb 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -38,6 +38,7 @@
 #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
 #include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
 #include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
 #include <drawinglayer/geometry/viewinformation2d.hxx>
 #include <drawinglayer/attribute/lineattribute.hxx>
@@ -1127,11 +1128,14 @@ void Primitive2dXmlDump::decomposeAndWrite(
             case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
             {
                 // ModifiedColorPrimitive2D.
+                const ModifiedColorPrimitive2D& rModifiedColorPrimitive2D
+                    = dynamic_cast<const 
ModifiedColorPrimitive2D&>(*pBasePrimitive);
                 rWriter.startElement("modifiedColor");
-                drawinglayer::primitive2d::Primitive2DContainer 
aPrimitiveContainer;
-                pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
-                                                   
drawinglayer::geometry::ViewInformation2D());
-                decomposeAndWrite(aPrimitiveContainer, rWriter);
+                const basegfx::BColorModifierSharedPtr& aColorModifier
+                    = rModifiedColorPrimitive2D.getColorModifier();
+                rWriter.attribute("modifier", 
aColorModifier->getModifierName());
+
+                decomposeAndWrite(rModifiedColorPrimitive2D.getChildren(), 
rWriter);
                 rWriter.endElement();
                 break;
             }
diff --git a/include/basegfx/color/bcolormodifier.hxx 
b/include/basegfx/color/bcolormodifier.hxx
index 911d74289a17..28ab7487eec3 100644
--- a/include/basegfx/color/bcolormodifier.hxx
+++ b/include/basegfx/color/bcolormodifier.hxx
@@ -22,6 +22,7 @@
 #include <config_options.h>
 #include <basegfx/basegfxdllapi.h>
 #include <basegfx/color/bcolor.hxx>
+#include <rtl/ustring.hxx>
 
 #include <osl/diagnose.h>
 
@@ -80,6 +81,8 @@ namespace basegfx
 
         // compute modified color
         virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& 
aSourceColor) const = 0;
+
+        virtual OUString getModifierName() const = 0;
     };
 
     /** convert color to gray
@@ -98,6 +101,7 @@ namespace basegfx
 
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /** invert color
@@ -118,6 +122,7 @@ namespace basegfx
 
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /** convert to alpha based on luminance
@@ -142,6 +147,7 @@ namespace basegfx
 
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /** replace color
@@ -171,6 +177,7 @@ namespace basegfx
 
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /** interpolate color
@@ -200,6 +207,35 @@ namespace basegfx
 
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
+    };
+
+    /** Apply saturation
+        This derivation is used for the svg importer and does exactly what SVG
+        defines for this needed case.
+
+        See:
+        https://www.w3.org/TR/filter-effects/#elementdef-fecolormatrix
+    */
+    class SAL_WARN_UNUSED BASEGFX_DLLPUBLIC BColorModifier_saturate final : 
public BColorModifier
+    {
+    private:
+        double                      mfValue;
+
+    public:
+        BColorModifier_saturate(double fValue)
+        :   mfValue(fValue)
+        {
+        }
+
+        virtual ~BColorModifier_saturate() override;
+
+        // compare operator
+        SAL_DLLPRIVATE virtual bool operator==(const BColorModifier& rCompare) 
const override;
+
+        // compute modified color
+        SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /** convert color to black and white
@@ -225,6 +261,7 @@ namespace basegfx
 
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /** gamma correction
@@ -252,6 +289,7 @@ namespace basegfx
 
         // compute modified color
         virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& 
aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /** Red, Green, Blue, Luminance and Contrast correction
@@ -288,6 +326,7 @@ namespace basegfx
 
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /** mix a part of the original color with randomized color (mainly for 
debug visualizations)
@@ -309,6 +348,7 @@ namespace basegfx
 
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
+        SAL_DLLPRIVATE virtual OUString getModifierName() const override;
     };
 
     /// typedef to allow working with shared instances of BColorModifier
diff --git a/svgio/inc/svgfecolormatrixnode.hxx 
b/svgio/inc/svgfecolormatrixnode.hxx
index 7436f737b04c..631da8877372 100644
--- a/svgio/inc/svgfecolormatrixnode.hxx
+++ b/svgio/inc/svgfecolormatrixnode.hxx
@@ -25,16 +25,18 @@
 
 namespace svgio::svgreader
 {
-enum class Type
+enum class ColorType
 {
     None,
+    Saturate,
     LuminanceToAlpha
 };
 
 class SvgFeColorMatrixNode final : public SvgNode
 {
 private:
-    Type maType;
+    ColorType maType;
+    SvgNumber maValues;
 
 public:
     SvgFeColorMatrixNode(SvgDocument& rDocument, SvgNode* pParent);
diff --git a/svgio/inc/svgtoken.hxx b/svgio/inc/svgtoken.hxx
index 18c1a092c238..a28be73df50a 100644
--- a/svgio/inc/svgtoken.hxx
+++ b/svgio/inc/svgtoken.hxx
@@ -122,6 +122,7 @@ namespace svgio::svgreader
             XMaxYMax,
             Meet,
             Slice,
+            Values,
 
             // structural elements
             Defs,
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index 559af49af695..bdfbfcccb911 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -153,17 +153,30 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf155819)
     assertXPath(pDocument, "/primitive2D/transform/transform", 4);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testFilterSaturate)
+{
+    Primitive2DSequence aSequence = 
parseSvg(u"/svgio/qa/cppunit/data/filterSaturate.svg");
+    CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+
+    drawinglayer::Primitive2dXmlDump dumper;
+    xmlDocUniquePtr pDocument = dumper.dumpAndParse(aSequence);
+
+    CPPUNIT_ASSERT (pDocument);
+
+    assertXPath(pDocument, "/primitive2D/transform/modifiedColor", "modifier", 
"saturate");
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testFilterLuminanceToAlpha)
 {
-    Primitive2DSequence aSequenceTdf132246 = 
parseSvg(u"/svgio/qa/cppunit/data/filterLuminanceToAlpha.svg");
-    CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequenceTdf132246.getLength()));
+    Primitive2DSequence aSequence = 
parseSvg(u"/svgio/qa/cppunit/data/filterLuminanceToAlpha.svg");
+    CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
 
     drawinglayer::Primitive2dXmlDump dumper;
-    xmlDocUniquePtr pDocument = dumper.dumpAndParse(aSequenceTdf132246);
+    xmlDocUniquePtr pDocument = dumper.dumpAndParse(aSequence);
 
     CPPUNIT_ASSERT (pDocument);
 
-    assertXPath(pDocument, "/primitive2D/transform/modifiedColor");
+    assertXPath(pDocument, "/primitive2D/transform/modifiedColor", "modifier", 
"luminance_to_alpha");
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testFilterFeGaussianBlur)
diff --git a/svgio/qa/cppunit/data/filterSaturate.svg 
b/svgio/qa/cppunit/data/filterSaturate.svg
new file mode 100644
index 000000000000..3fc1ab89f538
--- /dev/null
+++ b/svgio/qa/cppunit/data/filterSaturate.svg
@@ -0,0 +1,11 @@
+<svg
+  width="230"
+  height="120"
+  xmlns="http://www.w3.org/2000/svg";
+  xmlns:xlink="http://www.w3.org/1999/xlink";>
+  <filter id="saturate">
+    <feColorMatrix type="saturate" values="0.5"/>
+  </filter>
+  <circle cx="170" cy="60" r="50" fill="green" filter="url(#saturate)" />
+</svg>
+
diff --git a/svgio/source/svgreader/svgfecolormatrixnode.cxx 
b/svgio/source/svgreader/svgfecolormatrixnode.cxx
index fb53f1d5c503..2a02ddc3c0bd 100644
--- a/svgio/source/svgreader/svgfecolormatrixnode.cxx
+++ b/svgio/source/svgreader/svgfecolormatrixnode.cxx
@@ -25,7 +25,8 @@ namespace svgio::svgreader
 {
 SvgFeColorMatrixNode::SvgFeColorMatrixNode(SvgDocument& rDocument, SvgNode* 
pParent)
     : SvgNode(SVGToken::FeColorMatrix, rDocument, pParent)
-    , maType(Type::None)
+    , maType(ColorType::None)
+    , maValues(1.0)
 {
 }
 
@@ -43,8 +44,22 @@ void SvgFeColorMatrixNode::parseAttribute(const OUString& 
/*rTokenName*/, SVGTok
             {
                 if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), 
u"luminanceToAlpha"))
                 {
-                    maType = Type::LuminanceToAlpha;
+                    maType = ColorType::LuminanceToAlpha;
                 }
+                else if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), 
u"saturate"))
+                {
+                    maType = ColorType::Saturate;
+                }
+            }
+            break;
+        }
+        case SVGToken::Values:
+        {
+            SvgNumber aNum;
+
+            if (readSingleNumber(aContent, aNum))
+            {
+                maValues = aNum;
             }
             break;
         }
@@ -57,7 +72,7 @@ void SvgFeColorMatrixNode::parseAttribute(const OUString& 
/*rTokenName*/, SVGTok
 
 void 
SvgFeColorMatrixNode::apply(drawinglayer::primitive2d::Primitive2DContainer& 
rTarget) const
 {
-    if (maType == Type::LuminanceToAlpha)
+    if (maType == ColorType::LuminanceToAlpha)
     {
         const drawinglayer::primitive2d::Primitive2DReference xRef(
             new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
@@ -65,6 +80,14 @@ void 
SvgFeColorMatrixNode::apply(drawinglayer::primitive2d::Primitive2DContainer
                 
std::make_shared<basegfx::BColorModifier_luminance_to_alpha>()));
         rTarget = drawinglayer::primitive2d::Primitive2DContainer{ xRef };
     }
+    else if (maType == ColorType::Saturate)
+    {
+        const drawinglayer::primitive2d::Primitive2DReference xRef(
+            new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
+                std::move(rTarget),
+                
std::make_shared<basegfx::BColorModifier_saturate>(maValues.getNumber())));
+        rTarget = drawinglayer::primitive2d::Primitive2DContainer{ xRef };
+    }
 }
 
 } // end of namespace svgio::svgreader
diff --git a/svgio/source/svgreader/svgtoken.cxx 
b/svgio/source/svgreader/svgtoken.cxx
index 8228689606bf..09ed13459b2e 100644
--- a/svgio/source/svgreader/svgtoken.cxx
+++ b/svgio/source/svgreader/svgtoken.cxx
@@ -113,6 +113,7 @@ namespace svgio::svgreader
         const char aSVGStrXMaxYMax[] = "xMaxYMax";
         const char aSVGStrMeet[] = "meet";
         const char aSVGStrSlice[] = "slice";
+        const char aSVGStrValues[] = "values";
 
         const char aSVGStrDefs[] = "defs";
         const char aSVGStrG[] = "g";
@@ -265,6 +266,7 @@ namespace svgio::svgreader
                 { aSVGStrXMaxYMax, SVGToken::XMaxYMax },
                 { aSVGStrMeet, SVGToken::Meet },
                 { aSVGStrSlice, SVGToken::Slice },
+                { aSVGStrValues, SVGToken::Values },
 
                 { aSVGStrDefs, SVGToken::Defs },
                 { aSVGStrG, SVGToken::G },

Reply via email to