summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/oox/export/drawingml.hxx8
-rw-r--r--include/oox/export/vmlexport.hxx6
-rw-r--r--oox/source/export/drawingml.cxx31
-rw-r--r--oox/source/export/vmlexport.cxx10
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf118535.odtbin0 -> 12032 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport16.cxx13
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx42
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.hxx11
-rw-r--r--sw/source/filter/ww8/docxexport.cxx4
9 files changed, 88 insertions, 37 deletions
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
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf118535.odt
Binary files 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();
}