summaryrefslogtreecommitdiff
path: root/oox/source
diff options
context:
space:
mode:
authorBalazs Varga <balazs.varga991@gmail.com>2020-12-11 20:31:28 +0100
committerLászló Németh <nemeth@numbertext.org>2020-12-16 16:11:40 +0100
commit3184cfc493c6931725dce1de19ac958067b1fd25 (patch)
tree26913d99fb8f7368132b24d42027d09d662401f4 /oox/source
parentfbe77e5d61ca63a688c12be721e760935d78e780 (diff)
tdf#128621 OOXML Chart: export embedded shapes in chart
Use ShapeExport to export additional shapes (userShapes) in Chart. Change-Id: Ic70a7f84c4ac028b6f09a69bec2cf4949944b16c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107605 Tested-by: Jenkins Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'oox/source')
-rw-r--r--oox/source/export/chartexport.cxx108
-rw-r--r--oox/source/export/drawingml.cxx69
-rw-r--r--oox/source/token/relationship.inc1
-rw-r--r--oox/source/token/tokens.txt1
4 files changed, 179 insertions, 0 deletions
diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx
index e87fba060646..24fc7dc88aad 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -74,6 +74,7 @@
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/awt/XBitmap.hpp>
@@ -927,6 +928,9 @@ void ChartExport::exportChartSpace( const Reference< css::chart::XChartDocument
//XML_externalData
exportExternalData(xChartDoc);
+ // export additional shapes in chart
+ exportAdditionalShapes(xChartDoc);
+
pFS->endElement( FSNS( XML_c, XML_chartSpace ) );
}
@@ -977,6 +981,110 @@ void ChartExport::exportExternalData( const Reference< css::chart::XChartDocumen
pFS->singleElementNS(XML_c, XML_externalData, FSNS(XML_r, XML_id), sRelId);
}
+void ChartExport::exportAdditionalShapes( const Reference< css::chart::XChartDocument >& xChartDoc )
+{
+ Reference< beans::XPropertySet > xDocPropSet(xChartDoc, uno::UNO_QUERY);
+ if (xDocPropSet.is())
+ {
+ css::uno::Reference< css::drawing::XShapes > mxAdditionalShapes;
+ // get a sequence of non-chart shapes
+ try
+ {
+ Any aShapesAny = xDocPropSet->getPropertyValue("AdditionalShapes");
+ if( (aShapesAny >>= mxAdditionalShapes) && mxAdditionalShapes.is() )
+ {
+ OUString sId;
+ const char* sFullPath = nullptr;
+ const char* sRelativePath = nullptr;
+ sal_Int32 nDrawing = getNewDrawingUniqueId();
+
+ switch (GetDocumentType())
+ {
+ case DOCUMENT_DOCX:
+ {
+ sFullPath = "word/drawings/drawing";
+ sRelativePath = "../drawings/drawing";
+ break;
+ }
+ case DOCUMENT_PPTX:
+ {
+ sFullPath = "ppt/drawings/drawing";
+ sRelativePath = "../drawings/drawing";
+ break;
+ }
+ case DOCUMENT_XLSX:
+ {
+ sFullPath = "xl/drawings/drawing";
+ sRelativePath = "../drawings/drawing";
+ break;
+ }
+ default:
+ {
+ sFullPath = "drawings/drawing";
+ sRelativePath = "drawings/drawing";
+ break;
+ }
+ }
+ OUString sFullStream = OUStringBuffer()
+ .appendAscii(sFullPath)
+ .append(nDrawing)
+ .append(".xml")
+ .makeStringAndClear();
+ OUString sRelativeStream = OUStringBuffer()
+ .appendAscii(sRelativePath)
+ .append(nDrawing)
+ .append(".xml")
+ .makeStringAndClear();
+
+ sax_fastparser::FSHelperPtr pDrawing = CreateOutputStream(
+ sFullStream,
+ sRelativeStream,
+ GetFS()->getOutputStream(),
+ "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml",
+ OUStringToOString(oox::getRelationship(Relationship::CHARTUSERSHAPES), RTL_TEXTENCODING_UTF8).getStr(),
+ &sId);
+
+ GetFS()->singleElementNS(XML_c, XML_userShapes, FSNS(XML_r, XML_id), sId);
+
+ XmlFilterBase* pFB = GetFB();
+ pDrawing->startElement(FSNS(XML_c, XML_userShapes),
+ FSNS(XML_xmlns, XML_cdr), pFB->getNamespaceURL(OOX_NS(dmlChartDr)),
+ FSNS(XML_xmlns, XML_a), pFB->getNamespaceURL(OOX_NS(dml)),
+ FSNS(XML_xmlns, XML_c), pFB->getNamespaceURL(OOX_NS(dmlChart)));
+
+ const sal_Int32 nShapeCount(mxAdditionalShapes->getCount());
+ for (sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++)
+ {
+ Reference< drawing::XShape > xShape;
+ mxAdditionalShapes->getByIndex(nShapeId) >>= xShape;
+ SAL_WARN_IF(!xShape.is(), "xmloff.chart", "Shape without an XShape?");
+ if (!xShape.is())
+ continue;
+
+ // TODO: absSizeAnchor: we import both (absSizeAnchor and relSizeAnchor), but there is no essential difference between them.
+ pDrawing->startElement(FSNS(XML_cdr, XML_relSizeAnchor));
+ uno::Reference< beans::XPropertySet > xShapeProperties(xShape, uno::UNO_QUERY);
+ if( xShapeProperties.is() )
+ {
+ Reference<embed::XVisualObject> xVisObject(mxChartModel, uno::UNO_QUERY);
+ awt::Size aPageSize = xVisObject->getVisualAreaSize(embed::Aspects::MSOLE_CONTENT);
+ WriteFromTo( xShape, aPageSize, pDrawing );
+
+ ShapeExport aExport(XML_cdr, pDrawing, nullptr, GetFB(), GetDocumentType());
+ aExport.WriteShape(xShape);
+ }
+ pDrawing->endElement(FSNS(XML_cdr, XML_relSizeAnchor));
+ }
+ pDrawing->endElement(FSNS(XML_c, XML_userShapes));
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_INFO_EXCEPTION("xmloff.chart", "AdditionalShapes not found");
+ }
+ }
+}
+
void ChartExport::exportChart( const Reference< css::chart::XChartDocument >& xChartDoc )
{
Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 5374812fa094..f291de8662ef 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -209,6 +209,8 @@ void WriteGradientPath(const awt::Gradient& rGradient, const FSHelperPtr& pFS, c
int DrawingML::mnImageCounter = 1;
int DrawingML::mnWdpImageCounter = 1;
std::map<OUString, OUString> DrawingML::maWdpCache;
+sal_Int32 DrawingML::mnDrawingMLCount = 0;
+sal_Int32 DrawingML::mnVmlCount = 0;
sal_Int16 DrawingML::GetScriptType(const OUString& rStr)
{
@@ -241,6 +243,12 @@ void DrawingML::ResetCounters()
maWdpCache.clear();
}
+void DrawingML::ResetMlCounters()
+{
+ mnDrawingMLCount = 0;
+ mnVmlCount = 0;
+}
+
bool DrawingML::GetProperty( const Reference< XPropertySet >& rXPropertySet, const OUString& aName )
{
try
@@ -4952,6 +4960,67 @@ void DrawingML::writeDiagramRels(const uno::Sequence<uno::Sequence<uno::Any>>& x
}
}
+void DrawingML::WriteFromTo(const uno::Reference<css::drawing::XShape>& rXShape, const awt::Size& aPageSize,
+ const FSHelperPtr& pDrawing)
+{
+ awt::Point aTopLeft = rXShape->getPosition();
+ awt::Size aSize = rXShape->getSize();
+
+ SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rXShape.get());
+ if (pObj)
+ {
+ sal_Int32 nRotation = pObj->GetRotateAngle();
+ if (nRotation != 0)
+ {
+ sal_Int16 nHalfWidth = aSize.Width / 2;
+ sal_Int16 nHalfHeight = aSize.Height / 2;
+ // aTopLeft needs correction for rotated customshapes
+ if (pObj->GetObjIdentifier() == OBJ_CUSTOMSHAPE)
+ {
+ const tools::Rectangle& aSnapRect(pObj->GetSnapRect()); // bounding box of the rotated shape
+ aTopLeft.X = aSnapRect.getX() + (aSnapRect.GetWidth() / 2) - nHalfWidth;
+ aTopLeft.Y = aSnapRect.getY() + (aSnapRect.GetHeight() / 2) - nHalfHeight;
+ }
+
+ // MSO changes the anchor positions at these angles and that does an extra 90 degrees
+ // rotation on our shapes, so we output it in such position that MSO
+ // can draw this shape correctly.
+ if ((nRotation >= 45 * 100 && nRotation < 135 * 100) || (nRotation >= 225 * 100 && nRotation < 315 * 100))
+ {
+ aTopLeft.X = aTopLeft.X - nHalfHeight + nHalfWidth;
+ aTopLeft.Y = aTopLeft.Y - nHalfWidth + nHalfHeight;
+
+ std::swap(aSize.Width, aSize.Height);
+ }
+ }
+ }
+
+ tools::Rectangle aLocation(aTopLeft.X, aTopLeft.Y, aTopLeft.X + aSize.Width, aTopLeft.Y + aSize.Height);
+ double nXpos = static_cast<double>(aLocation.TopLeft().getX()) / static_cast<double>(aPageSize.Width);
+ double nYpos = static_cast<double>(aLocation.TopLeft().getY()) / static_cast<double>(aPageSize.Height);
+
+ pDrawing->startElement(FSNS(XML_cdr, XML_from));
+ pDrawing->startElement(FSNS(XML_cdr, XML_x));
+ pDrawing->write(nXpos);
+ pDrawing->endElement(FSNS(XML_cdr, XML_x));
+ pDrawing->startElement(FSNS(XML_cdr, XML_y));
+ pDrawing->write(nYpos);
+ pDrawing->endElement(FSNS(XML_cdr, XML_y));
+ pDrawing->endElement(FSNS(XML_cdr, XML_from));
+
+ nXpos = static_cast<double>(aLocation.BottomRight().getX()) / static_cast<double>(aPageSize.Width);
+ nYpos = static_cast<double>(aLocation.BottomRight().getY()) / static_cast<double>(aPageSize.Height);
+
+ pDrawing->startElement(FSNS(XML_cdr, XML_to));
+ pDrawing->startElement(FSNS(XML_cdr, XML_x));
+ pDrawing->write(nXpos);
+ pDrawing->endElement(FSNS(XML_cdr, XML_x));
+ pDrawing->startElement(FSNS(XML_cdr, XML_y));
+ pDrawing->write(nYpos);
+ pDrawing->endElement(FSNS(XML_cdr, XML_y));
+ pDrawing->endElement(FSNS(XML_cdr, XML_to));
+}
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/token/relationship.inc b/oox/source/token/relationship.inc
index 2b973ded1653..e0b282c94848 100644
--- a/oox/source/token/relationship.inc
+++ b/oox/source/token/relationship.inc
@@ -1,5 +1,6 @@
{Relationship::ACTIVEXCONTROLBINARY, "http://schemas.microsoft.com/office/2006/relationships/activeXControlBinary"},
{Relationship::CHART, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"},
+{Relationship::CHARTUSERSHAPES, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartUserShapes"},
{Relationship::COMMENTS, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"},
{Relationship::COMMENTAUTHORS, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/commentAuthors"},
{Relationship::CONTROL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/control"},
diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt
index 27396f5b8dfa..e81ff50a217c 100644
--- a/oox/source/token/tokens.txt
+++ b/oox/source/token/tokens.txt
@@ -1024,6 +1024,7 @@ byte
c
c15
cBhvr
+cdr
cGp
cGpRule
cMediaNode