summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2022-05-11 12:54:48 +0200
committerBartosz Kosiorek <gang65@poczta.onet.pl>2022-05-13 13:49:18 +0200
commite709ebe42ad06974b822366e4eea1a6c2ee61e10 (patch)
tree6a1d2f1638fb92de8fbd07a7965fbde9003d80f7
parent99e10099b5d63c30b9a960fc94fc438ae7ab63dd (diff)
tdf#142261 EMF+ Add support for Miter Limit
With this commit the Miter is properly implemented, according to [EMF-PLUS] documentation: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-emfplus/5ef071f3-f503-4f16-b027-7c4bcf2d1d81 The formula for stroke miter limit is described here: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit Change-Id: Ida87063cc045460e61ffae118f64cf133c810dbf Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134164 Tested-by: Jenkins Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
-rw-r--r--drawinglayer/source/tools/emfphelperdata.cxx4
-rw-r--r--drawinglayer/source/tools/emfppen.cxx23
-rw-r--r--drawinglayer/source/tools/emfppen.hxx2
-rw-r--r--drawinglayer/source/tools/primitive2dxmldump.cxx5
-rw-r--r--emfio/qa/cppunit/emf/EmfImportTest.cxx50
-rw-r--r--emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithMiterLimit.emfbin0 -> 1104 bytes
6 files changed, 76 insertions, 8 deletions
diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx
index c5b282998d71..4d0db58c026b 100644
--- a/drawinglayer/source/tools/emfphelperdata.cxx
+++ b/drawinglayer/source/tools/emfphelperdata.cxx
@@ -596,8 +596,8 @@ namespace emfplushelper
const double transformedPenWidth = mdExtractedYScale * pen->penWidth;
drawinglayer::attribute::LineAttribute lineAttribute(
pen->GetColor().getBColor(), transformedPenWidth, pen->GetLineJoinType(),
- css::drawing::LineCap_BUTT,
- basegfx::deg2rad(15.0)); // TODO Add MiterLimit support
+ css::drawing::LineCap_BUTT, //TODO implement PenDataDashedLineCap supportr here
+ pen->fMiterMinimumAngle);
drawinglayer::attribute::LineStartEndAttribute aStart;
if (pen->penDataFlags & EmfPlusPenDataStartCap)
diff --git a/drawinglayer/source/tools/emfppen.cxx b/drawinglayer/source/tools/emfppen.cxx
index b0408f8d0e80..ec073d56ea59 100644
--- a/drawinglayer/source/tools/emfppen.cxx
+++ b/drawinglayer/source/tools/emfppen.cxx
@@ -58,7 +58,7 @@ namespace emfplushelper
, startCap(0)
, endCap(0)
, lineJoin(0)
- , miterLimit(0.0)
+ , fMiterMinimumAngle(basegfx::deg2rad(5.0))
, dashStyle(0)
, dashCap(0)
, dashOffset(0.0)
@@ -286,13 +286,26 @@ namespace emfplushelper
if (penDataFlags & PenDataMiterLimit)
{
+ float miterLimit;
s.ReadFloat(miterLimit);
- SAL_WARN("drawinglayer.emf", "EMF+\t\tTODO PenDataMiterLimit: " << std::dec << miterLimit);
+
+ // EMF+ JoinTypeMiterClipped is working as our B2DLineJoin::Miter
+ // For EMF+ LineJoinTypeMiter we are simulating it by changing angle
+ if (lineJoin == EmfPlusLineJoinTypeMiter)
+ miterLimit = 3.0 * miterLimit;
+ // asin angle must be in range [-1, 1]
+ if (abs(miterLimit) > 1.0)
+ fMiterMinimumAngle = 2.0 * asin(1.0 / miterLimit);
+ else
+ // enable miter limit for all angles
+ fMiterMinimumAngle = basegfx::deg2rad(180.0);
+ SAL_INFO("drawinglayer.emf",
+ "EMF+\t\t MiterLimit: " << std::dec << miterLimit
+ << ", Miter minimum angle (rad): " << fMiterMinimumAngle);
}
else
- {
- miterLimit = 0;
- }
+ fMiterMinimumAngle = basegfx::deg2rad(5.0);
+
if (penDataFlags & PenDataLineStyle)
{
diff --git a/drawinglayer/source/tools/emfppen.hxx b/drawinglayer/source/tools/emfppen.hxx
index cad849e4f278..6a7929f332f8 100644
--- a/drawinglayer/source/tools/emfppen.hxx
+++ b/drawinglayer/source/tools/emfppen.hxx
@@ -105,7 +105,7 @@ namespace emfplushelper
sal_Int32 startCap;
sal_Int32 endCap;
sal_Int32 lineJoin;
- float miterLimit;
+ double fMiterMinimumAngle;
sal_Int32 dashStyle;
sal_Int32 dashCap;
float dashOffset;
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx
index 886ffbf7fdd3..4e35d599876f 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -167,8 +167,12 @@ void writeLineAttribute(::tools::XmlWriter& rWriter,
rWriter.attribute("linejoin", "Bevel");
break;
case basegfx::B2DLineJoin::Miter:
+ {
rWriter.attribute("linejoin", "Miter");
+ rWriter.attribute("miterangle",
+ basegfx::rad2deg(rLineAttribute.getMiterMinimumAngle()));
break;
+ }
case basegfx::B2DLineJoin::Round:
rWriter.attribute("linejoin", "Round");
break;
@@ -191,6 +195,7 @@ void writeLineAttribute(::tools::XmlWriter& rWriter,
rWriter.attribute("linecap", "Unknown");
break;
}
+
rWriter.endElement();
}
diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index f83688745e02..6c5e77bb67dd 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -67,6 +67,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools, public unotest:
void TestFillRegion();
void TestEmfPlusGetDC();
void TestEmfPlusSave();
+ void TestEmfPlusDrawPathWithMiterLimit();
void TestExtTextOutOpaqueAndClipTransform();
void TestBitBltStretchBltWMF();
@@ -115,6 +116,7 @@ public:
CPPUNIT_TEST(TestFillRegion);
CPPUNIT_TEST(TestEmfPlusGetDC);
CPPUNIT_TEST(TestEmfPlusSave);
+ CPPUNIT_TEST(TestEmfPlusDrawPathWithMiterLimit);
CPPUNIT_TEST(TestExtTextOutOpaqueAndClipTransform);
CPPUNIT_TEST(TestBitBltStretchBltWMF);
@@ -1019,6 +1021,54 @@ void Test::TestEmfPlusSave()
"12832.6557236512,4907.54325697157");
}
+void Test::TestEmfPlusDrawPathWithMiterLimit()
+{
+ // tdf#142261 EMF+ records: DrawPath, TranslateWorldTransform, Object (Brush, Pen, Path)
+ // Check if Miter is correctly set for Lines
+ Primitive2DSequence aSequence
+ = parseEmf(u"emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithMiterLimit.emf");
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+ drawinglayer::Primitive2dXmlDump dumper;
+ xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence));
+ CPPUNIT_ASSERT(pDocument);
+
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke", 3);
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "color", "#c800c8");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "width", "1057");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "linejoin", "Miter");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "miterangle", "5");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/stroke", 0);
+
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence", 3);
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[1]", "transparence", "85");
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[1]/polypolygonstroke/line", "color",
+ "#6400c8");
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[1]/polypolygonstroke/line", "width",
+ "1057");
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[1]/polypolygonstroke/line",
+ "linejoin", "Miter");
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[1]/polypolygonstroke/line",
+ "miterangle", "19");
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[2]", "transparence", "69");
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[2]/polypolygonstroke/line",
+ "miterangle", "19");
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[3]", "transparence", "53");
+ assertXPath(pDocument, aXPathPrefix + "unifiedtransparence[3]/polypolygonstroke/line",
+ "miterangle", "19");
+
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "color", "#0000ff");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "width", "1057");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "linejoin", "Miter");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "miterangle", "60");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/stroke", 0);
+
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[3]/line", "color", "#0000ff");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[3]/line", "width", "1057");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[3]/line", "linejoin", "Miter");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[3]/line", "miterangle", "60");
+ assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[3]/stroke", 0);
+}
+
void Test::TestExtTextOutOpaqueAndClipTransform()
{
// tdf#142495 EMF records: SETBKCOLOR, SELECTOBJECT, EXTTEXTOUTW, MODIFYWORLDTRANSFORM, CREATEFONTINDIRECT.
diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithMiterLimit.emf b/emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithMiterLimit.emf
new file mode 100644
index 000000000000..e8e46486384b
--- /dev/null
+++ b/emfio/qa/cppunit/emf/data/TestEmfPlusDrawPathWithMiterLimit.emf
Binary files differ