From aafaf1f55fa413ad49d4556cf7c0a713dd206ae4 Mon Sep 17 00:00:00 2001 From: Grzegorz Araminowicz Date: Wed, 13 Mar 2019 10:49:30 +0100 Subject: PPTX export: save SmartArt as diagram instead of group of shapes preserving SmartArt allows editing it in PowerPoint after saving as pptx file * moved common parts for docx and pptx export to oox/drawingml * fixed export tests that expected shapes on output Change-Id: I3e70a9f4177bebf5e1671232f4cd0ef0e7212626 Reviewed-on: https://gerrit.libreoffice.org/69598 Tested-by: Jenkins Reviewed-by: Miklos Vajna --- sw/source/filter/ww8/docxattributeoutput.cxx | 34 +--- sw/source/filter/ww8/docxattributeoutput.hxx | 3 - sw/source/filter/ww8/docxsdrexport.cxx | 275 +-------------------------- sw/source/filter/ww8/docxsdrexport.hxx | 5 +- 4 files changed, 7 insertions(+), 310 deletions(-) (limited to 'sw/source') diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index f1c56fa5b686..7e621fa52948 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -5677,7 +5677,10 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const ww8::Frame &rFrame, const P const SdrObject* pSdrObj = rFrame.GetFrameFormat().FindRealSdrObject(); if ( pSdrObj ) { - if ( IsDiagram( pSdrObj ) ) + uno::Reference xShape( + const_cast(pSdrObj)->getUnoShape(), uno::UNO_QUERY); + + if (xShape.is() && oox::drawingml::DrawingML::IsDiagram(xShape)) { if ( !m_pPostponedDiagrams ) { @@ -5786,35 +5789,6 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const ww8::Frame &rFrame, const P m_pSerializer->mergeTopMarks(Tag_OutputFlyFrame, sax_fastparser::MergeMarks::POSTPONE); } -bool DocxAttributeOutput::IsDiagram( const SdrObject* sdrObject ) -{ - uno::Reference< drawing::XShape > xShape( const_cast(sdrObject)->getUnoShape(), uno::UNO_QUERY ); - if ( !xShape.is() ) - return false; - - uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); - if ( !xPropSet.is() ) - return false; - - // if the shape doesn't have the InteropGrabBag property, it's not a diagram - uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); - OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; - if ( !xPropSetInfo->hasPropertyByName( aName ) ) - return false; - - uno::Sequence< beans::PropertyValue > propList; - xPropSet->getPropertyValue( aName ) >>= propList; - for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp ) - { - // if we find any of the diagram components, it's a diagram - OUString propName = propList[nProp].Name; - if ( propName == "OOXData" || propName == "OOXLayout" || propName == "OOXStyle" || - propName == "OOXColor" || propName == "OOXDrawing") - return true; - } - return false; -} - void DocxAttributeOutput::WriteOutliner(const OutlinerParaObject& rParaObj) { const EditTextObject& rEditObj = rParaObj.GetTextObject(); diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 4ed30cccf7cf..2ea64b8f207b 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -400,9 +400,6 @@ private: void WriteActiveXControl(const SdrObject* pObject, const SwFrameFormat& rFrameFormat, bool bInsideRun); bool ExportAsActiveXControl(const SdrObject* pObject) const; - /// checks whether the current component is a diagram - static bool IsDiagram (const SdrObject* sdrObject); - void InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner ); void StartTable( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner ); void StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner ); diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx index 5f5cfe9ceb39..d28c3c9b21a6 100644 --- a/sw/source/filter/ww8/docxsdrexport.cxx +++ b/sw/source/filter/ww8/docxsdrexport.cxx @@ -1125,290 +1125,19 @@ void DocxSdrExport::writeDMLEffectLst(const SwFrameFormat& rFrameFormat) m_pImpl->getSerializer()->endElementNS(XML_a, XML_effectLst); } -void DocxSdrExport::writeDiagramRels(const uno::Sequence>& xRelSeq, - const uno::Reference& xOutStream, - const OUString& sGrabBagProperyName, int nAnchorId) -{ - // add image relationships of OOXData, OOXDiagram - OUString sType(oox::getRelationship(Relationship::IMAGE)); - uno::Reference 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 diagramDataRelTuple = xRelSeq[j]; - - OUString sRelId; - OUString sExtension; - diagramDataRelTuple[0] >>= sRelId; - diagramDataRelTuple[2] >>= sExtension; - OUString sContentType; - if (sExtension.equalsIgnoreAsciiCase(".WMF")) - sContentType = "image/x-wmf"; - else - sContentType = "image/" + sExtension.copy(1); - sRelId = sRelId.copy(3); - - StreamDataSequence dataSeq; - diagramDataRelTuple[1] >>= dataSeq; - uno::Reference dataImagebin( - new ::comphelper::SequenceInputStream(dataSeq)); - - OUString sFragment("../media/"); - //nAnchorId is used to make the name unique irrespective of the number of smart arts. - sFragment += sGrabBagProperyName + OUString::number(nAnchorId) + "_" + OUString::number(j) - + sExtension; - - PropertySet aProps(xOutStream); - aProps.setAnyProperty(PROP_RelId, uno::makeAny(sRelId.toInt32())); - - m_pImpl->getExport().GetFilter().addRelation(xOutStream, sType, sFragment); - - sFragment = sFragment.replaceFirst("..", "word"); - uno::Reference xBinOutStream - = m_pImpl->getExport().GetFilter().openFragmentStream(sFragment, sContentType); - - try - { - sal_Int32 nBufferSize = 512; - uno::Sequence 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); - } - dataImagebin->closeInput(); - } -} - void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat, - int nAnchorId) + int nDiagramId) { - sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer(); uno::Reference xShape(const_cast(sdrObject)->getUnoShape(), uno::UNO_QUERY); - uno::Reference xPropSet(xShape, uno::UNO_QUERY); - - uno::Reference dataDom; - uno::Reference layoutDom; - uno::Reference styleDom; - uno::Reference colorDom; - uno::Reference drawingDom; - uno::Sequence> xDataRelSeq; - uno::Sequence diagramDrawing; - - // retrieve the doms from the GrabBag - uno::Sequence propList; - xPropSet->getPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG) >>= propList; - for (sal_Int32 nProp = 0; nProp < propList.getLength(); ++nProp) - { - OUString propName = propList[nProp].Name; - if (propName == "OOXData") - propList[nProp].Value >>= dataDom; - else if (propName == "OOXLayout") - propList[nProp].Value >>= layoutDom; - else if (propName == "OOXStyle") - propList[nProp].Value >>= styleDom; - else if (propName == "OOXColor") - propList[nProp].Value >>= colorDom; - else if (propName == "OOXDrawing") - { - propList[nProp].Value >>= diagramDrawing; - diagramDrawing[0] - >>= drawingDom; // if there is OOXDrawing property then set drawingDom here only. - } - else if (propName == "OOXDiagramDataRels") - propList[nProp].Value >>= xDataRelSeq; - } - - // 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()) - return; // write necessary tags to document.xml Size aSize(sdrObject->GetSnapRect().GetWidth(), sdrObject->GetSnapRect().GetHeight()); startDMLAnchorInline(&rFrameFormat, aSize); - // generate a unique id - sax_fastparser::FastAttributeList* pDocPrAttrList - = sax_fastparser::FastSerializerHelper::createAttrList(); - pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr()); - OUString sName = "Diagram" + OUString::number(nAnchorId); - pDocPrAttrList->add(XML_name, OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr()); - sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList); - pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef); - - sal_Int32 diagramCount; - diagramCount = nAnchorId; - - pFS->singleElementNS(XML_wp, XML_cNvGraphicFramePr, FSEND); - - pFS->startElementNS( - XML_a, XML_graphic, FSNS(XML_xmlns, XML_a), - OUStringToOString(m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dml)), - RTL_TEXTENCODING_UTF8) - .getStr(), - FSEND); - - pFS->startElementNS(XML_a, XML_graphicData, XML_uri, - "http://schemas.openxmlformats.org/drawingml/2006/diagram", FSEND); - - // add data relation - OUString dataFileName = "diagrams/data" + OUString::number(diagramCount) + ".xml"; - OString dataRelId = OUStringToOString( - m_pImpl->getExport().GetFilter().addRelation( - pFS->getOutputStream(), oox::getRelationship(Relationship::DIAGRAMDATA), dataFileName), - RTL_TEXTENCODING_UTF8); - - // add layout relation - OUString layoutFileName = "diagrams/layout" + OUString::number(diagramCount) + ".xml"; - OString layoutRelId - = OUStringToOString(m_pImpl->getExport().GetFilter().addRelation( - pFS->getOutputStream(), - oox::getRelationship(Relationship::DIAGRAMLAYOUT), layoutFileName), - RTL_TEXTENCODING_UTF8); - - // add style relation - OUString styleFileName = "diagrams/quickStyle" + OUString::number(diagramCount) + ".xml"; - OString styleRelId = OUStringToOString( - m_pImpl->getExport().GetFilter().addRelation( - pFS->getOutputStream(), oox::getRelationship(Relationship::DIAGRAMQUICKSTYLE), - styleFileName), - RTL_TEXTENCODING_UTF8); - - // add color relation - OUString colorFileName = "diagrams/colors" + OUString::number(diagramCount) + ".xml"; - OString colorRelId - = OUStringToOString(m_pImpl->getExport().GetFilter().addRelation( - pFS->getOutputStream(), - oox::getRelationship(Relationship::DIAGRAMCOLORS), colorFileName), - RTL_TEXTENCODING_UTF8); - - OUString drawingFileName; - if (drawingDom.is()) - { - // add drawing relation - drawingFileName = "diagrams/drawing" + OUString::number(diagramCount) + ".xml"; - OUString drawingRelId = m_pImpl->getExport().GetFilter().addRelation( - pFS->getOutputStream(), oox::getRelationship(Relationship::DIAGRAMDRAWING), - drawingFileName); - - // the data dom contains a reference to the drawing relation. We need to update it with the new generated - // relation value before writing the dom to a file + m_pImpl->getDrawingML()->WriteDiagram(xShape, nDiagramId); - // Get the dsp:damaModelExt node from the dom - uno::Reference nodeList = dataDom->getElementsByTagNameNS( - "http://schemas.microsoft.com/office/drawing/2008/diagram", "dataModelExt"); - - // There must be one element only so get it - uno::Reference node = nodeList->item(0); - - // Get the list of attributes of the node - uno::Reference nodeMap = node->getAttributes(); - - // Get the node with the relId attribute and set its new value - uno::Reference relIdNode = nodeMap->getNamedItem("relId"); - relIdNode->setNodeValue(drawingRelId); - } - - pFS->singleElementNS( - XML_dgm, XML_relIds, FSNS(XML_xmlns, XML_dgm), - OUStringToOString(m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dmlDiagram)), - RTL_TEXTENCODING_UTF8) - .getStr(), - FSNS(XML_xmlns, XML_r), - OUStringToOString(m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(officeRel)), - RTL_TEXTENCODING_UTF8) - .getStr(), - FSNS(XML_r, XML_dm), dataRelId.getStr(), FSNS(XML_r, XML_lo), layoutRelId.getStr(), - FSNS(XML_r, XML_qs), styleRelId.getStr(), FSNS(XML_r, XML_cs), colorRelId.getStr(), FSEND); - - pFS->endElementNS(XML_a, XML_graphicData); - pFS->endElementNS(XML_a, XML_graphic); endDMLAnchorInline(&rFrameFormat); - - uno::Reference serializer; - uno::Reference writer - = xml::sax::Writer::create(comphelper::getProcessComponentContext()); - - // write data file - serializer.set(dataDom, uno::UNO_QUERY); - uno::Reference xDataOutputStream - = m_pImpl->getExport().GetFilter().openFragmentStream( - "word/" + dataFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml"); - writer->setOutputStream(xDataOutputStream); - serializer->serialize(uno::Reference(writer, uno::UNO_QUERY_THROW), - uno::Sequence()); - - // write the associated Images and rels for data file - writeDiagramRels(xDataRelSeq, xDataOutputStream, "OOXDiagramDataRels", nAnchorId); - - // write layout file - serializer.set(layoutDom, uno::UNO_QUERY); - writer->setOutputStream(m_pImpl->getExport().GetFilter().openFragmentStream( - "word/" + layoutFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml")); - serializer->serialize(uno::Reference(writer, uno::UNO_QUERY_THROW), - uno::Sequence()); - - // write style file - serializer.set(styleDom, uno::UNO_QUERY); - writer->setOutputStream(m_pImpl->getExport().GetFilter().openFragmentStream( - "word/" + styleFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml")); - serializer->serialize(uno::Reference(writer, uno::UNO_QUERY_THROW), - uno::Sequence()); - - // write color file - serializer.set(colorDom, uno::UNO_QUERY); - writer->setOutputStream(m_pImpl->getExport().GetFilter().openFragmentStream( - "word/" + colorFileName, - "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml")); - serializer->serialize(uno::Reference(writer, uno::UNO_QUERY_THROW), - uno::Sequence()); - - // write drawing file - - if (drawingDom.is()) - { - serializer.set(drawingDom, uno::UNO_QUERY); - uno::Reference xDrawingOutputStream - = m_pImpl->getExport().GetFilter().openFragmentStream( - "word/" + drawingFileName, - "application/vnd.ms-office.drawingml.diagramDrawing+xml"); - writer->setOutputStream(xDrawingOutputStream); - serializer->serialize( - uno::Reference(writer, uno::UNO_QUERY_THROW), - uno::Sequence()); - - // write the associated Images and rels for drawing file - uno::Sequence> xDrawingRelSeq; - diagramDrawing[1] >>= xDrawingRelSeq; - writeDiagramRels(xDrawingRelSeq, xDrawingOutputStream, "OOXDiagramDrawingRels", nAnchorId); - } } void DocxSdrExport::writeOnlyTextOfFrame(ww8::Frame const* pParentFrame) diff --git a/sw/source/filter/ww8/docxsdrexport.hxx b/sw/source/filter/ww8/docxsdrexport.hxx index 81a8da881381..613978761706 100644 --- a/sw/source/filter/ww8/docxsdrexport.hxx +++ b/sw/source/filter/ww8/docxsdrexport.hxx @@ -95,10 +95,7 @@ public: /// Write , the effect list. void writeDMLEffectLst(const SwFrameFormat& rFrameFormat); /// Writes a diagram (smartart). - void writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat, int nAnchorId); - void writeDiagramRels(const css::uno::Sequence< css::uno::Sequence >& xRelSeq, - const css::uno::Reference& xOutStream, const OUString& sGrabBagProperyName, - int nAnchorId); + void writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat, int nDiagramId); /// Writes text frame in DML format. void writeDMLTextFrame(ww8::Frame const* pParentFrame, int nAnchorId, bool bTextBoxOnly = false); /// Writes text frame in VML format. -- cgit