summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--basegfx/source/color/bcolormodifier.cxx32
-rwxr-xr-xbasegfx/test/BColorModifierTest.cxx85
-rw-r--r--include/basegfx/color/bcolormodifier.hxx28
-rw-r--r--svgio/inc/svgfecolormatrixnode.hxx3
-rw-r--r--svgio/inc/svgtools.hxx2
-rw-r--r--svgio/qa/cppunit/SvgImportTest.cxx8
-rw-r--r--svgio/source/svgreader/svgfecolormatrixnode.cxx13
-rw-r--r--svgio/source/svgreader/svgtools.cxx34
8 files changed, 200 insertions, 5 deletions
diff --git a/basegfx/source/color/bcolormodifier.cxx b/basegfx/source/color/bcolormodifier.cxx
index 8d6f99a3faf5..829b0abda659 100644
--- a/basegfx/source/color/bcolormodifier.cxx
+++ b/basegfx/source/color/bcolormodifier.cxx
@@ -142,6 +142,38 @@ namespace basegfx
return "interpolate";
}
+ BColorModifier_matrix::~BColorModifier_matrix()
+ {
+ }
+
+ bool BColorModifier_matrix::operator==(const BColorModifier& rCompare) const
+ {
+ const BColorModifier_matrix* pCompare = dynamic_cast< const BColorModifier_matrix* >(&rCompare);
+
+ if(!pCompare)
+ {
+ return false;
+ }
+
+ return maMatrix == pCompare->maMatrix;
+ }
+
+ ::basegfx::BColor BColorModifier_matrix::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
+ {
+ basegfx::B3DHomMatrix aColorMatrix;
+ aColorMatrix.set(0, 0, aSourceColor.getRed());
+ aColorMatrix.set(1, 0, aSourceColor.getGreen());
+ aColorMatrix.set(2, 0, aSourceColor.getBlue());
+
+ aColorMatrix = maMatrix * aColorMatrix;
+ return ::basegfx::BColor(aColorMatrix.get(0, 0), aColorMatrix.get(1, 0), aColorMatrix.get(2, 0));
+ }
+
+ OUString BColorModifier_matrix::getModifierName() const
+ {
+ return "matrix";
+ }
+
BColorModifier_saturate::BColorModifier_saturate(double fValue)
{
maSatMatrix.set(0, 0, 0.213 + 0.787 * fValue);
diff --git a/basegfx/test/BColorModifierTest.cxx b/basegfx/test/BColorModifierTest.cxx
index d6e0648d2c17..17b6a0c22257 100755
--- a/basegfx/test/BColorModifierTest.cxx
+++ b/basegfx/test/BColorModifierTest.cxx
@@ -269,6 +269,89 @@ public:
CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2));
}
+ void testMatrix()
+ {
+ // green matrix
+ basegfx::B3DHomMatrix aMatrix;
+ aMatrix.set(0, 0, 0.0);
+ aMatrix.set(0, 1, 0.0);
+ aMatrix.set(0, 2, 0.0);
+ aMatrix.set(0, 3, 0.0);
+ aMatrix.set(1, 0, 1.0);
+ aMatrix.set(1, 1, 1.0);
+ aMatrix.set(1, 2, 1.0);
+ aMatrix.set(1, 3, 1.0);
+ aMatrix.set(2, 0, 0.0);
+ aMatrix.set(2, 1, 0.0);
+ aMatrix.set(2, 2, 0.0);
+ aMatrix.set(2, 3, 0.0);
+
+ const basegfx::BColorModifierSharedPtr aBColorModifier
+ = std::make_shared<basegfx::BColorModifier_matrix>(aMatrix);
+
+ BColor aExpectedWhite(0.0, 3.0, 0.0);
+ CPPUNIT_ASSERT_EQUAL(aExpectedWhite, aBColorModifier->getModifiedColor(maWhite));
+ BColor aExpectedGray(0.0, 1.5, 0.0);
+ CPPUNIT_ASSERT_EQUAL(aExpectedGray, aBColorModifier->getModifiedColor(maGray));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maBlack));
+
+ CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maGreen));
+ CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maBlue));
+ BColor aExpectedYellow(0.0, 2.0, 0.0);
+ CPPUNIT_ASSERT_EQUAL(aExpectedYellow, aBColorModifier->getModifiedColor(maYellow));
+ BColor aExpectedMagenta = aExpectedYellow;
+ CPPUNIT_ASSERT_EQUAL(aExpectedMagenta, aBColorModifier->getModifiedColor(maMagenta));
+ BColor aExpectedCyan = aExpectedYellow;
+ CPPUNIT_ASSERT_EQUAL(aExpectedCyan, aBColorModifier->getModifiedColor(maCyan));
+
+ CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier));
+ const basegfx::BColorModifierSharedPtr aBColorModifierInvert
+ = std::make_shared<basegfx::BColorModifier_invert>();
+ CPPUNIT_ASSERT(*aBColorModifier != *aBColorModifierInvert);
+
+ const basegfx::BColorModifierSharedPtr aBColorModifier2
+ = std::make_shared<basegfx::BColorModifier_matrix>(aMatrix);
+ CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2));
+ }
+
+ void testIdentityMatrix()
+ {
+ basegfx::B3DHomMatrix aMatrix;
+ aMatrix.set(0, 0, 1.0);
+ aMatrix.set(0, 1, 0.0);
+ aMatrix.set(0, 2, 0.0);
+ aMatrix.set(1, 0, 0.0);
+ aMatrix.set(1, 1, 1.0);
+ aMatrix.set(1, 2, 0.0);
+ aMatrix.set(2, 0, 0.0);
+ aMatrix.set(2, 1, 0.0);
+ aMatrix.set(2, 2, 1.0);
+
+ const basegfx::BColorModifierSharedPtr aBColorModifier
+ = std::make_shared<basegfx::BColorModifier_matrix>(aMatrix);
+
+ CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maWhite));
+ CPPUNIT_ASSERT_EQUAL(maGray, aBColorModifier->getModifiedColor(maGray));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maBlack));
+
+ CPPUNIT_ASSERT_EQUAL(maRed, aBColorModifier->getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maGreen));
+ CPPUNIT_ASSERT_EQUAL(maBlue, aBColorModifier->getModifiedColor(maBlue));
+ CPPUNIT_ASSERT_EQUAL(maYellow, aBColorModifier->getModifiedColor(maYellow));
+ CPPUNIT_ASSERT_EQUAL(maMagenta, aBColorModifier->getModifiedColor(maMagenta));
+ CPPUNIT_ASSERT_EQUAL(maCyan, aBColorModifier->getModifiedColor(maCyan));
+
+ CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier));
+ const basegfx::BColorModifierSharedPtr aBColorModifierInvert
+ = std::make_shared<basegfx::BColorModifier_invert>();
+ CPPUNIT_ASSERT(*aBColorModifier != *aBColorModifierInvert);
+
+ const basegfx::BColorModifierSharedPtr aBColorModifier2
+ = std::make_shared<basegfx::BColorModifier_matrix>(aMatrix);
+ CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2));
+ }
+
CPPUNIT_TEST_SUITE(bcolormodifier);
CPPUNIT_TEST(testGray);
CPPUNIT_TEST(testInvert);
@@ -277,6 +360,8 @@ public:
CPPUNIT_TEST(testSaturate);
CPPUNIT_TEST(testLuminanceToAlpha);
CPPUNIT_TEST(testHueRotate);
+ CPPUNIT_TEST(testMatrix);
+ CPPUNIT_TEST(testIdentityMatrix);
CPPUNIT_TEST_SUITE_END();
};
diff --git a/include/basegfx/color/bcolormodifier.hxx b/include/basegfx/color/bcolormodifier.hxx
index 5a3ca0a78adf..ceffae841847 100644
--- a/include/basegfx/color/bcolormodifier.hxx
+++ b/include/basegfx/color/bcolormodifier.hxx
@@ -21,6 +21,7 @@
#include <config_options.h>
#include <basegfx/basegfxdllapi.h>
+#include <basegfx/matrix/b3dhommatrix.hxx>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/matrix/b3dhommatrix.hxx>
#include <rtl/ustring.hxx>
@@ -236,6 +237,33 @@ namespace basegfx
SAL_DLLPRIVATE virtual OUString getModifierName() const override;
};
+ /** Apply matrix
+ 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_matrix final : public BColorModifier
+ {
+ private:
+ basegfx::B3DHomMatrix maMatrix;
+
+ public:
+ BColorModifier_matrix(basegfx::B3DHomMatrix aMatrix)
+ : maMatrix(aMatrix)
+ {
+ }
+
+ virtual ~BColorModifier_matrix() 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;
+ };
+
/** Apply hueRotate
This derivation is used for the svg importer and does exactly what SVG
defines for this needed case.
diff --git a/svgio/inc/svgfecolormatrixnode.hxx b/svgio/inc/svgfecolormatrixnode.hxx
index a63d44715457..78d8b027f653 100644
--- a/svgio/inc/svgfecolormatrixnode.hxx
+++ b/svgio/inc/svgfecolormatrixnode.hxx
@@ -21,7 +21,7 @@
#include "svgnode.hxx"
#include "svgstyleattributes.hxx"
-#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
namespace svgio::svgreader
{
@@ -29,6 +29,7 @@ enum class ColorType
{
None,
HueRotate,
+ Matrix,
Saturate,
LuminanceToAlpha
};
diff --git a/svgio/inc/svgtools.hxx b/svgio/inc/svgtools.hxx
index fd9bdd396d9d..1bca409001b6 100644
--- a/svgio/inc/svgtools.hxx
+++ b/svgio/inc/svgtools.hxx
@@ -20,6 +20,7 @@
#pragma once
#include <basegfx/color/bcolor.hxx>
+#include <basegfx/range/b3drange.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/vector/b2ivector.hxx>
#include <rtl/ustrbuf.hxx>
@@ -109,6 +110,7 @@ namespace svgio::svgreader
bool match_colorKeyword(basegfx::BColor& rColor, const OUString& rName);
bool read_color(const OUString& rCandidate, basegfx::BColor& rColor, SvgNumber& rOpacity);
basegfx::B2DRange readViewBox(std::u16string_view rCandidate, InfoProvider const & rInfoProvider);
+ basegfx::B3DHomMatrix readFilterMatrix(std::u16string_view rCandidate, InfoProvider const & rInfoProvider);
basegfx::B2DHomMatrix readTransform(std::u16string_view rCandidate, InfoProvider const & rInfoProvider);
bool readSingleNumber(std::u16string_view rCandidate, SvgNumber& aNum);
bool readLocalLink(std::u16string_view rCandidate, OUString& rURL);
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx
index 87beb7742405..df1337090ff3 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -163,10 +163,10 @@ CPPUNIT_TEST_FIXTURE(Test, testFeColorMatrix)
CPPUNIT_ASSERT (pDocument);
- //assertXPath(pDocument, "/primitive2D/transform/mask/modifiedColor", "modifier", "matrix");
- assertXPath(pDocument, "/primitive2D/transform/mask/modifiedColor[1]", "modifier", "saturate");
- assertXPath(pDocument, "/primitive2D/transform/mask/modifiedColor[2]", "modifier", "hueRotate");
- assertXPath(pDocument, "/primitive2D/transform/mask/modifiedColor[3]", "modifier", "luminance_to_alpha");
+ assertXPath(pDocument, "/primitive2D/transform/mask/modifiedColor[1]", "modifier", "matrix");
+ assertXPath(pDocument, "/primitive2D/transform/mask/modifiedColor[2]", "modifier", "saturate");
+ assertXPath(pDocument, "/primitive2D/transform/mask/modifiedColor[3]", "modifier", "hueRotate");
+ assertXPath(pDocument, "/primitive2D/transform/mask/modifiedColor[4]", "modifier", "luminance_to_alpha");
}
CPPUNIT_TEST_FIXTURE(Test, testFilterFeGaussianBlur)
diff --git a/svgio/source/svgreader/svgfecolormatrixnode.cxx b/svgio/source/svgreader/svgfecolormatrixnode.cxx
index 42611e48efdd..5f8e03c4318b 100644
--- a/svgio/source/svgreader/svgfecolormatrixnode.cxx
+++ b/svgio/source/svgreader/svgfecolormatrixnode.cxx
@@ -53,6 +53,10 @@ void SvgFeColorMatrixNode::parseAttribute(const OUString& /*rTokenName*/, SVGTok
{
maType = ColorType::HueRotate;
}
+ else if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"matrix"))
+ {
+ maType = ColorType::Matrix;
+ }
}
break;
}
@@ -99,6 +103,15 @@ void SvgFeColorMatrixNode::apply(drawinglayer::primitive2d::Primitive2DContainer
basegfx::deg2rad(aNum.getNumber()))));
rTarget = drawinglayer::primitive2d::Primitive2DContainer{ xRef };
}
+ else if (maType == ColorType::Matrix)
+ {
+ basegfx::B3DHomMatrix aMatrix = readFilterMatrix(maValuesContent, *this);
+
+ const drawinglayer::primitive2d::Primitive2DReference xRef(
+ new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
+ std::move(rTarget), std::make_shared<basegfx::BColorModifier_matrix>(aMatrix)));
+ rTarget = drawinglayer::primitive2d::Primitive2DContainer{ xRef };
+ }
}
} // end of namespace svgio::svgreader
diff --git a/svgio/source/svgreader/svgtools.cxx b/svgio/source/svgreader/svgtools.cxx
index af10626af3ad..f885086497c1 100644
--- a/svgio/source/svgreader/svgtools.cxx
+++ b/svgio/source/svgreader/svgtools.cxx
@@ -24,6 +24,7 @@
#include <o3tl/string_view.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
#include <svgtoken.hxx>
#include <unordered_map>
@@ -844,6 +845,39 @@ namespace svgio::svgreader
return basegfx::B2DRange();
}
+ basegfx::B3DHomMatrix readFilterMatrix(std::u16string_view rCandidate, InfoProvider const & rInfoProvider)
+ {
+ basegfx::B3DHomMatrix aMatrix;
+ const sal_Int32 nLen(rCandidate.size());
+
+ sal_Int32 nPos(0);
+ skip_char(rCandidate, ' ', ',', nPos, nLen);
+
+ SvgNumber aVal;
+
+ // create a 3x5 matrix using the first 15 values from the list of 20 matrix values.
+ // FIXME: support alpha (the last 5 values)
+ for (sal_uInt16 nRow = 0; nRow < 3; ++nRow)
+ {
+ for (sal_uInt16 nColumn = 0; nColumn < 5; ++nColumn)
+ {
+ // return earlier if there are not enough values
+ if (nPos >= nLen)
+ {
+ return basegfx::B3DHomMatrix();
+ }
+
+ if(readNumberAndUnit(rCandidate, nPos, aVal, nLen))
+ {
+ aMatrix.set(nRow, nColumn, aVal.solve(rInfoProvider));
+ skip_char(rCandidate, ' ', ',', nPos, nLen);
+ }
+ }
+ }
+
+ return aMatrix;
+ }
+
basegfx::B2DHomMatrix readTransform(std::u16string_view rCandidate, InfoProvider const & rInfoProvider)
{
basegfx::B2DHomMatrix aMatrix;