sw XHTML / reqif export: implement OLE wrapper support for shapes

ExportImagesAsOLE=true was only handled for Writer images, not for Draw
shapes, fix this.

Change-Id: If5018ff4b7c8b303d63a862f7428aa4e8b77d498
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116641
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 9d6a084..3484ff9 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -1659,6 +1659,41 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedJPGShapeDirectly)
                "image/png");
}

CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedPNGShapeAsOLE)
{
    // Given a document with an image shape:
    loadURL("private:factory/swriter", nullptr);
    OUString aImageURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "ole2.png";
    uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
    uno::Reference<drawing::XShape> xShape(
        xFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), uno::UNO_QUERY);
    xShape->setSize(awt::Size(10000, 10000));
    uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
    xShapeProps->setPropertyValue("GraphicURL", uno::makeAny(aImageURL));
    uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
    xDrawPageSupplier->getDrawPage()->add(xShape);

    // 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")),
        comphelper::makePropertyValue("ExportImagesAsOLE", true),
    };
    xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);

    // Then make sure the PNG is embedded with an RTF wrapper:
    SvMemoryStream aStream;
    HtmlExportTest::wrapFragment(maTempFile, aStream);
    xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
    CPPUNIT_ASSERT(pXmlDoc);
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: text/rtf
    // - Actual  : image/png
    // i.e. the OLE wrapper around the PNG was missing.
    assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object", "type", "text/rtf");
}

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 4f0cc13..cd2350a 100644
--- a/sw/source/filter/html/htmlflywriter.cxx
+++ b/sw/source/filter/html/htmlflywriter.cxx
@@ -1737,9 +1737,52 @@ static Writer& OutHTML_FrameFormatAsDivOrSpan( Writer& rWrt,
    return rWrt;
}

/// Starts the OLE version of an image in the ReqIF + OLE case.
static void OutHTML_ImageOLEStart(SwHTMLWriter& rHTMLWrt, const Graphic& rGraphic,
                                  const SwFrameFormat& rFrameFormat)
{
    if (rHTMLWrt.mbReqIF && rHTMLWrt.m_bExportImagesAsOLE)
    {
        // Write the original image as an RTF fragment.
        OUString aFileName;
        if (rHTMLWrt.GetOrigFileName())
            aFileName = *rHTMLWrt.GetOrigFileName();
        INetURLObject aURL(aFileName);
        OUString aName = aURL.getBase() + "_" + aURL.getExtension() + "_"
                         + OUString::number(rGraphic.GetChecksum(), 16);
        aURL.setBase(aName);
        aURL.setExtension(u"ole");
        aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);

        SvFileStream aOutStream(aFileName, StreamMode::WRITE);
        if (!SwReqIfReader::WrapGraphicInRtf(rGraphic, rFrameFormat, aOutStream))
            SAL_WARN("sw.html", "SwReqIfReader::WrapGraphicInRtf() failed");

        // Refer to this data.
        aFileName = URIHelper::simpleNormalizedMakeRelative(rHTMLWrt.GetBaseURL(), aFileName);
        rHTMLWrt.Strm().WriteOString(
            OString("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object));
        rHTMLWrt.Strm().WriteOString(OString(" data=\"" + aFileName.toUtf8() + "\""));
        rHTMLWrt.Strm().WriteOString(" type=\"text/rtf\"");
        rHTMLWrt.Strm().WriteOString(">");
        rHTMLWrt.OutNewLine();
    }
}

/// Ends the OLE version of an image in the ReqIF + OLE case.
static void OutHTML_ImageOLEEnd(SwHTMLWriter& rHTMLWrt)
{
    if (rHTMLWrt.mbReqIF && rHTMLWrt.m_bExportImagesAsOLE)
    {
        rHTMLWrt.Strm().WriteOString(
            OString("</" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">"));
    }
}

static Writer & OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& rFrameFormat, bool bPNGFallback)
{
    SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
    bool bWritePNGFallback = !rHTMLWrt.m_bExportImagesAsOLE && bPNGFallback;

    if (rHTMLWrt.mbSkipImages)
        return rWrt;
@@ -1767,7 +1810,7 @@ static Writer & OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& r
        OUString aFilterName("JPG");
        XOutFlags nFlags = XOutFlags::UseGifIfPossible | XOutFlags::UseNativeIfPossible;

        if (rHTMLWrt.mbReqIF && !bPNGFallback)
        if (rHTMLWrt.mbReqIF && !bWritePNGFallback)
        {
            // Writing image without fallback PNG in ReqIF mode: force PNG output.
            aFilterName = "PNG";
@@ -1800,19 +1843,23 @@ static Writer & OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& r
    if (xGraphic.is() && aMimeType.isEmpty())
        xGraphic->getPropertyValue("MimeType") >>= aMimeType;

    OutHTML_ImageOLEStart(rHTMLWrt, aGraphic, rFrameFormat);

    HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
    OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, GraphicURL, aGraphic, rFrameFormat.GetName(), aSz,
                    HtmlFrmOpts::GenImgMask, "frame",
                    aIMap.GetIMapObjectCount() ? &aIMap : nullptr, aMimeType );

    GfxLink aLink = aGraphic.GetGfxLink();
    if (bPNGFallback && aLink.GetType() != GfxLinkType::NativePng)
    if (bWritePNGFallback && aLink.GetType() != GfxLinkType::NativePng)
    {
        OutHTML_FrameFormatAsImage( rWrt, rFrameFormat, /*bPNGFallback=*/false);
    }

    OutHTML_ImageEnd(aHtml, rWrt);

    OutHTML_ImageOLEEnd(rHTMLWrt);

    return rWrt;
}

@@ -1912,32 +1959,7 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF
    if (xGraphic.is() && aMimeType.isEmpty())
        xGraphic->getPropertyValue("MimeType") >>= aMimeType;

    if (rHTMLWrt.mbReqIF && rHTMLWrt.m_bExportImagesAsOLE)
    {
        // Write the original image as an RTF fragment.
        OUString aFileName;
        if (rHTMLWrt.GetOrigFileName())
            aFileName = *rHTMLWrt.GetOrigFileName();
        INetURLObject aURL(aFileName);
        OUString aName = aURL.getBase() + "_" +
            aURL.getExtension() + "_" +
            OUString::number(aGraphic.GetChecksum(), 16);
        aURL.setBase(aName);
        aURL.setExtension(u"ole");
        aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);

        SvFileStream aOutStream(aFileName, StreamMode::WRITE);
        if (!SwReqIfReader::WrapGraphicInRtf(aGraphic, rFrameFormat, aOutStream))
            SAL_WARN("sw.html", "SwReqIfReader::WrapGraphicInRtf() failed");

        // Refer to this data.
        aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName);
        rWrt.Strm().WriteOString(OString("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object));
        rWrt.Strm().WriteOString(OString(" data=\"" + aFileName.toUtf8() + "\""));
        rWrt.Strm().WriteOString(" type=\"text/rtf\"");
        rWrt.Strm().WriteOString(">");
        rHTMLWrt.OutNewLine();
    }
    OutHTML_ImageOLEStart(rHTMLWrt, aGraphic, rFrameFormat);

    HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
    OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic, pGrfNd->GetTitle(),
@@ -1953,8 +1975,7 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF

    OutHTML_ImageEnd(aHtml, rWrt);

    if (rHTMLWrt.mbReqIF && rHTMLWrt.m_bExportImagesAsOLE)
        rWrt.Strm().WriteOString(OString("</" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">"));
    OutHTML_ImageOLEEnd(rHTMLWrt);

    return rWrt;
}