SmartArt: Added export of OOXDiagram
This change adds writing the OOXDiagram SmartArt replacement graphic. This makes stuff working better, but still stuff missing. With this we have now two of the 4-7 (optional) DomTrees used for the Diagram data representation. Still deactivated, to use for experiments you will need to set ACTIVATE_RECREATE_DIAGRAM_DATADOMS. Change-Id: Ic6c1108d6cf0037302085b6f22433b199d40ee53 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198435 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
This commit is contained in:
committed by
Armin Le Grand
parent
d7c2f3dfe7
commit
f2d455d03f
@@ -28,6 +28,7 @@
|
||||
namespace oox::drawingml {
|
||||
|
||||
class Diagram;
|
||||
class DrawingML;
|
||||
|
||||
// Advanced DiagramHelper
|
||||
//
|
||||
@@ -101,7 +102,7 @@ public:
|
||||
|
||||
// check if mandatory DiagramDomS exist (or can be created)
|
||||
bool checkMinimalDataDoms() const;
|
||||
void tryToCreateMissingDataDoms(oox::core::XmlFilterBase& rFB);
|
||||
void tryToCreateMissingDataDoms(DrawingML& rOriginalDrawingML);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -316,6 +316,9 @@ protected:
|
||||
/// True when exporting presentation placeholder shape.
|
||||
bool mbPlaceholder;
|
||||
|
||||
/// True when DiagramReplacementVisualization is exported
|
||||
bool mbDiagaramExport;
|
||||
|
||||
bool mbEmbedFonts = false;
|
||||
|
||||
bool GetProperty( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet, const OUString& aName );
|
||||
@@ -376,6 +379,10 @@ public:
|
||||
/// The application-specific text exporter callback, if there is one.
|
||||
DMLTextExport* GetTextExport() { return mpTextExport; }
|
||||
|
||||
/// get/set mbDiagaramExport
|
||||
void setDiagaramExport(bool bNew) { mbDiagaramExport = bNew; }
|
||||
bool isDiagaramExport() const { return mbDiagaramExport;}
|
||||
|
||||
void SetBackgroundDark(bool bIsDark) { mbIsBackgroundDark = bIsDark; }
|
||||
/// If bRelPathToMedia is true add "../" to image folder path while adding the image relationship
|
||||
OOX_DLLPUBLIC OUString writeGraphicToStorage(const Graphic &rGraphic , bool bRelPathToMedia = false, GraphicExport::TypeHint eHint = GraphicExport::TypeHint::Detect);
|
||||
|
||||
@@ -121,6 +121,9 @@ public:
|
||||
|
||||
// access to PropertyValues
|
||||
virtual css::uno::Any getOOXDomValue(svx::diagram::DomMapFlag aDomMapFlag) const = 0;
|
||||
|
||||
// access to RootShape - the GroupObject used to host this Diagram
|
||||
css::uno::Reference< css::drawing::XShape >& getRootShape() { return accessRootShape(); }
|
||||
};
|
||||
|
||||
}} // end of namespace
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <oox/token/namespaces.hxx>
|
||||
#include <oox/export/drawingml.hxx>
|
||||
#include <sax/fastattribs.hxx>
|
||||
#include <oox/export/shapes.hxx>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
@@ -59,14 +60,63 @@ Shape* DiagramData_oox::getOrCreateAssociatedShape(const svx::diagram::Point& rP
|
||||
return rShapePtr.get();
|
||||
}
|
||||
|
||||
void DiagramData_oox::writeDiagramData(oox::core::XmlFilterBase& rFB, sax_fastparser::FSHelperPtr& rTarget)
|
||||
void DiagramData_oox::writeDiagramReplacement(DrawingML& rOriginalDrawingML, sax_fastparser::FSHelperPtr& rTarget)
|
||||
{
|
||||
if (!rTarget)
|
||||
return;
|
||||
|
||||
uno::Reference<drawing::XShapes> xShapes(accessRootShape(), uno::UNO_QUERY);
|
||||
if (!xShapes.is())
|
||||
return;
|
||||
|
||||
// create an own ShapeExport with the needed target and namespace, mark as DiagramExport
|
||||
::oox::core::XmlFilterBase* pOriginalFB(rOriginalDrawingML.GetFB());
|
||||
ShapeExport aShapeExport(XML_dsp, rTarget, nullptr, pOriginalFB, rOriginalDrawingML.GetDocumentType(), rOriginalDrawingML.GetTextExport(), true);
|
||||
aShapeExport.setDiagaramExport(true);
|
||||
const sal_Int32 nCount(xShapes->getCount());
|
||||
|
||||
// write header infos
|
||||
const OUString aNsDmlDiagram(pOriginalFB->getNamespaceURL(OOX_NS(dmlDiagram)));
|
||||
const OUString aNsDsp(pOriginalFB->getNamespaceURL(OOX_NS(dsp)));
|
||||
const OUString aNsDml(pOriginalFB->getNamespaceURL(OOX_NS(dml)));
|
||||
rTarget->startElementNS(XML_dsp, XML_drawing,
|
||||
FSNS(XML_xmlns, XML_dgm), aNsDmlDiagram,
|
||||
FSNS(XML_xmlns, XML_dsp), aNsDsp,
|
||||
FSNS(XML_xmlns, XML_a), aNsDml);
|
||||
rTarget->startElementNS(XML_dsp, XML_spTree);
|
||||
|
||||
for ( sal_Int32 i = 0; i < nCount; ++i )
|
||||
{
|
||||
uno::Reference< drawing::XShape > xShape;
|
||||
if ( xShapes->getByIndex( i ) >>= xShape )
|
||||
{
|
||||
if (xShape)
|
||||
{
|
||||
// do *not* write BackgroundShape. MSO has BG infos just as fill properties
|
||||
// as part of the OOXData DomTree
|
||||
SdrObject* pTarget(SdrObject::getSdrObjectFromXShape(xShape));
|
||||
if (nullptr == pTarget || getBackgroundShapeModelID() == pTarget->getDiagramDataModelID())
|
||||
continue;
|
||||
|
||||
// write Shape & sub-shapes
|
||||
aShapeExport.WriteShape(xShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rTarget->endElementNS(XML_dsp, XML_spTree);
|
||||
rTarget->endElementNS(XML_dsp, XML_drawing);
|
||||
rTarget->endDocument();
|
||||
}
|
||||
|
||||
void DiagramData_oox::writeDiagramData(oox::core::XmlFilterBase& rOriginalFB, sax_fastparser::FSHelperPtr& rTarget)
|
||||
{
|
||||
if (!rTarget)
|
||||
return;
|
||||
|
||||
// write header infos
|
||||
const OUString aNsDmlDiagram(rFB.getNamespaceURL(OOX_NS(dmlDiagram)));
|
||||
const OUString aNsDml(rFB.getNamespaceURL(OOX_NS(dml)));
|
||||
const OUString aNsDmlDiagram(rOriginalFB.getNamespaceURL(OOX_NS(dmlDiagram)));
|
||||
const OUString aNsDml(rOriginalFB.getNamespaceURL(OOX_NS(dml)));
|
||||
rTarget->startElementNS(XML_dgm, XML_dataModel,
|
||||
FSNS(XML_xmlns, XML_dgm), aNsDmlDiagram,
|
||||
FSNS(XML_xmlns, XML_a), aNsDml);
|
||||
@@ -90,7 +140,7 @@ void DiagramData_oox::writeDiagramData(oox::core::XmlFilterBase& rFB, sax_fastpa
|
||||
if (xMasterText)
|
||||
{
|
||||
rTarget->startElementNS(XML_dgm, XML_t);
|
||||
DrawingML aTempML(rTarget, &rFB);
|
||||
DrawingML aTempML(rTarget, &rOriginalFB);
|
||||
aTempML.WriteText(xMasterText, false, true, XML_a);
|
||||
rTarget->endElementNS(XML_dgm, XML_t);
|
||||
|
||||
@@ -145,7 +195,7 @@ void DiagramData_oox::writeDiagramData(oox::core::XmlFilterBase& rFB, sax_fastpa
|
||||
{
|
||||
// if we have the BGShape as XShape, export using a temp DrawingML which uses
|
||||
// the target file combined with the XmlFilterBase representing the ongoing Diagram export
|
||||
DrawingML aTempML(rTarget, &rFB);
|
||||
DrawingML aTempML(rTarget, &rOriginalFB);
|
||||
uno::Reference<beans::XPropertySet> xProps(xBgShape, uno::UNO_QUERY);
|
||||
aTempML.WriteFill( xProps, xBgShape->getSize());
|
||||
}
|
||||
@@ -159,7 +209,7 @@ void DiagramData_oox::writeDiagramData(oox::core::XmlFilterBase& rFB, sax_fastpa
|
||||
// for this case where the only relevant data is the 'relId' entry I will allow
|
||||
// to construct the XML statement by own string concatenation
|
||||
rTarget->startElementNS(XML_dgm, XML_extLst);
|
||||
const OUString rNsDsp(rFB.getNamespaceURL(OOX_NS(dsp)));
|
||||
const OUString rNsDsp(rOriginalFB.getNamespaceURL(OOX_NS(dsp)));
|
||||
rTarget->startElementNS(XML_a, XML_ext, XML_uri, rNsDsp);
|
||||
OUString aDspLine("<dsp:dataModelExt xmlns:dsp=\"" + rNsDsp + "\" ");
|
||||
if (!getExtDrawings().empty())
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
namespace oox::drawingml {
|
||||
|
||||
class DrawingML;
|
||||
|
||||
class DiagramData_oox : public svx::diagram::DiagramData_svx
|
||||
{
|
||||
public:
|
||||
@@ -50,7 +52,8 @@ public:
|
||||
|
||||
Shape* getOrCreateAssociatedShape(const svx::diagram::Point& rPoint, bool bCreateOnDemand = false) const;
|
||||
|
||||
void writeDiagramData(oox::core::XmlFilterBase& rFB, sax_fastparser::FSHelperPtr& rTarget);
|
||||
void writeDiagramReplacement(DrawingML& rOriginalDrawingML, sax_fastparser::FSHelperPtr& rTarget);
|
||||
void writeDiagramData(oox::core::XmlFilterBase& rOriginalFB, sax_fastparser::FSHelperPtr& rTarget);
|
||||
|
||||
private:
|
||||
// The model definition, the parts *only* available in oox. Also look for already
|
||||
|
||||
@@ -44,10 +44,11 @@
|
||||
#include "diagramfragmenthandler.hxx"
|
||||
#include <comphelper/processfactory.hxx>
|
||||
#include <com/sun/star/io/TempFile.hpp>
|
||||
#include <oox/export/drawingml.hxx>
|
||||
|
||||
#ifdef DBG_UTIL
|
||||
#include <osl/file.hxx>
|
||||
#include <iostream>
|
||||
#include <o3tl/environment.hxx>
|
||||
#endif
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
@@ -200,25 +201,23 @@ bool Diagram::checkMinimalDataDoms() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Diagram::tryToCreateMissingDataDoms(oox::core::XmlFilterBase& rFB)
|
||||
void Diagram::tryToCreateMissingDataDoms(DrawingML& rOriginalDrawingML)
|
||||
{
|
||||
// internal testing: allow to force to always recreate
|
||||
static bool bForceAlwaysReCreate(false);
|
||||
static bool bForceAlwaysReCreate(nullptr != std::getenv("FORCE_RECREATE_DIAGRAM_DATADOMS"));
|
||||
|
||||
// check if activated, return if not to stay compatible for now
|
||||
static bool bReCreateDiagramDataDoms(nullptr != std::getenv("ACTIVATE_RECREATE_DIAGRAM_DATADOMS"));
|
||||
#ifdef DBG_UTIL
|
||||
std::cout << "DiagramReCreate: always==" << bForceAlwaysReCreate << ",bReCreate==" << bReCreateDiagramDataDoms << std::endl;
|
||||
#endif
|
||||
SAL_INFO("oox", "DiagramReCreate: always==" << bForceAlwaysReCreate << ",bReCreate==" << bReCreateDiagramDataDoms);
|
||||
if (!bForceAlwaysReCreate && !bReCreateDiagramDataDoms)
|
||||
return;
|
||||
|
||||
oox::core::XmlFilterBase& rFB(*rOriginalDrawingML.GetFB());
|
||||
|
||||
if (bForceAlwaysReCreate || maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXData))
|
||||
{
|
||||
// re-create OOXData DomFile from model data
|
||||
#ifdef DBG_UTIL
|
||||
std::cout << "DiagramReCreate: creating DomMapFlag::OOXData" << std::endl;
|
||||
#endif
|
||||
SAL_INFO("oox", "DiagramReCreate: creating DomMapFlag::OOXData");
|
||||
uno::Reference< io::XTempFile > xTempFile = io::TempFile::create(comphelper::getProcessComponentContext());
|
||||
uno::Reference< io::XOutputStream > xOutput = xTempFile->getOutputStream();
|
||||
|
||||
@@ -243,7 +242,52 @@ void Diagram::tryToCreateMissingDataDoms(oox::core::XmlFilterBase& rFB)
|
||||
}
|
||||
|
||||
#ifdef DBG_UTIL
|
||||
osl::File::move(xTempFile->getUri(), "file:///home/alg/Downloads/tonne/test.xml");
|
||||
const OUString env(o3tl::getEnvironment(u"DIAGRAM_DUMP_PATH"_ustr));
|
||||
if(!env.isEmpty())
|
||||
{
|
||||
OUString url;
|
||||
::osl::FileBase::getFileURLFromSystemPath(env, url);
|
||||
osl::File::move(xTempFile->getUri(), url + "data_T.xml");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (bForceAlwaysReCreate || maDiagramPRDomMap.end() == maDiagramPRDomMap.find(svx::diagram::DomMapFlag::OOXDrawing))
|
||||
{
|
||||
// re-create OOXDrawing DomFile from model data
|
||||
SAL_INFO("oox", "DiagramReCreate: creating DomMapFlag::OOXDrawing");
|
||||
uno::Reference< io::XTempFile > xTempFile = io::TempFile::create(comphelper::getProcessComponentContext());
|
||||
uno::Reference< io::XOutputStream > xOutput = xTempFile->getOutputStream();
|
||||
|
||||
if (xOutput)
|
||||
{
|
||||
sax_fastparser::FSHelperPtr aFS = std::make_shared<sax_fastparser::FastSerializerHelper>(xOutput, true);
|
||||
getData()->writeDiagramReplacement(rOriginalDrawingML, aFS);
|
||||
xOutput->flush();
|
||||
|
||||
// this call is *important*, without it xDocBuilder->parse below fails and some strange
|
||||
// and wrong assertion gets thrown in ~FastSerializerHelper that shall get called
|
||||
xOutput->closeOutput();
|
||||
|
||||
uno::Reference<xml::dom::XDocumentBuilder> xDocBuilder(xml::dom::DocumentBuilder::create(comphelper::getProcessComponentContext()));
|
||||
if (xDocBuilder)
|
||||
{
|
||||
uno::Reference<xml::dom::XDocument> xInstance = xDocBuilder->parse(xTempFile->getInputStream());
|
||||
if (xInstance)
|
||||
{
|
||||
maDiagramPRDomMap[svx::diagram::DomMapFlag::OOXDrawing] <<= xInstance;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DBG_UTIL
|
||||
const OUString env(o3tl::getEnvironment(u"DIAGRAM_DUMP_PATH"_ustr));
|
||||
if(!env.isEmpty())
|
||||
{
|
||||
OUString url;
|
||||
::osl::FileBase::getFileURLFromSystemPath(env, url);
|
||||
osl::File::move(xTempFile->getUri(), url + "drawing_T.xml");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
|
||||
// check if mandatory DiagramDomS exist (or can be created)
|
||||
bool checkMinimalDataDoms() const;
|
||||
void tryToCreateMissingDataDoms(oox::core::XmlFilterBase& rFB);
|
||||
void tryToCreateMissingDataDoms(DrawingML& rOriginalDrawingML);
|
||||
|
||||
private:
|
||||
// This contains groups of shapes: automatic font size is the same in each group.
|
||||
|
||||
@@ -469,12 +469,12 @@ bool DiagramHelper_oox::checkMinimalDataDoms() const
|
||||
return mpDiagramPtr->checkMinimalDataDoms();
|
||||
}
|
||||
|
||||
void DiagramHelper_oox::tryToCreateMissingDataDoms(oox::core::XmlFilterBase& rFB)
|
||||
void DiagramHelper_oox::tryToCreateMissingDataDoms(DrawingML& rOriginalDrawingML)
|
||||
{
|
||||
if (!mpDiagramPtr)
|
||||
return;
|
||||
|
||||
mpDiagramPtr->tryToCreateMissingDataDoms(rFB);
|
||||
mpDiagramPtr->tryToCreateMissingDataDoms(rOriginalDrawingML);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -265,6 +265,7 @@ DrawingML::DrawingML(::sax_fastparser::FSHelperPtr pFS, ::oox::core::XmlFilterBa
|
||||
, mpFB(pFB)
|
||||
, mbIsBackgroundDark(false)
|
||||
, mbPlaceholder(false)
|
||||
, mbDiagaramExport(false)
|
||||
{
|
||||
uno::Reference<beans::XPropertySet> xSettings(pFB->getModelFactory()->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY);
|
||||
if (xSettings.is())
|
||||
@@ -2327,6 +2328,25 @@ void DrawingML::WriteShapeTransformation( const Reference< XShape >& rXShape, sa
|
||||
bFlipH = bFlipH && !bFlippedBeforeRotation;
|
||||
bFlipV = bFlipV && !bFlippedBeforeRotation;
|
||||
|
||||
if (isDiagaramExport())
|
||||
{
|
||||
// need to offset from top-left of Diagram's GroupObject
|
||||
SdrObject* pShape(SdrObject::getSdrObjectFromXShape(rXShape));
|
||||
|
||||
if (nullptr != pShape)
|
||||
{
|
||||
std::shared_ptr< svx::diagram::DiagramHelper_svx > pDiagramHelper(pShape->getDiagramHelperFromDiagramOrMember());
|
||||
|
||||
if (pDiagramHelper)
|
||||
{
|
||||
const Reference< XShape >& rRootShape(pDiagramHelper->getRootShape());
|
||||
awt::Point aRootPos = rRootShape->getPosition();
|
||||
aPos.X -= aRootPos.X;
|
||||
aPos.Y -= aRootPos.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetDocumentType() == DOCUMENT_DOCX && m_xParent.is())
|
||||
{
|
||||
awt::Point aParentPos = m_xParent->getPosition();
|
||||
@@ -6793,7 +6813,7 @@ bool DrawingML::PrepareToWriteAsDiagram(const css::uno::Reference<css::drawing::
|
||||
return false;
|
||||
|
||||
// try to re-create (if needed is decided there)
|
||||
pAdvancedDiagramHelper->tryToCreateMissingDataDoms(*GetFB());
|
||||
pAdvancedDiagramHelper->tryToCreateMissingDataDoms(*this);
|
||||
|
||||
if (!pAdvancedDiagramHelper->checkMinimalDataDoms())
|
||||
return false;
|
||||
|
||||
@@ -912,6 +912,14 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
|
||||
}
|
||||
}
|
||||
|
||||
if (isDiagaramExport())
|
||||
{
|
||||
// add evtl. used DiagramDataModelID if DiagramExport
|
||||
SdrObject* pTarget(SdrObject::getSdrObjectFromXShape(xShape));
|
||||
if (nullptr != pTarget && !pTarget->getDiagramDataModelID().isEmpty())
|
||||
pAttrListSp->add(XML_modelId, pTarget->getDiagramDataModelID());
|
||||
}
|
||||
|
||||
// export <sp> element (with a namespace prefix)
|
||||
mpFS->startElementNS(mnXmlNamespace, XML_sp, pAttrListSp);
|
||||
}
|
||||
|
||||
@@ -2024,6 +2024,7 @@ dropLine
|
||||
dropLines
|
||||
dropauto
|
||||
ds
|
||||
dsp
|
||||
dstNode
|
||||
dstrike
|
||||
dt
|
||||
|
||||
Reference in New Issue
Block a user