summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf103001.docxbin0 -> 33883 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport4.cxx13
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx32
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.hxx7
-rw-r--r--sw/source/filter/ww8/docxexport.cxx8
5 files changed, 44 insertions, 16 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/tdf103001.docx b/sw/qa/extras/ooxmlexport/data/tdf103001.docx
new file mode 100644
index 000000000000..332d415698ba
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf103001.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
index 1a6c967e45b3..d08d75126fa2 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
@@ -958,6 +958,19 @@ DECLARE_OOXMLEXPORT_TEST(testTdf83227, "tdf83227.docx")
CPPUNIT_ASSERT_EQUAL(false, bool(xNameAccess->hasByName("word/media/image2.png")));
}
+DECLARE_OOXMLEXPORT_TEST(testTdf103001, "tdf103001.docx")
+{
+ // The same image is featured in the header and in the body text, make sure
+ // the header relation is still written, even when caching is enabled.
+ if (!mbExported)
+ return;
+
+ uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL());
+ // This failed: header reused the RelId of the body text, even if RelIds
+ // are local to their stream.
+ CPPUNIT_ASSERT(xNameAccess->hasByName("word/_rels/header1.xml.rels"));
+}
+
DECLARE_OOXMLEXPORT_TEST(testTdf92521, "tdf92521.odt")
{
if (xmlDocPtr pXmlDoc = parseExport("word/document.xml"))
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 582e8cde7b92..4096694ead7f 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -4166,25 +4166,34 @@ void DocxAttributeOutput::WriteSrcRect(const SdrObject* pSdrObj )
}
}
-void DocxAttributeOutput::ClearRelIdCache()
+void DocxAttributeOutput::PopRelIdCache()
{
- m_aRelIdCache.clear();
- m_aSdrRelIdCache.clear();
+ if (!m_aRelIdCache.empty())
+ m_aRelIdCache.pop();
+ if (!m_aSdrRelIdCache.empty())
+ m_aSdrRelIdCache.pop();
+}
+
+void DocxAttributeOutput::PushRelIdCache()
+{
+ m_aRelIdCache.push(std::map<const Graphic*, OString>());
+ m_aSdrRelIdCache.push(std::map<BitmapChecksum, OUString>());
}
OUString DocxAttributeOutput::FindRelId(BitmapChecksum nChecksum)
{
OUString aRet;
- if (m_aSdrRelIdCache.find(nChecksum) != m_aSdrRelIdCache.end())
- aRet = m_aSdrRelIdCache[nChecksum];
+ if (!m_aSdrRelIdCache.empty() && m_aSdrRelIdCache.top().find(nChecksum) != m_aSdrRelIdCache.top().end())
+ aRet = m_aSdrRelIdCache.top()[nChecksum];
return aRet;
}
void DocxAttributeOutput::CacheRelId(BitmapChecksum nChecksum, const OUString& rRelId)
{
- m_aSdrRelIdCache[nChecksum] = rRelId;
+ if (!m_aSdrRelIdCache.empty())
+ m_aSdrRelIdCache.top()[nChecksum] = rRelId;
}
void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrameFormat* pOLEFrameFormat, SwOLENode* pOLENode, const SdrObject* pSdrObj )
@@ -4222,9 +4231,9 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size
else
pGraphic = pOLENode->GetGraphic();
- if (m_aRelIdCache.find(pGraphic) != m_aRelIdCache.end())
+ if (!m_aRelIdCache.empty() && m_aRelIdCache.top().find(pGraphic) != m_aRelIdCache.top().end())
// We already have a RelId for this Graphic.
- aRelId = m_aRelIdCache[pGraphic];
+ aRelId = m_aRelIdCache.top()[pGraphic];
else
{
// Not in cache, then need to write it.
@@ -4233,7 +4242,8 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size
OUString aImageId = m_rDrawingML.WriteImage( *pGraphic );
aRelId = OUStringToOString( aImageId, RTL_TEXTENCODING_UTF8 );
- m_aRelIdCache[pGraphic] = aRelId;
+ if (!m_aRelIdCache.empty())
+ m_aRelIdCache.top()[pGraphic] = aRelId;
}
nImageType = XML_embed;
@@ -8497,6 +8507,10 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
, m_nStateOfFlyFrame( FLY_NOT_PROCESSED )
, m_bParagraphSdtHasId(false)
{
+ // Push initial items to the RelId cache. In case the document contains no
+ // special streams (headers, footers, etc.) then these items are used
+ // during the full export.
+ PushRelIdCache();
}
DocxAttributeOutput::~DocxAttributeOutput()
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 6d69690777db..18339f453514 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -371,7 +371,8 @@ public:
void WriteBookmarks_Impl( std::vector< OUString >& rStarts, std::vector< OUString >& rEnds );
void WriteAnnotationMarks_Impl( std::vector< OUString >& rStarts, std::vector< OUString >& rEnds );
- void ClearRelIdCache();
+ void PushRelIdCache();
+ void PopRelIdCache();
/// End possibly opened paragraph sdt block.
void EndParaSdtBlock();
@@ -915,9 +916,9 @@ private:
bool m_setFootnote;
/// RelId <-> Graphic* cache, so that in case of alternate content, the same graphic only gets written once.
- std::map<const Graphic*, OString> m_aRelIdCache;
+ std::stack< std::map<const Graphic*, OString> > m_aRelIdCache;
/// RelId <-> BitmapChecksum cache, similar to m_aRelIdCache, but used for non-Writer graphics, handled in oox.
- std::map<BitmapChecksum, OUString> m_aSdrRelIdCache;
+ std::stack< std::map<BitmapChecksum, OUString> > m_aSdrRelIdCache;
/// members to control the existence of grabbagged SDT properties in the paragraph
sal_Int32 m_nParagraphSdtPrToken;
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 05459deb461e..8373fef89194 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -729,15 +729,15 @@ void DocxExport::WriteHeaderFooter( const SwFormat& rFormat, bool bHeader, const
DocxTableExportContext aTableExportContext;
m_pAttrOutput->pushToTableExportContext(aTableExportContext);
+ //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
WriteHeaderFooterText( rFormat, bHeader );
+ m_pAttrOutput->PopRelIdCache();
m_pAttrOutput->popFromTableExportContext(aTableExportContext);
m_pAttrOutput->EndParaSdtBlock();
- //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->ClearRelIdCache();
-
// switch the serializer back
m_pAttrOutput->SetSerializer( m_pDocumentFS );
m_pVMLExport->SetFS( m_pDocumentFS );