oox/source/drawingml/diagram/diagramlayoutatoms.cxx |  103 +++++++++++++++++---
 1 file changed, 90 insertions(+), 13 deletions(-)

New commits:
commit b41e6bd13f419fed23a0a5743c2f11b9bf91c40d
Author:     Miklos Vajna <[email protected]>
AuthorDate: Tue Sep 29 11:55:26 2020 +0200
Commit:     Miklos Vajna <[email protected]>
CommitDate: Wed Sep 30 17:25:31 2020 +0200

    oox smartart: snake algo: start parsing relative width constraints
    
    This is needed, but not enough to have the correct width for each shape
    and spacing item on the path of the snake. Currently we give the same
    width for all children, while the shapes typically have a larger width
    than the spacings.
    
    (cherry picked from commit ab291c94fb5338a1cf0ab8fe7cbf57dd5c5f81cb)
    
    Change-Id: I4e2638ea5b566c21cb1cf503a8cf2e5d35256e3c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103701
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx 
b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index 3ab17ec6904a..4e0870d51ee5 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -361,6 +361,12 @@ void 
ConstraintAtom::parseConstraint(std::vector<Constraint>& rConstraints,
                 bRequireForName = false;
                 break;
         }
+        switch (maConstraint.mnPointType)
+        {
+            case XML_sibTrans:
+                bRequireForName = false;
+                break;
+        }
     }
 
     if (bRequireForName && maConstraint.msForName.isEmpty())
@@ -456,6 +462,12 @@ namespace
  */
 void ApplyConstraintToLayout(const Constraint& rConstraint, LayoutPropertyMap& 
rProperties)
 {
+    // TODO handle the case when we have ptType="...", not forName="...".
+    if (rConstraint.msForName.isEmpty())
+    {
+        return;
+    }
+
     const LayoutPropertyMap::const_iterator aRef = 
rProperties.find(rConstraint.msRefForName);
     if (aRef != rProperties.end())
     {
@@ -1285,8 +1297,24 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const 
std::vector<Constraint>&
             if (rShape->getChildren().empty() || rShape->getSize().Width == 0 
|| rShape->getSize().Height == 0)
                 break;
 
-            // Parse constraints, only self spacing from height as a start.
+            // Parse constraints.
+            double fChildAspectRatio = 
rShape->getChildren()[0]->getAspectRatio();
+            double fShapeHeight = rShape->getSize().Height;
+            double fShapeWidth = rShape->getSize().Width;
+            // Check if we have a child aspect ratio. If so, need to shrink 
one dimension to
+            // achieve that ratio.
+            if (fChildAspectRatio && fShapeHeight
+                && fChildAspectRatio < (fShapeWidth / fShapeHeight))
+            {
+                fShapeWidth = fShapeHeight * fChildAspectRatio;
+            }
+
             double fSpaceFromConstraint = 0;
+            LayoutPropertyMap aPropertiesByName;
+            std::map<sal_Int32, LayoutProperty> aPropertiesByType;
+            LayoutProperty& rParent = aPropertiesByName[""];
+            rParent[XML_w] = fShapeWidth;
+            rParent[XML_h] = fShapeHeight;
             for (const auto& rConstr : rConstraints)
             {
                 if (rConstr.mnRefType == XML_h)
@@ -1294,7 +1322,64 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const 
std::vector<Constraint>&
                     if (rConstr.mnType == XML_sp && 
rConstr.msForName.isEmpty())
                         fSpaceFromConstraint = rConstr.mfFactor;
                 }
+
+                auto itRefForName = 
aPropertiesByName.find(rConstr.msRefForName);
+                if (itRefForName == aPropertiesByName.end())
+                {
+                    continue;
+                }
+
+                auto it = itRefForName->second.find(rConstr.mnRefType);
+                if (it == itRefForName->second.end())
+                {
+                    continue;
+                }
+
+                if (rConstr.mfValue != 0.0)
+                {
+                    continue;
+                }
+
+                sal_Int32 nValue = it->second * rConstr.mfFactor;
+
+                if (rConstr.mnPointType == XML_none)
+                {
+                    aPropertiesByName[rConstr.msForName][rConstr.mnType] = 
nValue;
+                }
+                else
+                {
+                    aPropertiesByType[rConstr.mnPointType][rConstr.mnType] = 
nValue;
+                }
+            }
+
+            std::vector<sal_Int32> aShapeWidths(rShape->getChildren().size());
+            for (size_t i = 0; i < rShape->getChildren().size(); ++i)
+            {
+                ShapePtr pChild = rShape->getChildren()[i];
+                if (!pChild->getDataNodeType())
+                {
+                    // TODO handle the case when the requirement applies by 
name, not by point type.
+                    aShapeWidths[i] = fShapeWidth;
+                    continue;
+                }
+
+                auto itNodeType = 
aPropertiesByType.find(pChild->getDataNodeType());
+                if (itNodeType == aPropertiesByType.end())
+                {
+                    aShapeWidths[i] = fShapeWidth;
+                    continue;
+                }
+
+                auto it = itNodeType->second.find(XML_w);
+                if (it == itNodeType->second.end())
+                {
+                    aShapeWidths[i] = fShapeWidth;
+                    continue;
+                }
+
+                aShapeWidths[i] = it->second;
             }
+
             bool bSpaceFromConstraints = fSpaceFromConstraint != 0;
 
             const sal_Int32 nDir = maMap.count(XML_grDir) ? 
maMap.find(XML_grDir)->second : XML_tL;
@@ -1315,27 +1400,19 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const 
std::vector<Constraint>&
 
             sal_Int32 nCol = 1;
             sal_Int32 nRow = 1;
-            double fChildAspectRatio = 
rShape->getChildren()[0]->getAspectRatio();
             if (nCount <= fChildAspectRatio)
                 // Child aspect ratio request (width/height) is N, and we have 
at most N shapes.
                 // This means we don't need multiple columns.
                 nRow = nCount;
             else
             {
-                double fShapeHeight = rShape->getSize().Height;
-                double fShapeWidth = rShape->getSize().Width;
-                // Check if we have a child aspect ratio. If so, need to 
shrink one dimension to
-                // achieve that ratio.
-                if (fChildAspectRatio && fShapeHeight && fChildAspectRatio < 
(fShapeWidth/fShapeHeight))
-                {
-                    fShapeWidth = fShapeHeight * fChildAspectRatio;
-                }
-
                 for ( ; nRow<nCount; nRow++)
                 {
-                    nCol = (nCount+nRow-1) / nRow;
-                    if ((fShapeHeight / nCol) / (fShapeWidth / nRow) >= 
fAspectRatio)
+                    nCol = std::ceil(static_cast<double>(nCount) / nRow);
+                    if ((fShapeHeight * nRow) / (fShapeWidth * nCol) >= 
fAspectRatio)
+                    {
                         break;
+                    }
                 }
             }
 
_______________________________________________
Libreoffice-commits mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to