[Libreoffice-commits] core.git: include/oox oox/source sw/qa sw/source
Daniel Arato (NISZ) (via logerrit)
logerrit at kemper.freedesktop.org
Fri Mar 26 12:08:41 UTC 2021
include/oox/export/drawingml.hxx | 8 +++--
include/oox/export/vmlexport.hxx | 6 ++-
oox/source/export/drawingml.cxx | 31 ++++++++++++++-----
oox/source/export/vmlexport.cxx | 10 +++---
sw/qa/extras/ooxmlexport/data/tdf118535.odt |binary
sw/qa/extras/ooxmlexport/ooxmlexport16.cxx | 13 ++++++++
sw/source/filter/ww8/docxattributeoutput.cxx | 42 ++++++++++++++++++++-------
sw/source/filter/ww8/docxattributeoutput.hxx | 11 +++----
sw/source/filter/ww8/docxexport.cxx | 4 --
9 files changed, 88 insertions(+), 37 deletions(-)
New commits:
commit 797fef38612fb2fd62d1f6591619b9361e526bca
Author: Daniel Arato (NISZ) <arato.daniel at nisz.hu>
AuthorDate: Tue Mar 9 14:11:11 2021 +0100
Commit: László Németh <nemeth at numbertext.org>
CommitDate: Fri Mar 26 13:07:57 2021 +0100
tdf#118535 DOCX export: save header image once
Writer used to dump the same image file as many times
as it was featured in different headers or footers in
the document, bloating the .docx file size.
This is countered by making all "relationships" in the
header*.xml.rels files point to the same image.
Change-Id: I44d72630289c721d58d8f7e208517df2f1fe621c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112656
Tested-by: László Németh <nemeth at numbertext.org>
Reviewed-by: László Németh <nemeth at numbertext.org>
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 2cd17e6defb0..cfcad30fa257 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -125,8 +125,10 @@ public:
virtual void WriteTextBox(css::uno::Reference<css::drawing::XShape> xShape) = 0;
/// Look up the RelId of a graphic based on its checksum.
virtual OUString FindRelId(BitmapChecksum nChecksum) = 0;
- /// Store the RelId of a graphic based on its checksum.
- virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId) = 0;
+ /// Look up the filename of a graphic based on its checksum.
+ virtual OUString FindFileName(BitmapChecksum nChecksum) = 0;
+ /// Store the RelId and filename of a graphic based on its checksum.
+ virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId, const OUString& rFileName) = 0;
/// Get textbox which belongs to the shape.
virtual css::uno::Reference<css::text::XTextFrame> GetUnoTextFrame(
css::uno::Reference<css::drawing::XShape> xShape) = 0;
@@ -192,7 +194,7 @@ public:
void SetBackgroundDark(bool bIsDark) { mbIsBackgroundDark = bIsDark; }
/// If bRelPathToMedia is true add "../" to image folder path while adding the image relationship
- OUString WriteImage( const Graphic &rGraphic , bool bRelPathToMedia = false);
+ OUString WriteImage( const Graphic &rGraphic , bool bRelPathToMedia = false, OUString* pFileName = nullptr );
void WriteColor( ::Color nColor, sal_Int32 nAlpha = MAX_PERCENT );
void WriteColor( const OUString& sColorSchemeName, const css::uno::Sequence< css::beans::PropertyValue >& aTransformations, sal_Int32 nAlpha = MAX_PERCENT );
diff --git a/include/oox/export/vmlexport.hxx b/include/oox/export/vmlexport.hxx
index dd5edc57c208..9a53a07652c8 100644
--- a/include/oox/export/vmlexport.hxx
+++ b/include/oox/export/vmlexport.hxx
@@ -67,8 +67,10 @@ public:
virtual void WriteVMLTextBox(css::uno::Reference<css::drawing::XShape> xShape) = 0;
/// Look up the RelId of a graphic based on its checksum.
virtual OUString FindRelId(BitmapChecksum nChecksum) = 0;
- /// Store the RelId of a graphic based on its checksum.
- virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId) = 0;
+ /// Look up the filename of a graphic based on its checksum.
+ virtual OUString FindFileName(BitmapChecksum nChecksum) = 0;
+ /// Store the RelId and filename of a graphic based on its checksum.
+ virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId, const OUString& rFileName) = 0;
protected:
VMLTextExport() {}
virtual ~VMLTextExport() {}
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 67f26e71daea..32780296ce89 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -1162,7 +1162,7 @@ const char* DrawingML::GetRelationCompPrefix() const
return "unknown";
}
-OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia )
+OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia, OUString* pFileName )
{
GfxLink aLink = rGraphic.GetGfxLink ();
OUString sMediaType;
@@ -1266,15 +1266,18 @@ OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia )
sRelationCompPrefix = "../";
else
sRelationCompPrefix = GetRelationCompPrefix();
+ OUString sPath = OUStringBuffer()
+ .appendAscii( sRelationCompPrefix.getStr() )
+ .appendAscii( sRelPathToMedia.getStr() )
+ .append( static_cast<sal_Int32>(mnImageCounter ++) )
+ .appendAscii( pExtension )
+ .makeStringAndClear();
sRelId = mpFB->addRelation( mpFS->getOutputStream(),
oox::getRelationship(Relationship::IMAGE),
- OUStringBuffer()
- .appendAscii( sRelationCompPrefix.getStr() )
- .appendAscii( sRelPathToMedia.getStr() )
- .append( static_cast<sal_Int32>(mnImageCounter ++) )
- .appendAscii( pExtension )
- .makeStringAndClear() );
+ sPath );
+ if (pFileName)
+ *pFileName = sPath;
return sRelId;
}
@@ -1434,6 +1437,7 @@ OUString DrawingML::WriteXGraphicBlip(uno::Reference<beans::XPropertySet> const
bool bRelPathToMedia)
{
OUString sRelId;
+ OUString sFileName;
if (!rxGraphic.is())
return sRelId;
@@ -1443,16 +1447,25 @@ OUString DrawingML::WriteXGraphicBlip(uno::Reference<beans::XPropertySet> const
{
BitmapChecksum nChecksum = aGraphic.GetChecksum();
sRelId = mpTextExport->FindRelId(nChecksum);
+ sFileName = mpTextExport->FindFileName(nChecksum);
}
if (sRelId.isEmpty())
{
- sRelId = WriteImage(aGraphic, bRelPathToMedia);
+ sRelId = WriteImage(aGraphic, bRelPathToMedia, &sFileName);
if (mpTextExport)
{
BitmapChecksum nChecksum = aGraphic.GetChecksum();
- mpTextExport->CacheRelId(nChecksum, sRelId);
+ mpTextExport->CacheRelId(nChecksum, sRelId, sFileName);
}
}
+ else
+ {
+ // Include the same relation again. This makes it possible to
+ // reuse an image across different headers.
+ sRelId = mpFB->addRelation( mpFS->getOutputStream(),
+ oox::getRelationship(Relationship::IMAGE),
+ sFileName );
+ }
mpFS->startElementNS(XML_a, XML_blip, FSNS(XML_r, XML_embed), sRelId);
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 9c6b89ef7dd7..9f8df2279611 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -741,8 +741,9 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
OUString aImageId = m_pTextExport->FindRelId(nChecksum);
if (aImageId.isEmpty())
{
- aImageId = m_pTextExport->GetDrawingML().WriteImage(aGraphic);
- m_pTextExport->CacheRelId(nChecksum, aImageId);
+ OUString aFileName;
+ aImageId = m_pTextExport->GetDrawingML().WriteImage(aGraphic, false, &aFileName);
+ m_pTextExport->CacheRelId(nChecksum, aImageId, aFileName);
}
pAttrList->add(FSNS(XML_r, XML_id),
OUStringToOString(aImageId, RTL_TEXTENCODING_UTF8));
@@ -763,8 +764,9 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
OUString aImageId = m_pTextExport->FindRelId(nChecksum);
if (aImageId.isEmpty())
{
- aImageId = m_pTextExport->GetDrawingML().WriteImage(aGraphic);
- m_pTextExport->CacheRelId(nChecksum, aImageId);
+ OUString aFileName;
+ aImageId = m_pTextExport->GetDrawingML().WriteImage(aGraphic, false, &aFileName);
+ m_pTextExport->CacheRelId(nChecksum, aImageId, aFileName);
}
pAttrList->add(FSNS(XML_r, XML_id),
OUStringToOString(aImageId, RTL_TEXTENCODING_UTF8));
diff --git a/sw/qa/extras/ooxmlexport/data/tdf118535.odt b/sw/qa/extras/ooxmlexport/data/tdf118535.odt
new file mode 100644
index 000000000000..146c6f471a18
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf118535.odt differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
index 28a2edb234bf..ac46467b87f7 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
@@ -18,6 +18,8 @@
#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
+#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
+#include <comphelper/configuration.hxx>
#include <editeng/escapementitem.hxx>
#include <unotools/fltrcfg.hxx>
@@ -224,6 +226,17 @@ DECLARE_OOXMLEXPORT_TEST(testTdf138953, "croppedAndRotated.odt")
CPPUNIT_ASSERT_EQUAL(sal_Int32(8664), frameRect.Width);
}
+DECLARE_OOXMLEXPORT_TEST(testTdf118535, "tdf118535.odt")
+{
+ uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL());
+ CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/media/image1.jpeg")));
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: false
+ // - Actual : true
+ // i.e. the embedded picture would have been saved twice.
+ CPPUNIT_ASSERT_EQUAL(false, bool(xNameAccess->hasByName("word/media/image2.jpeg")));
+}
+
DECLARE_OOXMLEXPORT_TEST(testTdf133473_shadowSize, "tdf133473.docx")
{
uno::Reference<drawing::XShape> xShape = getShape(1);
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index c0b0059d464a..46d19f82cec0 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -4893,15 +4893,25 @@ OUString DocxAttributeOutput::FindRelId(BitmapChecksum nChecksum)
OUString aRet;
if (!m_aSdrRelIdCache.empty() && m_aSdrRelIdCache.top().find(nChecksum) != m_aSdrRelIdCache.top().end())
- aRet = m_aSdrRelIdCache.top()[nChecksum];
+ aRet = m_aSdrRelIdCache.top()[nChecksum].first;
return aRet;
}
-void DocxAttributeOutput::CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId)
+OUString DocxAttributeOutput::FindFileName(BitmapChecksum nChecksum)
+{
+ OUString aRet;
+
+ if (!m_aSdrRelIdCache.empty() && m_aSdrRelIdCache.top().find(nChecksum) != m_aSdrRelIdCache.top().end())
+ aRet = m_aSdrRelIdCache.top()[nChecksum].second;
+
+ return aRet;
+}
+
+void DocxAttributeOutput::CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId, const OUString& rFileName)
{
if (!m_aSdrRelIdCache.empty())
- m_aSdrRelIdCache.top()[nChecksum] = rRelId;
+ m_aSdrRelIdCache.top()[nChecksum] = std::pair(rRelId, rFileName);
}
uno::Reference<css::text::XTextFrame> DocxAttributeOutput::GetUnoTextFrame(
@@ -4910,9 +4920,9 @@ uno::Reference<css::text::XTextFrame> DocxAttributeOutput::GetUnoTextFrame(
return SwTextBoxHelper::getUnoTextFrame(xShape);
}
-OString DocxAttributeOutput::getExistingGraphicRelId(BitmapChecksum nChecksum)
+std::pair<OString, OUString> DocxAttributeOutput::getExistingGraphicRelId(BitmapChecksum nChecksum)
{
- OString aResult;
+ std::pair<OString, OUString> aResult;
if (m_aRelIdCache.empty())
return aResult;
@@ -4927,10 +4937,10 @@ OString DocxAttributeOutput::getExistingGraphicRelId(BitmapChecksum nChecksum)
return aResult;
}
-void DocxAttributeOutput::cacheGraphicRelId(BitmapChecksum nChecksum, OString const & rRelId)
+void DocxAttributeOutput::cacheGraphicRelId(BitmapChecksum nChecksum, OString const & rRelId, OUString const & rFileName)
{
if (!m_aRelIdCache.empty())
- m_aRelIdCache.top().emplace(nChecksum, rRelId);
+ m_aRelIdCache.top().emplace(nChecksum, std::pair(rRelId, rFileName));
}
void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrameFormat* pOLEFrameFormat, SwOLENode* pOLENode, const SdrObject* pSdrObj )
@@ -4979,17 +4989,29 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size
aGraphic = *pOLENode->GetGraphic();
BitmapChecksum aChecksum = aGraphic.GetChecksum();
- aRelId = getExistingGraphicRelId(aChecksum);
+ OUString aFileName;
+ std::tie(aRelId, aFileName) = getExistingGraphicRelId(aChecksum);
+ OUString aImageId;
if (aRelId.isEmpty())
{
// Not in cache, then need to write it.
m_rDrawingML.SetFS( m_pSerializer ); // to be sure that we write to the right stream
- OUString aImageId = m_rDrawingML.WriteImage(aGraphic);
+ aImageId = m_rDrawingML.WriteImage(aGraphic, false, &aFileName);
+
+ aRelId = OUStringToOString( aImageId, RTL_TEXTENCODING_UTF8 );
+ cacheGraphicRelId(aChecksum, aRelId, aFileName);
+ }
+ else
+ {
+ // Include the same relation again. This makes it possible to
+ // reuse an image across different headers.
+ aImageId = m_rDrawingML.GetFB()->addRelation( m_pSerializer->getOutputStream(),
+ oox::getRelationship(Relationship::IMAGE),
+ aFileName );
aRelId = OUStringToOString( aImageId, RTL_TEXTENCODING_UTF8 );
- cacheGraphicRelId(aChecksum, aRelId);
}
nImageType = XML_embed;
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 423396196153..565741bd0afe 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -960,14 +960,14 @@ private:
// store hardcoded value which was set during import.
sal_Int32 m_nParaBeforeSpacing,m_nParaAfterSpacing;
- OString getExistingGraphicRelId(BitmapChecksum aChecksum);
- void cacheGraphicRelId(BitmapChecksum nChecksum, OString const & rRelId);
+ std::pair<OString, OUString> getExistingGraphicRelId(BitmapChecksum aChecksum);
+ void cacheGraphicRelId(BitmapChecksum nChecksum, OString const & rRelId, OUString const & rFileName);
/// RelId <-> Graphic* cache, so that in case of alternate content, the same graphic only gets written once.
- std::stack< std::map<BitmapChecksum, OString> > m_aRelIdCache;
+ std::stack< std::map<BitmapChecksum, std::pair<OString, OUString>> > m_aRelIdCache;
/// RelId <-> BitmapChecksum cache, similar to m_aRelIdCache, but used for non-Writer graphics, handled in oox.
- std::stack< std::map<BitmapChecksum, OUString> > m_aSdrRelIdCache;
+ std::stack< std::map<BitmapChecksum, std::pair<OUString, OUString>> > m_aSdrRelIdCache;
/// members to control the existence of grabbagged SDT properties in the paragraph
sal_Int32 m_nParagraphSdtPrToken;
@@ -1026,7 +1026,8 @@ public:
/// DMLTextExport
virtual void WriteTextBox(css::uno::Reference<css::drawing::XShape> xShape) override;
virtual OUString FindRelId(BitmapChecksum nChecksum) override;
- virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId) override;
+ virtual OUString FindFileName(BitmapChecksum nChecksum) override;
+ virtual void CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId, const OUString& rFileName) override;
virtual css::uno::Reference<css::text::XTextFrame> GetUnoTextFrame(
css::uno::Reference<css::drawing::XShape> xShape) override;
virtual oox::drawingml::DrawingML& GetDrawingML() override;
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 89fac4af6e0a..20a6f906e72d 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -818,15 +818,11 @@ void DocxExport::WriteHeaderFooter( const SwFormat* pFormat, bool bHeader, const
SetFS( pFS );
{
DocxTableExportContext aTableExportContext(*m_pAttrOutput);
- //When the stream changes the cache which is maintained for the graphics in case of alternate content is not cleared.
- //So clearing the alternate content graphic cache.
- m_pAttrOutput->PushRelIdCache();
// do the work
if (pFormat == nullptr)
AttrOutput().EmptyParagraph();
else
WriteHeaderFooterText(*pFormat, bHeader);
- m_pAttrOutput->PopRelIdCache();
m_pAttrOutput->EndParaSdtBlock();
}
More information about the Libreoffice-commits
mailing list