drawinglayer/source/tools/emfpcustomlinecap.cxx                |   26 +-
 drawinglayer/source/tools/emfpcustomlinecap.hxx                |    2 
 drawinglayer/source/tools/emfphelperdata.cxx                   |  113 
+---------
 emfio/qa/cppunit/emf/EmfImportTest.cxx                         |   26 ++
 emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emf |binary
 5 files changed, 61 insertions(+), 106 deletions(-)

New commits:
commit ba806269c998b96842bcf0986095f22ab99a686a
Author:     Bartosz Kosiorek <gan...@poczta.onet.pl>
AuthorDate: Thu Jun 16 02:47:23 2022 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Mon Jun 27 16:40:26 2022 +0200

    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 <gan...@poczta.onet.pl>
    (cherry picked from commit 5b21b65572610df88986e700b81f1156aff14f65)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136463
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

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 94a50fc05cea..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(
-                                startCapPolygon,
-                                pen->GetColor().getBColor()));
-            }
-            else
-            {
-                mrTargetHolders.Current().append(
-                            new 
drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
-                                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(
-                                endCapPolygon,
-                                pen->GetColor().getBColor()));
-            }
-            else
-            {
-                mrTargetHolders.Current().append(
-                            new 
drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
-                                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
new file mode 100644
index 000000000000..e94986431618
Binary files /dev/null and 
b/emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emf differ

Reply via email to