/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { using namespace css; using namespace css::uno; using namespace css::io; using namespace css::graphic; using drawinglayer::primitive2d::Primitive2DSequence; using drawinglayer::primitive2d::Primitive2DContainer; class Test : public test::BootstrapFixture, public XmlTestTools, public unotest::MacrosTest { uno::Reference mxComponent; void testPolyPolygon(); void TestDrawString(); void TestDrawStringTransparent(); void TestDrawLine(); void TestLinearGradient(); void TestTextMapMode(); void TestCreatePen(); void TestPdfInEmf(); Primitive2DSequence parseEmf(const OUString& aSource); public: void setUp() override; void tearDown() override; uno::Reference& getComponent() { return mxComponent; } CPPUNIT_TEST_SUITE(Test); CPPUNIT_TEST(testPolyPolygon); CPPUNIT_TEST(TestDrawString); CPPUNIT_TEST(TestDrawStringTransparent); CPPUNIT_TEST(TestDrawLine); CPPUNIT_TEST(TestLinearGradient); CPPUNIT_TEST(TestTextMapMode); CPPUNIT_TEST(TestCreatePen); CPPUNIT_TEST(TestPdfInEmf); CPPUNIT_TEST_SUITE_END(); }; void Test::setUp() { test::BootstrapFixture::setUp(); mxDesktop.set(frame::Desktop::create(mxComponentContext)); } void Test::tearDown() { if (mxComponent.is()) mxComponent->dispose(); test::BootstrapFixture::tearDown(); } Primitive2DSequence Test::parseEmf(const OUString& aSource) { const Reference xEmfParser = EmfTools::create(m_xContext); OUString aUrl = m_directories.getURLFromSrc(aSource); OUString aPath = m_directories.getPathFromSrc(aSource); SvFileStream aFileStream(aUrl, StreamMode::READ); std::size_t nSize = aFileStream.remainingSize(); std::unique_ptr pBuffer(new sal_Int8[nSize + 1]); aFileStream.ReadBytes(pBuffer.get(), nSize); pBuffer[nSize] = 0; Sequence aData(pBuffer.get(), nSize + 1); Reference aInputStream(new comphelper::SequenceInputStream(aData)); css::uno::Sequence< css::beans::PropertyValue > aEmptyValues; return xEmfParser->getDecomposition(aInputStream, aPath, aEmptyValues); } void Test::testPolyPolygon() { Primitive2DSequence aSequence = parseEmf("/emfio/qa/cppunit/emf/data/fdo79679-2.emf"); CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); drawinglayer::tools::Primitive2dXmlDump dumper; xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer(aSequence)); CPPUNIT_ASSERT (pDocument); // Chart axis assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygon", "path", "m0 0h19746v14817h-19746z"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygoncolor", 2); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygoncolor[1]", "color", "#ffffff"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygoncolor[1]/polypolygon", "path", "m0 0h19780v14851h-19780z"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygoncolor[2]/polypolygon", "path", "m2574 13194v-12065h15303v12065z"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke", 116); assertXPathContent(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[1]/polygon", "2574,13194 2574,1129 17877,1129 17877,13194"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[1]/line", "color", "#ffffff"); assertXPathContent(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[10]/polygon", "8674,13194 8674,1129"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonstroke[10]/line", "color", "#000000"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion", 28); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[6]", "width", "459"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[6]", "x", "9908"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[6]", "text", "0.5"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/textsimpleportion[6]", "fontcolor", "#000000"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/pointarray", 98); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/pointarray[1]", "color", "#000000"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/pointarray[1]/point", "x", "2574"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/pointarray[1]/point", "y", "1129"); } void Test::TestDrawString() { #if HAVE_MORE_FONTS // This unit checks for a correct import of an EMF+ file with only one DrawString Record // Since the text is undecorated the optimal choice is a simpletextportion primitive // first, get the sequence of primitives and dump it Primitive2DSequence aSequence = parseEmf("/emfio/qa/cppunit/emf/data/TestDrawString.emf"); CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); drawinglayer::tools::Primitive2dXmlDump dumper; xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer(aSequence)); CPPUNIT_ASSERT (pDocument); // check correct import of the DrawString: height, position, text, color and font assertXPath(pDocument, "/primitive2D/metafile/transform/transform/textsimpleportion", "height", "120"); assertXPath(pDocument, "/primitive2D/metafile/transform/transform/textsimpleportion", "x", "817"); assertXPath(pDocument, "/primitive2D/metafile/transform/transform/textsimpleportion", "y", "1137"); assertXPath(pDocument, "/primitive2D/metafile/transform/transform/textsimpleportion", "text", "TEST"); assertXPath(pDocument, "/primitive2D/metafile/transform/transform/textsimpleportion", "fontcolor", "#000000"); assertXPath(pDocument, "/primitive2D/metafile/transform/transform/textsimpleportion", "familyname", "CALIBRI"); #endif } void Test::TestDrawStringTransparent() { #if HAVE_MORE_FONTS // This unit checks for a correct import of an EMF+ file with one DrawString Record with transparency // first, get the sequence of primitives and dump it Primitive2DSequence aSequence = parseEmf("/emfio/qa/cppunit/emf/data/TestDrawStringTransparent.emf"); CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); drawinglayer::tools::Primitive2dXmlDump dumper; xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer(aSequence)); CPPUNIT_ASSERT (pDocument); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence", "transparence", "0.498039215686275"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence/textsimpleportion", "height", "24"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence/textsimpleportion", "x", "66"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence/textsimpleportion", "y", "74"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence/textsimpleportion", "text", "Transparent Text"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence/textsimpleportion", "fontcolor", "#0000ff"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence/textsimpleportion", "familyname", "ARIAL"); #endif } void Test::TestDrawLine() { // This unit checks for a correct import of an EMF+ file with only one DrawLine Record // The line is colored and has a specified width, therefore a polypolygonstroke primitive is the optimal choice // first, get the sequence of primitives and dump it Primitive2DSequence aSequence = parseEmf("/emfio/qa/cppunit/emf/data/TestDrawLine.emf"); CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); drawinglayer::tools::Primitive2dXmlDump dumper; xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer(aSequence)); CPPUNIT_ASSERT (pDocument); // check correct import of the DrawLine: color and width of the line assertXPath(pDocument, "/primitive2D/metafile/transform/polypolygonstroke/line", "color", "#000000"); assertXPath(pDocument, "/primitive2D/metafile/transform/polypolygonstroke/line", "width", "33"); } void Test::TestLinearGradient() { // This unit checks for a correct import of an EMF+ file with LinearGradient brush Primitive2DSequence aSequence = parseEmf("/emfio/qa/cppunit/emf/data/TestLinearGradient.emf"); CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); drawinglayer::tools::Primitive2dXmlDump dumper; xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer(aSequence)); CPPUNIT_ASSERT (pDocument); assertXPath(pDocument, "/primitive2D/metafile/transform", "xy11", "1.0000656512605"); assertXPath(pDocument, "/primitive2D/metafile/transform", "xy12", "0"); assertXPath(pDocument, "/primitive2D/metafile/transform", "xy13", "0"); assertXPath(pDocument, "/primitive2D/metafile/transform", "xy21", "0"); assertXPath(pDocument, "/primitive2D/metafile/transform", "xy22", "1.00013140604468"); assertXPath(pDocument, "/primitive2D/metafile/transform", "xy23", "0"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygon", "height", "7610"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygon", "width", "15232"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygon", "path", "m0 0h15232v7610h-15232z"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[1]", "startx", "0"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[1]", "starty", "-1"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[1]", "endx", "0"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[1]", "endy", "-1"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[1]", "opacity", "0.392156862745098"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[1]/polypolygon", "path", "m0 0.216110019646294h7615.75822989746v7610.21611001965h-7615.75822989746z"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[2]", "startx", "-1"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[2]", "starty", "-1"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[2]", "endx", "0"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[2]", "endy", "-1"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[2]", "opacity", "1"); assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[2]/polypolygon", "path", "m7615.75822989746 0.216110019646294h7615.75822989746v7610.21611001965h-7615.75822989746z"); } void Test::TestTextMapMode() { // Check import of EMF image with records: SETMAPMODE with MM_TEXT MapMode, POLYLINE16, EXTCREATEPEN, EXTTEXTOUTW // MM_TEXT is mapped to one device pixel. Positive x is to the right; positive y is down. Primitive2DSequence aSequence = parseEmf("/emfio/qa/cppunit/emf/data/TextMapMode.emf"); CPPUNIT_ASSERT_EQUAL(1, static_cast(aSequence.getLength())); drawinglayer::tools::Primitive2dXmlDump dumper; xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer(aSequence)); CPPUNIT_ASSERT (pDocument); assertXPath(pDocument, "/primitive2D/metafile/transform/polypolygoncolor", 2); assertXPath(pDocument, "/primitive2D/metafile/transform/polypolygoncolor[1]", "color", "#ffffff"); assertXPath(pDocument, "/primitive2D/metafile/transform/polypolygoncolor[1]/polypolygon", "path", "m0 0h3542v4647h-3542z"); assertXPath(pDocument, "/primitive2D/metafile/transform/textsimpleportion", 20); assertXPath(pDocument, "/primitive2D/metafile/transform/textsimpleportion[1]", "text", "N"); assertXPath(pDocument, "/primitive2D/metafile/transform/textsimpleportion[1]", "fontcolor", "#4a70e3"); assertXPath(pDocument, "/primitive2D/metafile/transform/textsimpleportion[1]", "x", "2099"); assertXPath(pDocument, "/primitive2D/metafile/transform/textsimpleportion[1]", "y", "1859"); assertXPath(pDocument, "/primitive2D/metafile/transform/polygonstroke", 138); assertXPathContent(pDocument, "/primitive2D/metafile/transform/polygonstroke[1]/polygon", "2142,1638 2142,1489"); assertXPath(pDocument, "/primitive2D/metafile/transform/polygonstroke[1]/line", "color", "#4a70e3"); assertXPath(pDocument, "/primitive2D/metafile/transform/polygonstroke[1]/line", "width", "11"); assertXPathContent(pDocument, "/primitive2D/metafile/transform/polygonstroke[10]/polygon", "1967,1029 1869,952"); assertXPath(pDocument, "/primitive2D/metafile/transform/polygonstroke[10]/line", "color", "#4a70e3"); assertXPath(pDocument, "/primitive2D/metafile/transform/polygonstroke[10]/line", "width", "11"); assertXPathContent(pDocument, "/primitive2D/metafile/transform/polygonstroke[20]/polygon", "2710,1113 2873,1330"); assertXPath(pDocument, "/primitive2D/metafile/transform/polygonstroke[20]/line", "color", "#666666"); 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::tools::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. OUString aURL = m_directories.getURLFromSrc("emfio/qa/cppunit/emf/data/pdf-in-emf.pptx"); getComponent() = loadFromDesktop(aURL); // Get the EMF. uno::Reference xDrawPagesSupplier(getComponent(), uno::UNO_QUERY); uno::Reference xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); uno::Reference xGraphic; xShape->getPropertyValue("FillBitmap") >>= xGraphic; Graphic aGraphic(xGraphic); // Check the size hint of the EMF, which influences the bitmap generated from the PDF. const std::shared_ptr& pVectorGraphicData = aGraphic.getVectorGraphicData(); // Without the accompanying fix in place, this test would have failed with: // - Expected: 14321 // - Actual : 0 // i.e. there was no size hint, the shape with 14cm height had a bitmap-from-PDF fill, the PDF // height was only 5cm, so it looked blurry. CPPUNIT_ASSERT_EQUAL(14321.0, pVectorGraphicData->getSizeHint().getY()); } CPPUNIT_TEST_SUITE_REGISTRATION(Test); } CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */