diff options
author | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2022-06-16 02:47:23 +0200 |
---|---|---|
committer | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2022-06-27 10:24:13 +0200 |
commit | 5b21b65572610df88986e700b81f1156aff14f65 (patch) | |
tree | 340f3853fa498974e5108bef05fc9f2bcd804267 | |
parent | 75e2d313760847110479f00a86a19fba4f508181 (diff) |
tdf#142770 tdf#143031 EMF+ Implement CustomLineCap
Change-Id: I9fae1d259ecdca37a1babac8a8a0e503b2dc0118
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135960
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
-rw-r--r-- | drawinglayer/source/tools/emfpcustomlinecap.cxx | 26 | ||||
-rw-r--r-- | drawinglayer/source/tools/emfpcustomlinecap.hxx | 2 | ||||
-rw-r--r-- | drawinglayer/source/tools/emfphelperdata.cxx | 113 | ||||
-rw-r--r-- | emfio/qa/cppunit/emf/EmfImportTest.cxx | 26 | ||||
-rw-r--r-- | emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emf | bin | 0 -> 492 bytes |
5 files changed, 61 insertions, 106 deletions
diff --git a/drawinglayer/source/tools/emfpcustomlinecap.cxx b/drawinglayer/source/tools/emfpcustomlinecap.cxx index 49cc912ed33c..e457a36cc2c4 100644 --- a/drawinglayer/source/tools/emfpcustomlinecap.cxx +++ b/drawinglayer/source/tools/emfpcustomlinecap.cxx @@ -21,6 +21,7 @@ #include "emfpcustomlinecap.hxx" #include "emfppath.hxx" #include "emfppen.hxx" +#include <basegfx/matrix/b2dhommatrixtools.hxx> using namespace ::com::sun::star; using namespace ::basegfx; @@ -39,6 +40,7 @@ namespace emfplushelper , strokeEndCap(0) , strokeJoin(0) , miterLimit(0.0) + , widthScale(0.0) , mbIsFilled(false) { } @@ -57,6 +59,8 @@ namespace emfplushelper EMFPPath path(pathPoints); path.Read(s, pathFlags); polygon = path.GetPolygon(rR, false); + // rotate polygon by 180 degrees + polygon.transform(basegfx::utils::createRotateB2DHomMatrix(M_PI)); mbIsFilled = bFill; } @@ -71,7 +75,6 @@ namespace emfplushelper { sal_uInt32 customLineCapDataFlags, baseCap; float baseInset; - float widthScale; float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY; s.ReadUInt32(customLineCapDataFlags).ReadUInt32(baseCap).ReadFloat(baseInset) @@ -82,11 +85,6 @@ namespace emfplushelper SAL_INFO("drawinglayer.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags); SAL_INFO("drawinglayer.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap); SAL_INFO("drawinglayer.emf", "EMF+\t\tbaseInset: " << baseInset); - SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap); - SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap); - SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin); - SAL_INFO("drawinglayer.emf", "EMF+\t\tmiterLimit: " << miterLimit); - SAL_INFO("drawinglayer.emf", "EMF+\t\twidthScale: " << widthScale); if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath) { @@ -103,16 +101,20 @@ namespace emfplushelper // TODO only reads the data, does not use them [I've had // no test document to be able to implement it] - sal_Int32 width, height, middleInset, fillState, lineStartCap; - sal_Int32 lineEndCap, lineJoin, widthScale; - float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY; + sal_Int32 fillState; + float width, height, middleInset, unusedHotSpot; - s.ReadInt32(width).ReadInt32(height).ReadInt32(middleInset).ReadInt32(fillState).ReadInt32(lineStartCap) - .ReadInt32(lineEndCap).ReadInt32(lineJoin).ReadFloat(miterLimit).ReadInt32(widthScale) - .ReadFloat(fillHotSpotX).ReadFloat(fillHotSpotY).ReadFloat(lineHotSpotX).ReadFloat(lineHotSpotY); + s.ReadFloat(width).ReadFloat(height).ReadFloat(middleInset).ReadInt32(fillState).ReadUInt32(strokeStartCap) + .ReadUInt32(strokeEndCap).ReadUInt32(strokeJoin).ReadFloat(miterLimit).ReadFloat(widthScale) + .ReadFloat(unusedHotSpot).ReadFloat(unusedHotSpot).ReadFloat(unusedHotSpot).ReadFloat(unusedHotSpot); SAL_INFO("drawinglayer.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)"); } + SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap); + SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap); + SAL_INFO("drawinglayer.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin); + SAL_INFO("drawinglayer.emf", "EMF+\t\tmiterLimit: " << miterLimit); + SAL_INFO("drawinglayer.emf", "EMF+\t\twidthScale: " << widthScale); } } diff --git a/drawinglayer/source/tools/emfpcustomlinecap.hxx b/drawinglayer/source/tools/emfpcustomlinecap.hxx index e6202ae98179..22ed6be6dd4d 100644 --- a/drawinglayer/source/tools/emfpcustomlinecap.hxx +++ b/drawinglayer/source/tools/emfpcustomlinecap.hxx @@ -27,7 +27,7 @@ namespace emfplushelper { sal_uInt32 type; sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin; - float miterLimit; + float miterLimit, widthScale; basegfx::B2DPolyPolygon polygon; bool mbIsFilled; diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx index 9e0c78c4551b..542259568cd0 100644 --- a/drawinglayer/source/tools/emfphelperdata.cxx +++ b/drawinglayer/source/tools/emfphelperdata.cxx @@ -603,11 +603,29 @@ namespace emfplushelper drawinglayer::attribute::LineStartEndAttribute aStart; if (pen->penDataFlags & EmfPlusPenDataStartCap) - aStart = EmfPlusHelperData::CreateLineEnd(pen->startCap, pen->penWidth); + { + if ((pen->penDataFlags & EmfPlusPenDataCustomStartCap) + && (pen->customStartCap->polygon.begin()->count() > 1)) + aStart = drawinglayer::attribute::LineStartEndAttribute( + pen->customStartCap->polygon.getB2DRange().getRange().getX() * mdExtractedXScale + * pen->customStartCap->widthScale * pen->penWidth, + pen->customStartCap->polygon, false); + else + aStart = EmfPlusHelperData::CreateLineEnd(pen->startCap, pen->penWidth); + } drawinglayer::attribute::LineStartEndAttribute aEnd; if (pen->penDataFlags & EmfPlusPenDataEndCap) - aEnd = EmfPlusHelperData::CreateLineEnd(pen->endCap, pen->penWidth); + { + if ((pen->penDataFlags & EmfPlusPenDataCustomEndCap) + && (pen->customEndCap->polygon.begin()->count() > 1)) + aEnd = drawinglayer::attribute::LineStartEndAttribute( + pen->customEndCap->polygon.getB2DRange().getRange().getX() * mdExtractedXScale + * pen->customEndCap->widthScale * pen->penWidth, + pen->customEndCap->polygon, false); + else + aEnd = EmfPlusHelperData::CreateLineEnd(pen->endCap, pen->penWidth); + } if (pen->GetColor().IsTransparent()) { @@ -644,97 +662,6 @@ namespace emfplushelper pen->GetStrokeAttribute(mdExtractedXScale), aStart, aEnd)); } } - - if ((pen->penDataFlags & EmfPlusPenDataCustomStartCap) && (pen->customStartCap->polygon.begin()->count() > 1)) - { - SAL_WARN("drawinglayer.emf", "EMF+\tCustom Start Line Cap"); - ::basegfx::B2DPolyPolygon startCapPolygon(pen->customStartCap->polygon); - - // get the gradient of the first line in the polypolygon - double x1 = polygon.begin()->getB2DPoint(0).getX(); - double y1 = polygon.begin()->getB2DPoint(0).getY(); - double x2 = polygon.begin()->getB2DPoint(1).getX(); - double y2 = polygon.begin()->getB2DPoint(1).getY(); - - if ((x2 - x1) != 0) - { - double gradient = (y2 - y1) / (x2 - x1); - - // now we get the angle that we need to rotate the arrow by - double angle = (M_PI / 2) - atan(gradient); - - // rotate the arrow - startCapPolygon.transform(basegfx::utils::createRotateB2DHomMatrix(angle)); - } - - startCapPolygon.transform(maMapTransform); - - basegfx::B2DHomMatrix tran(pen->penWidth, 0.0, polygon.begin()->getB2DPoint(0).getX(), - 0.0, pen->penWidth, polygon.begin()->getB2DPoint(0).getY()); - startCapPolygon.transform(tran); - - if (pen->customStartCap->mbIsFilled) - { - mrTargetHolders.Current().append( - new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( - std::move(startCapPolygon), - pen->GetColor().getBColor())); - } - else - { - mrTargetHolders.Current().append( - new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( - std::move(startCapPolygon), - lineAttribute, - pen->GetStrokeAttribute(mdExtractedXScale))); - } - } - - if ((pen->penDataFlags & EmfPlusPenDataCustomEndCap) && (pen->customEndCap->polygon.begin()->count() > 1)) - { - SAL_WARN("drawinglayer.emf", "EMF+\tCustom End Line Cap"); - - ::basegfx::B2DPolyPolygon endCapPolygon(pen->customEndCap->polygon); - - // get the gradient of the first line in the polypolygon - double x1 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getX(); - double y1 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getY(); - double x2 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 2).getX(); - double y2 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 2).getY(); - - if ((x2 - x1) != 0) - { - double gradient = (y2 - y1) / (x2 - x1); - - // now we get the angle that we need to rotate the arrow by - double angle = (M_PI / 2) - atan(gradient); - - // rotate the arrow - endCapPolygon.transform(basegfx::utils::createRotateB2DHomMatrix(angle)); - } - - endCapPolygon.transform(maMapTransform); - basegfx::B2DHomMatrix tran(pen->penWidth, 0.0, polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getX(), - 0.0, pen->penWidth, polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getY()); - endCapPolygon.transform(tran); - - if (pen->customEndCap->mbIsFilled) - { - mrTargetHolders.Current().append( - new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( - std::move(endCapPolygon), - pen->GetColor().getBColor())); - } - else - { - mrTargetHolders.Current().append( - new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( - std::move(endCapPolygon), - lineAttribute, - pen->GetStrokeAttribute(mdExtractedXScale))); - } - } - mrPropertyHolders.Current().setLineColor(pen->GetColor().getBColor()); mrPropertyHolders.Current().setLineColorActive(true); mrPropertyHolders.Current().setFillColorActive(false); diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx index 40db85d69d2e..b423eae91721 100644 --- a/emfio/qa/cppunit/emf/EmfImportTest.cxx +++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx @@ -68,6 +68,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools, public unotest: void TestEmfPlusBrushPathGradientWithBlendColors(); void TestEmfPlusGetDC(); void TestEmfPlusSave(); + void TestEmfPlusDrawPathWithCustomCap(); void TestEmfPlusDrawPathWithMiterLimit(); void TestEmfPlusFillClosedCurve(); void TestExtTextOutOpaqueAndClipTransform(); @@ -119,6 +120,7 @@ public: CPPUNIT_TEST(TestEmfPlusBrushPathGradientWithBlendColors); CPPUNIT_TEST(TestEmfPlusGetDC); CPPUNIT_TEST(TestEmfPlusSave); + CPPUNIT_TEST(TestEmfPlusDrawPathWithCustomCap); CPPUNIT_TEST(TestEmfPlusDrawPathWithMiterLimit); CPPUNIT_TEST(TestEmfPlusFillClosedCurve); CPPUNIT_TEST(TestExtTextOutOpaqueAndClipTransform); @@ -1046,6 +1048,30 @@ void Test::TestEmfPlusSave() "12832.6557236512,4907.54325697157"); } +void Test::TestEmfPlusDrawPathWithCustomCap() +{ + // tdf#142261 EMF+ records: DrawPath, SetWorldTransform, Object (Brush, Pen, Path) + // Check if CustomEndCap is displayed correctly + Primitive2DSequence aSequence + = parseEmf(u"emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + CPPUNIT_ASSERT(pDocument); + + assertXPathContent(pDocument, aXPathPrefix + "polygonstrokearrow/polygon", + "1423.297394625,1268.98481214025 830.006276132353,558.656004112967"); + assertXPath(pDocument, aXPathPrefix + "polygonstrokearrow/line", "color", "#cc0000"); + assertXPath(pDocument, aXPathPrefix + "polygonstrokearrow/line", "width", "96"); + assertXPath(pDocument, aXPathPrefix + "polygonstrokearrow/line", "linecap", "BUTT"); + assertXPath(pDocument, aXPathPrefix + "polygonstrokearrow/stroke", 0); + assertXPath(pDocument, aXPathPrefix + "polygonstrokearrow/linestartattribute", 0); + + assertXPath(pDocument, aXPathPrefix + "polygonstrokearrow/lineendattribute", "centered", "0"); + assertXPath(pDocument, aXPathPrefix + "polygonstrokearrow/lineendattribute/polypolygon", "path", + "m-1.5 3 1.5-3 1.5 3z"); +} + void Test::TestEmfPlusDrawPathWithMiterLimit() { // tdf#142261 EMF+ records: DrawPath, TranslateWorldTransform, Object (Brush, Pen, Path) diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emf b/emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emf Binary files differnew file mode 100644 index 000000000000..e94986431618 --- /dev/null +++ b/emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emf |