summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-02-07 16:26:31 +0100
committerAndras Timar <andras.timar@collabora.com>2019-02-21 22:32:44 +0100
commita6d9ccf26910e35f22ccec8a75472e2fa947abe1 (patch)
treeb7dd72d15a83867e4442f1f4e116c17f1a901257 /oox
parent90069045f4bab7b4dc8701533fdbf5d53c71d4ae (diff)
Related: tdf#117761 oox smartart: backport fixes related to cycle matrix
This is a combination of 6 commits. This is the 1st commit: oox smartart, cycle matrix: fix counting presentation children The markup is: <dgm:if name="Name6" axis="ch ch" ptType="node node" st="1 1" cnt="1 0" func="cnt" op="gte" val="1"> Where PowerPoint evaluated the condition to true, but Impress evaluated to false. This means that the undocumented relation between the child lists is "OR" (not "AND"). Also, our code assumed that "node" has to be a data node (not presentation node), but it seems the only way this condition can be true if presentation children is also counted. (The presentation node in question is not a presentation of anything.) (cherry picked from commit e3c6f249c10f7f1bcc528e643f5723288c514b29) This is the commit #2: oox smartart, cycle matrix: handle left/bottom constraint in composite algo The bugdoc has 3 shapes in the "outer" circle which have a position where either x or y is not 0. But these are defined using constraints talking about the right or bottom edge of the shape. Map that to top/left, given that we already know the shape size. (cherry picked from commit b9b4e9223b6c0d6e0b48b694c9aabbe54a250660) This is the commit #3: oox smartart, cycle matrix: fix too large height in composite algo The user-level problem was that the height of the entire smartart was too large. The reason for this was that: - composite algorithm gets the constraint height should be 77% of width, this means 6096000 -> 4693920 EMUs - at the same time the parent container is already smaller, 4064000 EMUs - a few lines later we already limit the max height with std::min(), but in the meantime an incorrect y position is calculated, exactly due to the lack of early limited height Solve the problem by making sure composite algorithm never works with a height (even when using it to calculate vertical center) that exceeds the height of the parent. (cherry picked from commit 5b2e38e0cfc7006d6982f741cf158a8a98dc8630) This is the commit #4: oox smartart, cycle matrix: handle aspect ratio in composite algo This way the 4 quadrant shapes in the center of the SmartArt form a circle, as width is shrinking. It's not height growing, as OOXML spec clearly says "ar" always just shrinks one axis. (>1 and <1 "ar" is to be handled when they are seen in action in an actual document.) (cherry picked from commit 34383064ac061497b0c46c449313877c6b6a2087) This is the commit #5: oox smartart, cycle matrix: handle destination order in connections It is possible to have connections from multiple data nodes to the same presentation node with a presOf type. We use to order these based on as they appear in the data XML, but we need to order them according to the destOrd attribute. Introduce an std::map for that, so get ordering automatically as we iterate. Turn the std::pair into a struct to make the code a bit more readable. (cherry picked from commit ecb733da58b74714eb66d2063a2835ce5c471870) Conflicts: oox/source/drawingml/diagram/diagramlayoutatoms.cxx This is the commit #6: oox smartart, cycle matrix: fix fill and line props of shape The topmost shape may not have 0 depth, but something larger. In that case at least it's safe to still use fill & line properties. The B1 quadrant of the test file now has the proper orange background, and B2's border is also properly orange. (cherry picked from commit 8193e697d286595aa62859011761adeb002244e3) Conflicts: oox/source/drawingml/diagram/diagramlayoutatoms.cxx Change-Id: Iccc5f6993693a0f1cf8f50d163003c24d3ad690e Reviewed-on: https://gerrit.libreoffice.org/68144 Tested-by: Jenkins Reviewed-by: Andras Timar <andras.timar@collabora.com>
Diffstat (limited to 'oox')
-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
5 files changed, 88 insertions, 22 deletions
diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx
index 64dc5dde6d91..d1de1c72f94d 100644
--- a/oox/source/drawingml/diagram/diagram.cxx
+++ b/oox/source/drawingml/diagram/diagram.cxx
@@ -271,8 +271,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;
}
}
@@ -282,9 +284,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 7758ad3a1910..869b02180a89 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -370,6 +370,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;
}
@@ -483,12 +491,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)
{
@@ -527,25 +552,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);
}
@@ -1128,11 +1158,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
@@ -1142,7 +1182,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();
@@ -1159,6 +1199,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() &&
@@ -1184,8 +1231,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 440db0ef21ed..f056e4f7e637 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 2cfeec2e8db6..ff508a24fcae 100644
--- a/oox/source/drawingml/diagram/layoutnodecontext.cxx
+++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx
@@ -67,10 +67,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: