Kaydet (Commit) e807d615 authored tarafından Miklos Vajna's avatar Miklos Vajna

sw reqif-xhtml export: write graphic of OLE object at an RTF level as well

An embedded object have have its replacement graphic at 3 levels in
reqif-xhtml: PNG at HTML level, WMF at RTF level and as a stream in the
OLE2 storage. Some reqif readers depend on having the replacement
graphic at an RTF level, so write that variant, too.

Change-Id: I3391303248d2792a4c370e8fc84db0f22185312e
Reviewed-on: https://gerrit.libreoffice.org/63419
Tested-by: Jenkins
Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.com>
üst 39aa91cf
......@@ -23,6 +23,8 @@
#include <usrpref.hxx>
#include <test/htmltesttools.hxx>
#include <tools/urlobj.hxx>
#include <svtools/rtfkeywd.hxx>
class HtmlExportTest : public SwModelTestBase, public HtmlTestTools
{
......@@ -564,6 +566,32 @@ DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testReqIfOle2, "reqif-ole2.xhtml")
// Finally the export also failed as it tried to open the stream from the
// document storage, but the embedded object already opened it, so an
// exception of type com.sun.star.io.IOException was thrown.
if (mbExported)
{
// Check that the replacement graphic is exported at RTF level.
SvMemoryStream aStream;
wrapFragment(aStream);
xmlDocPtr pDoc = parseXmlStream(&aStream);
CPPUNIT_ASSERT(pDoc);
// Get the path of the RTF data.
OUString aOlePath = getXPath(
pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object", "data");
OUString aOleSuffix(".ole");
CPPUNIT_ASSERT(aOlePath.endsWith(aOleSuffix));
INetURLObject aUrl(maTempFile.GetURL());
aUrl.setBase(aOlePath.copy(0, aOlePath.getLength() - aOleSuffix.getLength()));
aUrl.setExtension("ole");
OUString aOleUrl = aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE);
// Search for \result in the RTF data.
SvFileStream aOleStream(aOleUrl, StreamMode::READ);
CPPUNIT_ASSERT(aOleStream.IsOpen());
OString aOleString(read_uInt8s_ToOString(aOleStream, aOleStream.TellEnd()));
// Without the accompanying fix in place, this test would have failed,
// replacement graphic was missing at RTF level.
CPPUNIT_ASSERT(aOleString.indexOf(OOO_STRING_SVTOOLS_RTF_RESULT) != -1);
}
}
DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testReqIfOle2Odg, "reqif-ole-odg.xhtml")
......
......@@ -1534,7 +1534,7 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame
if (xStream.is())
{
std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xStream));
if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream))
if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream, *pOLENd))
{
// Data always wrapped in RTF.
aFileType = "text/rtf";
......@@ -1553,7 +1553,7 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame
aOLEExp.ExportOLEObject(rOLEObj.GetObject(), *pStorage);
pStorage->Commit();
aMemory.Seek(0);
if (SwReqIfReader::WrapOleInRtf(aMemory, aOutStream))
if (SwReqIfReader::WrapOleInRtf(aMemory, aOutStream, *pOLENd))
{
// Data always wrapped in RTF.
aFileType = "text/rtf";
......
......@@ -18,6 +18,8 @@
#include <svtools/rtftoken.h>
#include <tools/stream.hxx>
#include <filter/msfilter/msdffimp.hxx>
#include <vcl/cvtgrf.hxx>
#include <ndole.hxx>
namespace
{
......@@ -132,6 +134,42 @@ OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1)
return aClassName;
}
/// Writes rGraphic with size from rOLENode to rRtf as an RTF hexdump.
void WrapOleGraphicInRtf(SvStream& rRtf, SwOLENode& rOLENode, const Graphic& rGraphic)
{
// Start result.
rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_RESULT);
// Start pict.
rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_PICT);
rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_WMETAFILE "8");
Size aSize(rOLENode.GetTwipSize());
rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICW);
rRtf.WriteCharPtr(OString::number(aSize.getWidth()).getStr());
rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICH);
rRtf.WriteCharPtr(OString::number(aSize.getHeight()).getStr());
rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICWGOAL);
rRtf.WriteCharPtr(OString::number(aSize.getWidth()).getStr());
rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICHGOAL);
rRtf.WriteCharPtr(OString::number(aSize.getHeight()).getStr());
SvMemoryStream aGraphicStream;
if (GraphicConverter::Export(aGraphicStream, rGraphic, ConvertDataFormat::WMF) == ERRCODE_NONE)
{
const sal_uInt8* pGraphicAry = static_cast<const sal_uInt8*>(aGraphicStream.GetData());
sal_uInt64 nSize = aGraphicStream.TellEnd();
msfilter::rtfutil::StripMetafileHeader(pGraphicAry, nSize);
rRtf.WriteCharPtr(SAL_NEWLINE_STRING);
msfilter::rtfutil::WriteHex(pGraphicAry, nSize, &rRtf);
}
// End pict.
rRtf.WriteCharPtr("}");
// End result.
rRtf.WriteCharPtr("}");
}
}
namespace SwReqIfReader
......@@ -177,7 +215,7 @@ bool ExtractOleFromRtf(SvStream& rRtf, SvStream& rOle, bool& bOwnFormat)
return true;
}
bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf)
bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode)
{
sal_uInt64 nPos = rOle2.Tell();
comphelper::ScopeGuard g([&rOle2, nPos] { rOle2.Seek(nPos); });
......@@ -196,6 +234,13 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf)
// End objclass.
rRtf.WriteCharPtr("}");
// Object size.
Size aSize(rOLENode.GetTwipSize());
rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_OBJW);
rRtf.WriteCharPtr(OString::number(aSize.getWidth()).getStr());
rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_OBJH);
rRtf.WriteCharPtr(OString::number(aSize.getHeight()).getStr());
// Start objdata.
rRtf.WriteCharPtr(
"{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA SAL_NEWLINE_STRING);
......@@ -203,6 +248,10 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf)
&rRtf);
// End objdata.
rRtf.WriteCharPtr("}");
if (const Graphic* pGraphic = rOLENode.GetGraphic())
WrapOleGraphicInRtf(rRtf, rOLENode, *pGraphic);
// End object.
rRtf.WriteCharPtr("}");
......
......@@ -12,6 +12,7 @@
class Graphic;
class Size;
class SvStream;
class SwOLENode;
namespace SwReqIfReader
{
......@@ -23,7 +24,7 @@ namespace SwReqIfReader
bool ExtractOleFromRtf(SvStream& rRtf, SvStream& rOle, bool& bOwnFormat);
/// Wraps an OLE2 container binary in an RTF fragment.
bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf);
bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode);
/**
* Wraps an image in an RTF fragment.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment