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 90b6fa56e3f478ce25da891cbb12339e90dbf2ba Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Sep 26 15:40:29 2022 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Sep 27 18:27:20 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 Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140645 diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx index 76333c842d96..5a2dca9618e5 100644 --- a/sw/qa/extras/htmlexport/htmlexport.cxx +++ b/sw/qa/extras/htmlexport/htmlexport.cxx @@ -197,20 +197,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) { @@ -292,7 +278,7 @@ public: OUString SwHtmlDomExportTest::GetOlePath() { SvMemoryStream aStream; - HtmlExportTest::wrapFragment(maTempFile, aStream); + WrapReqifFromTempFile(aStream); xmlDocUniquePtr pDoc = parseXmlStream(&aStream); CPPUNIT_ASSERT(pDoc); OUString aOlePath = getXPath( @@ -308,7 +294,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( @@ -842,7 +828,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. @@ -903,7 +889,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. @@ -975,7 +961,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); @@ -992,7 +978,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); @@ -1007,7 +993,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); @@ -1083,7 +1069,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); @@ -1110,7 +1096,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); @@ -1131,7 +1117,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 @@ -1152,7 +1138,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 @@ -1176,7 +1162,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. @@ -1199,7 +1185,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. @@ -1375,7 +1361,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"); @@ -1403,7 +1389,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"); @@ -1510,7 +1496,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); @@ -1551,7 +1537,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: @@ -1592,7 +1578,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 @@ -1622,7 +1608,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: @@ -1698,7 +1684,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: @@ -1728,7 +1714,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"); @@ -1764,7 +1750,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: @@ -1797,7 +1783,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: @@ -1834,7 +1820,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: @@ -1865,7 +1851,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: @@ -1968,7 +1954,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"); @@ -2112,7 +2098,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); @@ -2172,7 +2158,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: @@ -2195,7 +2181,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: @@ -2245,7 +2231,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: @@ -2354,7 +2340,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 @@ -2417,7 +2403,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 fd610f790908..ed7beefbbb89 100644 --- a/sw/qa/inc/swmodeltestbase.hxx +++ b/sw/qa/inc/swmodeltestbase.hxx @@ -383,6 +383,12 @@ protected: */ SwDoc* createSwWebDoc( std::u16string_view rDataDirectory = std::u16string_view(), const char* pName = nullptr); + + /** + * 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 a19fb9fa785d..707d306ce751 100644 --- a/sw/qa/unit/swmodeltestbase.cxx +++ b/sw/qa/unit/swmodeltestbase.cxx @@ -756,4 +756,13 @@ SwDoc* SwModelTestBase::createSwWebDoc(std::u16string_view rDataDirectory, const return pTextDoc->GetDocShell()->GetDoc(); } +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 0e27a89d8516..a8c4435186e9 100644 --- a/sw/source/filter/html/htmlflywriter.cxx +++ b/sw/source/filter/html/htmlflywriter.cxx @@ -1925,6 +1925,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)