summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--oox/source/drawingml/diagram/diagram.cxx11
-rw-r--r--oox/source/drawingml/diagram/diagram.hxx8
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.cxx71
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.hxx4
-rw-r--r--oox/source/drawingml/diagram/layoutnodecontext.cxx16
-rw-r--r--sd/qa/unit/data/pptx/smartart-cycle-matrix.pptxbin0 -> 56986 bytes
-rw-r--r--sd/qa/unit/import-tests-smartart.cxx93
7 files changed, 181 insertions, 22 deletions
diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx
index 4664a55e594c..daddf1fa6991 100644
--- a/oox/source/drawingml/diagram/diagram.cxx
+++ b/oox/source/drawingml/diagram/diagram.cxx
@@ -270,8 +270,10 @@ void Diagram::build( )
if( connection.mnType == XML_presOf )
{
DiagramData::StringMap::value_type::second_type& rVec=getData()->getPresOfNameMap()[connection.msDestId];
- rVec.emplace_back(
- connection.msSourceId,sal_Int32(0));
+ DiagramData::SourceIdAndDepth aSourceIdAndDepth;
+ aSourceIdAndDepth.msSourceId = connection.msSourceId;
+ aSourceIdAndDepth.mnDepth = 0;
+ rVec[connection.mnDestOrder] = aSourceIdAndDepth;
}
}
@@ -281,9 +283,8 @@ void Diagram::build( )
{
for (auto & elem : elemPresOf.second)
{
- const sal_Int32 nDepth=calcDepth(elem.first,
- getData()->getConnections());
- elem.second = nDepth != 0 ? nDepth : -1;
+ const sal_Int32 nDepth = calcDepth(elem.second.msSourceId, getData()->getConnections());
+ elem.second.mnDepth = nDepth != 0 ? nDepth : -1;
if (nDepth > getData()->getMaxDepth())
getData()->setMaxDepth(nDepth);
}
diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx
index 242ff09fa152..a0955b124230 100644
--- a/oox/source/drawingml/diagram/diagram.hxx
+++ b/oox/source/drawingml/diagram/diagram.hxx
@@ -160,8 +160,14 @@ public:
typedef std::map< OUString,
std::vector<dgm::Point*> > PointsNameMap;
typedef std::map< OUString, const dgm::Connection* > ConnectionNameMap;
+ struct SourceIdAndDepth
+ {
+ OUString msSourceId;
+ sal_Int32 mnDepth = 0;
+ };
+ /// Tracks connections: destination id -> {destination order, details} map.
typedef std::map< OUString,
- std::vector<std::pair<OUString,sal_Int32> > > StringMap;
+ std::map<sal_Int32, SourceIdAndDepth > > StringMap;
DiagramData();
FillPropertiesPtr & getFillProperties()
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index 513dc9926e82..09edf0022259 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -369,6 +369,14 @@ sal_Int32 ConditionAtom::getNodeCount() const
if (aCxn.mnType == XML_parOf && aCxn.msSourceId == sNodeId)
nCount++;
}
+ else
+ {
+ // No presentation child is a presentation of a model node: just
+ // count presentation children.
+ for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections())
+ if (aCxn.mnType == XML_presParOf && aCxn.msSourceId == pPoint->msModelId)
+ nCount++;
+ }
}
return nCount;
}
@@ -482,12 +490,29 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
LayoutPropertyMap aProperties;
LayoutProperty& rParent = aProperties[""];
- rParent[XML_w] = rShape->getSize().Width;
- rParent[XML_h] = rShape->getSize().Height;
- rParent[XML_l] = 0;
- rParent[XML_t] = 0;
- rParent[XML_r] = rShape->getSize().Width;
- rParent[XML_b] = rShape->getSize().Height;
+
+ sal_Int32 nParentXOffset = 0;
+ if (mfAspectRatio != 1.0)
+ {
+ rParent[XML_w] = rShape->getSize().Width;
+ rParent[XML_h] = rShape->getSize().Height;
+ rParent[XML_l] = 0;
+ rParent[XML_t] = 0;
+ rParent[XML_r] = rShape->getSize().Width;
+ rParent[XML_b] = rShape->getSize().Height;
+ }
+ else
+ {
+ // Shrink width to be only as large as height.
+ rParent[XML_w] = std::min(rShape->getSize().Width, rShape->getSize().Height);
+ rParent[XML_h] = rShape->getSize().Height;
+ if (rParent[XML_w] < rShape->getSize().Width)
+ nParentXOffset = (rShape->getSize().Width - rParent[XML_w]) / 2;
+ rParent[XML_l] = nParentXOffset;
+ rParent[XML_t] = 0;
+ rParent[XML_r] = rShape->getSize().Width - rParent[XML_l];
+ rParent[XML_b] = rShape->getSize().Height;
+ }
for (const auto & rConstr : rConstraints)
{
@@ -526,25 +551,30 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
LayoutProperty::const_iterator it, it2;
if ( (it = rProp.find(XML_w)) != rProp.end() )
- aSize.Width = it->second;
+ aSize.Width = std::min(it->second, rShape->getSize().Width);
if ( (it = rProp.find(XML_h)) != rProp.end() )
- aSize.Height = it->second;
+ aSize.Height = std::min(it->second, rShape->getSize().Height);
if ( (it = rProp.find(XML_l)) != rProp.end() )
aPos.X = it->second;
else if ( (it = rProp.find(XML_ctrX)) != rProp.end() )
aPos.X = it->second - aSize.Width/2;
+ else if ((it = rProp.find(XML_r)) != rProp.end())
+ aPos.X = it->second - aSize.Width;
if ( (it = rProp.find(XML_t)) != rProp.end())
aPos.Y = it->second;
else if ( (it = rProp.find(XML_ctrY)) != rProp.end() )
aPos.Y = it->second - aSize.Height/2;
+ else if ((it = rProp.find(XML_b)) != rProp.end())
+ aPos.Y = it->second - aSize.Height;
if ( (it = rProp.find(XML_l)) != rProp.end() && (it2 = rProp.find(XML_r)) != rProp.end() )
aSize.Width = it2->second - it->second;
if ( (it = rProp.find(XML_t)) != rProp.end() && (it2 = rProp.find(XML_b)) != rProp.end() )
aSize.Height = it2->second - it->second;
+ aPos.X += nParentXOffset;
aSize.Width = std::min(aSize.Width, rShape->getSize().Width - aPos.X);
aSize.Height = std::min(aSize.Height, rShape->getSize().Height - aPos.Y);
}
@@ -1096,11 +1126,21 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode
{
DiagramData::StringMap::value_type::second_type::const_iterator aVecIter=aNodeName->second.begin();
const DiagramData::StringMap::value_type::second_type::const_iterator aVecEnd=aNodeName->second.end();
+ // Calculate the depth of what is effectively the topmost element.
+ sal_Int32 nMinDepth = std::numeric_limits<sal_Int32>::max();
+ for (const auto& rPair : aNodeName->second)
+ {
+ if (rPair.second.mnDepth < nMinDepth)
+ nMinDepth = rPair.second.mnDepth;
+ }
+
while( aVecIter != aVecEnd )
{
+ const auto& rPair = *aVecIter;
+ const DiagramData::SourceIdAndDepth& rItem = rPair.second;
DiagramData::PointNameMap& rMap = mrDgm.getData()->getPointNameMap();
// pPresNode is the presentation node of the aDataNode2 data node.
- DiagramData::PointNameMap::const_iterator aDataNode2 = rMap.find(aVecIter->first);
+ DiagramData::PointNameMap::const_iterator aDataNode2 = rMap.find(rItem.msSourceId);
if (aDataNode2 == rMap.end())
{
//busted, skip it
@@ -1110,7 +1150,7 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode
rShape->setDataNodeType(aDataNode2->second->mnType);
- if( aVecIter->second == 0 )
+ if( rItem.mnDepth == 0 )
{
// grab shape attr from topmost element(s)
rShape->getShapeProperties() = aDataNode2->second->mpShape->getShapeProperties();
@@ -1127,6 +1167,13 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode
<< " added for layout node named \"" << msName
<< "\"");
}
+ else if (rItem.mnDepth == nMinDepth)
+ {
+ // If no real topmost element, then take properties from the one that's the closest
+ // to topmost.
+ rShape->getLineProperties() = aDataNode2->second->mpShape->getLineProperties();
+ rShape->getFillProperties() = aDataNode2->second->mpShape->getFillProperties();
+ }
// append text with right outline level
if( aDataNode2->second->mpShape->getTextBody() &&
@@ -1152,8 +1199,8 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode
for (const auto& pSourceParagraph : rSourceParagraphs)
{
TextParagraph& rPara = pTextBody->addParagraph();
- if (aVecIter->second != -1)
- rPara.getProperties().setLevel(aVecIter->second);
+ if (rItem.mnDepth != -1)
+ rPara.getProperties().setLevel(rItem.mnDepth);
for (const auto& pRun : pSourceParagraph->getRuns())
rPara.addRun(pRun);
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
index 500495b6f2ca..75149a5cbecd 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
@@ -169,9 +169,13 @@ public:
/// Gives access to <dgm:param type="..." val="..."/>.
const ParamMap& getMap() const { return maMap; }
+ void setAspectRatio(double fAspectRatio) { mfAspectRatio = fAspectRatio; }
+
private:
sal_Int32 mnType;
ParamMap maMap;
+ /// Aspect ratio is not integer, so not part of maMap.
+ double mfAspectRatio = 0;
};
typedef std::shared_ptr< AlgAtom > AlgAtomPtr;
diff --git a/oox/source/drawingml/diagram/layoutnodecontext.cxx b/oox/source/drawingml/diagram/layoutnodecontext.cxx
index ad62ba5d712b..24264135478b 100644
--- a/oox/source/drawingml/diagram/layoutnodecontext.cxx
+++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx
@@ -66,10 +66,18 @@ public:
{
case DGM_TOKEN( param ):
{
- const sal_Int32 nValTok = rAttribs.getToken( XML_val, 0 );
- mpNode->addParam(
- rAttribs.getToken( XML_type, 0 ),
- nValTok>0 ? nValTok : rAttribs.getInteger( XML_val, 0 ) );
+ sal_Int32 nType = rAttribs.getToken(XML_type, 0);
+ switch (nType)
+ {
+ case XML_ar:
+ mpNode->setAspectRatio(rAttribs.getDouble(XML_val, 0));
+ break;
+ default:
+ const sal_Int32 nValTok = rAttribs.getToken(XML_val, 0);
+ mpNode->addParam(nType, nValTok > 0 ? nValTok
+ : rAttribs.getInteger(XML_val, 0));
+ break;
+ }
break;
}
default:
diff --git a/sd/qa/unit/data/pptx/smartart-cycle-matrix.pptx b/sd/qa/unit/data/pptx/smartart-cycle-matrix.pptx
new file mode 100644
index 000000000000..fb1cb7ea2c2e
--- /dev/null
+++ b/sd/qa/unit/data/pptx/smartart-cycle-matrix.pptx
Binary files differ
diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx
index 9de4061a072b..29f998ce6f43 100644
--- a/sd/qa/unit/import-tests-smartart.cxx
+++ b/sd/qa/unit/import-tests-smartart.cxx
@@ -51,6 +51,7 @@ public:
void testAccentProcess();
void testContinuousBlockProcess();
void testOrgChart();
+ void testCycleMatrix();
CPPUNIT_TEST_SUITE(SdImportTestSmartArt);
@@ -67,6 +68,7 @@ public:
CPPUNIT_TEST(testAccentProcess);
CPPUNIT_TEST(testContinuousBlockProcess);
CPPUNIT_TEST(testOrgChart);
+ CPPUNIT_TEST(testCycleMatrix);
CPPUNIT_TEST_SUITE_END();
};
@@ -547,6 +549,97 @@ void SdImportTestSmartArt::testOrgChart()
xDocShRef->DoClose();
}
+void SdImportTestSmartArt::testCycleMatrix()
+{
+ sd::DrawDocShellRef xDocShRef = loadURL(
+ m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/smartart-cycle-matrix.pptx"), PPTX);
+ uno::Reference<drawing::XShape> xGroup(getShapeFromPage(0, 0, xDocShRef), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xGroup.is());
+
+ // Without the accompanying fix in place, this test would have failed: the height was 12162,
+ // which is not the mm100 equivalent of the 4064000 EMU in the input file.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(11287), xGroup->getSize().Height);
+
+ uno::Reference<text::XText> xA1(getChildShape(getChildShape(xGroup, 1), 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xA1.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("A1"), xA1->getString());
+
+ // Test fill color of B1, should be orange.
+ uno::Reference<text::XText> xB1(getChildShape(getChildShape(xGroup, 1), 1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xB1.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("B1"), xB1->getString());
+
+ uno::Reference<beans::XPropertySet> xB1Props(xB1, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xB1Props.is());
+ sal_Int32 nFillColor = 0;
+ xB1Props->getPropertyValue("FillColor") >>= nFillColor;
+ // Without the accompanying fix in place, this test would have failed: the background color was
+ // 0x4f81bd, i.e. blue, not orange.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xf79646), nFillColor);
+
+ // Without the accompanying fix in place, this test would have failed: the
+ // content of the "A2" shape was lost.
+ uno::Reference<text::XText> xA2(getChildShape(getChildShape(getChildShape(xGroup, 0), 0), 1),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xA2.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("A2"), xA2->getString());
+
+ // Test that the layout of shapes is like this:
+ // A2 B2
+ // D2 C2
+
+ uno::Reference<drawing::XShape> xA2Shape(xA2, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xA2Shape.is());
+
+ uno::Reference<text::XText> xB2(getChildShape(getChildShape(getChildShape(xGroup, 0), 1), 1),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xB2.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("B2"), xB2->getString());
+ uno::Reference<drawing::XShape> xB2Shape(xB2, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xB2Shape.is());
+
+ // Test line color of B2, should be orange.
+ uno::Reference<beans::XPropertySet> xB2Props(xB2, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xB2Props.is());
+ sal_Int32 nLineColor = 0;
+ xB2Props->getPropertyValue("LineColor") >>= nLineColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xf79646), nLineColor);
+
+ uno::Reference<text::XText> xC2(getChildShape(getChildShape(getChildShape(xGroup, 0), 2), 1),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xC2.is());
+ // Without the accompanying fix in place, this test would have failed, i.e. the order of the
+ // lines in the shape were wrong: C2-1\nC2-4\nC2-3\nC2-2.
+ CPPUNIT_ASSERT_EQUAL(OUString("C2-1\nC2-2\nC2-3\nC2-4"), xC2->getString());
+ uno::Reference<drawing::XShape> xC2Shape(xC2, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xC2Shape.is());
+
+ uno::Reference<text::XText> xD2(getChildShape(getChildShape(getChildShape(xGroup, 0), 3), 1),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xD2.is());
+ CPPUNIT_ASSERT_EQUAL(OUString("D2"), xD2->getString());
+ uno::Reference<drawing::XShape> xD2Shape(xD2, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xD2Shape.is());
+
+ // Without the accompanying fix in place, this test would have failed, i.e.
+ // the A2 and B2 shapes had the same horizontal position, while B2 should
+ // be on the right of A2.
+ CPPUNIT_ASSERT_GREATER(xA2Shape->getPosition().X, xB2Shape->getPosition().X);
+ CPPUNIT_ASSERT_EQUAL(xA2Shape->getPosition().Y, xB2Shape->getPosition().Y);
+ CPPUNIT_ASSERT_GREATER(xA2Shape->getPosition().X, xC2Shape->getPosition().X);
+ CPPUNIT_ASSERT_GREATER(xA2Shape->getPosition().Y, xC2Shape->getPosition().Y);
+ CPPUNIT_ASSERT_EQUAL(xA2Shape->getPosition().X, xD2Shape->getPosition().X);
+ CPPUNIT_ASSERT_GREATER(xA2Shape->getPosition().Y, xD2Shape->getPosition().Y);
+
+ // Without the accompanying fix in place, this test would have failed: width was expected to be
+ // 4887, was actually 7331.
+ uno::Reference<drawing::XShape> xA1Shape(xA1, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xA1Shape.is());
+ CPPUNIT_ASSERT_EQUAL(xA1Shape->getSize().Height, xA1Shape->getSize().Width);
+
+ xDocShRef->DoClose();
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTestSmartArt);
CPPUNIT_PLUGIN_IMPLEMENT();