sw/qa/extras/htmlexport/htmlexport.cxx | 78 +++++++++++++------------------- sw/qa/filter/html/html.cxx | 39 ++++++++++++++++ sw/qa/inc/swmodeltestbase.hxx | 13 +++++ sw/source/filter/html/htmlflywriter.cxx | 7 ++ 4 files changed, 91 insertions(+), 46 deletions(-)
New commits: commit 6627358f67ac71eac6b5e13c08f8a1bd89954399 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Sep 26 15:40:29 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Sep 27 11:09:40 2022 +0200 sw HTML export: fix PNG export of Writer images containing metafiles We attempted to export SVM metafiles as SVM+PNG, but then the SVM was turned into GIF. A GIF+PNG pair is not useful, just write PNG. This is similar to commit c8a9396e5695675ffe92935a9ba40354fc76ed79 (sw XHTML / reqif export: fix PNG export of shapes, 2021-06-03), which did the same for non-SdrGrafObj shapes. (cherry picked from commit 92259b092e7271a638c2f88d7565983dfe49f0b1) Conflicts: sw/qa/inc/swmodeltestbase.hxx sw/qa/unit/swmodeltestbase.cxx Change-Id: I1a0ab266473787d263573b4813dc19426e272435 diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx index 442feecaa145..19e40fb1c256 100644 --- a/sw/qa/extras/htmlexport/htmlexport.cxx +++ b/sw/qa/extras/htmlexport/htmlexport.cxx @@ -183,20 +183,6 @@ public: m_eUnit(FieldUnit::NONE) {} - /** - * Wraps a reqif-xhtml fragment into an XHTML file, so an XML parser can - * parse it. - */ - static void wrapFragment(const utl::TempFile& rTempFile, SvMemoryStream& rStream) - { - rStream.WriteCharPtr( - "<reqif-xhtml:html xmlns:reqif-xhtml=\"http://www.w3.org/1999/xhtml\">\n"); - SvFileStream aFileStream(rTempFile.GetURL(), StreamMode::READ); - rStream.WriteStream(aFileStream); - rStream.WriteCharPtr("</reqif-xhtml:html>\n"); - rStream.Seek(0); - } - /// Wraps an RTF fragment into a complete RTF file, so an RTF parser can handle it. static void wrapRtfFragment(const OUString& rURL, SvMemoryStream& rStream) { @@ -279,7 +265,7 @@ public: OUString SwHtmlDomExportTest::GetOlePath() { SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); OUString aOlePath = getXPath( @@ -295,7 +281,7 @@ OUString SwHtmlDomExportTest::GetOlePath() OUString SwHtmlDomExportTest::GetPngPath() { SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); OUString aPngPath = getXPath( @@ -787,7 +773,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIfTableHeight) // Then make sure that the explicit cell height is omitted from the output: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); // Without the accompanying fix in place, this test would have failed, explicit height was // written, which is not valid reqif-xhtml. @@ -847,7 +833,7 @@ DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testReqIfOle2, "reqif-ole2.xhtml") { // Check that the replacement graphic is exported at RTF level. SvMemoryStream aStream; - wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); // Get the path of the RTF data. @@ -919,7 +905,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTransparentImageReqIf) }; xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); @@ -936,7 +922,7 @@ DECLARE_HTMLEXPORT_TEST(testOleNodataReqIf, "reqif-ole-nodata.odt") { // This failed, io::IOException was thrown during the filter() call. SvMemoryStream aStream; - wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); @@ -951,7 +937,7 @@ DECLARE_HTMLEXPORT_TEST(testOleNodataReqIf, "reqif-ole-nodata.odt") DECLARE_HTMLEXPORT_TEST(testNoLangReqIf, "reqif-no-lang.odt") { SvMemoryStream aStream; - wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); @@ -1003,7 +989,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testBlockQuoteReqIf) aMediaDescriptor["FilterOptions"] <<= OUString("xhtmlns=reqif-xhtml"); xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); @@ -1030,7 +1016,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testRTFOLEMimeType) }; xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); @@ -1062,7 +1048,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testChinese) xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); // Without the accompanying fix in place, this test would have failed as the output was not @@ -1090,7 +1076,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifComment) }; xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); // Without the accompanying fix in place, this test would have failed as the output was not @@ -1119,7 +1105,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifFontNameSize) }; xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); // Make sure the output is well-formed. @@ -1147,7 +1133,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifParagraphAlignment) }; xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); // Make sure the output is well-formed. @@ -1336,7 +1322,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testMultiParaListItem) xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); assertXPathContent(pXmlDoc, "//reqif-xhtml:ol/reqif-xhtml:li[1]/reqif-xhtml:p", "A"); @@ -1369,7 +1355,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testUnderlineNone) // Make sure that the paragraph has no explicit style, because "text-decoration: none" is // filtered out. SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); assertXPathNoAttribute(pXmlDoc, "//reqif-xhtml:div/reqif-xhtml:p", "style"); @@ -1491,7 +1477,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testListHeading) // Then make sure the output is valid xhtml: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); @@ -1532,7 +1518,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testPartiallyNumberedList) // Then make sure the output is well-formed xhtml: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); // Without the accompanying fix in place, this test would have failed: @@ -1573,7 +1559,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testListHeaderAndItem) // Then make sure the output is well-formed xhtml: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); // Without the accompanying fix in place, this test would have failed: // Entity: line 3: parser error : Opening and ending tag mismatch: ol line 3 and li @@ -1603,7 +1589,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testBlockQuoteNoMargin) // Then make sure the output is valid xhtml: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); // Without the accompanying fix in place, this test would have failed: @@ -1679,7 +1665,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedPNGDirectly) // Then make sure the PNG is embedded directly, without an RTF wrapper: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); // Without the accompanying fix in place, this test would have failed with: @@ -1709,7 +1695,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedJPGDirectly) // Then make sure the JPG is embedded directly, without an RTF wrapper: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", "image/jpeg"); @@ -1745,7 +1731,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedPNGShapeDirectly) // Then make sure the PNG is embedded directly, without an RTF wrapper: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); // Without the accompanying fix in place, this test would have failed with: @@ -1778,7 +1764,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedJPGShapeDirectly) // Then make sure the JPG is embedded directly, without an RTF wrapper: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); // Without the accompanying fix in place, this test would have failed with: @@ -1815,7 +1801,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedPNGShapeAsOLE) // Then make sure the PNG is embedded with an RTF wrapper: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); // Without the accompanying fix in place, this test would have failed with: @@ -1846,7 +1832,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedShapeAsPNG) // Then make sure the shape is embedded as a PNG: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); // Without the accompanying fix in place, this test would have failed with: @@ -1916,7 +1902,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedShapeAsPNGCustomDPI) // Then make sure the shape is embedded as a PNG: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pXmlDoc); assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", "image/png"); @@ -2060,7 +2046,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testListsHeading) // Then make sure the output is valid xhtml: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); @@ -2122,7 +2108,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testNestedBullets) // Then make sure that there is a <li> between the outer and the inner <ol>: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); // Without the accompanying fix in place, this test would have failed with: @@ -2147,7 +2133,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTrailingLineBreak) // Then make sure that we still have a single line-break: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); // Without the accompanying fix in place, this test would have failed with: @@ -2199,7 +2185,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testLeadingTab) // Then make sure that leading tabs are replaced with 2 nbsps: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); // Without the accompanying fix in place, this test would have failed with: @@ -2270,7 +2256,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTableBackground) // Then make sure that CSS markup is used, not HTML one: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); // Without the accompanying fix in place, this test would have failed with: // - XPath '//reqif-xhtml:table[1]' no attribute 'style' exist @@ -2334,7 +2320,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testSectionDir) // Then make sure CSS is used to export the text direction of the section: SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); // Without the accompanying fix in place, this test would have failed with: // - XPath '//reqif-xhtml:div[@id='mysect']' no attribute 'style' exist diff --git a/sw/qa/filter/html/html.cxx b/sw/qa/filter/html/html.cxx index 56c1f899352b..5fb02c46e2c4 100644 --- a/sw/qa/filter/html/html.cxx +++ b/sw/qa/filter/html/html.cxx @@ -10,6 +10,7 @@ #include <swmodeltestbase.hxx> #include <comphelper/propertyvalue.hxx> +#include <vcl/gdimtf.hxx> #include <docsh.hxx> #include <fmtfsize.hxx> @@ -105,6 +106,44 @@ CPPUNIT_TEST_FIXTURE(Test, testRelativeKeepAspectImage) CPPUNIT_ASSERT_EQUAL(static_cast<int>(SwFormatFrameSize::SYNCED), static_cast<int>(rSize.GetHeightPercent())); } + +CPPUNIT_TEST_FIXTURE(Test, testSvmImageExport) +{ + // Given a document with an image, which has an SVM image data: + loadURL("private:factory/swriter", nullptr); + uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xTextGraphic( + xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY); + xTextGraphic->setPropertyValue("AnchorType", + uno::Any(text::TextContentAnchorType_AS_CHARACTER)); + GDIMetaFile aMetafile; + Graphic aGraphic(aMetafile); + xTextGraphic->setPropertyValue("Graphic", uno::Any(aGraphic.GetXGraphic())); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xBodyText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor(xBodyText->createTextCursor()); + uno::Reference<text::XTextContent> xTextContent(xTextGraphic, uno::UNO_QUERY); + xBodyText->insertTextContent(xCursor, xTextContent, false); + + // When exporting to reqif: + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> aStoreProperties = { + comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")), + comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")), + }; + xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); + + // Then make sure we we only export PNG: + SvMemoryStream aStream; + WrapReqifFromTempFile(aStream); + xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // - XPath '//reqif-xhtml:object' number of nodes is incorrect + // i.e. we wrote both GIF and PNG, not just PNG for SVM images. + assertXPath(pXmlDoc, "//reqif-xhtml:object", "type", "image/png"); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/qa/inc/swmodeltestbase.hxx b/sw/qa/inc/swmodeltestbase.hxx index 8265801f36f8..ce9960696333 100644 --- a/sw/qa/inc/swmodeltestbase.hxx +++ b/sw/qa/inc/swmodeltestbase.hxx @@ -1030,6 +1030,19 @@ protected: // reqif-xhtml xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("reqif-xhtml"), BAD_CAST("http://www.w3.org/1999/xhtml")); } + + /** + * Wraps a reqif-xhtml fragment into an XHTML file, so an XML parser can + * parse it. + */ + void WrapReqifFromTempFile(SvMemoryStream& rStream) + { + rStream.WriteCharPtr("<reqif-xhtml:html xmlns:reqif-xhtml=\"http://www.w3.org/1999/xhtml\">\n"); + SvFileStream aFileStream(maTempFile.GetURL(), StreamMode::READ); + rStream.WriteStream(aFileStream); + rStream.WriteCharPtr("</reqif-xhtml:html>\n"); + rStream.Seek(0); + } }; /** diff --git a/sw/source/filter/html/htmlflywriter.cxx b/sw/source/filter/html/htmlflywriter.cxx index 06652a450121..a4fc1a7a5723 100644 --- a/sw/source/filter/html/htmlflywriter.cxx +++ b/sw/source/filter/html/htmlflywriter.cxx @@ -1953,6 +1953,13 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF nFrameFlags |= HTML_FRMOPTS_IMG_CSS1; Graphic aGraphic = pGrfNd->GetGraphic(); + + if (aGraphic.GetType() == GraphicType::GdiMetafile) + { + // We only have a metafile, write that as PNG without any fallback. + bWritePNGFallback = false; + } + OUString aGraphicURL; OUString aMimeType; if(!rHTMLWrt.mbEmbedImages)