From eb2fdd9bc6696732fa472f6883993334898cef7a Mon Sep 17 00:00:00 2001 From: Bartosz Kosiorek Date: Fri, 13 Nov 2020 13:24:36 +0100 Subject: tdf#35986 EMF import: Add support for PS_COSMETIC line style in CREATEPEN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the PS_COSMETIC line style is set in CREATEPEN, line width should be set to one logical unit and a style that is a solid color This patch is fixing that, allowing to properly import EMF file. The corresponding unit tests were added Change-Id: I1a0caf6382d9c313d9725d0b94e2fcd37122a099 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105790 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl --- emfio/qa/cppunit/emf/EmfImportTest.cxx | 53 ++++++++++++++++++++++++++++ emfio/qa/cppunit/emf/data/TestCreatePen.emf | Bin 0 -> 133136 bytes emfio/source/reader/emfreader.cxx | 29 +++++++++------ 3 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 emfio/qa/cppunit/emf/data/TestCreatePen.emf (limited to 'emfio') diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx index 94914da60f8a..29c084874b6d 100644 --- a/emfio/qa/cppunit/emf/EmfImportTest.cxx +++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx @@ -50,6 +50,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools, public unotest: void TestDrawLine(); void TestLinearGradient(); void TestTextMapMode(); + void TestCreatePen(); void TestPdfInEmf(); Primitive2DSequence parseEmf(const OUString& aSource); @@ -66,6 +67,7 @@ public: CPPUNIT_TEST(TestDrawLine); CPPUNIT_TEST(TestLinearGradient); CPPUNIT_TEST(TestTextMapMode); + CPPUNIT_TEST(TestCreatePen); CPPUNIT_TEST(TestPdfInEmf); CPPUNIT_TEST_SUITE_END(); }; @@ -270,6 +272,57 @@ void Test::TestTextMapMode() assertXPath(pDocument, "/primitive2D/metafile/transform/polygonstroke[20]/line", "width", "11"); } + +void Test::TestCreatePen() +{ + // Check import of EMF image with records: RESTOREDC, SAVEDC, MOVETOEX, LINETO, POLYLINE16, EXTTEXTOUTW with DxBuffer + // The CREATEPEN record is used with PS_COSMETIC line style, which will be displayed as solid hairline + Primitive2DSequence aSequence = parseEmf("/emfio/qa/cppunit/emf/data/TestCreatePen.emf"); + CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer(aSequence)); + CPPUNIT_ASSERT (pDocument); + + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygon", "path", "m0 0h31250v18192h-31250z"); + + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke", 3); + assertXPathContent(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[1]/polygon", "17898,5693 20172,5693"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[1]/line", "color", "#008000"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[1]/line", "width", "3"); + + assertXPathContent(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[2]/polygon", "17898,6959 20172,6959"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[2]/line", "color", "#000080"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[2]/line", "width", "3"); + + assertXPathContent(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[3]/polygon", "17898,7381 20172,7381"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[3]/line", "color", "#ff0000"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[3]/line", "width", "3"); + + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonhairline", 755); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonhairline[10]", "color", "#ff0000"); + assertXPathContent(pDocument, "/primitive2D/metafile/transform/mask/polygonhairline[10]/polygon", "27925,14180 27875,14180"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonhairline[100]", "color", "#008000"); + assertXPathContent(pDocument, "/primitive2D/metafile/transform/mask/polygonhairline[100]/polygon", "26100,14414 26050,14414"); + + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion", 69); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[1]", "width", "374"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[1]", "x", "28124"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[1]", "y", "16581"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[1]", "text", "0.0"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[1]", "fontcolor", "#000000"); + + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[10]", "width", "266"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[10]", "x", "28000"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[10]", "y", "428"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[10]", "text", "-6"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[10]", "fontcolor", "#000000"); + + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/pointarray", 8); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/pointarray[1]", "color", "#008000"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/pointarray[1]/point", "x", "25844"); + assertXPath(pDocument, "/primitive2D/metafile/transform/mask/pointarray[1]/point", "y", "8918"); +} + void Test::TestPdfInEmf() { // Load a PPTX file, which has a shape, with a bitmap fill, which is an EMF, containing a PDF. diff --git a/emfio/qa/cppunit/emf/data/TestCreatePen.emf b/emfio/qa/cppunit/emf/data/TestCreatePen.emf new file mode 100644 index 000000000000..5a13910ecf79 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestCreatePen.emf differ diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx index 8114584ba61f..b1d3ae4394da 100644 --- a/emfio/source/reader/emfreader.cxx +++ b/emfio/source/reader/emfreader.cxx @@ -1116,19 +1116,23 @@ namespace emfio mpInputStream->ReadUInt32( nIndex ); if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 ) { - LineInfo aLineInfo; sal_uInt32 nStyle; - Size aSize; - // #fdo39428 Remove SvStream operator>>(long&) - sal_Int32 nTmpW(0), nTmpH(0); + sal_Int32 nPenWidth, nIgnored; - mpInputStream->ReadUInt32( nStyle ).ReadInt32( nTmpW ).ReadInt32( nTmpH ); - aSize.setWidth( nTmpW ); - aSize.setHeight( nTmpH ); + mpInputStream->ReadUInt32( nStyle ).ReadInt32( nPenWidth ).ReadInt32( nIgnored ); - if ( aSize.Width() ) - aLineInfo.SetWidth( aSize.Width() ); + SAL_INFO("emfio", "\t\tIndex: " << nIndex << " nStyle: 0x" << std::hex << nStyle << std::dec << " nPenWidth: " << nPenWidth); + // nStyle = PS_COSMETIC = 0x0 - line with a width of one logical unit and a style that is a solid color + if ( !nStyle ) + { + // Width 0 means default width for LineInfo (HairLine) with 1 pixel wide + aLineInfo.SetWidth( 0 ); + } + else + { + aLineInfo.SetWidth( nPenWidth ); + } bool bTransparent = false; switch( nStyle & PS_STYLE_MASK ) @@ -1165,14 +1169,14 @@ namespace emfio switch( nStyle & PS_ENDCAP_STYLE_MASK ) { case PS_ENDCAP_ROUND : - if ( aSize.Width() ) + if ( nPenWidth ) { aLineInfo.SetLineCap( css::drawing::LineCap_ROUND ); break; } [[fallthrough]]; case PS_ENDCAP_SQUARE : - if ( aSize.Width() ) + if ( nPenWidth ) { aLineInfo.SetLineCap( css::drawing::LineCap_SQUARE ); break; @@ -1209,6 +1213,9 @@ namespace emfio sal_uInt32 offBmi, cbBmi, offBits, cbBits, nStyle, nWidth, nBrushStyle, elpNumEntries; sal_Int32 elpHatch; mpInputStream->ReadUInt32( offBmi ).ReadUInt32( cbBmi ).ReadUInt32( offBits ).ReadUInt32( cbBits ). ReadUInt32( nStyle ).ReadUInt32( nWidth ).ReadUInt32( nBrushStyle ); + + SAL_INFO("emfio", "\t\tStyle: 0x" << std::hex << nStyle << std::dec); + SAL_INFO("emfio", "\t\tWidth: " << nWidth); Color aColorRef = ReadColor(); mpInputStream->ReadInt32( elpHatch ).ReadUInt32( elpNumEntries ); -- cgit