File bsc1169982.diff of Package libreoffice

From 3f9eb185eb304c4d9f38babd4f7fdf6d16e20c6a Mon Sep 17 00:00:00 2001
From: Miklos Vajna <vmiklos@collabora.com>
Date: Tue, 8 Sep 2020 17:26:12 +0200
Subject: [PATCH 1/3] bsc1169982.diff

This is a combination of 4 commits.

This is the 1st commit message:

svx UNO API for shapes: expose what scaling factor is used for autofit scaling

TextFitToSizeScale is 0 when the shape has no text or autofit is not
enabled, 100 when there is autofit (but no scale-down), a value between
the two otherwise.

Towards allowing both "autofit" and "same font size for these shapes" at
the same time for SmartArt purposes.

(cherry picked from commit cd268f0047443ddbb22361cdc15093e881f83588)

Conflicts:
	include/svx/unoshprp.hxx
	svx/source/unodraw/unoshape.cxx

This is the commit message #2:

svx UNO API for shapes: allow setting a max factor for autofit text scale

This allows getting the scale factor from multiple shapes (that have
text), seeing what factors they use and then setting the factor to the
minimum of the values.

Towards allowing both "autofit" and "same font size for these shapes" at
the same time for SmartArt purposes.

(cherry picked from commit 81345de4858d6e72ecb8fc6621396570f4a4ee93)

Conflicts:
	include/svx/sdtfsitm.hxx
	include/svx/unoshprp.hxx

This is the commit message #3:

oox smartart: add support for syncing font heights of multiple shapes

When 2 or more shapes have their text set to autofit and they have a
constraint like:

<dgm:constr type="primFontSz" for="des" forName="node" op="equ"/>

Then make sure that the automatic font size is the same for all shapes
and all content fits, by using the smallest scaling factor from all
relevant shapes.

Some rework is needed, because normally oox::drawingml::Shapes don't
have access to their parents, at the same time there can be multiple
SmartArts on a single slide, so storing the grouping info in the filter
is problematic, too. Solve this by storing the grouping in the toplevel
oox::drawingml::Shape and exposing them in XmlFilterBase just during the
time the children of the toplevel shape of the SmartArt are added.

This works, because we know SmartArts can't be nested.

(cherry picked from commit 1bd3474c7c7945e1182dfbaca89be05ea98dd3e8)

Conflicts:
	include/oox/core/xmlfilterbase.hxx
	oox/source/drawingml/diagram/diagram.cxx

This is the commit message #4:

oox smartart: handle <dgm:prSet ... custT="1"/>

Which defines that a data node has text properties as direct formatting,
so autoscale should not happen.

We decide autofit at a shape level, smartart defines custom text props
at a data node level. So take the shape, go to its first presentation
node, get its data node and see if it has custom text props. If not,
continue to scale text down till it fits.

smartart-autofit-sync.pptx is extended to contain a 3rd shape: the first
two have their autofit scaling synchronized, while the 3rd has a fixed
font size of 10pt.

(cherry picked from commit 89b385c2336e5b3868d2a040e11134b349b7d010)

Change-Id: I6caacdaab9a36072b9ad5021bd217c955b09b790
---
 include/oox/core/xmlfilterbase.hxx            |  8 ++
 include/oox/drawingml/shape.hxx               |  8 ++
 include/svl/solar.hrc                         |  2 +-
 include/svx/sdtfsitm.hxx                      | 10 +++
 include/svx/svdotext.hxx                      |  2 +-
 include/svx/unoshprp.hxx                      |  4 +-
 oox/source/core/xmlfilterbase.cxx             |  8 ++
 oox/source/drawingml/diagram/diagram.cxx      |  9 +-
 oox/source/drawingml/diagram/diagram.hxx      | 14 +++-
 .../drawingml/diagram/diagramlayoutatoms.cxx  | 82 ++++++++++++++++++-
 .../drawingml/diagram/diagramlayoutatoms.hxx  | 12 ++-
 oox/source/drawingml/shape.cxx                | 55 +++++++++++++
 oox/source/ppt/pptshape.cxx                   | 13 +++
 svx/source/svdraw/svdattr.cxx                 | 10 +++
 svx/source/svdraw/svdotext.cxx                | 10 ++-
 svx/source/unodraw/unoshape.cxx               | 50 +++++++++++
 16 files changed, 281 insertions(+), 16 deletions(-)

diff --git a/include/oox/core/xmlfilterbase.hxx b/include/oox/core/xmlfilterbase.hxx
index 68bd801eaefd..cb8be7117fdf 100644
--- a/include/oox/core/xmlfilterbase.hxx
+++ b/include/oox/core/xmlfilterbase.hxx
@@ -65,6 +65,7 @@ namespace sax_fastparser {
 namespace utl { class MediaDescriptor; }
 
 namespace oox {
+namespace drawingml { class Shape; }
 namespace core {
 
 class FragmentHandler;
@@ -79,6 +80,10 @@ typedef std::vector< TextField > TextFieldStack;
 
 struct XmlFilterBaseImpl;
 
+using ShapePairs
+    = std::map<std::shared_ptr<drawingml::Shape>, css::uno::Reference<css::drawing::XShape>>;
+using NamedShapePairs = std::map<OUString, ShapePairs>;
+
 class OOX_DLLPUBLIC XmlFilterBase : public FilterBase
 {
 public:
@@ -242,6 +247,9 @@ public:
     /// user about it.
     void setMissingExtDrawing();
 
+    void setDiagramFontHeights(NamedShapePairs* pDiagramFontHeights);
+    NamedShapePairs* getDiagramFontHeights();
+
     void checkDocumentProperties(
             const css::uno::Reference<css::document::XDocumentProperties>& xDocProps);
 
diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx
index 1895c2f2aad6..5b6fd21ce00d 100644
--- a/include/oox/drawingml/shape.hxx
+++ b/include/oox/drawingml/shape.hxx
@@ -29,6 +29,8 @@
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/uno/Reference.hxx>
 #include <com/sun/star/uno/Sequence.hxx>
+
+#include <oox/core/xmlfilterbase.hxx>
 #include <oox/dllapi.h>
 #include <oox/drawingml/color.hxx>
 #include <oox/drawingml/drawingmltypes.hxx>
@@ -239,6 +241,8 @@ public:
 
     void keepDiagramDrawing(::oox::core::XmlFilterBase& rFilterBase, const OUString& rFragmentPath);
 
+    oox::core::NamedShapePairs& getDiagramFontHeights() { return maDiagramFontHeights; }
+
 protected:
 
     enum FrameType
@@ -272,6 +276,7 @@ protected:
                             const basegfx::B2DHomMatrix& aTransformation );
 
     void                keepDiagramCompatibilityInfo();
+    void syncDiagramFontHeights();
     void                convertSmartArtToMetafile( ::oox::core::XmlFilterBase const& rFilterBase );
 
     css::uno::Reference< css::drawing::XShape >
@@ -377,6 +382,9 @@ private:
 
     /// The shape fill should be set to that of the slide background surface.
     bool mbUseBgFill = false;
+
+    /// For SmartArt, this contains groups of shapes: automatic font size is the same in each group.
+    oox::core::NamedShapePairs maDiagramFontHeights;
 };
 
 } }
diff --git a/include/svl/solar.hrc b/include/svl/solar.hrc
index 6b4cb07bbc33..317d45a84bc1 100644
--- a/include/svl/solar.hrc
+++ b/include/svl/solar.hrc
@@ -23,7 +23,7 @@
 // defines ------------------------------------------------------------------
 
 #define OWN_ATTR_VALUE_START                    3900
-#define OWN_ATTR_VALUE_END                      4004
+#define OWN_ATTR_VALUE_END                      4005
 
 #define RID_LIB_START               10000
 #define RID_LIB_END                 19999
diff --git a/include/svx/sdtfsitm.hxx b/include/svx/sdtfsitm.hxx
index ac5b71cec722..d884dc7a5995 100644
--- a/include/svx/sdtfsitm.hxx
+++ b/include/svx/sdtfsitm.hxx
@@ -38,7 +38,13 @@ public:
     SdrTextFitToSizeTypeItem(
             css::drawing::TextFitToSizeType const eFit = css::drawing::TextFitToSizeType_NONE)
         : SfxEnumItem(SDRATTR_TEXT_FITTOSIZE, eFit) {}
+    SdrTextFitToSizeTypeItem(const SdrTextFitToSizeTypeItem& rItem)
+        : SfxEnumItem(rItem),
+        m_nMaxScale(rItem.GetMaxScale())
+    {
+    }
     virtual SfxPoolItem*     Clone(SfxItemPool* pPool=nullptr) const override;
+    bool operator==(const SfxPoolItem& rItem) const override;
     virtual sal_uInt16       GetValueCount() const override;
 
     virtual bool             QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const override;
@@ -49,6 +55,10 @@ public:
     virtual bool             HasBoolValue() const override;
     virtual bool             GetBoolValue() const override;
     virtual void             SetBoolValue(bool bVal) override;
+    void SetMaxScale(sal_Int16 nMaxScale) { m_nMaxScale = nMaxScale; }
+    sal_Int16 GetMaxScale() const { return m_nMaxScale; }
+private:
+    sal_Int16 m_nMaxScale = 0;
 };
 
 #endif
diff --git a/include/svx/svdotext.hxx b/include/svx/svdotext.hxx
index 78e09d508199..020bcb6cdd22 100644
--- a/include/svx/svdotext.hxx
+++ b/include/svx/svdotext.hxx
@@ -263,7 +263,7 @@ private:
                                        tools::Rectangle&       rPaintRect,
                                        Fraction&        aFitXCorrection ) const;
     void ImpAutoFitText( SdrOutliner& rOutliner ) const;
-    static void ImpAutoFitText( SdrOutliner& rOutliner, const Size& rShapeSize, bool bIsVerticalWriting );
+    void ImpAutoFitText( SdrOutliner& rOutliner, const Size& rShapeSize, bool bIsVerticalWriting ) const;
     SVX_DLLPRIVATE SdrObjectUniquePtr ImpConvertContainedTextToSdrPathObjs(bool bToPoly) const;
     SVX_DLLPRIVATE void ImpRegisterLink();
     SVX_DLLPRIVATE void ImpDeregisterLink();
diff --git a/include/svx/unoshprp.hxx b/include/svx/unoshprp.hxx
index 54b8db4b2715..cf263ea8cadd 100644
--- a/include/svx/unoshprp.hxx
+++ b/include/svx/unoshprp.hxx
@@ -192,7 +192,8 @@
 #define OWN_ATTR_SIGNATURELINE_UNSIGNED_IMAGE   (OWN_ATTR_VALUE_START+102)
 #define OWN_ATTR_SIGNATURELINE_IS_SIGNED        (OWN_ATTR_VALUE_START+103)
 #define OWN_ATTR_QRCODE                         (OWN_ATTR_VALUE_START+104)
-// ATTENTION: maximum is OWN_ATTR_VALUE_START+104 svx, see include/svl/solar.hrc
+#define OWN_ATTR_TEXTFITTOSIZESCALE             (OWN_ATTR_VALUE_START+105)
+// ATTENTION: maximum is OWN_ATTR_VALUE_START+105 svx, see include/svl/solar.hrc
 
 // #FontWork#
 #define FONTWORK_PROPERTIES \
@@ -340,6 +341,7 @@
     { OUString(UNO_NAME_MISC_OBJ_SIZEPROTECT),  SDRATTR_OBJSIZEPROTECT          , cppu::UnoType<bool>::get(),                      0,  0},\
     { OUString("UINameSingular"),               OWN_ATTR_UINAME_SINGULAR        , ::cppu::UnoType<OUString>::get(),    css::beans::PropertyAttribute::READONLY,   0}, \
     { OUString("UINamePlural"),                 OWN_ATTR_UINAME_PLURAL          , ::cppu::UnoType<OUString>::get(),    css::beans::PropertyAttribute::READONLY,   0}, \
+    { OUString("TextFitToSizeScale"), OWN_ATTR_TEXTFITTOSIZESCALE, ::cppu::UnoType<sal_Int16>::get(), 0, 0}, \
     /* #i68101# */ \
     { OUString(UNO_NAME_MISC_OBJ_TITLE),        OWN_ATTR_MISC_OBJ_TITLE         , ::cppu::UnoType<OUString>::get(),    0,  0}, \
     { OUString(UNO_NAME_MISC_OBJ_DESCRIPTION),  OWN_ATTR_MISC_OBJ_DESCRIPTION   , ::cppu::UnoType<OUString>::get(),    0,  0},
diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx
index 2cc1daa54b04..fe449dd70909 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -180,6 +180,7 @@ struct XmlFilterBaseImpl
     RelationsMap                   maRelationsMap;
     TextFieldStack                 maTextFieldStack;
     const NamespaceMap&            mrNamespaceMap;
+    NamedShapePairs* mpDiagramFontHeights = nullptr;
 
     /// @throws RuntimeException
     explicit            XmlFilterBaseImpl();
@@ -957,6 +958,13 @@ void XmlFilterBase::setMissingExtDrawing()
     mbMissingExtDrawing = true;
 }
 
+void XmlFilterBase::setDiagramFontHeights(NamedShapePairs* pDiagramFontHeights)
+{
+    mxImpl->mpDiagramFontHeights = pDiagramFontHeights;
+}
+
+NamedShapePairs* XmlFilterBase::getDiagramFontHeights() { return mxImpl->mpDiagramFontHeights; }
+
 OUString XmlFilterBase::getNamespaceURL(sal_Int32 nNSID) const
 {
     auto itr = mxImpl->mrNamespaceMap.maTransitionalNamespaceMap.find(nNSID);
diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx
index 509a1f845e25..21dea33204bc 100644
--- a/oox/source/drawingml/diagram/diagram.cxx
+++ b/oox/source/drawingml/diagram/diagram.cxx
@@ -135,6 +135,11 @@ void Diagram::addTo( const ShapePtr & pParentShape )
     aChildren.insert(aChildren.begin(), pBackground);
 }
 
+Diagram::Diagram(const ShapePtr& pShape)
+    : mpShape(pShape)
+{
+}
+
 uno::Sequence<beans::PropertyValue> Diagram::getDomsAsPropertyValues() const
 {
     sal_Int32 length = maMainDomMap.size();
@@ -245,7 +250,7 @@ void loadDiagram( ShapePtr const & pShape,
                   const OUString& rColorStylePath,
                   const oox::core::Relations& rRelations )
 {
-    DiagramPtr pDiagram( new Diagram );
+    DiagramPtr pDiagram( new Diagram(pShape) );
 
     DiagramDataPtr pData( new DiagramData() );
     pDiagram->setData( pData );
@@ -365,7 +370,7 @@ void loadDiagram(ShapePtr const& pShape,
                  const uno::Reference<xml::dom::XDocument>& colorDom,
                  core::XmlFilterBase& rFilter)
 {
-    DiagramPtr pDiagram(new Diagram);
+    DiagramPtr pDiagram(new Diagram(pShape));
 
     pDiagram->setData(pDiagramData);
 
diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx
index a674e248961e..5cf562d075fd 100644
--- a/oox/source/drawingml/diagram/diagram.hxx
+++ b/oox/source/drawingml/diagram/diagram.hxx
@@ -49,7 +49,10 @@ typedef std::map<const dgm::Point*, ShapePtr> PresPointShapeMap;
 class DiagramLayout
 {
 public:
-    DiagramLayout(const Diagram& rDgm) : mrDgm(rDgm) {}
+    DiagramLayout(Diagram& rDgm)
+        : mrDgm(rDgm)
+    {
+    }
     void setDefStyle( const OUString & sDefStyle )
         { msDefStyle = sDefStyle; }
     void setMinVer( const OUString & sMinVer )
@@ -60,8 +63,7 @@ public:
         { msTitle = sTitle; }
     void setDesc( const OUString & sDesc )
         { msDesc = sDesc; }
-    const Diagram& getDiagram() const
-        { return mrDgm; }
+    Diagram& getDiagram() { return mrDgm; }
     LayoutNodePtr & getNode()
         { return mpNode; }
     const LayoutNodePtr & getNode() const
@@ -80,7 +82,7 @@ public:
         { return maPresPointShapeMap; }
 
 private:
-    const Diagram& mrDgm;
+    Diagram& mrDgm;
     OUString msDefStyle;
     OUString msMinVer;
     OUString msUniqueId;
@@ -128,6 +130,7 @@ typedef std::map<OUString,DiagramColor> DiagramColorMap;
 class Diagram
 {
 public:
+    explicit Diagram(const ShapePtr& pShape);
     void setData( const DiagramDataPtr & pData )
         { mpData = pData; }
     const DiagramDataPtr& getData() const
@@ -146,7 +149,10 @@ public:
     void addTo( const ShapePtr & pShape );
 
     css::uno::Sequence<css::beans::PropertyValue> getDomsAsPropertyValues() const;
+    ShapePtr getShape() { return mpShape; }
+
 private:
+    ShapePtr mpShape;
     DiagramDataPtr                 mpData;
     DiagramLayoutPtr               mpLayout;
     DiagramQStyleMap               maStyles;
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index 44a66f819e98..6175832a426d 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -217,7 +217,7 @@ namespace
  * Takes the connection list from rLayoutNode, navigates from rFrom on an edge
  * of type nType, using a direction determined by bSourceToDestination.
  */
-OUString navigate(const LayoutNode& rLayoutNode, sal_Int32 nType, const OUString& rFrom,
+OUString navigate(LayoutNode& rLayoutNode, sal_Int32 nType, const OUString& rFrom,
                   bool bSourceToDestination)
 {
     for (const auto& rConnection : rLayoutNode.getDiagram().getData()->getConnections())
@@ -479,6 +479,54 @@ void ApplyConstraintToLayout(const Constraint& rConstraint, LayoutPropertyMap& r
         }
     }
 }
+
+/// Does the first data node of this shape have customized text properties?
+bool HasCustomText(const ShapePtr& rShape, LayoutNode& rLayoutNode)
+{
+    const PresPointShapeMap& rPresPointShapeMap
+        = rLayoutNode.getDiagram().getLayout()->getPresPointShapeMap();
+    const DiagramData::StringMap& rPresOfNameMap
+        = rLayoutNode.getDiagram().getData()->getPresOfNameMap();
+    const DiagramData::PointNameMap& rPointNameMap
+        = rLayoutNode.getDiagram().getData()->getPointNameMap();
+    // Get the first presentation node of the shape.
+    const dgm::Point* pPresNode = nullptr;
+    for (const auto& rPair : rPresPointShapeMap)
+    {
+        if (rPair.second == rShape)
+        {
+            pPresNode = rPair.first;
+            break;
+        }
+    }
+    // Get the first data node of the presentation node.
+    dgm::Point* pDataNode = nullptr;
+    if (pPresNode)
+    {
+        auto itPresToData = rPresOfNameMap.find(pPresNode->msModelId);
+        if (itPresToData != rPresOfNameMap.end())
+        {
+            for (const auto& rPair : itPresToData->second)
+            {
+                const DiagramData::SourceIdAndDepth& rItem = rPair.second;
+                auto it = rPointNameMap.find(rItem.msSourceId);
+                if (it != rPointNameMap.end())
+                {
+                    pDataNode = it->second;
+                    break;
+                }
+            }
+        }
+    }
+
+    // If we have a data node, see if its text is customized or not.
+    if (pDataNode)
+    {
+        return pDataNode->mbCustomText;
+    }
+
+    return false;
+}
 }
 
 void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>& rConstraints,
@@ -649,6 +697,16 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>&
 
                 nVertMin = std::min(aPos.Y, nVertMin);
                 nVertMax = std::max(aPos.Y + aSize.Height, nVertMax);
+
+                NamedShapePairs& rDiagramFontHeights
+                    = getLayoutNode().getDiagram().getShape()->getDiagramFontHeights();
+                auto it = rDiagramFontHeights.find(aCurrShape->getInternalName());
+                if (it != rDiagramFontHeights.end())
+                {
+                    // Internal name matches: put drawingml::Shape to the relevant group, for
+                    // syncronized font height handling.
+                    it->second.insert({ aCurrShape, {} });
+                }
             }
 
             // See if all vertical space is used or we have to center the content.
@@ -943,6 +1001,20 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>&
                     }
                 }
 
+                if (rConstraint.mnType == XML_primFontSz && rConstraint.mnFor == XML_des
+                    && rConstraint.mnOperator == XML_equ)
+                {
+                    NamedShapePairs& rDiagramFontHeights
+                        = getLayoutNode().getDiagram().getShape()->getDiagramFontHeights();
+                    auto it = rDiagramFontHeights.find(rConstraint.msForName);
+                    if (it == rDiagramFontHeights.end())
+                    {
+                        // Start tracking all shapes with this internal name: they'll have the same
+                        // font height.
+                        rDiagramFontHeights[rConstraint.msForName] = {};
+                    }
+                }
+
                 // TODO: get values from differently named constraints as well
                 if (rConstraint.msForName == "sp" || rConstraint.msForName == "space" || rConstraint.msForName == "sibTrans")
                 {
@@ -1429,7 +1501,13 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>&
                         if (!aRun->getTextCharacterProperties().moHeight.has())
                             aRun->getTextCharacterProperties().moHeight = fFontSize * 100;
             }
-            pTextBody->getTextProperties().maPropertyMap.setProperty(PROP_TextFitToSize, drawing::TextFitToSizeType_AUTOFIT);
+
+            if (!HasCustomText(rShape, getLayoutNode()))
+            {
+                // No customized text properties: enable autofit.
+                pTextBody->getTextProperties().maPropertyMap.setProperty(
+                    PROP_TextFitToSize, drawing::TextFitToSizeType_AUTOFIT);
+            }
 
             // ECMA-376-1:2016 21.4.7.5 ST_AutoTextRotation (Auto Text Rotation)
             const sal_Int32 nautoTxRot = maMap.count(XML_autoTxRot) ? maMap.find(XML_autoTxRot)->second : XML_upr;
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
index ab152bed0b70..7789007622dc 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
@@ -260,9 +260,13 @@ class LayoutNode
 public:
     typedef std::map<sal_Int32, OUString> VarMap;
 
-    LayoutNode(const Diagram& rDgm) : LayoutAtom(*this), mrDgm(rDgm), mnChildOrder(0) {}
-    const Diagram& getDiagram() const
-        { return mrDgm; }
+    LayoutNode(Diagram& rDgm)
+        : LayoutAtom(*this)
+        , mrDgm(rDgm)
+        , mnChildOrder(0)
+    {
+    }
+    Diagram& getDiagram() { return mrDgm; }
     virtual void accept( LayoutAtomVisitor& ) override;
     VarMap & variables()
         { return mVariables; }
@@ -289,7 +293,7 @@ public:
     const LayoutNode* getParentLayoutNode() const;
 
 private:
-    const Diagram&               mrDgm;
+    Diagram& mrDgm;
     VarMap                       mVariables;
     OUString                     msMoveWith;
     OUString                     msStyleLabel;
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 2e100a41c309..84e59293b335 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -190,6 +190,7 @@ Shape::Shape( const ShapePtr& pSourceShape )
 , mnDataNodeType(pSourceShape->mnDataNodeType)
 , mfAspectRatio(pSourceShape->mfAspectRatio)
 , mbUseBgFill(pSourceShape->mbUseBgFill)
+, maDiagramFontHeights(pSourceShape->maDiagramFontHeights)
 {}
 
 Shape::~Shape()
@@ -300,6 +301,22 @@ void Shape::addShape(
                 if( !SvtFilterOptions::Get().IsSmartArt2Shape() )
                     convertSmartArtToMetafile( rFilterBase );
             }
+
+            NamedShapePairs* pNamedShapePairs = rFilterBase.getDiagramFontHeights();
+            if (xShape.is() && pNamedShapePairs)
+            {
+                auto itPairs = pNamedShapePairs->find(getInternalName());
+                if (itPairs != pNamedShapePairs->end())
+                {
+                    auto it = itPairs->second.find(shared_from_this());
+                    if (it != itPairs->second.end())
+                    {
+                        // Our drawingml::Shape is in the list of an internal name, remember the now
+                        // inserted XShape.
+                        it->second = xShape;
+                    }
+                }
+            }
         }
     }
     catch( const Exception& )
@@ -1528,6 +1545,44 @@ void Shape::keepDiagramCompatibilityInfo()
     }
 }
 
+void Shape::syncDiagramFontHeights()
+{
+    // Each name represents a group of shapes, for which the font height should have the same
+    // scaling.
+    for (const auto& rNameAndPairs : maDiagramFontHeights)
+    {
+        // Find out the minimum scale within this group.
+        const ShapePairs& rShapePairs = rNameAndPairs.second;
+        sal_Int16 nMinScale = 100;
+        for (const auto& rShapePair : rShapePairs)
+        {
+            uno::Reference<beans::XPropertySet> xPropertySet(rShapePair.second, uno::UNO_QUERY);
+            if (xPropertySet.is())
+            {
+                sal_Int16 nTextFitToSizeScale = 0;
+                xPropertySet->getPropertyValue("TextFitToSizeScale") >>= nTextFitToSizeScale;
+                if (nTextFitToSizeScale > 0 && nTextFitToSizeScale < nMinScale)
+                {
+                    nMinScale = nTextFitToSizeScale;
+                }
+            }
+        }
+
+        // Set that minimum scale for all members of the group.
+        if (nMinScale < 100)
+        {
+            for (const auto& rShapePair : rShapePairs)
+            {
+                uno::Reference<beans::XPropertySet> xPropertySet(rShapePair.second, uno::UNO_QUERY);
+                if (xPropertySet.is())
+                {
+                    xPropertySet->setPropertyValue("TextFitToSizeScale", uno::makeAny(nMinScale));
+                }
+            }
+        }
+    }
+}
+
 void Shape::convertSmartArtToMetafile(XmlFilterBase const & rFilterBase)
 {
     try
diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx
index 88277219d0b0..71b94c727132 100644
--- a/oox/source/ppt/pptshape.cxx
+++ b/oox/source/ppt/pptshape.cxx
@@ -411,10 +411,23 @@ void PPTShape::addShape(
             // if this is a group shape, we have to add also each child shape
             Reference<XShapes> xShapes(xShape, UNO_QUERY);
             if (xShapes.is())
+            {
+                if (meFrameType == FRAMETYPE_DIAGRAM)
+                {
+                    rFilterBase.setDiagramFontHeights(&getDiagramFontHeights());
+                }
                 addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aTransformation );
+                if (meFrameType == FRAMETYPE_DIAGRAM)
+                {
+                    rFilterBase.setDiagramFontHeights(nullptr);
+                }
+            }
 
             if (meFrameType == FRAMETYPE_DIAGRAM)
+            {
                 keepDiagramCompatibilityInfo();
+                syncDiagramFontHeights();
+            }
         }
     }
     catch (const Exception&)
diff --git a/svx/source/svdraw/svdattr.cxx b/svx/source/svdraw/svdattr.cxx
index 31cf34a76c73..1eb98121a203 100644
--- a/svx/source/svdraw/svdattr.cxx
+++ b/svx/source/svdraw/svdattr.cxx
@@ -939,6 +939,16 @@ SfxPoolItem* SdrTextFitToSizeTypeItem::CreateDefault() { return new SdrTextFitTo
 
 SfxPoolItem* SdrTextFitToSizeTypeItem::Clone(SfxItemPool* /*pPool*/) const         { return new SdrTextFitToSizeTypeItem(*this); }
 
+bool SdrTextFitToSizeTypeItem::operator==(const SfxPoolItem& rItem) const
+{
+    if (!SfxEnumItem<css::drawing::TextFitToSizeType>::operator==(rItem))
+    {
+        return false;
+    }
+
+    return m_nMaxScale == static_cast<const SdrTextFitToSizeTypeItem&>(rItem).m_nMaxScale;
+}
+
 sal_uInt16 SdrTextFitToSizeTypeItem::GetValueCount() const { return 4; }
 
 OUString SdrTextFitToSizeTypeItem::GetValueTextByPos(sal_uInt16 nPos)
diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx
index 4ce65ca33f61..3df06ba3bfb2 100644
--- a/svx/source/svdraw/svdotext.cxx
+++ b/svx/source/svdraw/svdotext.cxx
@@ -1277,7 +1277,8 @@ void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const
                     IsVerticalWriting() );
 }
 
-void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner, const Size& rTextSize, bool bIsVerticalWriting )
+void SdrTextObj::ImpAutoFitText(SdrOutliner& rOutliner, const Size& rTextSize,
+                                bool bIsVerticalWriting) const
 {
     // EditEngine formatting is unstable enough for
     // line-breaking text that we need some more samples
@@ -1333,6 +1334,13 @@ void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner, const Size& rTextSize,
         }
     }
 
+    const SdrTextFitToSizeTypeItem& rItem = GetObjectItem(SDRATTR_TEXT_FITTOSIZE);
+    if (rItem.GetMaxScale() > 0)
+    {
+        nMinStretchX = std::min<sal_uInt16>(rItem.GetMaxScale(), nMinStretchX);
+        nMinStretchY = std::min<sal_uInt16>(rItem.GetMaxScale(), nMinStretchY);
+    }
+
     SAL_INFO("svx", "final zoom is " << nMinStretchX);
     rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nMinStretchX),
                                       std::min(sal_uInt16(100),nMinStretchY));
diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx
index 3f07f5ab9a82..9ab31b26dfa0 100644
--- a/svx/source/unodraw/unoshape.cxx
+++ b/svx/source/unodraw/unoshape.cxx
@@ -93,6 +93,8 @@
 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
 
 #include <vcl/wmf.hxx>
+#include <svx/sdtfsitm.hxx>
+#include <svx/svdoutl.hxx>
 
 #include <memory>
 #include <vector>
@@ -174,6 +176,35 @@ protected:
     }
 };
 
+namespace
+{
+/// Calculates what scaling factor will be used for autofit text scaling of this shape.
+sal_Int16 GetTextFitToSizeScale(SdrObject* pObject)
+{
+    SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(pObject);
+    if (!pTextObj)
+    {
+        return 0;
+    }
+
+    const SfxItemSet& rTextObjSet = pTextObj->GetMergedItemSet();
+    if (rTextObjSet.GetItem<SdrTextFitToSizeTypeItem>(SDRATTR_TEXT_FITTOSIZE)->GetValue()
+        != drawing::TextFitToSizeType_AUTOFIT)
+    {
+        return 0;
+    }
+
+    std::unique_ptr<SdrOutliner> pOutliner
+        = pTextObj->getSdrModelFromSdrObject().createOutliner(OutlinerMode::TextObject);
+    tools::Rectangle aBoundRect(pTextObj->GetCurrentBoundRect());
+    pTextObj->SetupOutlinerFormatting(*pOutliner, aBoundRect);
+    sal_uInt16 nX = 0;
+    sal_uInt16 nY = 0;
+    pOutliner->GetGlobalCharStretching(nX, nY);
+    return nY;
+}
+}
+
 SvxShape::SvxShape( SdrObject* pObject )
 :   maSize(100,100)
 ,   mpImpl( new SvxShapeImpl( *this, maMutex ) )
@@ -2389,6 +2420,19 @@ bool SvxShape::setPropertyValueImpl( const OUString&, const SfxItemPropertySimpl
         break;
     }
 
+    case OWN_ATTR_TEXTFITTOSIZESCALE:
+    {
+        sal_Int16 nMaxScale = 0;
+        if (rValue >>= nMaxScale)
+        {
+            SdrTextFitToSizeTypeItem aItem(GetSdrObject()->GetMergedItem(SDRATTR_TEXT_FITTOSIZE));
+            aItem.SetMaxScale(nMaxScale);
+            GetSdrObject()->SetMergedItem(aItem);
+            return true;
+        }
+        break;
+    }
+
     // #i68101#
     case OWN_ATTR_MISC_OBJ_TITLE:
     {
@@ -2838,6 +2882,12 @@ bool SvxShape::getPropertyValueImpl( const OUString&, const SfxItemPropertySimpl
         break;
     }
 
+    case OWN_ATTR_TEXTFITTOSIZESCALE:
+    {
+        rValue <<= GetTextFitToSizeScale(GetSdrObject());
+        break;
+    }
+
     case OWN_ATTR_UINAME_PLURAL:
     {
         rValue <<= GetSdrObject()->TakeObjNamePlural();
-- 
2.26.2

openSUSE Build Service is sponsored by