diff options
author | Vinaya Mandke <vinaya.mandke@synerzip.com> | 2014-02-25 13:13:11 +0530 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2014-03-05 10:13:40 +0100 |
commit | 6536826f2f4c747582d60ed40b0418c6a67a9829 (patch) | |
tree | 24cd3f23906b7c86dea42f62cf44bbea65113d60 | |
parent | d043c9e3be791993348afaba6effdc3731f7c33d (diff) |
fdo#74792 [DOCX] Grab-bag rels and images for SmartArt
Added support to grab-bag rels and associated Images for
data[i].xml, and drawing[i].xml.
Added UT for the same
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport.cxx
Reviewed on:
https://gerrit.libreoffice.org/8362
Change-Id: I545825f67214f14037ab72b77764a07d575b8b5b
-rw-r--r-- | include/oox/drawingml/shape.hxx | 3 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagram.cxx | 15 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagram.hxx | 4 | ||||
-rw-r--r-- | oox/source/drawingml/shape.cxx | 40 | ||||
-rw-r--r-- | oox/source/shape/ShapeContextHandler.cxx | 11 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/fdo74792.docx | bin | 0 -> 127945 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 24 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxsdrexport.cxx | 101 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxsdrexport.hxx | 5 |
9 files changed, 193 insertions, 10 deletions
diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx index fa3f58c83d9c..7f3ba65c716d 100644 --- a/include/oox/drawingml/shape.hxx +++ b/include/oox/drawingml/shape.hxx @@ -178,7 +178,8 @@ public: const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> & getDiagramDoms() { return maDiagramDoms; } void setDiagramDoms(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& rDiagramDoms) { maDiagramDoms = rDiagramDoms; } - + com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< com::sun::star::uno::Any > >resolveRelationshipsOfType( + core::XmlFilterBase& rFilter, OUString sFragment, OUString sType ); protected: ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index da439ea4f6f5..4672a2818cc3 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -338,6 +338,9 @@ uno::Sequence<beans::PropertyValue> Diagram::getDomsAsPropertyValues() const { sal_Int32 length = maMainDomMap.size(); + if ( 0 < maDataRelsMap.getLength() ) + ++length; + uno::Sequence<beans::PropertyValue> aValue(length); beans::PropertyValue* pValue = aValue.getArray(); for (DiagramDomMap::const_iterator i = maMainDomMap.begin(); @@ -349,6 +352,13 @@ uno::Sequence<beans::PropertyValue> Diagram::getDomsAsPropertyValues() const ++pValue; } + if ( 0 < maDataRelsMap.getLength() ) + { + pValue[0].Name = OUString("OOXDiagramDataRels"); + pValue[0].Value = uno::makeAny ( maDataRelsMap ); + ++pValue; + } + return aValue; } @@ -410,6 +420,11 @@ void loadDiagram( ShapePtr& pShape, "OOXData", pDiagram, xRefDataModel); + + pDiagram->getDataRelsMap() = pShape->resolveRelationshipsOfType( rFilter, xRefDataModel->getFragmentPath(), + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ); + + // Pass the info to pShape for( ::std::vector<OUString>::const_iterator aIt = pData->getExtDrawings().begin(), aEnd = pData->getExtDrawings().end(); aIt != aEnd; ++aIt ) diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index 031c66b1cbf6..ae611c9d81f9 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -157,6 +157,7 @@ typedef boost::shared_ptr< LayoutNode > LayoutNodePtr; typedef std::map< OUString, uno::Reference<xml::dom::XDocument> > DiagramDomMap; +typedef uno::Sequence< uno::Sequence< uno::Any > > DiagramRelsMap; @@ -296,7 +297,7 @@ public: DiagramColorMap& getColors() { return maColors; } const DiagramColorMap& getColors() const { return maColors; } DiagramDomMap & getDomMap() { return maMainDomMap; } - + DiagramRelsMap & getDataRelsMap() { return maDataRelsMap; } void addTo( const ShapePtr & pShape ); uno::Sequence<beans::PropertyValue> getDomsAsPropertyValues() const; @@ -308,6 +309,7 @@ private: DiagramColorMap maColors; std::map< OUString, ShapePtr > maShapeMap; DiagramDomMap maMainDomMap; + DiagramRelsMap maDataRelsMap; }; diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index ce1d3b6596fd..3a2ebae8ddb1 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -1200,6 +1200,46 @@ void Shape::putPropertiesToGrabBag( const Sequence< PropertyValue >& aProperties } } +uno::Sequence< uno::Sequence< uno::Any > > Shape::resolveRelationshipsOfType(core::XmlFilterBase& rFilter, OUString sFragment, OUString sType ) +{ + uno::Sequence< uno::Sequence< uno::Any > > xRelListTemp; + sal_Int32 counter = 0; + + core::RelationsRef xRels = rFilter.importRelations( sFragment ); + if ( xRels ) + { + core::RelationsRef xImageRels = xRels->getRelationsFromType( sType ); + if ( xImageRels ) + { + xRelListTemp.realloc( xImageRels->size() ); + for( ::std::map< OUString, core::Relation >::const_iterator aIt = xImageRels->begin(), aEnd = xImageRels->end(); aIt != aEnd; ++aIt ) + { + uno::Sequence< uno::Any > diagramRelTuple (3); + // [0] => RID, [1] => InputStream [2] => extension + OUString sRelId = aIt->second.maId; + + diagramRelTuple[0] = uno::makeAny ( sRelId ); + OUString sTarget = xImageRels->getFragmentPathFromRelId( sRelId ); + + uno::Reference< io::XInputStream > xImageInputStrm( rFilter.openInputStream( sTarget ), uno::UNO_SET_THROW ); + StreamDataSequence dataSeq; + if ( rFilter.importBinaryData( dataSeq, sTarget ) ) + { + diagramRelTuple[1] = uno::makeAny( dataSeq ); + } + + diagramRelTuple[2] = uno::makeAny( sTarget.copy( sTarget.lastIndexOf(".") ) ); + + xRelListTemp[counter] = diagramRelTuple; + ++counter; + } + xRelListTemp.realloc(counter); + + } + } + return xRelListTemp; +} + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/ShapeContextHandler.cxx b/oox/source/shape/ShapeContextHandler.cxx index d97069b839ad..dc20747b0fd6 100644 --- a/oox/source/shape/ShapeContextHandler.cxx +++ b/oox/source/shape/ShapeContextHandler.cxx @@ -426,11 +426,20 @@ ShapeContextHandler::getShape() throw (uno::RuntimeException, std::exception) mxFilterBase->importFragment(new ShapeDrawingFragmentHandler(*mxFilterBase, aFragmentPath, pShapePtr)); uno::Sequence<beans::PropertyValue> aValue(mpShape->getDiagramDoms()); + uno::Sequence < uno::Any > diagramDrawing(2); + // drawingValue[0] => dom, drawingValue[1] => Sequence of associated relationships + sal_Int32 length = aValue.getLength(); aValue.realloc(length+1); + + diagramDrawing[0] = uno::makeAny( mxFilterBase->importFragment( aFragmentPath ) ); + diagramDrawing[1] = uno::makeAny( pShapePtr->resolveRelationshipsOfType( *mxFilterBase, aFragmentPath, + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ) ); + beans::PropertyValue* pValue = aValue.getArray(); pValue[length].Name = "OOXDrawing"; - pValue[length].Value = uno::makeAny( mxFilterBase->importFragment( aFragmentPath ) ); + pValue[length].Value = uno::makeAny( diagramDrawing ); + pShapePtr->setDiagramDoms( aValue ); pShapePtr->addShape( *mxFilterBase, mpThemePtr.get(), xShapes, aMatrix, pShapePtr->getFillProperties() ); diff --git a/sw/qa/extras/ooxmlexport/data/fdo74792.docx b/sw/qa/extras/ooxmlexport/data/fdo74792.docx Binary files differnew file mode 100644 index 000000000000..3d00009a03f3 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/fdo74792.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index f88543882ebf..094519cf6c12 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -1443,8 +1443,10 @@ DECLARE_OOXMLEXPORT_TEST(testSmartart, "smartart.docx") else if (aGrabBag[i].Name == "OOXDrawing") { bDrawing = sal_True; + uno::Sequence< uno::Any > diagramDrawing; uno::Reference<xml::dom::XDocument> aDrawingDom; - CPPUNIT_ASSERT(aGrabBag[i].Value >>= aDrawingDom); // PropertyValue of proper type + CPPUNIT_ASSERT(aGrabBag[i].Value >>= diagramDrawing); + CPPUNIT_ASSERT(diagramDrawing[0] >>= aDrawingDom); // PropertyValue of proper type CPPUNIT_ASSERT(aDrawingDom.get()); // Reference not empty } } @@ -2940,6 +2942,26 @@ DECLARE_OOXMLEXPORT_TEST(testCompatSettingsForW14, "TextEffects_StylisticSets_Cn assertXPath(pXmlDoc, "/w:settings/w:compat/w:compatSetting[5]", "val", "1"); } +DECLARE_OOXMLEXPORT_TEST(testFdo74792, "fdo74792.docx") +{ + /* + * fdo#74792 : The images associated with smart-art data[i].xml + * were not preserved on exporting to DOCX format + * Added support to grabbag the rels, with associated images. + */ + xmlDocPtr pXmlDoc = parseExport("word/diagrams/_rels/data1.xml.rels"); + if(!pXmlDoc) + return; + assertXPath(pXmlDoc,"/rels:Relationships/rels:Relationship", 4); + uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL( + comphelper::getComponentContext(m_xSFactory), m_aTempFile.GetURL()); + + //check that images are also saved + OUString sImageFile( "word/media/OOXDiagramDataRels0.jpeg" ); + uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName( sImageFile ), uno::UNO_QUERY); + CPPUNIT_ASSERT( xInputStream.is() ); +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx index d8480db3c9e4..d07e477b06e8 100644 --- a/sw/source/filter/ww8/docxsdrexport.cxx +++ b/sw/source/filter/ww8/docxsdrexport.cxx @@ -25,6 +25,7 @@ #include <oox/drawingml/drawingmltypes.hxx> #include <oox/export/utils.hxx> #include <oox/export/vmlexport.hxx> +#include <oox/token/properties.hxx> #include <frmatr.hxx> #include <frmfmt.hxx> @@ -41,6 +42,7 @@ #include <docxexport.hxx> #include <docxexportfilter.hxx> #include <writerhelper.hxx> +#include <comphelper/seqstream.hxx> using namespace com::sun::star; using namespace oox; @@ -683,6 +685,78 @@ void DocxSdrExport::writeDMLEffectLst(const SwFrmFmt& rFrmFmt) } +void DocxSdrExport::writeDiagramRels(uno::Reference<xml::dom::XDocument> xDom, + uno::Sequence< uno::Sequence< uno::Any > > xRelSeq, + uno::Reference< io::XOutputStream > xOutStream, OUString sGrabBagProperyName) +{ + // add image relationships of OOXData, OOXDiagram + OUString sType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"); + uno::Reference< xml::sax::XSAXSerializable > xSerializer(xDom, uno::UNO_QUERY); + uno::Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(comphelper::getProcessComponentContext()); + xWriter->setOutputStream(xOutStream); + + // retrieve the relationships from Sequence + for (sal_Int32 j = 0; j < xRelSeq.getLength(); j++) + { + // diagramDataRelTuple[0] => RID, + // diagramDataRelTuple[1] => xInputStream + // diagramDataRelTuple[2] => extension + uno::Sequence< uno::Any > diagramDataRelTuple = xRelSeq[j]; + + OUString sRelId, sExtension; + diagramDataRelTuple[0] >>= sRelId; + diagramDataRelTuple[2] >>= sExtension; + OUString sContentType; + if (sExtension == ".jpeg") + sContentType = "image/jpeg"; + else if (sExtension == ".WMF") + sContentType = "image/x-wmf"; + sRelId = sRelId.copy(3); + + StreamDataSequence dataSeq; + diagramDataRelTuple[1] >>= dataSeq; + uno::Reference<io::XInputStream> dataImagebin(new ::comphelper::SequenceInputStream(dataSeq)); + + OUString sFragment("../media/"); + sFragment += sGrabBagProperyName + OUString::number(j) + sExtension; + + PropertySet aProps(xOutStream); + aProps.setAnyProperty(PROP_RelId, uno::makeAny(sal_Int32(sRelId.toInt32()))); + + m_pImpl->m_rExport.GetFilter().addRelation(xOutStream, sType, sFragment); + + sFragment = sFragment.replaceFirst("..","word"); + uno::Reference< io::XOutputStream > xBinOutStream = m_pImpl->m_rExport.GetFilter().openFragmentStream(sFragment, sContentType); + + try + { + sal_Int32 nBufferSize = 512; + uno::Sequence< sal_Int8 > aDataBuffer(nBufferSize); + sal_Int32 nRead; + do + { + nRead = dataImagebin->readBytes(aDataBuffer, nBufferSize); + if (nRead) + { + if (nRead < nBufferSize) + { + nBufferSize = nRead; + aDataBuffer.realloc(nRead); + } + xBinOutStream->writeBytes(aDataBuffer); + } + } + while (nRead); + xBinOutStream->flush(); + } + catch (const uno::Exception& rException) + { + SAL_WARN("sw.ww8", "DocxSdrExport::writeDiagramRels Failed to copy grabbaged Image: " << rException.Message); + } + dataImagebin->closeInput(); + } +} + void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFrmFmt, int nAnchorId) { sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer; @@ -694,6 +768,8 @@ void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFr uno::Reference<xml::dom::XDocument> styleDom; uno::Reference<xml::dom::XDocument> colorDom; uno::Reference<xml::dom::XDocument> drawingDom; + uno::Sequence< uno::Sequence< uno::Any > > xDataRelSeq; + uno::Sequence< uno::Any > diagramDrawing; // retrieve the doms from the GrabBag OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; @@ -711,9 +787,12 @@ void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFr else if (propName == "OOXColor") propList[nProp].Value >>= colorDom; else if (propName == "OOXDrawing") - propList[nProp].Value >>= drawingDom; + propList[nProp].Value >>= diagramDrawing; + else if (propName == "OOXDiagramDataRels") + propList[nProp].Value >>= xDataRelSeq; } + diagramDrawing[0] >>= drawingDom; // check that we have the 4 mandatory XDocuments // if not, there was an error importing and we won't output anything if (!dataDom.is() || !layoutDom.is() || !styleDom.is() || !colorDom.is()) @@ -751,6 +830,7 @@ void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFr "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData", dataFileName, false), RTL_TEXTENCODING_UTF8); + // add layout relation OUString layoutFileName = "diagrams/layout" + OUString::number(diagramCount) + ".xml"; OString layoutRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(), @@ -814,11 +894,15 @@ void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFr // write data file serializer.set(dataDom, uno::UNO_QUERY); - writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + dataFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml")); + uno::Reference< io::XOutputStream > xDataOutputStream = m_pImpl->m_rExport.GetFilter().openFragmentStream( + "word/" + dataFileName, "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml"); + writer->setOutputStream(xDataOutputStream); serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), uno::Sequence< beans::StringPair >()); + // write the associated Images and rels for data file + writeDiagramRels(dataDom, xDataRelSeq, xDataOutputStream, OUString("OOXDiagramDataRels")); + // write layout file serializer.set(layoutDom, uno::UNO_QUERY); writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + layoutFileName, @@ -841,13 +925,20 @@ void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFr uno::Sequence< beans::StringPair >()); // write drawing file + if (drawingDom.is()) { serializer.set(drawingDom, uno::UNO_QUERY); - writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + drawingFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramDrawing+xml")); + uno::Reference< io::XOutputStream > xDrawingOutputStream = m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + drawingFileName, + "application/vnd.openxmlformats-officedocument.drawingml.diagramDrawing+xml"); + writer->setOutputStream(xDrawingOutputStream); serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), uno::Sequence< beans::StringPair >()); + + // write the associated Images and rels for drawing file + uno::Sequence< uno::Sequence< uno::Any > > xDrawingRelSeq; + diagramDrawing[1] >>= xDrawingRelSeq; + writeDiagramRels(drawingDom, xDrawingRelSeq, xDrawingOutputStream, OUString("OOXDiagramDrawingRels")); } } diff --git a/sw/source/filter/ww8/docxsdrexport.hxx b/sw/source/filter/ww8/docxsdrexport.hxx index 25c0ea126cbc..675d756a8a6e 100644 --- a/sw/source/filter/ww8/docxsdrexport.hxx +++ b/sw/source/filter/ww8/docxsdrexport.hxx @@ -11,7 +11,7 @@ #define INCLUDED_SW_SOURCE_FILTER_WW8_DOCXSDREXPORT_HXX #include <boost/shared_ptr.hpp> - +#include <com/sun/star/xml/dom/XDocument.hpp> namespace oox { namespace drawingml @@ -83,6 +83,9 @@ public: void writeDMLEffectLst(const SwFrmFmt& rFrmFmt); /// Writes a diagram (smartart). void writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFrmFmt, int nAnchorId); + void writeDiagramRels( com::sun::star::uno::Reference< com::sun::star::xml::dom::XDocument> xDom, + com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< com::sun::star::uno::Any > > xRelSeq, + com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > xOutStream, OUString sGrabBagProperyName); /// Writes text frame in DML format. void writeDMLTextFrame(sw::Frame* pParentFrame, int nAnchorId); /// Writes text frame in VML format. |