summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2021-06-01 14:50:01 +0200
committerMiklos Vajna <vmiklos@collabora.com>2021-06-01 16:13:11 +0200
commit3fe661041aadbfd945a20afe2310a19f5e76976e (patch)
treed6ea99a898ee453dfd32e65739f9909f7633a865 /sw
parente45575443ca5e4b6683e81e1c2e8e4a543b506fb (diff)
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@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx32
-rw-r--r--sw/source/filter/html/htmlflywriter.cxx76
-rw-r--r--sw/source/filter/html/htmlplug.cxx5
-rw-r--r--sw/source/filter/html/wrthtml.hxx3
4 files changed, 86 insertions, 30 deletions
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,