summaryrefslogtreecommitdiff
path: root/svgio/source/svgreader/svgfecompositenode.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svgio/source/svgreader/svgfecompositenode.cxx')
-rw-r--r--svgio/source/svgreader/svgfecompositenode.cxx214
1 files changed, 166 insertions, 48 deletions
diff --git a/svgio/source/svgreader/svgfecompositenode.cxx b/svgio/source/svgreader/svgfecompositenode.cxx
index 88ba5c62df68..28f161d7b6ce 100644
--- a/svgio/source/svgreader/svgfecompositenode.cxx
+++ b/svgio/source/svgreader/svgfecompositenode.cxx
@@ -23,6 +23,14 @@
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/processor2d/contourextractor2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/BitmapArithmeticBlendFilter.hxx>
+#include <drawinglayer/converters.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <vcl/BitmapWriteAccess.hxx>
+#include <vcl/BitmapTools.hxx>
namespace svgio::svgreader
{
@@ -83,6 +91,50 @@ void SvgFeCompositeNode::parseAttribute(SVGToken aSVGToken, const OUString& aCon
{
maOperator = Operator::Atop;
}
+ else if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"arithmetic"))
+ {
+ maOperator = Operator::Arithmetic;
+ }
+ }
+ break;
+ }
+ case SVGToken::K1:
+ {
+ SvgNumber aNum;
+
+ if (readSingleNumber(aContent, aNum))
+ {
+ maK1 = aNum;
+ }
+ break;
+ }
+ case SVGToken::K2:
+ {
+ SvgNumber aNum;
+
+ if (readSingleNumber(aContent, aNum))
+ {
+ maK2 = aNum;
+ }
+ break;
+ }
+ case SVGToken::K3:
+ {
+ SvgNumber aNum;
+
+ if (readSingleNumber(aContent, aNum))
+ {
+ maK3 = aNum;
+ }
+ break;
+ }
+ case SVGToken::K4:
+ {
+ SvgNumber aNum;
+
+ if (readSingleNumber(aContent, aNum))
+ {
+ maK4 = aNum;
}
break;
}
@@ -96,61 +148,127 @@ void SvgFeCompositeNode::parseAttribute(SVGToken aSVGToken, const OUString& aCon
void SvgFeCompositeNode::apply(drawinglayer::primitive2d::Primitive2DContainer& rTarget,
const SvgFilterNode* pParent) const
{
- basegfx::B2DPolyPolygon aPolyPolygon, aPolyPolygon2;
-
- // Process maIn2 first
- if (const drawinglayer::primitive2d::Primitive2DContainer* pSource2
- = pParent->findGraphicSource(maIn2))
+ if (maOperator != Operator::Arithmetic)
{
- rTarget.append(*pSource2);
- drawinglayer::processor2d::ContourExtractor2D aExtractor(
- drawinglayer::geometry::ViewInformation2D(), true);
- aExtractor.process(*pSource2);
- const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour());
- aPolyPolygon2 = basegfx::utils::mergeToSinglePolyPolygon(rResult);
- }
+ basegfx::B2DPolyPolygon aPolyPolygon, aPolyPolygon2;
- if (const drawinglayer::primitive2d::Primitive2DContainer* pSource
- = pParent->findGraphicSource(maIn))
- {
- rTarget.append(*pSource);
- drawinglayer::processor2d::ContourExtractor2D aExtractor(
- drawinglayer::geometry::ViewInformation2D(), true);
- aExtractor.process(*pSource);
- const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour());
- aPolyPolygon = basegfx::utils::mergeToSinglePolyPolygon(rResult);
- }
+ // Process maIn2 first
+ if (const drawinglayer::primitive2d::Primitive2DContainer* pSource2
+ = pParent->findGraphicSource(maIn2))
+ {
+ rTarget.append(*pSource2);
+ drawinglayer::processor2d::ContourExtractor2D aExtractor(
+ drawinglayer::geometry::ViewInformation2D(), true);
+ aExtractor.process(*pSource2);
+ const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour());
+ aPolyPolygon2 = basegfx::utils::mergeToSinglePolyPolygon(rResult);
+ }
- basegfx::B2DPolyPolygon aResult;
- if (maOperator == Operator::Over)
- {
- aResult = basegfx::utils::solvePolygonOperationOr(aPolyPolygon, aPolyPolygon2);
- }
- else if (maOperator == Operator::Out)
- {
- aResult = basegfx::utils::solvePolygonOperationDiff(aPolyPolygon, aPolyPolygon2);
- }
- else if (maOperator == Operator::In)
- {
- aResult = basegfx::utils::solvePolygonOperationAnd(aPolyPolygon, aPolyPolygon2);
- }
- else if (maOperator == Operator::Xor)
- {
- aResult = basegfx::utils::solvePolygonOperationXor(aPolyPolygon, aPolyPolygon2);
+ if (const drawinglayer::primitive2d::Primitive2DContainer* pSource
+ = pParent->findGraphicSource(maIn))
+ {
+ rTarget.append(*pSource);
+ drawinglayer::processor2d::ContourExtractor2D aExtractor(
+ drawinglayer::geometry::ViewInformation2D(), true);
+ aExtractor.process(*pSource);
+ const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour());
+ aPolyPolygon = basegfx::utils::mergeToSinglePolyPolygon(rResult);
+ }
+
+ basegfx::B2DPolyPolygon aResult;
+ if (maOperator == Operator::Over)
+ {
+ aResult = basegfx::utils::solvePolygonOperationOr(aPolyPolygon, aPolyPolygon2);
+ }
+ else if (maOperator == Operator::Out)
+ {
+ aResult = basegfx::utils::solvePolygonOperationDiff(aPolyPolygon, aPolyPolygon2);
+ }
+ else if (maOperator == Operator::In)
+ {
+ aResult = basegfx::utils::solvePolygonOperationAnd(aPolyPolygon, aPolyPolygon2);
+ }
+ else if (maOperator == Operator::Xor)
+ {
+ aResult = basegfx::utils::solvePolygonOperationXor(aPolyPolygon, aPolyPolygon2);
+ }
+ else if (maOperator == Operator::Atop)
+ {
+ // Atop is the union of In and Out.
+ // The parts of in2 graphic that do not overlap with the in graphic stay untouched.
+ aResult = basegfx::utils::solvePolygonOperationDiff(aPolyPolygon2, aPolyPolygon);
+ aResult.append(basegfx::utils::solvePolygonOperationAnd(aPolyPolygon, aPolyPolygon2));
+ }
+
+ rTarget = drawinglayer::primitive2d::Primitive2DContainer{
+ new drawinglayer::primitive2d::MaskPrimitive2D(std::move(aResult), std::move(rTarget))
+ };
+
+ pParent->addGraphicSourceToMapper(maResult, rTarget);
}
- else if (maOperator == Operator::Atop)
+ else
{
- // Atop is the union of In and Out.
- // The parts of in2 graphic that do not overlap with the in graphic stay untouched.
- aResult = basegfx::utils::solvePolygonOperationDiff(aPolyPolygon2, aPolyPolygon);
- aResult.append(basegfx::utils::solvePolygonOperationAnd(aPolyPolygon, aPolyPolygon2));
- }
+ basegfx::B2DRange aRange, aRange2;
+ BitmapEx aBmpEx, aBmpEx2;
+
+ if (const drawinglayer::primitive2d::Primitive2DContainer* pSource
+ = pParent->findGraphicSource(maIn))
+ {
+ const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
+ aRange = pSource->getB2DRange(aViewInformation2D);
+ basegfx::B2DHomMatrix aEmbedding(
+ basegfx::utils::createTranslateB2DHomMatrix(-aRange.getMinX(), -aRange.getMinY()));
+
+ aEmbedding.scale(aRange.getWidth(), aRange.getHeight());
- rTarget = drawinglayer::primitive2d::Primitive2DContainer{
- new drawinglayer::primitive2d::MaskPrimitive2D(std::move(aResult), std::move(rTarget))
- };
+ const drawinglayer::primitive2d::Primitive2DReference xEmbedRef(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
+ aEmbedding, drawinglayer::primitive2d::Primitive2DContainer(*pSource)));
+ drawinglayer::primitive2d::Primitive2DContainer xEmbedSeq{ xEmbedRef };
+
+ aBmpEx = drawinglayer::convertToBitmapEx(std::move(xEmbedSeq), aViewInformation2D,
+ aRange.getWidth(), aRange.getHeight(), 500000);
+ }
+
+ if (const drawinglayer::primitive2d::Primitive2DContainer* pSource2
+ = pParent->findGraphicSource(maIn2))
+ {
+ const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
+ aRange2 = pSource2->getB2DRange(aViewInformation2D);
+ basegfx::B2DHomMatrix aEmbedding(basegfx::utils::createTranslateB2DHomMatrix(
+ -aRange2.getMinX(), -aRange2.getMinY()));
- pParent->addGraphicSourceToMapper(maResult, rTarget);
+ aEmbedding.scale(aRange2.getWidth(), aRange2.getHeight());
+
+ const drawinglayer::primitive2d::Primitive2DReference xEmbedRef(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
+ aEmbedding, drawinglayer::primitive2d::Primitive2DContainer(*pSource2)));
+ drawinglayer::primitive2d::Primitive2DContainer xEmbedSeq{ xEmbedRef };
+
+ aBmpEx2
+ = drawinglayer::convertToBitmapEx(std::move(xEmbedSeq), aViewInformation2D,
+ aRange2.getWidth(), aRange2.getHeight(), 500000);
+ }
+
+ basegfx::B2DRectangle aBaseRect(std::min(aRange.getMinX(), aRange2.getMinX()),
+ std::min(aRange.getMinY(), aRange2.getMinY()),
+ std::max(aRange.getMaxX(), aRange2.getMaxX()),
+ std::max(aRange.getMaxY(), aRange2.getMaxY()));
+
+ aBmpEx = vcl::bitmap::DrawBitmapInRect(aBmpEx, aRange, aBaseRect);
+ aBmpEx2 = vcl::bitmap::DrawBitmapInRect(aBmpEx2, aRange2, aBaseRect);
+
+ BitmapArithmeticBlendFilter* pArithmeticFilter
+ = new BitmapArithmeticBlendFilter(aBmpEx, aBmpEx2);
+ BitmapEx aResBmpEx = pArithmeticFilter->execute(maK1.getNumber(), maK2.getNumber(),
+ maK3.getNumber(), maK4.getNumber());
+
+ const drawinglayer::primitive2d::Primitive2DReference xRef(
+ new drawinglayer::primitive2d::BitmapPrimitive2D(
+ aResBmpEx, basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aBaseRect.getRange(), aBaseRect.getMinimum())));
+ rTarget = drawinglayer::primitive2d::Primitive2DContainer{ xRef };
+ }
}
} // end of namespace svgio::svgreader