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

Miklos Vajna vmiklos at collabora.co.uk
Wed Jul 4 16:08:45 UTC 2018


 filter/source/msfilter/rtfutil.cxx          |   16 +++++++
 include/filter/msfilter/rtfutil.hxx         |    3 +
 sw/qa/extras/htmlexport/htmlexport.cxx      |   14 ++++--
 sw/source/filter/html/htmlflywriter.cxx     |   44 ++++++++++++++++++-
 sw/source/filter/html/htmlreqifreader.cxx   |   64 ++++++++++++++++++++++++++++
 sw/source/filter/html/htmlreqifreader.hxx   |    9 +++
 sw/source/filter/ww8/rtfattributeoutput.cxx |   20 --------
 7 files changed, 147 insertions(+), 23 deletions(-)

New commits:
commit 76abcd5f912f1a9e6f86ffc2a489ba7dba1aac56
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Jun 7 16:49:58 2018 +0200

    sw HTML export: use PNG fallback + RTF native data for all images for ReqIF
    
    ReqIF says the image should be either PNG or has a PNG fallback and then
    it can be something else. We used to convert images to PNG to avoid
    writing any native data, but results in data loss.
    
    So instead:
    
    1) Write the original image as an RTF fragment, so it's not lost.
    
    2) Some ReqIF parsers expect an RTF fragment even for PNG, so make sure
    we always write the RTF fragment, even if that means a small
    duplication.
    
    Change-Id: Ida0fcaa58d56b9e11f81992307505599807353b5
    Reviewed-on: https://gerrit.libreoffice.org/55430
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins

diff --git a/filter/source/msfilter/rtfutil.cxx b/filter/source/msfilter/rtfutil.cxx
index ad2031d5536f..4ff71330b85c 100644
--- a/filter/source/msfilter/rtfutil.cxx
+++ b/filter/source/msfilter/rtfutil.cxx
@@ -285,6 +285,22 @@ bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2)
 
     return true;
 }
+
+bool StripMetafileHeader(const sal_uInt8*& rpGraphicAry, sal_uInt64& rSize)
+{
+    if (rpGraphicAry && (rSize > 0x22))
+    {
+        if ((rpGraphicAry[0] == 0xd7) && (rpGraphicAry[1] == 0xcd) && (rpGraphicAry[2] == 0xc6)
+            && (rpGraphicAry[3] == 0x9a))
+        {
+            // we have to get rid of the metafileheader
+            rpGraphicAry += 22;
+            rSize -= 22;
+            return true;
+        }
+    }
+    return false;
+}
 }
 }
 
diff --git a/include/filter/msfilter/rtfutil.hxx b/include/filter/msfilter/rtfutil.hxx
index 1cadaa94bd50..58aa4d54addf 100644
--- a/include/filter/msfilter/rtfutil.hxx
+++ b/include/filter/msfilter/rtfutil.hxx
@@ -70,6 +70,9 @@ MSFILTER_DLLPUBLIC OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize,
  * Extract OLE2 data from an \objdata hex dump.
  */
 MSFILTER_DLLPUBLIC bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2);
+
+/// Strips the header of a WMF file.
+MSFILTER_DLLPUBLIC bool StripMetafileHeader(const sal_uInt8*& rpGraphicAry, sal_uInt64& rSize);
 }
 }
 
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index e3ca80a0430d..8cb60396691d 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -434,11 +434,15 @@ DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testReqIfPngImg, "reqif-png-img.xhtml")
     uno::Reference<container::XNamed> xShape(getShape(1), uno::UNO_QUERY);
     CPPUNIT_ASSERT(xShape.is());
 
-    // This was Object1, PNG without fallback was imported as OLE object.
-    CPPUNIT_ASSERT_EQUAL(OUString("Image1"), xShape->getName());
-
     if (!mbExported)
+    {
+        // Imported PNG image is not an object.
+        CPPUNIT_ASSERT_EQUAL(OUString("Image1"), xShape->getName());
         return;
+    }
+
+    // All images are exported as objects in ReqIF mode.
+    CPPUNIT_ASSERT_EQUAL(OUString("Object1"), xShape->getName());
 
     // This was <img>, not <object>, which is not valid in the reqif-xhtml
     // subset.
@@ -449,6 +453,10 @@ DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testReqIfPngImg, "reqif-png-img.xhtml")
     pStream->Seek(0);
     OString aStream(read_uInt8s_ToOString(*pStream, nLength));
     CPPUNIT_ASSERT(aStream.indexOf("<reqif-xhtml:object") != -1);
+
+    // Make sure that both RTF and PNG versions are written.
+    CPPUNIT_ASSERT(aStream.indexOf("text/rtf") != -1);
+    CPPUNIT_ASSERT(aStream.indexOf("image/png") != -1);
 }
 
 DECLARE_HTMLEXPORT_TEST(testReqIfJpgImg, "reqif-jpg-img.xhtml")
diff --git a/sw/source/filter/html/htmlflywriter.cxx b/sw/source/filter/html/htmlflywriter.cxx
index 8a2653608589..42a45951ed81 100644
--- a/sw/source/filter/html/htmlflywriter.cxx
+++ b/sw/source/filter/html/htmlflywriter.cxx
@@ -64,6 +64,7 @@
 #include "css1kywd.hxx"
 #include "htmlatr.hxx"
 #include "htmlfly.hxx"
+#include "htmlreqifreader.hxx"
 
 using namespace css;
 
@@ -1425,10 +1426,16 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat,
         aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_usemap, "#" + aIMapName);
     }
 
-    if (bReplacement && !rAlternateText.isEmpty())
+    if (bReplacement)
+    {
         // XHTML object replacement image's alternate text doesn't use the
         // "alt" attribute.
-        aHtml.characters(rAlternateText.toUtf8());
+        if (rAlternateText.isEmpty())
+            // Empty alternate text is not valid.
+            aHtml.characters(" ");
+        else
+            aHtml.characters(rAlternateText.toUtf8());
+    }
 
     aHtml.flushStack();
 
@@ -1855,9 +1862,42 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF
     uno::Reference<beans::XPropertySet> xGraphic(aGraphic.GetXGraphic(), uno::UNO_QUERY);
     if (xGraphic.is() && aMimeType.isEmpty())
         xGraphic->getPropertyValue("MimeType") >>= aMimeType;
+
+    if (rHTMLWrt.mbReqIF)
+    {
+        // Write the original image as an RTF fragment.
+        OUString aFileName;
+        if (rHTMLWrt.GetOrigFileName())
+            aFileName = *rHTMLWrt.GetOrigFileName();
+        INetURLObject aURL(aFileName);
+        OUString aName(aURL.getBase());
+        aName += "_";
+        aName += aURL.getExtension();
+        aName += "_";
+        aName += OUString::number(aGraphic.GetChecksum(), 16);
+        aURL.setBase(aName);
+        aURL.setExtension("ole");
+        aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+
+        SvFileStream aOutStream(aFileName, StreamMode::WRITE);
+        if (!SwReqIfReader::WrapGraphicInRtf(aGraphic, pGrfNd->GetTwipSize(), aOutStream))
+            SAL_WARN("sw.html", "SwReqIfReader::WrapGraphicInRtf() failed");
+
+        // Refer to this data.
+        aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName);
+        rWrt.Strm().WriteOString("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object);
+        rWrt.Strm().WriteOString(" data=\"" + aFileName.toUtf8() + "\"");
+        rWrt.Strm().WriteOString(" type=\"text/rtf\"");
+        rWrt.Strm().WriteOString(">");
+        rHTMLWrt.OutNewLine();
+    }
+
     OutHTML_Image( rWrt, rFrameFormat, aGraphicURL, aGraphic, pGrfNd->GetTitle(),
                   pGrfNd->GetTwipSize(), nFrameFlags, "graphic", nullptr, aMimeType );
 
+    if (rHTMLWrt.mbReqIF)
+        rWrt.Strm().WriteOString("</" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">");
+
     return rWrt;
 }
 
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index fcfff80358bf..234d15aa3964 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -209,6 +209,70 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf)
 
     return true;
 }
+
+bool WrapGraphicInRtf(const Graphic& rGraphic, const Size& rLogicSize, SvStream& rRtf)
+{
+    rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_PICT);
+
+    GfxLink aLink = rGraphic.GetGfxLink();
+    const sal_uInt8* pGraphicAry = aLink.GetData();
+    sal_uInt64 nSize = aLink.GetDataSize();
+    OString aBlipType;
+    bool bIsWMF = false;
+    switch (aLink.GetType())
+    {
+        case GfxLinkType::NativeBmp:
+            aBlipType = OOO_STRING_SVTOOLS_RTF_WBITMAP;
+            break;
+        case GfxLinkType::NativeJpg:
+            aBlipType = OOO_STRING_SVTOOLS_RTF_JPEGBLIP;
+            break;
+        case GfxLinkType::NativePng:
+            aBlipType = OOO_STRING_SVTOOLS_RTF_PNGBLIP;
+            break;
+        case GfxLinkType::NativeWmf:
+            if (aLink.IsEMF())
+                aBlipType = OOO_STRING_SVTOOLS_RTF_EMFBLIP;
+            else
+            {
+                aBlipType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
+                bIsWMF = true;
+            }
+            break;
+        default:
+            break;
+    }
+
+    if (aBlipType.isEmpty())
+        return false;
+
+    rRtf.WriteOString(aBlipType);
+
+    Size aMapped(rGraphic.GetPrefSize());
+    rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICW);
+    rRtf.WriteOString(OString::number(aMapped.Width()));
+    rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICH);
+    rRtf.WriteOString(OString::number(aMapped.Height()));
+
+    rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICWGOAL);
+    rRtf.WriteOString(OString::number(rLogicSize.Width()));
+    rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICHGOAL);
+    rRtf.WriteOString(OString::number(rLogicSize.Height()));
+
+    if (bIsWMF)
+    {
+        rRtf.WriteOString(OString::number(8));
+        msfilter::rtfutil::StripMetafileHeader(pGraphicAry, nSize);
+    }
+    rRtf.WriteOString(SAL_NEWLINE_STRING);
+
+    msfilter::rtfutil::WriteHex(pGraphicAry, nSize, &rRtf);
+    rRtf.WriteOString(SAL_NEWLINE_STRING);
+
+    // End pict.
+    rRtf.WriteCharPtr("}");
+    return true;
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlreqifreader.hxx b/sw/source/filter/html/htmlreqifreader.hxx
index 84d470ce4db1..3b24a4f28311 100644
--- a/sw/source/filter/html/htmlreqifreader.hxx
+++ b/sw/source/filter/html/htmlreqifreader.hxx
@@ -9,6 +9,8 @@
 #ifndef INCLUDED_SW_SOURCE_FILTER_HTML_HTMLREQIFREADER_HXX
 #define INCLUDED_SW_SOURCE_FILTER_HTML_HTMLREQIFREADER_HXX
 
+class Graphic;
+class Size;
 class SvStream;
 
 namespace SwReqIfReader
@@ -22,6 +24,13 @@ bool ExtractOleFromRtf(SvStream& rRtf, SvStream& rOle, bool& bOwnFormat);
 
 /// Wraps an OLE2 container binary in an RTF fragment.
 bool WrapOleInRtf(SvStream& rOle, SvStream& rRtf);
+
+/**
+ * Wraps an image in an RTF fragment.
+ *
+ * @param rLogicSize the size used in the document model (not pixel size)
+ */
+bool WrapGraphicInRtf(const Graphic& rGraphic, const Size& rLogicSize, SvStream& rRtf);
 }
 
 #endif // INCLUDED_SW_SOURCE_FILTER_HTML_HTMLREQIFREADER_HXX
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
index f5459efe4062..8aca7d56ede5 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -3682,22 +3682,6 @@ void RtfAttributeOutput::FontPitchType(FontPitch ePitch) const
     m_rExport.OutULong(nVal);
 }
 
-static bool StripMetafileHeader(const sal_uInt8*& rpGraphicAry, unsigned long& rSize)
-{
-    if (rpGraphicAry && (rSize > 0x22))
-    {
-        if ((rpGraphicAry[0] == 0xd7) && (rpGraphicAry[1] == 0xcd) && (rpGraphicAry[2] == 0xc6)
-            && (rpGraphicAry[3] == 0x9a))
-        {
-            // we have to get rid of the metafileheader
-            rpGraphicAry += 22;
-            rSize -= 22;
-            return true;
-        }
-    }
-    return false;
-}
-
 static void lcl_AppendSP(OStringBuffer& rBuffer, const char cName[], const OUString& rValue,
                          const RtfExport& rExport)
 {
@@ -3712,7 +3696,7 @@ static void lcl_AppendSP(OStringBuffer& rBuffer, const char cName[], const OUStr
 
 static OString ExportPICT(const SwFlyFrameFormat* pFlyFrameFormat, const Size& rOrig,
                           const Size& rRendered, const Size& rMapped, const SwCropGrf& rCr,
-                          const char* pBLIPType, const sal_uInt8* pGraphicAry, unsigned long nSize,
+                          const char* pBLIPType, const sal_uInt8* pGraphicAry, sal_uInt64 nSize,
                           const RtfExport& rExport, SvStream* pStream = nullptr,
                           bool bWritePicProp = true, const SwAttrSet* pAttrSet = nullptr)
 {
@@ -3784,7 +3768,7 @@ static OString ExportPICT(const SwFlyFrameFormat* pFlyFrameFormat, const Size& r
         if (bIsWMF)
         {
             aRet.append(sal_Int32(8));
-            StripMetafileHeader(pGraphicAry, nSize);
+            msfilter::rtfutil::StripMetafileHeader(pGraphicAry, nSize);
         }
         aRet.append(SAL_NEWLINE_STRING);
         if (pStream)


More information about the Libreoffice-commits mailing list