[Libreoffice-commits] core.git: sw/qa sw/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Tue Jun 1 14:13:55 UTC 2021


 sw/qa/extras/htmlexport/htmlexport.cxx  |   32 +++++++++++++
 sw/source/filter/html/htmlflywriter.cxx |   76 ++++++++++++++++++++------------
 sw/source/filter/html/htmlplug.cxx      |    5 +-
 sw/source/filter/html/wrthtml.hxx       |    3 -
 4 files changed, 86 insertions(+), 30 deletions(-)

New commits:
commit 3fe661041aadbfd945a20afe2310a19f5e76976e
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Tue Jun 1 14:50:01 2021 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Tue Jun 1 16:13:11 2021 +0200

    sw XHTML / reqif export: write PNG fallback for non-PNG images
    
    - split up OutHTML_Image, so it's possible to write
    
    <object type="image/jpeg">
        <object type="image/png"/>
    </object>
    
    - write PNG inside the original image
    
    - disable this when the original format is PNG already
    
    Change-Id: I3ad40089ee2b02b8850823dd536c58ac59af37f2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116544
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 9ace986366f3..275896ed7ccb 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -1558,6 +1558,38 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedPNGDirectly)
     assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", "image/png");
 }
 
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedJPGDirectly)
+{
+    // Given a document with an image:
+    loadURL("private:factory/swriter", nullptr);
+    OUString aImageURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "reqif-ole-img.jpg";
+    uno::Sequence<beans::PropertyValue> aArgs = {
+        comphelper::makePropertyValue("FileName", aImageURL),
+    };
+    dispatchCommand(mxComponent, ".uno:InsertGraphic", aArgs);
+
+    // When exporting to XHTML:
+    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 the JPG is embedded directly, without an RTF wrapper:
+    SvMemoryStream aStream;
+    HtmlExportTest::wrapFragment(maTempFile, aStream);
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+    CPPUNIT_ASSERT(pXmlDoc);
+    assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", "image/jpeg");
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: image/jpeg
+    // - Actual  : image/png
+    // i.e. first the original JPG data was lost, then the inner PNG fallback was missing.
+    assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object/reqif-xhtml:object", "type",
+                "image/png");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlflywriter.cxx b/sw/source/filter/html/htmlflywriter.cxx
index 09dfa97a5220..a050c9c2056b 100644
--- a/sw/source/filter/html/htmlflywriter.cxx
+++ b/sw/source/filter/html/htmlflywriter.cxx
@@ -137,7 +137,7 @@ static Writer& OutHTML_FrameFormatAsDivOrSpan( Writer& rWrt,
 static Writer& OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& rFormat );
 
 static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rFormat,
-                                      bool bInCntnr );
+                                      bool bInCntnr, bool bPNGFallback );
 
 static Writer& OutHTML_FrameFormatAsMarquee( Writer& rWrt, const SwFrameFormat& rFrameFormat,
                                         const SdrObject& rSdrObj    );
@@ -467,7 +467,7 @@ void SwHTMLWriter::OutFrameFormat( AllHtmlFlags nMode, const SwFrameFormat& rFra
         OutHTML_FrameFormatTableNode( *this, rFrameFormat );
         break;
     case HtmlOut::GraphicNode:      // OK
-        OutHTML_FrameFormatGrfNode( *this, rFrameFormat, !aContainerStr.isEmpty() );
+        OutHTML_FrameFormatGrfNode( *this, rFrameFormat, !aContainerStr.isEmpty(), /*bPNGFallback=*/true );
         break;
     case HtmlOut::OleNode:      // OK
         OutHTML_FrameFormatOLENode( *this, rFrameFormat, !aContainerStr.isEmpty() );
@@ -1192,7 +1192,7 @@ OUString lclWriteOutImap(SwHTMLWriter& rHTMLWrt, const SfxItemSet& rItemSet, con
 
 }
 
-Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
+Writer& OutHTML_ImageStart( HtmlWriter& rHtml, Writer& rWrt, const SwFrameFormat &rFrameFormat,
                        const OUString& rGraphicURL,
                        Graphic const & rGraphic, const OUString& rAlternateText,
                        const Size &rRealSize, HtmlFrmOpts nFrameOpts,
@@ -1228,8 +1228,6 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
     if( rHTMLWrt.m_bLFPossible )
         rHTMLWrt.OutNewLine( true );
 
-    HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
-
     // <a name=...></a>...<img ...>
     if( pMarkType && !rFrameFormat.GetName().isEmpty() )
     {
@@ -1260,22 +1258,22 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
 
         if( !aMapURL.isEmpty() || !aName.isEmpty() || !aTarget.isEmpty() || bEvents )
         {
-            aHtml.start(OOO_STRING_SVTOOLS_HTML_anchor);
+            rHtml.start(OOO_STRING_SVTOOLS_HTML_anchor);
 
             // Output "href" element if a link or macro exists
             if( !aMapURL.isEmpty() || bEvents )
             {
-                aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_href, OUStringToOString(rHTMLWrt.convertHyperlinkHRefValue(aMapURL), RTL_TEXTENCODING_UTF8));
+                rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_href, OUStringToOString(rHTMLWrt.convertHyperlinkHRefValue(aMapURL), RTL_TEXTENCODING_UTF8));
             }
 
             if( !aName.isEmpty() )
             {
-                aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_name, OUStringToOString(aName, RTL_TEXTENCODING_UTF8));
+                rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_name, OUStringToOString(aName, RTL_TEXTENCODING_UTF8));
             }
 
             if( !aTarget.isEmpty() )
             {
-                aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_target, OUStringToOString(aTarget, RTL_TEXTENCODING_UTF8));
+                rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_target, OUStringToOString(aTarget, RTL_TEXTENCODING_UTF8));
             }
 
             if( pMacItem )
@@ -1283,7 +1281,7 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
                 const SvxMacroTableDtor& rMacTable = pMacItem->GetMacroTable();
                 if (!rMacTable.empty())
                 {
-                    HtmlWriterHelper::applyEvents(aHtml, rMacTable, aAnchorEventTable, rHTMLWrt.m_bCfgStarBasic);
+                    HtmlWriterHelper::applyEvents(rHtml, rMacTable, aAnchorEventTable, rHTMLWrt.m_bCfgStarBasic);
                 }
             }
         }
@@ -1349,8 +1347,8 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
 
         if( pColBorderLine )
         {
-            aHtml.start(OOO_STRING_SVTOOLS_HTML_font);
-            HtmlWriterHelper::applyColor(aHtml, OOO_STRING_SVTOOLS_HTML_O_color, pColBorderLine->GetColor());
+            rHtml.start(OOO_STRING_SVTOOLS_HTML_font);
+            HtmlWriterHelper::applyColor(rHtml, OOO_STRING_SVTOOLS_HTML_O_color, pColBorderLine->GetColor());
         }
     }
 
@@ -1358,7 +1356,7 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
     if (bReplacement)
         // Write replacement graphic of OLE object as <object>.
         aTag = OOO_STRING_SVTOOLS_HTML_object;
-    aHtml.start(aTag);
+    rHtml.start(aTag);
 
     OStringBuffer sBuffer;
     if(rHTMLWrt.mbEmbedImages)
@@ -1369,7 +1367,7 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
             sBuffer.append(OOO_STRING_SVTOOLS_HTML_O_data);
             sBuffer.append(":");
             sBuffer.append(OUStringToOString(aGraphicInBase64, RTL_TEXTENCODING_UTF8));
-            aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_src, sBuffer.makeStringAndClear().getStr());
+            rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_src, sBuffer.makeStringAndClear().getStr());
         }
         else
             rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD;
@@ -1380,14 +1378,14 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
         OString aAttribute(OOO_STRING_SVTOOLS_HTML_O_src);
         if (bReplacement)
             aAttribute = OOO_STRING_SVTOOLS_HTML_O_data;
-        aHtml.attribute(aAttribute, sBuffer.makeStringAndClear().getStr());
+        rHtml.attribute(aAttribute, sBuffer.makeStringAndClear().getStr());
     }
 
     if (bReplacement)
     {
         // Handle XHTML type attribute for OLE replacement images.
         if (!rMimeType.isEmpty())
-            aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_type, rMimeType.toUtf8());
+            rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_type, rMimeType.toUtf8());
     }
 
     // Events
@@ -1396,28 +1394,28 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
         const SvxMacroTableDtor& rMacTable = static_cast<const SvxMacroItem *>(pItem)->GetMacroTable();
         if (!rMacTable.empty())
         {
-            HtmlWriterHelper::applyEvents(aHtml, rMacTable, aImageEventTable, rHTMLWrt.m_bCfgStarBasic);
+            HtmlWriterHelper::applyEvents(rHtml, rMacTable, aImageEventTable, rHTMLWrt.m_bCfgStarBasic);
         }
     }
 
     // alt, align, width, height, hspace, vspace
-    rHTMLWrt.writeFrameFormatOptions(aHtml, rFrameFormat, rAlternateText, nFrameOpts);
+    rHTMLWrt.writeFrameFormatOptions(rHtml, rFrameFormat, rAlternateText, nFrameOpts);
     if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) )
         rHTMLWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts );
 
     if ((nFrameOpts & HtmlFrmOpts::Border) && !bReplacement)
     {
-        aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_border, nBorderWidth);
+        rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_border, nBorderWidth);
     }
 
     if( pURLItem && pURLItem->IsServerMap() )
     {
-        aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_ismap);
+        rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_ismap);
     }
 
     if( !aIMapName.isEmpty() )
     {
-        aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_usemap, OUString("#" + aIMapName));
+        rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_usemap, OUString("#" + aIMapName));
     }
 
     if (bReplacement)
@@ -1426,12 +1424,18 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
         // "alt" attribute.
         if (rAlternateText.isEmpty())
             // Empty alternate text is not valid.
-            aHtml.characters(" ");
+            rHtml.characters(" ");
         else
-            aHtml.characters(rAlternateText.toUtf8());
+            rHtml.characters(rAlternateText.toUtf8());
     }
 
-    aHtml.flushStack();
+    return rHTMLWrt;
+}
+
+Writer& OutHTML_ImageEnd( HtmlWriter& rHtml, Writer& rWrt )
+{
+    SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
+    rHtml.flushStack();
 
     if( !rHTMLWrt.m_aINetFormats.empty() )
     {
@@ -1763,17 +1767,20 @@ static Writer & OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& r
             URIHelper::GetMaybeFileHdl() );
 
     }
-    OutHTML_Image( rWrt, rFrameFormat, GraphicURL, aGraphic, rFrameFormat.GetName(), aSz,
+    HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
+    OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, GraphicURL, aGraphic, rFrameFormat.GetName(), aSz,
                     HtmlFrmOpts::GenImgMask, "frame",
                     aIMap.GetIMapObjectCount() ? &aIMap : nullptr );
+    OutHTML_ImageEnd(aHtml, rWrt);
 
     return rWrt;
 }
 
 static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rFrameFormat,
-                                      bool bInCntnr )
+                                      bool bInCntnr, bool bPNGFallback )
 {
     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
+    bool bWritePNGFallback = !rHTMLWrt.m_bExportImagesAsOLE && bPNGFallback;
 
     if (rHTMLWrt.mbSkipImages)
         return rWrt;
@@ -1824,10 +1831,12 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF
 
             OUString aFilterName("");
 
-            if (rHTMLWrt.mbReqIF)
+            if (rHTMLWrt.mbReqIF && !bWritePNGFallback)
             {
                 // Writing image without fallback PNG in ReqIF mode: force PNG
                 // output.
+                // But don't force it when writing the original format and we'll write PNG inside
+                // that.
                 aFilterName = "PNG";
                 nFlags &= ~XOutFlags::UseNativeIfPossible;
                 nFlags &= ~XOutFlags::UseGifIfSensible;
@@ -1890,9 +1899,20 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF
         rHTMLWrt.OutNewLine();
     }
 
-    OutHTML_Image( rWrt, rFrameFormat, aGraphicURL, aGraphic, pGrfNd->GetTitle(),
+    HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
+    OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic, pGrfNd->GetTitle(),
                   pGrfNd->GetTwipSize(), nFrameFlags, "graphic", nullptr, aMimeType );
 
+    GfxLink aLink = aGraphic.GetGfxLink();
+    if (bWritePNGFallback && aLink.GetType() != GfxLinkType::NativePng)
+    {
+        // Not OLE mode, outer format is not PNG: write inner PNG.
+        OutHTML_FrameFormatGrfNode( rWrt, rFrameFormat,
+                                      bInCntnr, /*bPNGFallback=*/false );
+    }
+
+    OutHTML_ImageEnd(aHtml, rWrt);
+
     if (rHTMLWrt.mbReqIF && rHTMLWrt.m_bExportImagesAsOLE)
         rWrt.Strm().WriteOString(OString("</" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">"));
 
diff --git a/sw/source/filter/html/htmlplug.cxx b/sw/source/filter/html/htmlplug.cxx
index 5ce2ab50d90b..166c91931731 100644
--- a/sw/source/filter/html/htmlplug.cxx
+++ b/sw/source/filter/html/htmlplug.cxx
@@ -79,6 +79,7 @@
 #include <o3tl/safeint.hxx>
 #include <osl/file.hxx>
 #include <comphelper/propertyvalue.hxx>
+#include <svtools/HtmlWriter.hxx>
 
 using namespace com::sun::star;
 
@@ -1655,9 +1656,11 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame
         : HtmlFrmOpts::GenImgMask;
     if (bObjectOpened)
         nFlags |= HtmlFrmOpts::Replacement;
-    OutHTML_Image( rWrt, rFrameFormat, aGraphicURL, aGraphic,
+    HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
+    OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic,
             pOLENd->GetTitle(), pOLENd->GetTwipSize(),
             nFlags, "ole", nullptr, aMimeType );
+    OutHTML_ImageEnd(aHtml, rWrt);
 
     if (bObjectOpened)
         // Close native data.
diff --git a/sw/source/filter/html/wrthtml.hxx b/sw/source/filter/html/wrthtml.hxx
index 3e23616f6b21..8d6d1751e5a3 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -666,13 +666,14 @@ Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, const SwDrawFrameFormat&
 Writer& OutHTML_HeaderFooter( Writer& rWrt, const SwFrameFormat& rFrameFormat,
                               bool bHeader );
 
-Writer& OutHTML_Image( Writer&, const SwFrameFormat& rFormat,
+Writer& OutHTML_ImageStart( HtmlWriter& rHtml, Writer&, const SwFrameFormat& rFormat,
                        const OUString& rGraphicURL,
                        Graphic const & rGraphic, const OUString& rAlternateText,
                        const Size& rRealSize, HtmlFrmOpts nFrameOpts,
                        const char *pMarkType,
                        const ImageMap *pGenImgMap,
                        const OUString& rMimeType = OUString() );
+Writer& OutHTML_ImageEnd( HtmlWriter& rHtml, Writer& );
 
 Writer& OutHTML_BulletImage( Writer& rWrt, const char *pTag,
                              const SvxBrushItem* pBrush,


More information about the Libreoffice-commits mailing list