sw reqif-xhtml export: fix export of transparent TIF

Since commit 22b50f1937de67e4ad9e692d6964aa5b8d33af7a (use libtiff for
tiff import, 2022-05-21), transparent TIFs are imported correctly.
As the result, reqif export started to output the transparent TIF
images as GIFs, because XOutFlags::UseGifIfSensible handles case of
transparency, and XOutFlags::UseNativeIfPossible didn't handle TIF.
Additionally, the resulting mediatype was reported incorrectly:

  <reqif-xhtml:object data="[...].gif" type="image/tiff" ... >

1. Handle TIFs in XOutBitmap::WriteGraphic when XOutFlags::UseNativeIfPossible
   is specified.
2. Return the corrected mediatype from XOutBitmap::WriteGraphic,
   to inform the caller about the possible change.
3. Remove the XOutFlags::UseGifIfSensible flag when doing the
   reqif export, to avoid the format change at all.

Change-Id: I99f7cfb8d12ef66d372700ec810bd8b269868ffd
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149744
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/include/svx/xoutbmp.hxx b/include/svx/xoutbmp.hxx
index 43a666d..d2137f6 100644
--- a/include/svx/xoutbmp.hxx
+++ b/include/svx/xoutbmp.hxx
@@ -59,7 +59,8 @@ public:
    static ErrCode      WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
                                      const OUString& rFilterName, const XOutFlags nFlags,
                                      const Size* pMtfSize_100TH_MM = nullptr,
                                      const css::uno::Sequence< css::beans::PropertyValue >* pFilterData = nullptr);
                                      const css::uno::Sequence< css::beans::PropertyValue >* pFilterData = nullptr,
                                      OUString* pMediaType = nullptr );
    static bool GraphicToBase64(const Graphic& rGraphic, OUString& rOUString,
                                bool bAddPrefix = true,
                                ConvertDataFormat aTargetFormat = ConvertDataFormat::Unknown);
diff --git a/svx/source/xoutdev/_xoutbmp.cxx b/svx/source/xoutdev/_xoutbmp.cxx
index 7241fed..d392426 100644
--- a/svx/source/xoutdev/_xoutbmp.cxx
+++ b/svx/source/xoutdev/_xoutbmp.cxx
@@ -30,10 +30,13 @@
#include <vcl/cvtgrf.hxx>
#include <memory>

#include <com/sun/star/beans/XPropertySet.hpp>

constexpr OUStringLiteral FORMAT_BMP = u"bmp";
constexpr OUStringLiteral FORMAT_GIF = u"gif";
constexpr OUStringLiteral FORMAT_JPG = u"jpg";
constexpr OUStringLiteral FORMAT_PNG = u"png";
constexpr OUStringLiteral FORMAT_TIF = u"tif";
constexpr OUStringLiteral FORMAT_WEBP = u"webp";

using namespace com::sun::star;
@@ -104,7 +107,8 @@ Graphic XOutBitmap::MirrorGraphic( const Graphic& rGraphic, const BmpMirrorFlags
ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
                                 const OUString& rFilterName, const XOutFlags nFlags,
                                 const Size* pMtfSize_100TH_MM,
                                 const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
                                 const css::uno::Sequence< css::beans::PropertyValue >* pFilterData,
                                 OUString* pMediaType )
{
    if( rGraphic.GetType() == GraphicType::NONE )
        return ERRCODE_NONE;
@@ -183,6 +187,7 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,

            case GfxLinkType::NativeJpg: aExt = FORMAT_JPG; break;
            case GfxLinkType::NativePng: aExt = FORMAT_PNG; break;
            case GfxLinkType::NativeTif: aExt = FORMAT_TIF; break;
            case GfxLinkType::NativeWebp: aExt = FORMAT_WEBP; break;

            default:
@@ -197,6 +202,9 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
            if( !(nFlags & XOutFlags::DontAddExtension) )
                aURL.setExtension( aExt );
            rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
            if (pMediaType)
                if (auto xGraphic = rGraphic.GetXGraphic().query<css::beans::XPropertySet>())
                    xGraphic->getPropertyValue("MimeType") >>= *pMediaType;

            SfxMedium   aMedium(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE | StreamMode::SHARE_DENYNONE | StreamMode::TRUNC);
            SvStream*   pOStm = aMedium.GetOutStream();
@@ -308,6 +316,8 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
            if( !(nFlags & XOutFlags::DontAddExtension) )
                aURL.setExtension( aExt );
            rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
            if (pMediaType)
                *pMediaType = rFilter.GetExportFormatMediaType(nFilter);
            nErr = ExportGraphic( aGraphic, aURL, rFilter, nFilter, pFilterData );
        }
    }
diff --git a/sw/qa/extras/htmlexport/data/reqif-transparent-tif-img.odt b/sw/qa/extras/htmlexport/data/reqif-transparent-tif-img.odt
new file mode 100644
index 0000000..278cf9e
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/reqif-transparent-tif-img.odt
Binary files differ
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index ca9b816..1dd8dff 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -2488,6 +2488,29 @@ CPPUNIT_TEST_FIXTURE(HtmlExportTest, testTdf153923)
    assertXPath(pDoc, "/html/body//dd");
}

CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIfTransparentTifImg)
{
    // reqIf export must keep the TIF encoding of the image
    createSwDoc("reqif-transparent-tif-img.odt");
    ExportToReqif();

    SvMemoryStream aStream;
    WrapReqifFromTempFile(aStream);
    xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
    assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object[1]", "type", "image/tiff");
    OUString imageName = getXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object[1]", "data");
    // Without the accompanying fix in place, this test would have failed,
    // ending with .gif, because XOutFlags::UseGifIfSensible flag combined
    // with the transparent image would result in GIF export
    CPPUNIT_ASSERT(imageName.endsWith(".tif"));

    INetURLObject aURL(maTempFile.GetURL());
    aURL.setName(imageName);
    GraphicDescriptor aDescriptor(aURL);
    aDescriptor.Detect();
    CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::TIF, aDescriptor.GetFileFormat());
}

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 85caaff8..acfeec1 100644
--- a/sw/source/filter/html/htmlflywriter.cxx
+++ b/sw/source/filter/html/htmlflywriter.cxx
@@ -1951,18 +1951,21 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
            Size aMM100Size = o3tl::convert( rSize.GetSize(),
                            o3tl::Length::twip, o3tl::Length::mm100 );

            OUString aFilterName("");
            OUString aFilterName;

            if (rWrt.mbReqIF && !bWritePNGFallback)
            if (rWrt.mbReqIF)
            {
                // 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;
                // In ReqIF mode, do not try to write GIF for other image types
                nFlags &= ~XOutFlags::UseGifIfSensible;
                aMimeType = "image/png";
                if (!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;
                }
            }

            const Graphic& rGraphic = pGrfNd->GetGrf();
@@ -1971,6 +1974,8 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
            if (!rGraphic.isAvailable())
                const_cast<Graphic&>(rGraphic).makeAvailable();

            OUString aMimeTypeOverride;

            if (rWrt.mbReqIF && bWritePNGFallback)
            {
                // ReqIF: force native data if possible.
@@ -1982,7 +1987,7 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
                else if (rGraphic.GetGfxLink().IsEMF())
                {
                    aFilterName = "emf";
                    aMimeType = "image/x-emf"; // avoid image/x-wmf
                    aMimeTypeOverride = "image/x-emf"; // avoid image/x-wmf
                }
                else if (pVectorGraphicData && pVectorGraphicData->getType() == VectorGraphicDataType::Wmf)
                {
@@ -1991,12 +1996,12 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
                else if (rGraphic.GetGfxLink().GetType() == GfxLinkType::NativeTif)
                {
                    aFilterName = "tif";
                    aMimeType = "image/tiff"; // avoid image/x-vclgraphic
                    aMimeTypeOverride = "image/tiff"; // avoid image/x-vclgraphic
                }
            }

            ErrCode nErr = XOutBitmap::WriteGraphic( rGraphic, aGraphicURL,
                    aFilterName, nFlags, &aMM100Size );
                    aFilterName, nFlags, &aMM100Size, nullptr, &aMimeType );
            if( nErr )
            {
                rWrt.m_nWarn = WARN_SWG_POOR_LOAD;
@@ -2005,6 +2010,8 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
            aGraphicURL = URIHelper::SmartRel2Abs(
                INetURLObject(rWrt.GetBaseURL()), aGraphicURL,
                URIHelper::GetMaybeFileHdl() );
            if (!aMimeTypeOverride.isEmpty())
                aMimeType = aMimeTypeOverride;
        }
        else
        {