summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2022-06-16 02:47:23 +0200
committerBartosz Kosiorek <gang65@poczta.onet.pl>2022-06-27 10:24:13 +0200
commit5b21b65572610df88986e700b81f1156aff14f65 (patch)
tree340f3853fa498974e5108bef05fc9f2bcd804267
parent75e2d313760847110479f00a86a19fba4f508181 (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.cxx26
-rw-r--r--drawinglayer/source/tools/emfpcustomlinecap.hxx2
-rw-r--r--drawinglayer/source/tools/emfphelperdata.cxx113
-rw-r--r--emfio/qa/cppunit/emf/EmfImportTest.cxx26
-rw-r--r--emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emfbin0 -> 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
new file mode 100644
index 000000000000..e94986431618
--- /dev/null
+++ b/emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithCustomCap.emf
Binary files differ