sw/qa/extras/htmlexport/htmlexport.cxx | 78 +++++++++++++------------------- sw/qa/filter/html/html.cxx | 39 ++++++++++++++++ sw/qa/inc/swmodeltestbase.hxx | 6 ++ sw/qa/unit/swmodeltestbase.cxx | 9 +++ sw/source/filter/html/htmlflywriter.cxx | 7 ++ 5 files changed, 93 insertions(+), 46 deletions(-)
New commits: commit 92259b092e7271a638c2f88d7565983dfe49f0b1 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Sep 26 15:40:29 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Sep 26 19:11:30 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. Change-Id: I1a0ab266473787d263573b4813dc19426e272435 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140619 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx index 103f7bcc5a84..3a212d2242f5 100644 --- a/sw/qa/extras/htmlexport/htmlexport.cxx +++ b/sw/qa/extras/htmlexport/htmlexport.cxx @@ -196,20 +196,6 @@ public: { } - /** - * 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) { @@ -286,7 +272,7 @@ public: OUString SwHtmlDomExportTest::GetOlePath() { SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); OUString aOlePath = getXPath( @@ -302,7 +288,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( @@ -836,7 +822,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. @@ -897,7 +883,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. @@ -969,7 +955,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); @@ -986,7 +972,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); @@ -1001,7 +987,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); @@ -1077,7 +1063,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); @@ -1104,7 +1090,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); @@ -1125,7 +1111,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testChinese) // Export it. ExportToReqif(); 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 @@ -1146,7 +1132,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifComment) // Export it. ExportToReqif(); 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 @@ -1170,7 +1156,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifFontNameSize) // Export it. ExportToReqif(); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); // Make sure the output is well-formed. @@ -1193,7 +1179,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifParagraphAlignment) // Export it. ExportToReqif(); SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); // Make sure the output is well-formed. @@ -1369,7 +1355,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testMultiParaListItem) ExportToReqif(); 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"); @@ -1397,7 +1383,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"); @@ -1504,7 +1490,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); @@ -1545,7 +1531,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: @@ -1586,7 +1572,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 @@ -1616,7 +1602,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: @@ -1692,7 +1678,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: @@ -1722,7 +1708,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"); @@ -1758,7 +1744,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: @@ -1791,7 +1777,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: @@ -1828,7 +1814,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: @@ -1859,7 +1845,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: @@ -1962,7 +1948,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"); @@ -2106,7 +2092,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); @@ -2166,7 +2152,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: @@ -2189,7 +2175,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: @@ -2239,7 +2225,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: @@ -2348,7 +2334,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 @@ -2411,7 +2397,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 973feeec2951..8fc223268430 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: + createSwDoc(); + 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 61c13504094f..19255e6b3751 100644 --- a/sw/qa/inc/swmodeltestbase.hxx +++ b/sw/qa/inc/swmodeltestbase.hxx @@ -407,6 +407,12 @@ protected: void StoreToTempFile(const OUString& rFilterName); std::unique_ptr<vcl::pdf::PDFiumDocument> LoadPdfFromTempFile(); + + /** + * Wraps a reqif-xhtml fragment into an XHTML file, so an XML parser can + * parse it. + */ + void WrapReqifFromTempFile(SvMemoryStream& rStream); }; /** diff --git a/sw/qa/unit/swmodeltestbase.cxx b/sw/qa/unit/swmodeltestbase.cxx index c058dff2cd4f..963d1f2d49f4 100644 --- a/sw/qa/unit/swmodeltestbase.cxx +++ b/sw/qa/unit/swmodeltestbase.cxx @@ -779,4 +779,13 @@ std::unique_ptr<vcl::pdf::PDFiumDocument> SwModelTestBase::LoadPdfFromTempFile() return pPDFium->openDocument(maMemory.GetData(), maMemory.GetSize(), OString()); } +void SwModelTestBase::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); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlflywriter.cxx b/sw/source/filter/html/htmlflywriter.cxx index 47a63043fb75..8021b62f1ba9 100644 --- a/sw/source/filter/html/htmlflywriter.cxx +++ b/sw/source/filter/html/htmlflywriter.cxx @@ -1929,6 +1929,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)