diff options
-rw-r--r-- | include/oox/export/drawingml.hxx | 8 | ||||
-rw-r--r-- | include/oox/export/vmlexport.hxx | 6 | ||||
-rw-r--r-- | oox/source/export/drawingml.cxx | 31 | ||||
-rw-r--r-- | oox/source/export/vmlexport.cxx | 10 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf118535.odt | bin | 0 -> 12032 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport16.cxx | 13 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 42 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 11 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.cxx | 4 |
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 Binary files differnew file mode 100644 index 000000000000..146c6f471a18 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf118535.odt 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(); } |