chart2/qa/extras/chart2export.cxx            |   14 
 chart2/qa/extras/chart2export2.cxx           |    2 
 chart2/qa/extras/charttest.hxx               |   13 
 chart2/qa/extras/data/xlsx/column-style.xlsx |binary
 docmodel/source/uno/UnoChartStyle.cxx        |   11 
 include/docmodel/styles/ChartStyle.hxx       |   60 +-
 include/docmodel/uno/UnoChartStyle.hxx       |    2 
 include/oox/export/ThemeExport.hxx           |    5 
 include/oox/export/chartexport.hxx           |   12 
 include/oox/export/drawingml.hxx             |   32 +
 oox/inc/drawingml/chart/stylefragment.hxx    |    6 
 oox/inc/drawingml/chart/stylemodel.hxx       |    4 
 oox/source/drawingml/chart/stylefragment.cxx |   10 
 oox/source/drawingml/chart/stylemodel.cxx    |    5 
 oox/source/drawingml/shape.cxx               |   34 +
 oox/source/export/ThemeExport.cxx            |    4 
 oox/source/export/chartexport.cxx            |  601 ++++++++++++++++----------
 oox/source/export/drawingml.cxx              |  610 +++++++++++++--------------
 test/source/xmltesttools.cxx                 |    2 
 19 files changed, 846 insertions(+), 581 deletions(-)

New commits:
commit 526287a4aa7fe06bcfaa8fedc26106bd1a87fc88
Author:     Kurt Nordback <[email protected]>
AuthorDate: Thu Sep 4 06:46:27 2025 -0600
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Thu Dec 18 01:45:59 2025 +0100

    tdf#167941 - Chart style file is not supported in OOXML
    
    Implement chart style file export, beginning to use the document
    model data rather than hard-coded text. Also add a simple test
    that style data round-trips OOXML -> LO -> OOXML properly.
    
    This uses oox structures in docmodel. That will be fixed in a
    subsequent commit.
    
    Change-Id: Icc0ef5b212cc32c8c84b51529bc4cf05ab54636c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190586
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195578
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/chart2/qa/extras/chart2export.cxx 
b/chart2/qa/extras/chart2export.cxx
index 291f87586b9f..55f597dbe2f3 100644
--- a/chart2/qa/extras/chart2export.cxx
+++ b/chart2/qa/extras/chart2export.cxx
@@ -1396,6 +1396,20 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest, 
testInvertNegative)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testStyleImportExport)
+{
+    // column-style.xlsx is a hand-edited test that includes an axisTitle style
+    // with run property text size 777 (chosen simply as a distinctive number).
+    // Test that this value round-trips successfully.
+    loadFromFile(std::u16string_view(u"xlsx/column-style.xlsx"));
+
+    save("Calc Office Open XML");
+    xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/style1.xml");
+    CPPUNIT_ASSERT(pXmlDoc);
+    assertXPath(pXmlDoc, "/cs:chartStyle");
+    assertXPath(pXmlDoc, "/cs:chartStyle/cs:axisTitle");
+    assertXPath(pXmlDoc, "/cs:chartStyle/cs:axisTitle/a:defRPr", "sz", 
std::u16string_view(u"777"));
+}
 
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/chart2/qa/extras/chart2export2.cxx 
b/chart2/qa/extras/chart2export2.cxx
index d4881a353a59..95b03c2b4331 100644
--- a/chart2/qa/extras/chart2export2.cxx
+++ b/chart2/qa/extras/chart2export2.cxx
@@ -963,7 +963,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, test_style)
     xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chart1.xml"_ustr);
     CPPUNIT_ASSERT(pXmlDoc);
     // workaround: use leave-gap instead of zero to show the original line 
chart
-    assertXPath(pXmlDoc, "/c:chartSpace/c:style", "val", u"23");
+    assertXPath(pXmlDoc, "/c:chartSpace/c:style", "val", u"36");
 }
 
 CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCustomLabelText)
diff --git a/chart2/qa/extras/charttest.hxx b/chart2/qa/extras/charttest.hxx
index 696e3c7ab164..a8edb86bbde9 100644
--- a/chart2/qa/extras/charttest.hxx
+++ b/chart2/qa/extras/charttest.hxx
@@ -109,6 +109,8 @@ public:
     getShapeByName(const uno::Reference<drawing::XShapes>& rShapes, const 
OUString& rName,
                    const std::function<bool(const 
uno::Reference<drawing::XShape>&)>& pCondition
                    = nullptr);
+    Reference<chart2::XChartStyle>
+        getStyleFromDoc(Reference<chart2::XChartDocument> const& xChartDoc);
 };
 
 Reference< lang::XComponent > ChartTest::getChartCompFromSheet( sal_Int32 
nSheet, sal_Int32 nChart )
@@ -507,4 +509,15 @@ ChartTest::getShapeByName(const 
uno::Reference<drawing::XShapes>& rShapes, const
     return uno::Reference<drawing::XShape>();
 }
 
+Reference<chart2::XChartStyle>
+    getStyleFromDoc(Reference<chart2::XChartDocument> const& xChartDoc)
+{
+    CPPUNIT_ASSERT( xChartDoc.is() );
+
+    Reference <chart2::XChartStyle > xStyle = xChartDoc->getStyles();
+    CPPUNIT_ASSERT( xStyle.is() );
+
+    return xStyle;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/data/xlsx/column-style.xlsx 
b/chart2/qa/extras/data/xlsx/column-style.xlsx
index 95da9c97caa8..be9e29050d11 100644
Binary files a/chart2/qa/extras/data/xlsx/column-style.xlsx and 
b/chart2/qa/extras/data/xlsx/column-style.xlsx differ
diff --git a/docmodel/source/uno/UnoChartStyle.cxx 
b/docmodel/source/uno/UnoChartStyle.cxx
index 8aeb5cb52b99..d7e9b5019b63 100644
--- a/docmodel/source/uno/UnoChartStyle.cxx
+++ b/docmodel/source/uno/UnoChartStyle.cxx
@@ -20,15 +20,18 @@ uno::Reference<chart2::XChartStyle> 
createXChartStyle(model::StyleSet const& rSt
     return new UnoChartStyle(rStyle);
 }
 
-model::StyleSet getFromXChartStyle(uno::Reference<chart2::XChartStyle> const& 
rxStyle)
+model::StyleSet* getFromXChartStyle(uno::Reference<chart2::XChartStyle> const& 
rxStyle)
 {
-    model::StyleSet aChartStyle;
     UnoChartStyle* pUnoChartStyle = static_cast<UnoChartStyle*>(rxStyle.get());
+
     if (pUnoChartStyle)
     {
-        aChartStyle = pUnoChartStyle->getChartStyle();
+        return &pUnoChartStyle->getChartStyle();
+    }
+    else
+    {
+        return nullptr;
     }
-    return aChartStyle;
 }
 
 } // end model::style
diff --git a/include/docmodel/styles/ChartStyle.hxx 
b/include/docmodel/styles/ChartStyle.hxx
index e455e6e37b1f..18fffdc6b6e9 100644
--- a/include/docmodel/styles/ChartStyle.hxx
+++ b/include/docmodel/styles/ChartStyle.hxx
@@ -19,8 +19,10 @@
 
 namespace model
 {
-struct StyleColor
+struct FontOrStyleRef
 {
+    sal_Int32 mnIdx; // required
+
     enum class StyleColorEnum
     {
         AUTO
@@ -28,32 +30,56 @@ struct StyleColor
 
     // The schema uses 'union' here. Implement with a std::variant for safety.
     using StyleColorVal = std::variant<sal_uInt32, enum StyleColorEnum, 
OUString>;
-    typedef std::vector<StyleColorVal> StyleColorVec;
+    std::unique_ptr<StyleColorVal> maStyleClr; // optional
+
+    // Get a string version of the ColorVal, for output/streaming
+    OUString getColorValStr() const
+    {
+        OUString sV;
+
+        if (maStyleClr)
+        {
+            switch (maStyleClr->index())
+            {
+                case 0: // sal_uInt32, a raw color value
+                    sV = OUString::number(std::get<0>(*maStyleClr));
+                    break;
+                case 1: // enum; only value "auto"
+                    sV = "auto";
+                    break;
+                case 2: // arbitrary string
+                    sV = std::get<2>(*maStyleClr);
+                    break;
+            }
+        }
+        return sV;
+    }
 
-    StyleColorVec maStyleClr;
-    sal_Int32 mnIdx;
-    oox::drawingml::Color maColor;
-    model::ComplexColor maComplexColor;
+    // A child element of cs:CT_FontReference or cs:CT_StyleReference is
+    // a:EG_ColorChoice. The latter is handled by ColorValueContext.
+    oox::drawingml::Color maColor; // needed for ColorValueContext
+    model::ComplexColor maComplexColor; // needed for ColorValueContext
     // There's also an a:EG_ColorTransform member and a 'mods' member for
-    // StyleColor. Ignore those for now. TODO
+    // FontOrStyleRef. Ignore those for now. TODO
 };
 
 struct StyleEntry
 {
-    std::shared_ptr<StyleColor> mxLnClr;
+    std::shared_ptr<FontOrStyleRef> mxLnClr;
     double mfLineWidthScale = 1.0;
-    std::shared_ptr<StyleColor> mxFillClr;
-    std::shared_ptr<StyleColor> mxEffectClr;
-    std::shared_ptr<StyleColor> mxFontClr;
+    std::shared_ptr<FontOrStyleRef> mxFillClr;
+    std::shared_ptr<FontOrStyleRef> mxEffectClr;
+    std::shared_ptr<FontOrStyleRef> mxFontClr;
     std::shared_ptr<oox::drawingml::Shape> mxShapePr;
     // The following is derived from a TextCharacterProperties
     std::shared_ptr<oox::PropertyMap> mrTextCharacterPr;
     // The following is derived from a TextBodyProperties
     std::shared_ptr<oox::PropertyMap> mxTextBodyPr;
 
-    StyleEntry(std::shared_ptr<StyleColor> aLnClr, double fLineScale,
-               std::shared_ptr<StyleColor> aFillClr, 
std::shared_ptr<StyleColor> aEffectClr,
-               std::shared_ptr<StyleColor> aFontClr, 
std::shared_ptr<oox::drawingml::Shape> aShape,
+    StyleEntry(std::shared_ptr<FontOrStyleRef> aLnClr, double fLineScale,
+               std::shared_ptr<FontOrStyleRef> aFillClr, 
std::shared_ptr<FontOrStyleRef> aEffectClr,
+               std::shared_ptr<FontOrStyleRef> aFontClr,
+               std::shared_ptr<oox::drawingml::Shape> aShape,
                std::shared_ptr<oox::PropertyMap> aCharProps,
                std::shared_ptr<oox::PropertyMap> aBodyProps)
         : mxLnClr(aLnClr)
@@ -72,7 +98,8 @@ struct DOCMODEL_DLLPUBLIC StyleSet
 {
     enum class StyleEntryType
     {
-        AXISTITLE,
+        BEGIN = 0, // for iteration
+        AXISTITLE = BEGIN,
         CATEGORYAXIS,
         CHARTAREA,
         DATALABEL,
@@ -102,7 +129,8 @@ struct DOCMODEL_DLLPUBLIC StyleSet
         TRENDLINELABEL,
         UPBAR,
         VALUEAXIS,
-        WALL
+        WALL,
+        END // for iteration
     };
 
     std::map<enum StyleEntryType, StyleEntry> maEntryMap;
diff --git a/include/docmodel/uno/UnoChartStyle.hxx 
b/include/docmodel/uno/UnoChartStyle.hxx
index 91588a985c9d..45bb26811ba8 100644
--- a/include/docmodel/uno/UnoChartStyle.hxx
+++ b/include/docmodel/uno/UnoChartStyle.hxx
@@ -47,7 +47,7 @@ namespace model::style
 {
 DOCMODEL_DLLPUBLIC css::uno::Reference<css::chart2::XChartStyle>
 createXChartStyle(model::StyleSet const& rStyle);
-DOCMODEL_DLLPUBLIC model::StyleSet
+DOCMODEL_DLLPUBLIC model::StyleSet*
 getFromXChartStyle(css::uno::Reference<css::chart2::XChartStyle> const& 
rxStyle);
 }
 
diff --git a/include/oox/export/ThemeExport.hxx 
b/include/oox/export/ThemeExport.hxx
index c220d2d3037d..91c4b57ad8e8 100644
--- a/include/oox/export/ThemeExport.hxx
+++ b/include/oox/export/ThemeExport.hxx
@@ -40,9 +40,11 @@ private:
     sax_fastparser::FSHelperPtr mpFS;
 
 public:
-    ThemeExport(oox::core::XmlFilterBase* pFilterBase, 
oox::drawingml::DocumentType eDocumentType);
+    ThemeExport(oox::core::XmlFilterBase* pFilterBase, 
oox::drawingml::DocumentType eDocumentType,
+                sax_fastparser::FSHelperPtr pFS = nullptr);
 
     void write(OUString const& rPath, model::Theme const& rTheme);
+    void writeComplexColor(model::ComplexColor const& rComplexColor);
 
 private:
     bool writeColorSet(model::Theme const& rTheme);
@@ -58,7 +60,6 @@ private:
     void writePatternFill(model::PatternFill const& rPatternFill);
     void writeGradientFill(model::GradientFill const& rGradientFill);
     void writeSolidFill(model::SolidFill const& rSolidFill);
-    void writeComplexColor(model::ComplexColor const& rComplexColor);
     void writeColorPlaceholder(model::ComplexColor const& rComplexColor);
     void writeColorSystem(model::ComplexColor const& rComplexColor);
     void writeColorTheme(model::ComplexColor const& rComplexColor);
diff --git a/include/oox/export/chartexport.hxx 
b/include/oox/export/chartexport.hxx
index a4821b467434..4201bfab8997 100644
--- a/include/oox/export/chartexport.hxx
+++ b/include/oox/export/chartexport.hxx
@@ -69,6 +69,11 @@ namespace core {
     class XmlFilterBase;
 }}
 
+namespace model {
+    struct FontOrStyleRef;
+    struct StyleEntry;
+}
+
 namespace oox::drawingml {
 
 struct LabelPlacementParam;
@@ -237,7 +242,7 @@ private:
     void exportSeriesValues(
         const css::uno::Reference< css::chart2::data::XDataSequence >& 
xValueSeq, sal_Int32 nValueType = XML_val );
     void exportShapeProps( const css::uno::Reference< css::beans::XPropertySet 
>& xPropSet,
-            bool bIsChartex);
+            sal_Int32 nNS);
     void exportDataPoints(
         const css::uno::Reference< css::beans::XPropertySet >& 
xSeriesProperties,
         sal_Int32 nSeriesLength, sal_Int32 eChartType );
@@ -288,6 +293,11 @@ private:
         const css::uno::Reference<css::beans::XPropertySet>& xPropSet, const 
LabelPlacementParam& rLabelParam,
         sal_Int32 nLabelIndex, DataLabelsRange& rDLblsRange,
         bool bIsChartex);
+    // Functions for style file output
+    void outputStyleEntry(::sax_fastparser::FSHelperPtr pFS,
+            sal_Int32 nElTokenId, model::StyleEntry& aEntry);
+    void outputFontOrStyleRef(::sax_fastparser::FSHelperPtr pFS,
+            sal_Int32 nElTokenId, const model::FontOrStyleRef& aColor);
 
 public:
 
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index d398f836b95f..0cfe1cc34763 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -50,6 +50,8 @@
 #include <vcl/mapmod.hxx>
 #include <svx/EnhancedCustomShape2d.hxx>
 #include <basegfx/utils/bgradient.hxx>
+#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
+
 
 class Graphic;
 class SdrObjCustomShape;
@@ -291,6 +293,28 @@ struct WriteRunInput
     css::uno::Reference<css::beans::XPropertySet> xShapePropSet;
 };
 
+struct WriteBodyPropsInput
+{
+    bool bIsFontworkShape = false;
+    bool bHasWrap = false;
+    bool bWrap = false;
+    bool bFromWordArt = false;
+    sal_Int32 nTop = 0;
+    sal_Int32 nBottom = 0;
+    sal_Int32 nLeft = 0;
+    sal_Int32 nRight = 0;
+    std::optional<OUString> sHorzOverflow;
+    std::optional<OUString> sVertOverflow;
+    const char *sAnchor = nullptr;
+    bool bAnchorCtr = false;
+    std::optional<OString> sWritingMode;
+    std::optional<OString> sIsUpright;
+    std::optional<OString> sTextRotateAngleMSUnit;
+    css::uno::Sequence<css::drawing::EnhancedCustomShapeAdjustmentValue> 
aAdjustmentSeq;
+    OUString sPresetWarp;
+    OUString sMSWordPresetTextWarp;
+};
+
 class DrawingML
 {
 
@@ -303,6 +327,8 @@ private:
     /// Parent exporter, used for text callback.
     DMLTextExport* mpTextExport;
 
+    static constexpr const sal_Int32 mconstDefaultLeftRightInset = 254;
+    static constexpr const sal_Int32 mconstDefaultTopBottomInset = 127;
 
 protected:
     css::uno::Any                             mAny;
@@ -470,6 +496,12 @@ public:
                        bool& rbOverridingCharHeight, sal_Int32& rnCharHeight,
                        const css::uno::Reference<css::beans::XPropertySet>& 
rXShapePropSet,
                        sal_Int32 nElement);
+    void WriteBodyProps(
+            const css::uno::Reference< css::uno::XInterface >& rXIface,
+            const css::uno::Reference<css::beans::XPropertySet>& rXPropSet,
+            const css::uno::Reference<css::drawing::XShape>& xShape,
+            sal_Int32 nXmlNamespace, const WriteBodyPropsInput& aWBPInput);
+
     /** Populates the lstStyle with the shape's text run and paragraph 
properties */
     void WriteLstStyles(const css::uno::Reference<css::text::XTextContent>& 
rParagraph,
                        bool& rbOverridingCharHeight, sal_Int32& rnCharHeight,
diff --git a/oox/inc/drawingml/chart/stylefragment.hxx 
b/oox/inc/drawingml/chart/stylefragment.hxx
index aff1f59f870c..a7bb698a43e2 100644
--- a/oox/inc/drawingml/chart/stylefragment.hxx
+++ b/oox/inc/drawingml/chart/stylefragment.hxx
@@ -23,18 +23,18 @@
 
 namespace model
 {
-struct StyleColor;
+struct FontOrStyleRef;
 }
 
 namespace oox::drawingml::chart
 {
 /** Handler for a cs:CT_StyleReference or cs:CT_FontReference element.
  */
-class StyleReferenceContext final : public ContextBase<model::StyleColor>
+class StyleReferenceContext final : public ContextBase<model::FontOrStyleRef>
 {
 public:
     StyleReferenceContext(ContextHandler2Helper& rParent, sal_Int32 nIdx,
-                          model::StyleColor& rModel);
+                          model::FontOrStyleRef& rModel);
     virtual ~StyleReferenceContext() override;
 
     virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement,
diff --git a/oox/inc/drawingml/chart/stylemodel.hxx 
b/oox/inc/drawingml/chart/stylemodel.hxx
index d0c1bc92e82f..ce8c2c8e64d6 100644
--- a/oox/inc/drawingml/chart/stylemodel.hxx
+++ b/oox/inc/drawingml/chart/stylemodel.hxx
@@ -28,8 +28,8 @@ namespace oox::drawingml::chart
 // model for both.
 struct StyleEntryModel
 {
-    typedef ModelRef<model::StyleColor> StyleRef; // "idx" is 
ST_StyleMatrixColumnIndex
-    typedef ModelRef<model::StyleColor> FontRef; // "idx" is 
ST_FontCollectionIndex
+    typedef ModelRef<model::FontOrStyleRef> StyleRef; // "idx" is 
ST_StyleMatrixColumnIndex
+    typedef ModelRef<model::FontOrStyleRef> FontRef; // "idx" is 
ST_FontCollectionIndex
     typedef ModelRef<TextCharacterProperties> TextCharacterPropsRef;
     typedef ModelRef<TextBodyProperties> TextBodyPropsRef;
     typedef ModelRef<Shape> ShapeRef;
diff --git a/oox/source/drawingml/chart/stylefragment.cxx 
b/oox/source/drawingml/chart/stylefragment.cxx
index 562fe27bda31..a353ce445d91 100644
--- a/oox/source/drawingml/chart/stylefragment.cxx
+++ b/oox/source/drawingml/chart/stylefragment.cxx
@@ -43,8 +43,8 @@ using namespace model;
 // StyleReferenceContext
 //=======
 StyleReferenceContext::StyleReferenceContext(ContextHandler2Helper& rParent, 
sal_Int32 nIdx,
-                                             model::StyleColor& rModel)
-    : ContextBase<StyleColor>(rParent, rModel)
+                                             model::FontOrStyleRef& rModel)
+    : ContextBase<FontOrStyleRef>(rParent, rModel)
 {
     mrModel.mnIdx = nIdx;
 }
@@ -75,7 +75,7 @@ ContextHandlerRef 
StyleReferenceContext::onCreateContext(sal_Int32 nElement,
                 std::optional<OUString> str = rAttribs.getString(XML_val);
                 if (str)
                 {
-                    StyleColor::StyleColorVal v;
+                    FontOrStyleRef::StyleColorVal v;
 
                     const sal_Unicode* pRawStr = str->getStr();
                     std::wstring sBStr;
@@ -96,14 +96,14 @@ ContextHandlerRef 
StyleReferenceContext::onCreateContext(sal_Int32 nElement,
                         // Not an integer, so see if it's the fixed enum
                         if (*str == "auto")
                         {
-                            v = StyleColor::StyleColorEnum::AUTO;
+                            v = FontOrStyleRef::StyleColorEnum::AUTO;
                         }
                         else
                         {
                             v = *str;
                         }
                     }
-                    mrModel.maStyleClr.push_back(v);
+                    mrModel.maStyleClr = 
std::make_unique<FontOrStyleRef::StyleColorVal>(v);
                 }
                 return nullptr;
             }
diff --git a/oox/source/drawingml/chart/stylemodel.cxx 
b/oox/source/drawingml/chart/stylemodel.cxx
index c72c8391179a..ddfb24d9c35d 100644
--- a/oox/source/drawingml/chart/stylemodel.cxx
+++ b/oox/source/drawingml/chart/stylemodel.cxx
@@ -35,11 +35,12 @@ model::StyleEntry 
StyleEntryModel::toStyleEntry(oox::core::XmlFilterBase& rFilte
     // which can be set using pushTextDistances(). I'm not sure why the
     // interfaces are different, but that's why what's below is not parallel to
     // the above.
-    std::shared_ptr<PropertyMap> aBodyMap = std::make_shared<PropertyMap>();
+    std::shared_ptr<PropertyMap> aBodyMap;
     if (mxBodyPr)
     {
         mxBodyPr->pushTextDistances(Size(0, 0));
-        aBodyMap.reset(&mxBodyPr->maPropertyMap);
+        // Deep copy mxBodyPr->maPropertyMap so the shared_ptr can have 
ownership
+        aBodyMap = std::make_shared<PropertyMap>(mxBodyPr->maPropertyMap);
     }
 
     return model::StyleEntry(mxLnRef, mfLineWidthScale, mxFillRef, 
mxEffectRef, mxFontRef,
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 59f86ec73732..7afa155c976c 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -2634,11 +2634,31 @@ void Shape::finalizeXShape( XmlFilterBase& rFilter, 
const Reference< XShapes >&
                         rFilter, mxChartShapeInfo->maFragmentPath, aModel );
                 rFilter.importFragment( pChartSpaceFragment );
 
-                // Import styles file
+                // Import styles file.
+                // Create the styles path from the path to the chart*.xml file
                 sal_Int32 nLastSlash = 
mxChartShapeInfo->maFragmentPath.lastIndexOf('/');
                 const sal_Unicode *pFPath = 
mxChartShapeInfo->maFragmentPath.getStr();
                 OUString sStylePath(pFPath, nLastSlash + 1);
-                sStylePath += u"style1.xml"_ustr;
+                OUString sFullPath(pFPath);
+                sStylePath += u"style"_ustr;
+                OUString sChartFName(sFullPath.copy(nLastSlash + 1, 
sFullPath.getLength() - nLastSlash - 1));
+                OUString sTail;
+                // Verify that the path is the way we expect it, and extract 
the
+                // end bit. Don't put the startsWith() call inside an assert,
+                // because we don't want it optimized away.
+                const bool bWellFormed = 
sChartFName.startsWith(std::u16string_view(u"chart"), &sTail);
+                if (!bWellFormed) {
+                    assert(false);
+                }
+                // We should have something of the form 'chart1234.xml'. We
+                // want to get the numeric ('1234') part, since it should be
+                // the same for the style file.
+                sal_Int32 nPeriod = sTail.indexOf('.');
+                OUString sNumber(sTail.copy(0, nPeriod));
+
+                sStylePath += sNumber;
+                sStylePath += u".xml"_ustr;
+
                 chart::StyleModel aStyleModel;
                 rtl::Reference<chart::StyleFragment> pStyleFragment = new 
chart::StyleFragment(
                         rFilter, sStylePath, aStyleModel );
@@ -2690,14 +2710,8 @@ void Shape::finalizeXShape( XmlFilterBase& rFilter, 
const Reference< XShapes >&
                 }
 
                 // convert chart style model to docmodel style data
-                std::unique_ptr<chart::ChartStyleConverter> pChartStyleConv = 
std::make_unique<chart::ChartStyleConverter>();
-
-                if (pChartStyleConv) {
-                    Reference<com::sun::star::chart2::XChartStyle> xStyle = 
xChartDoc->getStyles();
-                    
oox::drawingml::chart::ChartStyleConverter::convertFromModel(rFilter, 
aStyleModel, xStyle);
-
-
-                }
+                Reference<com::sun::star::chart2::XChartStyle> xStyle = 
xChartDoc->getStyles();
+                
oox::drawingml::chart::ChartStyleConverter::convertFromModel(rFilter, 
aStyleModel, xStyle);
 
                 if (pPowerPointImport)
                 {
diff --git a/oox/source/export/ThemeExport.cxx 
b/oox/source/export/ThemeExport.cxx
index 069b38b090dd..64a0d9b5155a 100644
--- a/oox/source/export/ThemeExport.cxx
+++ b/oox/source/export/ThemeExport.cxx
@@ -38,9 +38,11 @@ void writeRelativeRectangle(sax_fastparser::FSHelperPtr pFS, 
sal_Int32 nToken,
 } // end anonymous namespace
 
 ThemeExport::ThemeExport(oox::core::XmlFilterBase* pFilterBase,
-                         oox::drawingml::DocumentType eDocumentType)
+                         oox::drawingml::DocumentType eDocumentType,
+                         sax_fastparser::FSHelperPtr pFS)
     : mpFilterBase(pFilterBase)
     , meDocumentType(eDocumentType)
+    , mpFS(pFS)
 {
 }
 
diff --git a/oox/source/export/chartexport.cxx 
b/oox/source/export/chartexport.cxx
index 4f72421f14e1..4aae477e7052 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -115,6 +115,11 @@
 #include <o3tl/temporary.hxx>
 #include <o3tl/sorted_vector.hxx>
 
+#include <docmodel/styles/ChartStyle.hxx>
+#include <docmodel/uno/UnoChartStyle.hxx>
+
+#include <oox/export/ThemeExport.hxx>
+
 using namespace css;
 using namespace css::uno;
 using namespace css::drawing;
@@ -162,75 +167,6 @@ private:
     OUString m_aRole;
 };
 
-void outputStyleEntry(FSHelperPtr pFS, sal_Int32 nElTokenId)
-{
-    // Just default values for now
-    pFS->startElement(FSNS(XML_cs, nElTokenId));
-    pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0");
-    pFS->singleElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0");
-    pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0");
-    pFS->singleElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor");
-    pFS->endElement(FSNS(XML_cs, nElTokenId));
-}
-
-void outputChartAreaStyleEntry(FSHelperPtr pFS)
-{
-    // Just default values for now
-    pFS->startElement(FSNS(XML_cs, XML_chartArea), XML_mods, 
"allowNoFillOverride allowNoLineOverride");
-    pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0");
-    pFS->singleElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0");
-    pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0");
-
-    pFS->startElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor");
-    pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "tx1");
-    pFS->endElement(FSNS(XML_cs, XML_fontRef));
-
-    pFS->startElement(FSNS(XML_cs, XML_spPr));
-
-    pFS->startElement(FSNS(XML_a, XML_solidFill));
-    pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "bg1");
-    pFS->endElement(FSNS(XML_a, XML_solidFill));
-
-    pFS->startElement(FSNS(XML_a, XML_ln), XML_w, "9525", XML_cap, "flat",
-            XML_cmpd, "sng", XML_algn, "ctr");
-    pFS->startElement(FSNS(XML_a, XML_solidFill));
-    pFS->startElement(FSNS(XML_a, XML_schemeClr), XML_val, "tx1");
-    pFS->singleElement(FSNS(XML_a, XML_lumMod), XML_val, "15000");
-    pFS->singleElement(FSNS(XML_a, XML_lumOff), XML_val, "85000");
-    pFS->endElement(FSNS(XML_a, XML_schemeClr));
-    pFS->endElement(FSNS(XML_a, XML_solidFill));
-    pFS->singleElement(FSNS(XML_a, XML_round));
-    pFS->endElement(FSNS(XML_a, XML_ln));
-
-    pFS->endElement(FSNS(XML_cs, XML_spPr));
-
-    pFS->endElement(FSNS(XML_cs, XML_chartArea));
-}
-
-void outputDataPointStyleEntry(FSHelperPtr pFS)
-{
-    pFS->startElement(FSNS(XML_cs, XML_dataPoint));
-    pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0");
-
-    pFS->startElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0");
-    pFS->singleElement(FSNS(XML_cs, XML_styleClr), XML_val, "auto");
-    pFS->endElement(FSNS(XML_cs, XML_fillRef));
-
-    pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0");
-
-    pFS->startElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor");
-    pFS->singleElement(FSNS(XML_cs, XML_schemeClr), XML_val, "tx1");
-    pFS->endElement(FSNS(XML_cs, XML_fontRef));
-
-    pFS->startElement(FSNS(XML_cs, XML_spPr));
-    pFS->startElement(FSNS(XML_a, XML_solidFill));
-    pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "phClr");
-    pFS->endElement(FSNS(XML_a, XML_solidFill));
-    pFS->endElement(FSNS(XML_cs, XML_spPr));
-
-    pFS->endElement(FSNS(XML_cs, XML_dataPoint));
-}
-
 std::vector<Sequence<Reference<chart2::XDataSeries> > > 
splitDataSeriesByAxis(const Reference< chart2::XChartType >& xChartType)
 {
     std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitSeries;
@@ -908,6 +844,175 @@ OUString ChartExport::parseFormula( const OUString& 
rRange )
     return aResult;
 }
 
+// Output the chartex AlternateContent fallback path
+static void writeChartexAlternateContent(FSHelperPtr pFS)
+{
+    pFS->startElementNS(XML_mc, XML_Fallback);
+    pFS->startElementNS(XML_xdr, XML_sp, XML_macro, "", XML_textlink, "");
+    pFS->startElementNS(XML_xdr, XML_nvSpPr);
+    pFS->singleElementNS(XML_xdr, XML_cNvPr, XML_id, "0", XML_name, "");
+    pFS->startElementNS(XML_xdr, XML_cNvSpPr);
+    pFS->singleElementNS(XML_a, XML_spLocks, XML_noTextEdit, "1");
+    pFS->endElementNS(XML_xdr, XML_cNvSpPr);
+    pFS->endElementNS(XML_xdr, XML_nvSpPr);
+    pFS->startElementNS(XML_xdr, XML_spPr);
+    pFS->startElementNS(XML_a, XML_xfrm);
+    pFS->singleElementNS(XML_a, XML_off, XML_x, "6600825", XML_y, "2533650");
+    pFS->singleElementNS(XML_a, XML_ext, XML_cx, "4572000", XML_cy, "2743200");
+    pFS->endElementNS(XML_a, XML_xfrm);
+    pFS->startElementNS(XML_a, XML_prstGeom, XML_prst, "rect");
+    pFS->singleElementNS(XML_a, XML_avLst);
+    pFS->endElementNS(XML_a, XML_prstGeom);
+    pFS->startElementNS(XML_a, XML_solidFill);
+    pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "white");
+    pFS->endElementNS(XML_a, XML_solidFill);
+    pFS->startElementNS(XML_a, XML_ln, XML_w, "1");
+    pFS->startElementNS(XML_a, XML_solidFill);
+    pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "green");
+    pFS->endElementNS(XML_a, XML_solidFill);
+    pFS->endElementNS(XML_a, XML_ln);
+    pFS->endElementNS(XML_xdr, XML_spPr);
+    pFS->startElementNS(XML_xdr, XML_txBody);
+    pFS->singleElementNS(XML_a, XML_bodyPr, XML_vertOverflow, "clip", 
XML_horzOverflow, "clip");
+    pFS->singleElementNS(XML_a, XML_lstStyle);
+    pFS->startElementNS(XML_a, XML_p);
+    pFS->startElementNS(XML_a, XML_r);
+    pFS->singleElementNS(XML_a, XML_rPr, XML_sz, "1100");
+    pFS->startElementNS(XML_a, XML_t);
+
+    const std::string_view sErrTxt("This chart isn't available in your version 
of Excel.

"
+        "Editing this shape or saving this workbook into a different file 
format will permanently break the chart.");
+    pFS->writeEscaped( sErrTxt );
+
+    pFS->endElementNS(XML_a, XML_t);
+    pFS->endElementNS(XML_a, XML_r);
+    pFS->endElementNS(XML_a, XML_p);
+    pFS->endElementNS(XML_xdr, XML_txBody);
+    pFS->endElementNS(XML_xdr, XML_sp);
+}
+
+namespace {
+
+// Map enumerated style entry types to corresponding XML tags
+struct styleTag {
+    model::StyleSet::StyleEntryType meType;
+    sal_Int32             mnTag;
+};
+
+std::array<styleTag, static_cast<int>(model::StyleSet::StyleEntryType::END)> 
styleTagMap {{
+    { model::StyleSet::StyleEntryType::AXISTITLE, XML_axisTitle },
+    { model::StyleSet::StyleEntryType::CATEGORYAXIS, XML_categoryAxis },
+    { model::StyleSet::StyleEntryType::CHARTAREA, XML_chartArea },
+    { model::StyleSet::StyleEntryType::DATALABEL, XML_dataLabel },
+    { model::StyleSet::StyleEntryType::DATALABELCALLOUT, XML_dataLabelCallout 
},
+    { model::StyleSet::StyleEntryType::DATAPOINT, XML_dataPoint },
+    { model::StyleSet::StyleEntryType::DATAPOINT3D, XML_dataPoint3D },
+    { model::StyleSet::StyleEntryType::DATAPOINTLINE, XML_dataPointLine },
+    { model::StyleSet::StyleEntryType::DATAPOINTMARKER, XML_dataPointMarker },
+    { model::StyleSet::StyleEntryType::DATAPOINTMARKERLAYOUT, 
XML_dataPointMarkerLayout },
+    { model::StyleSet::StyleEntryType::DATAPOINTWIREFRAME, 
XML_dataPointWireframe },
+    { model::StyleSet::StyleEntryType::DATATABLE, XML_dataTable },
+    { model::StyleSet::StyleEntryType::DOWNBAR, XML_downBar },
+    { model::StyleSet::StyleEntryType::DROPLINE, XML_dropLine },
+    { model::StyleSet::StyleEntryType::ERRORBAR, XML_errorBar },
+    { model::StyleSet::StyleEntryType::FLOOR, XML_floor },
+    { model::StyleSet::StyleEntryType::GRIDLINEMAJOR, XML_gridlineMajor },
+    { model::StyleSet::StyleEntryType::GRIDLINEMINOR, XML_gridlineMinor },
+    { model::StyleSet::StyleEntryType::HILOLINE, XML_hiLoLine },
+    { model::StyleSet::StyleEntryType::LEADERLINE, XML_leaderLine },
+    { model::StyleSet::StyleEntryType::LEGEND, XML_legend },
+    { model::StyleSet::StyleEntryType::PLOTAREA, XML_plotArea },
+    { model::StyleSet::StyleEntryType::PLOTAREA3D, XML_plotArea3D },
+    { model::StyleSet::StyleEntryType::SERIESAXIS, XML_seriesAxis },
+    { model::StyleSet::StyleEntryType::SERIESLINE, XML_seriesLine },
+    { model::StyleSet::StyleEntryType::TITLE, XML_title },
+    { model::StyleSet::StyleEntryType::TRENDLINE, XML_trendline },
+    { model::StyleSet::StyleEntryType::TRENDLINELABEL, XML_trendlineLabel },
+    { model::StyleSet::StyleEntryType::UPBAR, XML_upBar },
+    { model::StyleSet::StyleEntryType::VALUEAXIS, XML_valueAxis },
+    { model::StyleSet::StyleEntryType::WALL, XML_wall }
+}};
+
+// The following functions are intended to duplicate what appear to be the MS
+// Office defaults for various style entries. These are not documented 
anywhere,
+// so far as I can tell. The values here are just derived by looking at some
+// files Office creates. It's very possible that things are not as simple as 
the
+// hard-coded values here.
+
+// All style entries other than the special cases below
+void outputDefaultStyleEntry(FSHelperPtr pFS, sal_Int32 nElTokenId)
+{
+    pFS->startElement(FSNS(XML_cs, nElTokenId));
+    pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0");
+    pFS->singleElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0");
+    pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0");
+    pFS->singleElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor");
+    pFS->endElement(FSNS(XML_cs, nElTokenId));
+}
+
+// chartArea entry
+void outputDefaultChartAreaStyleEntry(FSHelperPtr pFS)
+{
+    pFS->startElement(FSNS(XML_cs, XML_chartArea), XML_mods, 
"allowNoFillOverride allowNoLineOverride");
+    pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0");
+    pFS->singleElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0");
+    pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0");
+
+    pFS->startElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor");
+    pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "tx1");
+    pFS->endElement(FSNS(XML_cs, XML_fontRef));
+
+    pFS->startElement(FSNS(XML_cs, XML_spPr));
+
+    pFS->startElement(FSNS(XML_a, XML_solidFill));
+    pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "bg1");
+    pFS->endElement(FSNS(XML_a, XML_solidFill));
+
+    pFS->startElement(FSNS(XML_a, XML_ln), XML_w, "9525", XML_cap, "flat",
+            XML_cmpd, "sng", XML_algn, "ctr");
+    pFS->startElement(FSNS(XML_a, XML_solidFill));
+    pFS->startElement(FSNS(XML_a, XML_schemeClr), XML_val, "tx1");
+    pFS->singleElement(FSNS(XML_a, XML_lumMod), XML_val, "15000");
+    pFS->singleElement(FSNS(XML_a, XML_lumOff), XML_val, "85000");
+    pFS->endElement(FSNS(XML_a, XML_schemeClr));
+    pFS->endElement(FSNS(XML_a, XML_solidFill));
+    pFS->singleElement(FSNS(XML_a, XML_round));
+    pFS->endElement(FSNS(XML_a, XML_ln));
+
+    pFS->endElement(FSNS(XML_cs, XML_spPr));
+
+    pFS->endElement(FSNS(XML_cs, XML_chartArea));
+}
+
+// dataPoint entry
+void outputDefaultDataPointStyleEntry(FSHelperPtr pFS)
+{
+    pFS->startElement(FSNS(XML_cs, XML_dataPoint));
+    pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0");
+
+    pFS->startElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0");
+    pFS->singleElement(FSNS(XML_cs, XML_styleClr), XML_val, "auto");
+    pFS->endElement(FSNS(XML_cs, XML_fillRef));
+
+    pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0");
+
+    pFS->startElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor");
+    pFS->singleElement(FSNS(XML_cs, XML_schemeClr), XML_val, "tx1");
+    pFS->endElement(FSNS(XML_cs, XML_fontRef));
+
+    pFS->startElement(FSNS(XML_cs, XML_spPr));
+    pFS->startElement(FSNS(XML_a, XML_solidFill));
+    pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "phClr");
+    pFS->endElement(FSNS(XML_a, XML_solidFill));
+    pFS->endElement(FSNS(XML_cs, XML_spPr));
+
+    pFS->endElement(FSNS(XML_cs, XML_dataPoint));
+}
+
+} // unnamed namespace
+
+
+
 void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 
nID, sal_Int32 nChartCount )
 {
     FSHelperPtr pFS = GetFS();
@@ -1069,50 +1174,9 @@ void ChartExport::WriteChartObj( const Reference< XShape 
>& xShape, sal_Int32 nI
     pFS->endElementNS( mnXmlNamespace, XML_graphicFrame );
 
     if (bIsChartex) {
-        // Do the AlternateContent fallback path
         pFS->endElementNS(XML_mc, XML_Choice);
-        pFS->startElementNS(XML_mc, XML_Fallback);
-        pFS->startElementNS(XML_xdr, XML_sp, XML_macro, "", XML_textlink, "");
-        pFS->startElementNS(XML_xdr, XML_nvSpPr);
-        pFS->singleElementNS(XML_xdr, XML_cNvPr, XML_id, "0", XML_name, "");
-        pFS->startElementNS(XML_xdr, XML_cNvSpPr);
-        pFS->singleElementNS(XML_a, XML_spLocks, XML_noTextEdit, "1");
-        pFS->endElementNS(XML_xdr, XML_cNvSpPr);
-        pFS->endElementNS(XML_xdr, XML_nvSpPr);
-        pFS->startElementNS(XML_xdr, XML_spPr);
-        pFS->startElementNS(XML_a, XML_xfrm);
-        pFS->singleElementNS(XML_a, XML_off, XML_x, "6600825", XML_y, 
"2533650");
-        pFS->singleElementNS(XML_a, XML_ext, XML_cx, "4572000", XML_cy, 
"2743200");
-        pFS->endElementNS(XML_a, XML_xfrm);
-        pFS->startElementNS(XML_a, XML_prstGeom, XML_prst, "rect");
-        pFS->singleElementNS(XML_a, XML_avLst);
-        pFS->endElementNS(XML_a, XML_prstGeom);
-        pFS->startElementNS(XML_a, XML_solidFill);
-        pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "white");
-        pFS->endElementNS(XML_a, XML_solidFill);
-        pFS->startElementNS(XML_a, XML_ln, XML_w, "1");
-        pFS->startElementNS(XML_a, XML_solidFill);
-        pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "green");
-        pFS->endElementNS(XML_a, XML_solidFill);
-        pFS->endElementNS(XML_a, XML_ln);
-        pFS->endElementNS(XML_xdr, XML_spPr);
-        pFS->startElementNS(XML_xdr, XML_txBody);
-        pFS->singleElementNS(XML_a, XML_bodyPr, XML_vertOverflow, "clip", 
XML_horzOverflow, "clip");
-        pFS->singleElementNS(XML_a, XML_lstStyle);
-        pFS->startElementNS(XML_a, XML_p);
-        pFS->startElementNS(XML_a, XML_r);
-        pFS->singleElementNS(XML_a, XML_rPr, XML_sz, "1100");
-        pFS->startElementNS(XML_a, XML_t);
-
-        const std::string_view sErrTxt("This chart isn't available in your 
version of Excel.

"
-            "Editing this shape or saving this workbook into a different file 
format will permanently break the chart.");
-        pFS->writeEscaped( sErrTxt );
-
-        pFS->endElementNS(XML_a, XML_t);
-        pFS->endElementNS(XML_a, XML_r);
-        pFS->endElementNS(XML_a, XML_p);
-        pFS->endElementNS(XML_xdr, XML_txBody);
-        pFS->endElementNS(XML_xdr, XML_sp);
+
+        writeChartexAlternateContent(pFS);
 
         pFS->endElementNS(XML_mc, XML_Fallback);
         pFS->endElementNS(XML_mc, XML_AlternateContent);
@@ -1121,112 +1185,114 @@ void ChartExport::WriteChartObj( const Reference< 
XShape >& xShape, sal_Int32 nI
     SetFS( pChart );
     ExportContent();
 
-    if (bIsChartex) {
-        SetFS( pChart );
-        sRelativePath ="";
-
-        FSHelperPtr pChartFS = GetFS();
+    // output style and colorstyle files
 
-        // output style and colorstyle files
+    SetFS( pChart );
+    sRelativePath ="";
+
+    FSHelperPtr pChartFS = GetFS();
+
+    // first style
+    static constexpr char sStyleFnamePrefix[] = "style";
+    OUStringBuffer sFullStreamBuf;
+    sFullStreamBuf.appendAscii(sFullPath);
+    sFullStreamBuf = sFullStreamBuf + sStyleFnamePrefix + 
OUString::number(nChartCount) + ".xml";
+    sFullStream = sFullStreamBuf.makeStringAndClear();
+    OUStringBuffer sRelativeStreamBuf;
+    sRelativeStreamBuf.appendAscii(sRelativePath);
+    sRelativeStreamBuf = sRelativeStreamBuf + sStyleFnamePrefix + 
OUString::number(nChartCount) + ".xml";
+    sRelativeStream = sRelativeStreamBuf.makeStringAndClear();
+
+    FSHelperPtr pStyle = CreateOutputStream(
+            sFullStream,
+            sRelativeStream,
+            pChartFS->getOutputStream(),
+            u"application/vnd.ms-office.chartstyle+xml"_ustr,
+            oox::getRelationship(Relationship::CHARTSTYLE),
+            &sId,
+            true /* for some reason this doesn't have a header line */);
+
+    SetFS( pStyle );
+    pFS = GetFS();
+
+    pFS->startElement(FSNS(XML_cs, XML_chartStyle),
+            FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)),
+            FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)),
+            XML_id, "419" /* no idea what this number is supposed to be */);
+
+    Reference<com::sun::star::chart2::XChartStyle> xStyle = 
xChartDoc->getStyles();
+    model::StyleSet* aSS = model::style::getFromXChartStyle(xStyle);
+
+    for (enum model::StyleSet::StyleEntryType eEType = 
model::StyleSet::StyleEntryType::BEGIN;
+            eEType != model::StyleSet::StyleEntryType::END;
+            eEType = 
static_cast<model::StyleSet::StyleEntryType>(static_cast<int>(eEType) + 1)) {
+        auto entryIt = aSS->maEntryMap.find(eEType);
+
+        if (entryIt == aSS->maEntryMap.end()) {
+            // We haven't stored any style information for this entry type, so
+            // just output a default value
+            switch (eEType) {
+                case model::StyleSet::StyleEntryType::CHARTAREA:
+                    outputDefaultChartAreaStyleEntry(pFS);
+                    break;
+                case model::StyleSet::StyleEntryType::DATAPOINT:
+                    outputDefaultDataPointStyleEntry(pFS);
+                    break;
+                case model::StyleSet::StyleEntryType::DATALABELCALLOUT:
+                    // no entry required?
+                    break;
+                default:
+                    if (styleTagMap[static_cast<int>(eEType)].meType != 
eEType) {
+                        assert(false);
+                    }
+                    outputDefaultStyleEntry(pFS, 
styleTagMap[static_cast<int>(eEType)].mnTag);
+                    break;
+            }
+        } else {
+            outputStyleEntry(pFS, styleTagMap[static_cast<int>(eEType)].mnTag,
+                    entryIt->second);
+        }
+    }
 
-        // first style
-        static constexpr char sStyleFnamePrefix[] = "style";
-        OUStringBuffer sFullStreamBuf;
-        sFullStreamBuf.appendAscii(sFullPath);
-        sFullStreamBuf = sFullStreamBuf + sStyleFnamePrefix + 
OUString::number(nChartCount) + ".xml";
-        sFullStream = sFullStreamBuf.makeStringAndClear();
-        OUStringBuffer sRelativeStreamBuf;
-        sRelativeStreamBuf.appendAscii(sRelativePath);
-        sRelativeStreamBuf = sRelativeStreamBuf + sStyleFnamePrefix + 
OUString::number(nChartCount) + ".xml";
-        sRelativeStream = sRelativeStreamBuf.makeStringAndClear();
+    pFS->endElement(FSNS(XML_cs, XML_chartStyle));
 
-        FSHelperPtr pStyle = CreateOutputStream(
-                sFullStream,
-                sRelativeStream,
-                pChartFS->getOutputStream(),
-                u"application/vnd.ms-office.chartstyle+xml"_ustr,
-                oox::getRelationship(Relationship::CHARTSTYLE),
-                &sId,
-                true /* for some reason this doesn't have a header line */);
+    pStyle->endDocument();
 
-        SetFS( pStyle );
-        pFS = GetFS();
+    // now colorstyle
+    static constexpr char sColorFnamePrefix[] = "colors";
+    sFullStreamBuf = OUStringBuffer();
+    sFullStreamBuf.appendAscii(sFullPath);
+    sFullStreamBuf = sFullStreamBuf + sColorFnamePrefix + 
OUString::number(nChartCount) + ".xml";
+    sFullStream = sFullStreamBuf.makeStringAndClear();
+    sRelativeStreamBuf = OUStringBuffer();
+    sRelativeStreamBuf.appendAscii(sRelativePath);
+    sRelativeStreamBuf = sRelativeStreamBuf + sColorFnamePrefix + 
OUString::number(nChartCount) + ".xml";
+    sRelativeStream = sRelativeStreamBuf.makeStringAndClear();
 
-        pFS->startElement(FSNS(XML_cs, XML_chartStyle),
-                FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)),
-                FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)),
-                XML_id, "419" /* no idea what this number is supposed to be 
*/);
-
-        outputStyleEntry(pFS, XML_axisTitle);;
-        outputStyleEntry(pFS, XML_categoryAxis);
-        outputChartAreaStyleEntry(pFS);
-        outputStyleEntry(pFS, XML_dataLabel);
-        outputDataPointStyleEntry(pFS);
-        outputStyleEntry(pFS, XML_dataPoint3D);
-        outputStyleEntry(pFS, XML_dataPointLine);
-        outputStyleEntry(pFS, XML_dataPointMarker);
-        outputStyleEntry(pFS, XML_dataPointWireframe);
-        outputStyleEntry(pFS, XML_dataTable);
-        outputStyleEntry(pFS, XML_downBar);
-        outputStyleEntry(pFS, XML_dropLine);
-        outputStyleEntry(pFS, XML_errorBar);
-        outputStyleEntry(pFS, XML_floor);
-        outputStyleEntry(pFS, XML_gridlineMajor);
-        outputStyleEntry(pFS, XML_gridlineMinor);
-        outputStyleEntry(pFS, XML_hiLoLine);
-        outputStyleEntry(pFS, XML_leaderLine);
-        outputStyleEntry(pFS, XML_legend);
-        outputStyleEntry(pFS, XML_plotArea);
-        outputStyleEntry(pFS, XML_plotArea3D);
-        outputStyleEntry(pFS, XML_seriesAxis);
-        outputStyleEntry(pFS, XML_seriesLine);
-        outputStyleEntry(pFS, XML_title);
-        outputStyleEntry(pFS, XML_trendline);
-        outputStyleEntry(pFS, XML_trendlineLabel);
-        outputStyleEntry(pFS, XML_upBar);
-        outputStyleEntry(pFS, XML_valueAxis);
-        outputStyleEntry(pFS, XML_wall);
-
-        pFS->endElement(FSNS(XML_cs, XML_chartStyle));
-
-        pStyle->endDocument();
-
-        // now colorstyle
-        static constexpr char sColorFnamePrefix[] = "colors";
-        sFullStreamBuf = OUStringBuffer();
-        sFullStreamBuf.appendAscii(sFullPath);
-        sFullStreamBuf = sFullStreamBuf + sColorFnamePrefix + 
OUString::number(nChartCount) + ".xml";
-        sFullStream = sFullStreamBuf.makeStringAndClear();
-        sRelativeStreamBuf = OUStringBuffer();
-        sRelativeStreamBuf.appendAscii(sRelativePath);
-        sRelativeStreamBuf = sRelativeStreamBuf + sColorFnamePrefix + 
OUString::number(nChartCount) + ".xml";
-        sRelativeStream = sRelativeStreamBuf.makeStringAndClear();
-
-        FSHelperPtr pColorStyle = CreateOutputStream(
-                sFullStream,
-                sRelativeStream,
-                pChartFS->getOutputStream(),
-                u"application/vnd.ms-office.chartcolorstyle+xml"_ustr,
-                oox::getRelationship(Relationship::CHARTCOLORSTYLE),
-                &sId,
-                true /* also no header line */);
+    FSHelperPtr pColorStyle = CreateOutputStream(
+            sFullStream,
+            sRelativeStream,
+            pChartFS->getOutputStream(),
+            u"application/vnd.ms-office.chartcolorstyle+xml"_ustr,
+            oox::getRelationship(Relationship::CHARTCOLORSTYLE),
+            &sId,
+            true /* also no header line */);
 
-        SetFS( pColorStyle );
-        pFS = GetFS();
+    SetFS( pColorStyle );
+    pFS = GetFS();
 
-        pFS->startElement(FSNS(XML_cs, XML_colorStyle),
-                FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)),
-                FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)),
-                XML_meth, "cycle",
-                XML_id, "10" /* no idea what this number is supposed to be */);
+    pFS->startElement(FSNS(XML_cs, XML_colorStyle),
+            FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)),
+            FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)),
+            XML_meth, "cycle",
+            XML_id, "10" /* no idea what this number is supposed to be */);
 
-        pFS->singleElement(FSNS(XML_a, XML_schemeClr),
-                XML_val, "accent1");
+    pFS->singleElement(FSNS(XML_a, XML_schemeClr),
+            XML_val, "accent1");
 
-        pFS->endElement(FSNS(XML_cs, XML_colorStyle));
+    pFS->endElement(FSNS(XML_cs, XML_colorStyle));
 
-        pColorStyle->endDocument();
-    }
+    pColorStyle->endDocument();
 
     pChart->endDocument();
 }
@@ -1360,7 +1426,7 @@ void ChartExport::exportChartSpace( const Reference< 
css::chart::XChartDocument
     // TODO: text properties
     Reference< XPropertySet > xPropSet = xChartDoc->getArea();
     if( xPropSet.is() )
-        exportShapeProps( xPropSet, bIsChartex );
+        exportShapeProps( xPropSet, nChartNS );
 
     // TODO for chartex
     if (!bIsChartex) {
@@ -1839,7 +1905,7 @@ void ChartExport::exportChart( const Reference< 
css::chart::XChartDocument >& xC
             if( xFloor.is() )
             {
                 pFS->startElement(FSNS(XML_c, XML_floor));
-                exportShapeProps( xFloor, false );
+                exportShapeProps( xFloor, XML_c );
                 pFS->endElement( FSNS( XML_c, XML_floor ) );
             }
 
@@ -1850,12 +1916,12 @@ void ChartExport::exportChart( const Reference< 
css::chart::XChartDocument >& xC
             {
                 // sideWall
                 pFS->startElement(FSNS(XML_c, XML_sideWall));
-                exportShapeProps( xWall, false );
+                exportShapeProps( xWall, XML_c );
                 pFS->endElement( FSNS( XML_c, XML_sideWall ) );
 
                 // backWall
                 pFS->startElement(FSNS(XML_c, XML_backWall));
-                exportShapeProps( xWall, false );
+                exportShapeProps( xWall, XML_c );
                 pFS->endElement( FSNS( XML_c, XML_backWall ) );
             }
         }
@@ -2100,7 +2166,7 @@ void ChartExport::exportLegend( const Reference< 
css::chart::XChartDocument >& x
         }
 
         // shape properties
-        exportShapeProps( xProp, bIsChartex );
+        exportShapeProps( xProp, bIsChartex ? XML_cx : XML_c );
 
         // draw-chart:txPr text properties
         exportTextProps( xProp, bIsChartex );
@@ -2166,7 +2232,7 @@ void ChartExport::exportTitle( const Reference< XShape >& 
xShape, bool bIsCharte
         // shape properties
         if( xPropSet.is() )
         {
-            exportShapeProps( xPropSet, bIsChartex );
+            exportShapeProps( xPropSet, bIsChartex ? XML_cx : XML_c );
         }
 
         pFS->startElement(FSNS(XML_cx, XML_txPr));
@@ -2300,7 +2366,7 @@ void ChartExport::exportTitle( const Reference< XShape >& 
xShape, bool bIsCharte
         // shape properties
         if( xPropSet.is() )
         {
-            exportShapeProps( xPropSet, bIsChartex );
+            exportShapeProps( xPropSet, bIsChartex ? XML_cx : XML_c );
         }
     }
 
@@ -2518,7 +2584,7 @@ void ChartExport::exportPlotArea(const Reference< 
css::chart::XChartDocument >&
             {
                 xWallPropSet->setPropertyValue( u"LineStyle"_ustr, 
uno::Any(drawing::LineStyle_NONE) );
             }
-            exportShapeProps( xWallPropSet, bIsChartex );
+            exportShapeProps( xWallPropSet, bIsChartex ? XML_cx : XML_c );
         }
     }
 
@@ -2844,7 +2910,7 @@ void ChartExport::exportDataTable( )
     if (bShowKeys)
         pFS->singleElement(FSNS(XML_c, XML_showKeys), XML_val, "1");
 
-    exportShapeProps(aPropSet, false);
+    exportShapeProps(aPropSet, XML_c);
     exportTextProps(aPropSet, false);
 
     pFS->endElement(FSNS(XML_c, XML_dTable));
@@ -3278,7 +3344,7 @@ void ChartExport::exportHiLowLines()
         return;
 
     pFS->startElement(FSNS(XML_c, XML_hiLowLines));
-    exportShapeProps( xStockPropSet, false );
+    exportShapeProps( xStockPropSet, XML_c );
     pFS->endElement( FSNS( XML_c, XML_hiLowLines ) );
 }
 
@@ -3306,7 +3372,7 @@ void ChartExport::exportUpDownBars( const Reference< 
chart2::XChartType >& xChar
         // so no need to call the exportShapeProps() for LineChart
         if(xChartType->getChartType() == 
"com.sun.star.chart2.CandleStickChartType")
         {
-            exportShapeProps(xChartPropSet, false);
+            exportShapeProps(xChartPropSet, XML_c);
         }
         pFS->endElement( FSNS( XML_c, XML_upBars ) );
     }
@@ -3316,7 +3382,7 @@ void ChartExport::exportUpDownBars( const Reference< 
chart2::XChartType >& xChar
         pFS->startElement(FSNS(XML_c, XML_downBars));
         if(xChartType->getChartType() == 
"com.sun.star.chart2.CandleStickChartType")
         {
-            exportShapeProps(xChartPropSet, false);
+            exportShapeProps(xChartPropSet, XML_c);
         }
         pFS->endElement( FSNS( XML_c, XML_downBars ) );
     }
@@ -3442,7 +3508,7 @@ void ChartExport::exportSeries_chart( const 
Reference<chart2::XChartType>& xChar
                     rSeries, getModel() );
                 if( xOldPropSet.is() )
                 {
-                    exportShapeProps( xOldPropSet, false );
+                    exportShapeProps( xOldPropSet, XML_c );
                 }
 
                 switch( eChartType )
@@ -3626,7 +3692,7 @@ void ChartExport::exportSeries_chartex( const 
Reference<chart2::XChartType>& xCh
                 rSeries, getModel() );
             if( xOldPropSet.is() )
             {
-                exportShapeProps( xOldPropSet, true );
+                exportShapeProps( xOldPropSet, XML_cx );
             }
 
             DataLabelsRange aDLblsRange;
@@ -3894,16 +3960,15 @@ void ChartExport::exportSeriesValues( const Reference< 
chart2::data::XDataSequen
 }
 
 void ChartExport::exportShapeProps( const Reference< XPropertySet >& xPropSet,
-        bool bIsChartex)
+        sal_Int32 nNS)
 {
-    sal_Int32 nChartNS = bIsChartex ? XML_cx : XML_c;
     FSHelperPtr pFS = GetFS();
-    pFS->startElement(FSNS(nChartNS, XML_spPr));
+    pFS->startElement(FSNS(nNS, XML_spPr));
 
     exportFill( xPropSet );
     WriteOutline( xPropSet, getModel() );
 
-    pFS->endElement( FSNS( nChartNS, XML_spPr ) );
+    pFS->endElement( FSNS( nNS, XML_spPr ) );
 }
 
 void ChartExport::exportTextProps(const Reference<XPropertySet>& xPropSet,
@@ -4288,7 +4353,7 @@ void ChartExport::exportOneAxis_chart(
     if( xMajorGrid.is())
     {
         pFS->startElement(FSNS(XML_c, XML_majorGridlines));
-        exportShapeProps( xMajorGrid, false );
+        exportShapeProps( xMajorGrid, XML_c );
         pFS->endElement( FSNS( XML_c, XML_majorGridlines ) );
     }
 
@@ -4296,7 +4361,7 @@ void ChartExport::exportOneAxis_chart(
     if( xMinorGrid.is())
     {
         pFS->startElement(FSNS(XML_c, XML_minorGridlines));
-        exportShapeProps( xMinorGrid, false );
+        exportShapeProps( xMinorGrid, XML_c );
         pFS->endElement( FSNS( XML_c, XML_minorGridlines ) );
     }
 
@@ -4368,7 +4433,7 @@ void ChartExport::exportOneAxis_chart(
     pFS->singleElement(FSNS(XML_c, XML_tickLblPos), XML_val, sTickLblPos);
 
     // shape properties
-    exportShapeProps( xAxisProp, false );
+    exportShapeProps( xAxisProp, XML_c );
 
     exportTextProps(xAxisProp, false);
 
@@ -4647,7 +4712,7 @@ void ChartExport::exportOneAxis_chartex(
     if( xMajorGrid.is())
     {
         pFS->startElement(FSNS(XML_cx, XML_majorGridlines));
-        exportShapeProps( xMajorGrid, true );
+        exportShapeProps( xMajorGrid, XML_cx );
         pFS->endElement( FSNS( XML_cx, XML_majorGridlines ) );
     }
 
@@ -4655,7 +4720,7 @@ void ChartExport::exportOneAxis_chartex(
     if( xMinorGrid.is())
     {
         pFS->startElement(FSNS(XML_cx, XML_minorGridlines));
-        exportShapeProps( xMinorGrid, true );
+        exportShapeProps( xMinorGrid, XML_cx );
         pFS->endElement( FSNS( XML_cx, XML_minorGridlines ) );
     }
 
@@ -4701,7 +4766,7 @@ void ChartExport::exportOneAxis_chartex(
             XML_sourceLinked, bLinkedNumFmt ? "1" : "0");
 
     // ==== spPr
-    exportShapeProps( xAxisProp, true );
+    exportShapeProps( xAxisProp, XML_cx );
 
     // ==== txPr
     exportTextProps(xAxisProp, true);
@@ -5246,7 +5311,7 @@ void ChartExport::exportDataPoints(
                     default:
                         break;
                 }
-                exportShapeProps( xPropSet, false );
+                exportShapeProps( xPropSet, XML_c );
 
                 pFS->endElement( FSNS( XML_c, XML_dPt ) );
             }
@@ -5290,7 +5355,7 @@ void ChartExport::exportDataPoints(
                 case chart::TYPEID_HORBAR:
                 case chart::TYPEID_BAR:
                     pFS->singleElement(FSNS(XML_c, XML_invertIfNegative), 
XML_val, "0");
-                    exportShapeProps(xPropSet, false);
+                    exportShapeProps(xPropSet, XML_c);
                     break;
 
                 case chart::TYPEID_LINE:
@@ -5300,7 +5365,7 @@ void ChartExport::exportDataPoints(
                     break;
 
                 default:
-                    exportShapeProps(xPropSet, false);
+                    exportShapeProps(xPropSet, XML_c);
                     break;
             }
 
@@ -5420,7 +5485,7 @@ void ChartExport::exportTrendlines( const Reference< 
chart2::XDataSeries >& xSer
             pFS->endElement( FSNS( XML_c, XML_name) );
         }
 
-        exportShapeProps( xProperties, false );
+        exportShapeProps( xProperties, XML_c );
 
         if( aService == "com.sun.star.chart2.LinearRegressionCurve" )
         {
@@ -5740,7 +5805,7 @@ void ChartExport::exportErrorBar(const Reference< 
XPropertySet>& xErrorBarProps,
         pFS->singleElement(FSNS(XML_c, XML_val), XML_val, 
OString::number(nVal));
     }
 
-    exportShapeProps( xErrorBarProps, false );
+    exportShapeProps( xErrorBarProps, XML_c );
 
     pFS->endElement( FSNS( XML_c, XML_errBars) );
 }
@@ -5908,6 +5973,68 @@ OUString ChartExport::getNumberFormatCode(sal_Int32 
nKey) const
     return aCode;
 }
 
+// Create cs:CT_FontReference or cs:CT_StyleReference
+void ChartExport::outputFontOrStyleRef(FSHelperPtr pFS, sal_Int32 nElTokenId, 
const
+        model::FontOrStyleRef& aColor)
+{
+    pFS->startElement(FSNS(XML_cs, nElTokenId), XML_idx, 
OUString::number(aColor.mnIdx));
+
+    ThemeExport aTE(mpFB, GetDocumentType(), pFS);
+    aTE.writeComplexColor(aColor.maComplexColor);
+
+    // Get the string for the StyleColorVal
+    OUString sV = aColor.getColorValStr();
+    if (!sV.isEmpty()) {
+        pFS->singleElement(FSNS(XML_cs, XML_styleClr), XML_val, sV);
+    }
+
+    pFS->endElement(FSNS(XML_cs, nElTokenId));
+}
+
+// Create cs:CT_StyleEntry
+void ChartExport::outputStyleEntry(FSHelperPtr pFS, sal_Int32 nElTokenId, 
model::StyleEntry& aEntry)
+{
+    // Just default values for now
+    pFS->startElement(FSNS(XML_cs, nElTokenId));
+
+    outputFontOrStyleRef(pFS, FSNS(XML_cs, XML_lnRef), *(aEntry.mxLnClr));
+
+    pFS->startElement(FSNS(XML_cs, XML_lineWidthScale));
+    pFS->write(aEntry.mfLineWidthScale);
+    pFS->endElement(FSNS(XML_cs, XML_lineWidthScale));
+
+    outputFontOrStyleRef(pFS, FSNS(XML_cs, XML_fillRef), *(aEntry.mxFillClr));
+    outputFontOrStyleRef(pFS, FSNS(XML_cs, XML_effectRef), 
*(aEntry.mxEffectClr));
+    outputFontOrStyleRef(pFS, FSNS(XML_cs, XML_fontRef), *(aEntry.mxFontClr));
+
+    if (aEntry.mxShapePr) {
+        
exportShapeProps(aEntry.mxShapePr->getShapeProperties().makePropertySet(), 
XML_cs);
+    }
+
+    if (aEntry.mrTextCharacterPr) {
+        PropertyMap *pPM = aEntry.mrTextCharacterPr.get();
+        Reference< XPropertySet > rPS = pPM->makePropertySet();
+
+        WriteRunInput aInput;
+        aInput.bCheckDirect = false;
+        aInput.bUseTextSchemeColors = false;
+        WriteRunProperties(rPS, XML_defRPr, aInput );
+    }
+
+    if (aEntry.mxTextBodyPr) {
+        PropertyMap *pPM = aEntry.mxTextBodyPr.get();
+        aEntry.mxTextBodyPr.reset();
+        Reference< XPropertySet > rPS = pPM->makePropertySet();
+        uno::Reference<drawing::XShape> xShape(rPS, UNO_QUERY);
+        uno::Reference<XPropertySet> rXPropSet = rPS;
+        WriteBodyPropsInput aWBPInput;
+
+        WriteBodyProps(rPS, rXPropSet, xShape, XML_cs, aWBPInput);
+    }
+
+    pFS->endElement(FSNS(XML_cs, nElTokenId));
+}
+
 }// oox
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index a3fd38496787..0ca14190fe50 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2675,10 +2675,10 @@ void DrawingML::WriteRunProperties(const 
Reference<XPropertySet>& rRun, sal_Int3
             usLanguage = aLanguageTag.getBcp47MS();
     }
 
-    if (GetDirectProperty(rXPropSet, rXPropState, u"CharEscapement"_ustr))
+    if (rXPropState && GetDirectProperty(rXPropSet, rXPropState, 
u"CharEscapement"_ustr))
         mAny >>= nCharEscapement;
 
-    if (GetDirectProperty(rXPropSet, rXPropState, 
u"CharEscapementHeight"_ustr))
+    if (rXPropState && GetDirectProperty(rXPropSet, rXPropState, 
u"CharEscapementHeight"_ustr))
         mAny >>= nCharEscapementHeight;
 
     if (DFLT_ESC_AUTO_SUPER == nCharEscapement)
@@ -2870,7 +2870,7 @@ void DrawingML::WriteRunProperties(const 
Reference<XPropertySet>& rRun, sal_Int3
                                XML_charset, charset );
     }
 
-    if (GetDirectProperty(rXPropSet, rXPropState,
+    if (rXPropState && GetDirectProperty(rXPropSet, rXPropState,
                           bComplex ? u"CharFontNameComplex"_ustr : 
u"CharFontNameAsian"_ustr))
     {
         const char* const pitch = nullptr;
@@ -3958,6 +3958,236 @@ bool DrawingML::IsFontworkShape(const 
css::uno::Reference<css::beans::XPropertyS
     return bResult;
 }
 
+// Output text body properties
+void DrawingML::WriteBodyProps(const css::uno::Reference< css::uno::XInterface 
>& rXIface,
+        const uno::Reference<XPropertySet>& rXPropSet,
+        const uno::Reference<drawing::XShape>& xShape,
+        sal_Int32 nXmlNamespace, const WriteBodyPropsInput& aWBPInput)
+{
+    const char* pWrap = (aWBPInput.bHasWrap && !aWBPInput.bWrap) || 
aWBPInput.bIsFontworkShape ? "none" : nullptr;
+    if (GetDocumentType() == DOCUMENT_DOCX)
+    {
+        // In case of DOCX, if we want to have the same effect as
+        // TextShape's automatic word wrapping, then we need to set
+        // wrapping to square.
+        uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, 
uno::UNO_QUERY);
+        if ((xServiceInfo.is() && 
xServiceInfo->supportsService(u"com.sun.star.drawing.TextShape"_ustr))
+            || aWBPInput.bIsFontworkShape)
+            pWrap = "square";
+    }
+
+    sal_Int16 nCols = 0;
+    sal_Int32 nColSpacing = -1;
+    if (GetProperty(rXPropSet, u"TextColumns"_ustr))
+    {
+        if (css::uno::Reference<css::text::XTextColumns> xCols{ mAny, 
css::uno::UNO_QUERY })
+        {
+            nCols = xCols->getColumnCount();
+            if (css::uno::Reference<css::beans::XPropertySet> xProps{ mAny,
+                                                                      
css::uno::UNO_QUERY })
+            {
+                if (GetProperty(xProps, u"AutomaticDistance"_ustr))
+                    mAny >>= nColSpacing;
+            }
+        }
+    }
+
+    std::optional<OUString> sVertOverflow = aWBPInput.sVertOverflow;
+
+    if (!sVertOverflow && GetProperty(rXPropSet, 
u"TextClipVerticalOverflow"_ustr) && mAny.get<bool>())
+    {
+        sVertOverflow = "clip";
+    }
+
+    // tdf#151134 When writing placeholder shapes, inset must be explicitly 
specified
+    bool bRequireInset = GetProperty(rXPropSet, u"IsPresentationObject"_ustr) 
&& rXPropSet->getPropertyValue(u"IsPresentationObject"_ustr).get<bool>();
+
+    mpFS->startElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr,
+                           XML_numCol, 
sax_fastparser::UseIf(OString::number(nCols), nCols > 0),
+                           XML_spcCol, 
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nColSpacing)),
 nCols > 0 && nColSpacing >= 0),
+                           XML_wrap, pWrap,
+                           XML_horzOverflow, aWBPInput.sHorzOverflow,
+                           XML_vertOverflow, sVertOverflow,
+                           XML_fromWordArt, sax_fastparser::UseIf("1",
+                               aWBPInput.bFromWordArt),
+                           XML_lIns,
+                           
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(aWBPInput.nLeft)),
+                                                           bRequireInset ||
+                                                           aWBPInput.nLeft != 
mconstDefaultLeftRightInset),
+                           XML_tIns,
+                           
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(aWBPInput.nTop)),
+                                                           bRequireInset ||
+                                                           aWBPInput.nTop != 
mconstDefaultTopBottomInset),
+                           XML_rIns,
+                           
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(aWBPInput.nRight)),
+                                                           bRequireInset ||
+                                                           aWBPInput.nRight != 
mconstDefaultLeftRightInset),
+                           XML_bIns,
+                           
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(aWBPInput.nBottom)),
+                                                           bRequireInset ||
+                                                           aWBPInput.nBottom 
!= mconstDefaultTopBottomInset),
+                           XML_anchor, aWBPInput.sAnchor,
+                           XML_anchorCtr, sax_fastparser::UseIf("1", 
aWBPInput.bAnchorCtr),
+                           XML_vert, aWBPInput.sWritingMode,
+                           XML_upright, aWBPInput.sIsUpright,
+                           XML_rot, aWBPInput.sTextRotateAngleMSUnit);
+
+    if (aWBPInput.bIsFontworkShape)
+    {
+        if (aWBPInput.aAdjustmentSeq.hasElements())
+        {
+            mpFS->startElementNS(XML_a, XML_prstTxWarp, XML_prst, 
aWBPInput.sPresetWarp);
+            mpFS->startElementNS(XML_a, XML_avLst);
+            bool bHasTwoHandles(
+                aWBPInput.sPresetWarp == "textArchDownPour" || 
aWBPInput.sPresetWarp == "textArchUpPour"
+                || aWBPInput.sPresetWarp == "textButtonPour" || 
aWBPInput.sPresetWarp == "textCirclePour"
+                || aWBPInput.sPresetWarp == "textDoubleWave1" || 
aWBPInput.sPresetWarp == "textWave1"
+                || aWBPInput.sPresetWarp == "textWave2" || 
aWBPInput.sPresetWarp == "textWave4");
+            for (sal_Int32 i = 0, nElems = 
aWBPInput.aAdjustmentSeq.getLength(); i < nElems; ++i )
+            {
+                OString sName = "adj" + (bHasTwoHandles ? OString::number(i + 
1) : OString());
+                double fValue(0.0);
+                if (aWBPInput.aAdjustmentSeq[i].Value.getValueTypeClass() == 
TypeClass_DOUBLE)
+                    aWBPInput.aAdjustmentSeq[i].Value >>= fValue;
+                else
+                {
+                    sal_Int32 nNumber(0);
+                    aWBPInput.aAdjustmentSeq[i].Value >>= nNumber;
+                    fValue = static_cast<double>(nNumber);
+                }
+                // Convert from binary coordinate system with viewBox "0 0 
21600 21600" and simple degree
+                // to DrawingML with coordinate range 0..100000 and angle in 
1/60000 degree.
+                // Reverse to conversion in lcl_createPresetShape in 
drawingml/shape.cxx on import.
+                if (aWBPInput.sPresetWarp == "textArchDown" || 
aWBPInput.sPresetWarp == "textArchUp"
+                    || aWBPInput.sPresetWarp == "textButton" || 
aWBPInput.sPresetWarp == "textCircle"
+                    || ((i == 0)
+                        && (aWBPInput.sPresetWarp == "textArchDownPour" ||
+                            aWBPInput.sPresetWarp == "textArchUpPour"
+                            || aWBPInput.sPresetWarp == "textButtonPour" ||
+                            aWBPInput.sPresetWarp == "textCirclePour")))
+                {
+                    fValue *= 60000.0;
+                    if (fValue < 0)
+                        fValue += 21600000;
+                }
+                else if ((i == 1)
+                         && (aWBPInput.sPresetWarp == "textDoubleWave1" ||
+                             aWBPInput.sPresetWarp == "textWave1"
+                        || aWBPInput.sPresetWarp == "textWave2" || 
aWBPInput.sPresetWarp == "textWave4"))
+                {
+                    fValue = fValue / 0.216 - 50000.0;
+                }
+                else if ((i == 1)
+                         && (aWBPInput.sPresetWarp == "textArchDownPour"
+                             || aWBPInput.sPresetWarp == "textArchUpPour"
+                             || aWBPInput.sPresetWarp == "textButtonPour"
+                             || aWBPInput.sPresetWarp == "textCirclePour"))
+                {
+                    fValue /= 0.108;
+                }
+                else
+                {
+                    fValue /= 0.216;
+                }
+                OString sFmla = "val " + OString::number(std::lround(fValue));
+                mpFS->singleElementNS(XML_a, XML_gd, XML_name, sName, 
XML_fmla, sFmla);
+                // There exists faulty Favorite shapes with one handle but two 
adjustment values.
+                if (!bHasTwoHandles)
+                    break;
+            }
+            mpFS->endElementNS(XML_a, XML_avLst);
+            mpFS->endElementNS(XML_a, XML_prstTxWarp);
+        }
+        else
+        {
+            mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, 
aWBPInput.sPresetWarp);
+        }
+    }
+    else if (GetDocumentType() == DOCUMENT_DOCX)
+    {
+        // interim solution for fdo#80897, roundtrip DOCX > LO > DOCX
+        if (!aWBPInput.sMSWordPresetTextWarp.isEmpty())
+            mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, 
aWBPInput.sMSWordPresetTextWarp);
+    }
+
+    if (GetDocumentType() == DOCUMENT_DOCX || GetDocumentType() == 
DOCUMENT_XLSX)
+    {
+        // tdf#112312: only custom shapes obey the TextAutoGrowHeight option
+        bool bTextAutoGrowHeight = false;
+        auto pSdrObjCustomShape = xShape.is() ? 
dynamic_cast<SdrObjCustomShape*>(SdrObject::getSdrObjectFromXShape(xShape)) : 
nullptr;
+        if (pSdrObjCustomShape && GetProperty(rXPropSet, 
u"TextAutoGrowHeight"_ustr))
+        {
+            mAny >>= bTextAutoGrowHeight;
+        }
+        mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : 
XML_noAutofit));
+    }
+    if (GetDocumentType() == DOCUMENT_PPTX)
+    {
+        TextFitToSizeType eFit = TextFitToSizeType_NONE;
+        if (GetProperty(rXPropSet, u"TextFitToSize"_ustr))
+            mAny >>= eFit;
+
+        if (eFit == TextFitToSizeType_AUTOFIT)
+        {
+            const sal_Int32 MAX_SCALE_VAL = 100000;
+            sal_Int32 nFontScale = MAX_SCALE_VAL;
+            sal_Int32 nSpacingReduction = 0;
+            SvxShapeText* pTextShape = 
dynamic_cast<SvxShapeText*>(rXIface.get());
+            if (pTextShape)
+            {
+                SdrTextObj* pTextObject = 
DynCastSdrTextObj(pTextShape->GetSdrObject());
+                if (pTextObject)
+                {
+                    nFontScale = sal_Int32(pTextObject->GetFontScale() * 
100000.0);
+                    nSpacingReduction = sal_Int32((1.0 - 
pTextObject->GetSpacingScale()) * 100000.0);
+                }
+            }
+
+            bool bExportFontScale = false;
+            if (nFontScale < MAX_SCALE_VAL && nFontScale > 0)
+                bExportFontScale = true;
+
+            bool bExportSpaceReduction = false;
+            if (nSpacingReduction < MAX_SCALE_VAL && nSpacingReduction > 0)
+                bExportSpaceReduction = true;
+
+            mpFS->singleElementNS(XML_a, XML_normAutofit,
+                XML_fontScale, 
sax_fastparser::UseIf(OString::number(nFontScale), bExportFontScale),
+                XML_lnSpcReduction, 
sax_fastparser::UseIf(OString::number(nSpacingReduction), 
bExportSpaceReduction));
+        }
+        else
+        {
+            bool bAutoGrowHeightEnabled = false;
+            const SdrObject* pObj = xShape.is() ? 
SdrObject::getSdrObjectFromXShape(xShape) : nullptr;
+            if (pObj)
+            {
+                switch (pObj->GetObjIdentifier())
+                {
+                    case SdrObjKind::NONE:
+                    case SdrObjKind::Text:
+                    case SdrObjKind::TitleText:
+                    case SdrObjKind::OutlineText:
+                    case SdrObjKind::Caption:
+                    case SdrObjKind::CustomShape:
+                        bAutoGrowHeightEnabled = true;
+                        break;
+                    default:
+                        bAutoGrowHeightEnabled = false;
+                }
+            }
+
+            bool bTextAutoGrowHeight = false;
+            if (bAutoGrowHeightEnabled && GetProperty(rXPropSet, 
u"TextAutoGrowHeight"_ustr))
+                mAny >>= bTextAutoGrowHeight;
+            mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit 
: XML_noAutofit));
+        }
+    }
+
+    Write3DEffects( rXPropSet, /*bIsText=*/true );
+
+    mpFS->endElementNS((nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr);
+}
+
 void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, 
bool bText,
                           sal_Int32 nXmlNamespace, bool 
bWritePropertiesAsLstStyles)
 {
@@ -3966,26 +4196,28 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
     if( !xXText.is() )
         return;
 
+    WriteBodyPropsInput aWBPInput;
+
     uno::Reference<drawing::XShape> xShape(rXIface, UNO_QUERY);
     uno::Reference<XPropertySet> rXPropSet(rXIface, UNO_QUERY);
 
     constexpr const sal_Int32 constDefaultLeftRightInset = 254;
     constexpr const sal_Int32 constDefaultTopBottomInset = 127;
-    sal_Int32 nLeft = constDefaultLeftRightInset;
-    sal_Int32 nRight = constDefaultLeftRightInset;
-    sal_Int32 nTop = constDefaultTopBottomInset;
-    sal_Int32 nBottom = constDefaultTopBottomInset;
+    aWBPInput.nLeft = constDefaultLeftRightInset;
+    aWBPInput.nRight = constDefaultLeftRightInset;
+    aWBPInput.nTop = constDefaultTopBottomInset;
+    aWBPInput.nBottom = constDefaultTopBottomInset;
 
     // top inset looks a bit different compared to ppt export
     // check if something related doesn't work as expected
     if (GetProperty(rXPropSet, u"TextLeftDistance"_ustr))
-        mAny >>= nLeft;
+        mAny >>= aWBPInput.nLeft;
     if (GetProperty(rXPropSet, u"TextRightDistance"_ustr))
-        mAny >>= nRight;
+        mAny >>= aWBPInput.nRight;
     if (GetProperty(rXPropSet, u"TextUpperDistance"_ustr))
-        mAny >>= nTop;
+        mAny >>= aWBPInput.nTop;
     if (GetProperty(rXPropSet, u"TextLowerDistance"_ustr))
-        mAny >>= nBottom;
+        mAny >>= aWBPInput.nBottom;
 
     // Transform the text distance values so they are compatible with OOXML 
insets
     if (xShape.is())
@@ -4003,23 +4235,22 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
                 nTextHeight = convertTwipToMm100(nTextHeight);
         }
 
-        if (nTop + nBottom >= nTextHeight)
+        if (aWBPInput.nTop + aWBPInput.nBottom >= nTextHeight)
         {
             // Effective bottom would be above effective top of text area. LO 
normalizes the
             // effective text area in such case implicitly for rendering. MS 
needs indents so that
             // the result is the normalized effective text area.
-            std::swap(nTop, nBottom);
-            nTop = nTextHeight - nTop;
-            nBottom = nTextHeight - nBottom;
+            std::swap(aWBPInput.nTop, aWBPInput.nBottom);
+            aWBPInput.nTop = nTextHeight - aWBPInput.nTop;
+            aWBPInput.nBottom = nTextHeight - aWBPInput.nBottom;
         }
     }
 
-    std::optional<OString> sWritingMode;
     if (GetProperty(rXPropSet, u"TextWritingMode"_ustr))
     {
         WritingMode eMode;
         if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL )
-            sWritingMode = "eaVert";
+            aWBPInput.sWritingMode = "eaVert";
     }
     if (GetProperty(rXPropSet, u"WritingMode"_ustr))
     {
@@ -4027,24 +4258,22 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
         if (mAny >>= nWritingMode)
         {
             if (nWritingMode == text::WritingMode2::TB_RL)
-                sWritingMode = "eaVert";
+                aWBPInput.sWritingMode = "eaVert";
             else if (nWritingMode == text::WritingMode2::BT_LR)
-                sWritingMode = "vert270";
+                aWBPInput.sWritingMode = "vert270";
             else if (nWritingMode == text::WritingMode2::TB_RL90)
-                sWritingMode = "vert";
+                aWBPInput.sWritingMode = "vert";
             else if (nWritingMode == text::WritingMode2::TB_LR)
-                sWritingMode = "mongolianVert";
+                aWBPInput.sWritingMode = "mongolianVert";
             else if (nWritingMode == text::WritingMode2::STACKED)
-                sWritingMode = "wordArtVert";
+                aWBPInput.sWritingMode = "wordArtVert";
         }
     }
 
     // read values from CustomShapeGeometry
-    Sequence<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentSeq;
     uno::Sequence<beans::PropertyValue> aTextPathSeq;
     bool bScaleX(false);
     OUString sShapeType(u"non-primitive"_ustr);
-    OUString sMSWordPresetTextWarp;
     sal_Int32 nTextPreRotateAngle = 0; // degree
     std::optional<Degree100> nTextRotateAngleDeg100; // text area rotation
 
@@ -4058,7 +4287,7 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
                 if (rProp.Name == "TextPreRotateAngle")
                     rProp.Value >>= nTextPreRotateAngle;
                 else if (rProp.Name == "AdjustmentValues")
-                    rProp.Value >>= aAdjustmentSeq;
+                    rProp.Value >>= aWBPInput.aAdjustmentSeq;
                 else if (rProp.Name == "TextRotateAngle")
                 {
                     double fTextRotateAngle = 0; // degree
@@ -4077,7 +4306,7 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
                     }
                 }
                 else if (rProp.Name == "PresetTextWarp")
-                    rProp.Value >>= sMSWordPresetTextWarp;
+                    rProp.Value >>= aWBPInput.sMSWordPresetTextWarp;
             }
         }
     }
@@ -4098,16 +4327,16 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
                         switch (nWritingMode)
                         {
                         case WritingMode2::TB_RL:
-                            sWritingMode = "eaVert";
+                            aWBPInput.sWritingMode = "eaVert";
                             break;
                         case WritingMode2::BT_LR:
-                            sWritingMode = "vert270";
+                            aWBPInput.sWritingMode = "vert270";
                             break;
                         case WritingMode2::TB_RL90:
-                            sWritingMode = "vert";
+                            aWBPInput.sWritingMode = "vert";
                             break;
                         case WritingMode2::TB_LR:
-                            sWritingMode = "mongolianVert";
+                            aWBPInput.sWritingMode = "mongolianVert";
                             break;
                         default:
                             break;
@@ -4119,10 +4348,7 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
     }
 
     // read InteropGrabBag if any
-    std::optional<OUString> sHorzOverflow;
-    std::optional<OUString> sVertOverflow;
     bool bUpright = false;
-    std::optional<OString> isUpright;
     if 
(rXPropSet->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr))
     {
         uno::Sequence<beans::PropertyValue> aGrabBag;
@@ -4132,40 +4358,42 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
             if (aProp.Name == "Upright")
             {
                 aProp.Value >>= bUpright;
-                isUpright = OString(bUpright ? "1" : "0");
+                aWBPInput.sIsUpright = OString(bUpright ? "1" : "0");
             }
             else if (aProp.Name == "horzOverflow")
             {
                 OUString sValue;
                 aProp.Value >>= sValue;
-                sHorzOverflow = sValue;
+                aWBPInput.sHorzOverflow = sValue;
             }
             else if (aProp.Name == "vertOverflow")
             {
                 OUString sValue;
                 aProp.Value >>= sValue;
-                sVertOverflow = sValue;
+                aWBPInput.sVertOverflow = sValue;
             }
         }
     }
 
-    bool bIsFontworkShape(IsFontworkShape(rXPropSet));
-    OUString sPresetWarp(PresetGeometryTypeNames::GetMsoName(sShapeType));
+    aWBPInput.bIsFontworkShape = IsFontworkShape(rXPropSet);
+    aWBPInput.sPresetWarp = PresetGeometryTypeNames::GetMsoName(sShapeType);
     // ODF may have user defined TextPath, use "textPlain" as ersatz.
-    if (sPresetWarp.isEmpty())
-        sPresetWarp = bIsFontworkShape ? std::u16string_view(u"textPlain") : 
std::u16string_view(u"textNoShape");
+    if (aWBPInput.sPresetWarp.isEmpty())
+        aWBPInput.sPresetWarp = aWBPInput.bIsFontworkShape ? 
std::u16string_view(u"textPlain") : std::u16string_view(u"textNoShape");
 
-    bool bFromWordArt = !bScaleX
-                        && ( sPresetWarp == "textArchDown" || sPresetWarp == 
"textArchUp"
-                            || sPresetWarp == "textButton" || sPresetWarp == 
"textCircle");
+    aWBPInput.bFromWordArt = !bScaleX
+                        && ( aWBPInput.sPresetWarp == "textArchDown" ||
+                                aWBPInput.sPresetWarp == "textArchUp"
+                            || aWBPInput.sPresetWarp == "textButton" ||
+                            aWBPInput.sPresetWarp == "textCircle");
 
     // Fontwork shapes in LO ignore insets in rendering, Word interprets them.
-    if (GetDocumentType() == DOCUMENT_DOCX && bIsFontworkShape)
+    if (GetDocumentType() == DOCUMENT_DOCX && aWBPInput.bIsFontworkShape)
     {
-        nLeft = 0;
-        nRight = 0;
-        nTop = 0;
-        nBottom = 0;
+        aWBPInput.nLeft = 0;
+        aWBPInput.nRight = 0;
+        aWBPInput.nTop = 0;
+        aWBPInput.nBottom = 0;
     }
 
     if (bUpright)
@@ -4196,7 +4424,7 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
         else
         {
             // User changes. Keep current angles.
-            isUpright.reset();
+            aWBPInput.sIsUpright.reset();
             if (bWasAngleChanged)
             {
                 nTextPreRotateAngle += 90;
@@ -4207,12 +4435,12 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
 
     // ToDo: Unsure about this. Need to investigate shapes from diagram 
import, especially diagrams
     // with vertical text directions.
-    if (nTextPreRotateAngle != 0 && !sWritingMode)
+    if (nTextPreRotateAngle != 0 && !aWBPInput.sWritingMode)
     {
         if (nTextPreRotateAngle == -90 || nTextPreRotateAngle == 270)
-            sWritingMode = "vert";
+            aWBPInput.sWritingMode = "vert";
         else if (nTextPreRotateAngle == -270 || nTextPreRotateAngle == 90)
-            sWritingMode = "vert270";
+            aWBPInput.sWritingMode = "vert270";
         else if (nTextPreRotateAngle == -180 || nTextPreRotateAngle == 180)
         {
 #if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12
@@ -4229,7 +4457,7 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
         else
             SAL_WARN("oox", "unsuitable value for TextPreRotateAngle:" << 
nTextPreRotateAngle);
     }
-    else if (nTextPreRotateAngle != 0 && sWritingMode && sWritingMode.value() 
== "eaVert")
+    else if (nTextPreRotateAngle != 0 && aWBPInput.sWritingMode && 
aWBPInput.sWritingMode.value() == "eaVert")
     {
         // ToDo: eaVert plus 270deg clockwise rotation has to be written with 
vert="horz"
         // plus attribute 'normalEastAsianFlow="1"' on the <wps:wsp> element.
@@ -4238,38 +4466,37 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
 
     // Our WritingMode introduces text pre rotation which includes padding, 
MSO vert does not include
     // padding. Therefore set padding so, that is looks the same in MSO as in 
LO.
-    if (sWritingMode)
+    if (aWBPInput.sWritingMode)
     {
-        if (sWritingMode.value() == "vert" || sWritingMode.value() == "eaVert")
+        if (aWBPInput.sWritingMode.value() == "vert" || 
aWBPInput.sWritingMode.value() == "eaVert")
         {
-            sal_Int32 nHelp = nLeft;
-            nLeft = nBottom;
-            nBottom = nRight;
-            nRight = nTop;
-            nTop = nHelp;
+            sal_Int32 nHelp = aWBPInput.nLeft;
+            aWBPInput.nLeft = aWBPInput.nBottom;
+            aWBPInput.nBottom = aWBPInput.nRight;
+            aWBPInput.nRight = aWBPInput.nTop;
+            aWBPInput.nTop = nHelp;
         }
-        else if (sWritingMode.value() == "vert270")
+        else if (aWBPInput.sWritingMode.value() == "vert270")
         {
-            sal_Int32 nHelp = nLeft;
-            nLeft = nTop;
-            nTop = nRight;
-            nRight = nBottom;
-            nBottom = nHelp;
+            sal_Int32 nHelp = aWBPInput.nLeft;
+            aWBPInput.nLeft = aWBPInput.nTop;
+            aWBPInput.nTop = aWBPInput.nRight;
+            aWBPInput.nRight = aWBPInput.nBottom;
+            aWBPInput.nBottom = nHelp;
         }
-        else if (sWritingMode.value() == "mongolianVert")
+        else if (aWBPInput.sWritingMode.value() == "mongolianVert")
         {
             // ToDo: Examine padding
         }
     }
 
 
-    std::optional<OString> sTextRotateAngleMSUnit;
     if (nTextRotateAngleDeg100.has_value())
 #if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
 #endif
-        sTextRotateAngleMSUnit
+        aWBPInput.sTextRotateAngleMSUnit
             = 
oox::drawingml::calcRotationValue(nTextRotateAngleDeg100.value().get());
 #if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12
 #pragma GCC diagnostic pop
@@ -4285,42 +4512,40 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
     if (GetProperty(rXPropSet, u"TextHorizontalAdjust"_ustr))
         mAny >>= eHorizontalAlignment;
 
-    const char* sAnchor = nullptr;
-    bool bAnchorCtr = false;
-    if (sWritingMode.has_value()
-        && (sWritingMode.value() == "eaVert" || sWritingMode.value() == 
"mongolianVert"))
+    if (aWBPInput.sWritingMode.has_value()
+        && (aWBPInput.sWritingMode.value() == "eaVert" || 
aWBPInput.sWritingMode.value() == "mongolianVert"))
     {
-        bAnchorCtr = eVerticalAlignment == TextVerticalAdjust_CENTER
+        aWBPInput.bAnchorCtr = eVerticalAlignment == TextVerticalAdjust_CENTER
                      || eVerticalAlignment == TextVerticalAdjust_BOTTOM
                      || eVerticalAlignment == TextVerticalAdjust_BLOCK;
         switch (eHorizontalAlignment)
         {
             case TextHorizontalAdjust_CENTER:
-                sAnchor = "ctr";
+                aWBPInput.sAnchor = "ctr";
                 break;
             case TextHorizontalAdjust_LEFT:
-                sAnchor = sWritingMode.value() == "eaVert" ? "b" : "t";
+                aWBPInput.sAnchor = aWBPInput.sWritingMode.value() == "eaVert" 
? "b" : "t";
                 break;
             case TextHorizontalAdjust_RIGHT:
             default: // TextHorizontalAdjust_BLOCK, should not happen
-                sAnchor = sWritingMode.value() == "eaVert" ? "t" : "b";
+                aWBPInput.sAnchor = aWBPInput.sWritingMode.value() == "eaVert" 
? "t" : "b";
                 break;
         }
     }
     else
     {
-        bAnchorCtr = eHorizontalAlignment == TextHorizontalAdjust_CENTER
+        aWBPInput.bAnchorCtr = eHorizontalAlignment == 
TextHorizontalAdjust_CENTER
                      || eHorizontalAlignment == TextHorizontalAdjust_RIGHT;
-        sAnchor = GetTextVerticalAdjust(eVerticalAlignment);
+        aWBPInput.sAnchor = GetTextVerticalAdjust(eVerticalAlignment);
     }
 
-    bool bHasWrap = false;
-    bool bWrap = false;
+    aWBPInput.bHasWrap = false;
+    aWBPInput.bWrap = false;
     // Only custom shapes obey the TextWordWrap option, normal text always 
wraps.
     if (dynamic_cast<SvxCustomShape*>(rXIface.get()) && GetProperty(rXPropSet, 
u"TextWordWrap"_ustr))
     {
-        mAny >>= bWrap;
-        bHasWrap = true;
+        mAny >>= aWBPInput.bWrap;
+        aWBPInput.bHasWrap = true;
     }
 
     // tdf#134401: If AUTOGROWWIDTH and AUTOGROWHEIGHT are set, then export it 
as TextWordWrap
@@ -4334,222 +4559,15 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
 
         if (rSdrTextFitWidth.GetValue() == true && 
rSdrTextFitHeight.GetValue() == true)
         {
-            bHasWrap = true;
-            bWrap = false;
+            aWBPInput.bHasWrap = true;
+            aWBPInput.bWrap = false;
         }
     }
 
     if (bBodyPr)
     {
-        const char* pWrap = (bHasWrap && !bWrap) || bIsFontworkShape ? "none" 
: nullptr;
-        if (GetDocumentType() == DOCUMENT_DOCX)
-        {
-            // In case of DOCX, if we want to have the same effect as
-            // TextShape's automatic word wrapping, then we need to set
-            // wrapping to square.
-            uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, 
uno::UNO_QUERY);
-            if ((xServiceInfo.is() && 
xServiceInfo->supportsService(u"com.sun.star.drawing.TextShape"_ustr))
-                || bIsFontworkShape)
-                pWrap = "square";
-        }
-
-        sal_Int16 nCols = 0;
-        sal_Int32 nColSpacing = -1;
-        if (GetProperty(rXPropSet, u"TextColumns"_ustr))
-        {
-            if (css::uno::Reference<css::text::XTextColumns> xCols{ mAny, 
css::uno::UNO_QUERY })
-            {
-                nCols = xCols->getColumnCount();
-                if (css::uno::Reference<css::beans::XPropertySet> xProps{ mAny,
-                                                                          
css::uno::UNO_QUERY })
-                {
-                    if (GetProperty(xProps, u"AutomaticDistance"_ustr))
-                        mAny >>= nColSpacing;
-                }
-            }
-        }
-
-        if (!sVertOverflow && GetProperty(rXPropSet, 
u"TextClipVerticalOverflow"_ustr) && mAny.get<bool>())
-        {
-            sVertOverflow = "clip";
-        }
-
-        // tdf#151134 When writing placeholder shapes, inset must be 
explicitly specified
-        bool bRequireInset = GetProperty(rXPropSet, 
u"IsPresentationObject"_ustr) && 
rXPropSet->getPropertyValue(u"IsPresentationObject"_ustr).get<bool>();
-
-        mpFS->startElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), 
XML_bodyPr,
-                               XML_numCol, 
sax_fastparser::UseIf(OString::number(nCols), nCols > 0),
-                               XML_spcCol, 
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nColSpacing)),
 nCols > 0 && nColSpacing >= 0),
-                               XML_wrap, pWrap,
-                               XML_horzOverflow, sHorzOverflow,
-                               XML_vertOverflow, sVertOverflow,
-                               XML_fromWordArt, sax_fastparser::UseIf("1", 
bFromWordArt),
-                               XML_lIns, 
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nLeft)),
-                                                               bRequireInset 
|| nLeft != constDefaultLeftRightInset),
-                               XML_tIns, 
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nTop)),
-                                                               bRequireInset 
|| nTop != constDefaultTopBottomInset),
-                               XML_rIns, 
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nRight)),
-                                                               bRequireInset 
|| nRight != constDefaultLeftRightInset),
-                               XML_bIns, 
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nBottom)),
-                                                               bRequireInset 
|| nBottom != constDefaultTopBottomInset),
-                               XML_anchor, sAnchor,
-                               XML_anchorCtr, sax_fastparser::UseIf("1", 
bAnchorCtr),
-                               XML_vert, sWritingMode,
-                               XML_upright, isUpright,
-                               XML_rot, sTextRotateAngleMSUnit);
-
-        if (bIsFontworkShape)
-        {
-            if (aAdjustmentSeq.hasElements())
-            {
-                mpFS->startElementNS(XML_a, XML_prstTxWarp, XML_prst, 
sPresetWarp);
-                mpFS->startElementNS(XML_a, XML_avLst);
-                bool bHasTwoHandles(
-                    sPresetWarp == "textArchDownPour" || sPresetWarp == 
"textArchUpPour"
-                    || sPresetWarp == "textButtonPour" || sPresetWarp == 
"textCirclePour"
-                    || sPresetWarp == "textDoubleWave1" || sPresetWarp == 
"textWave1"
-                    || sPresetWarp == "textWave2" || sPresetWarp == 
"textWave4");
-                for (sal_Int32 i = 0, nElems = aAdjustmentSeq.getLength(); i < 
nElems; ++i )
-                {
-                    OString sName = "adj" + (bHasTwoHandles ? 
OString::number(i + 1) : OString());
-                    double fValue(0.0);
-                    if (aAdjustmentSeq[i].Value.getValueTypeClass() == 
TypeClass_DOUBLE)
-                        aAdjustmentSeq[i].Value >>= fValue;
-                    else
-                    {
-                        sal_Int32 nNumber(0);
-                        aAdjustmentSeq[i].Value >>= nNumber;
-                        fValue = static_cast<double>(nNumber);
-                    }
-                    // Convert from binary coordinate system with viewBox "0 0 
21600 21600" and simple degree
-                    // to DrawingML with coordinate range 0..100000 and angle 
in 1/60000 degree.
-                    // Reverse to conversion in lcl_createPresetShape in 
drawingml/shape.cxx on import.
-                    if (sPresetWarp == "textArchDown" || sPresetWarp == 
"textArchUp"
-                        || sPresetWarp == "textButton" || sPresetWarp == 
"textCircle"
-                        || ((i == 0)
-                            && (sPresetWarp == "textArchDownPour" || 
sPresetWarp == "textArchUpPour"
-                                || sPresetWarp == "textButtonPour" || 
sPresetWarp == "textCirclePour")))
-                    {
-                        fValue *= 60000.0;
-                        if (fValue < 0)
-                            fValue += 21600000;
-                    }
-                    else if ((i == 1)
-                             && (sPresetWarp == "textDoubleWave1" || 
sPresetWarp == "textWave1"
-                            || sPresetWarp == "textWave2" || sPresetWarp == 
"textWave4"))
-                    {
-                        fValue = fValue / 0.216 - 50000.0;
-                    }
-                    else if ((i == 1)
-                             && (sPresetWarp == "textArchDownPour"
-                                 || sPresetWarp == "textArchUpPour"
-                                 || sPresetWarp == "textButtonPour"
-                                 || sPresetWarp == "textCirclePour"))
-                    {
-                        fValue /= 0.108;
-                    }
-                    else
-                    {
-                        fValue /= 0.216;
-                    }
-                    OString sFmla = "val " + 
OString::number(std::lround(fValue));
-                    mpFS->singleElementNS(XML_a, XML_gd, XML_name, sName, 
XML_fmla, sFmla);
-                    // There exists faulty Favorite shapes with one handle but 
two adjustment values.
-                    if (!bHasTwoHandles)
-                        break;
-                }
-                mpFS->endElementNS(XML_a, XML_avLst);
-                mpFS->endElementNS(XML_a, XML_prstTxWarp);
-            }
-            else
-            {
-                mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, 
sPresetWarp);
-            }
-        }
-        else if (GetDocumentType() == DOCUMENT_DOCX)
-        {
-            // interim solution for fdo#80897, roundtrip DOCX > LO > DOCX
-            if (!sMSWordPresetTextWarp.isEmpty())
-                mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, 
sMSWordPresetTextWarp);
-        }
-
-        if (GetDocumentType() == DOCUMENT_DOCX || GetDocumentType() == 
DOCUMENT_XLSX)
-        {
-            // tdf#112312: only custom shapes obey the TextAutoGrowHeight 
option
-            bool bTextAutoGrowHeight = false;
-            auto pSdrObjCustomShape = xShape.is() ? 
dynamic_cast<SdrObjCustomShape*>(SdrObject::getSdrObjectFromXShape(xShape)) : 
nullptr;
-            if (pSdrObjCustomShape && GetProperty(rXPropSet, 
u"TextAutoGrowHeight"_ustr))
-            {
-                mAny >>= bTextAutoGrowHeight;
-            }
-            mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit 
: XML_noAutofit));
-        }
-        if (GetDocumentType() == DOCUMENT_PPTX)
-        {
-            TextFitToSizeType eFit = TextFitToSizeType_NONE;
-            if (GetProperty(rXPropSet, u"TextFitToSize"_ustr))
-                mAny >>= eFit;
-
-            if (eFit == TextFitToSizeType_AUTOFIT)
-            {
-                const sal_Int32 MAX_SCALE_VAL = 100000;
-                sal_Int32 nFontScale = MAX_SCALE_VAL;
-                sal_Int32 nSpacingReduction = 0;
-                SvxShapeText* pTextShape = 
dynamic_cast<SvxShapeText*>(rXIface.get());
-                if (pTextShape)
-                {
-                    SdrTextObj* pTextObject = 
DynCastSdrTextObj(pTextShape->GetSdrObject());
-                    if (pTextObject)
-                    {
-                        nFontScale = sal_Int32(pTextObject->GetFontScale() * 
100000.0);
-                        nSpacingReduction = sal_Int32((1.0 - 
pTextObject->GetSpacingScale()) * 100000.0);
-                    }
-                }
-
-                bool bExportFontScale = false;
-                if (nFontScale < MAX_SCALE_VAL && nFontScale > 0)
-                    bExportFontScale = true;
-
-                bool bExportSpaceReduction = false;
-                if (nSpacingReduction < MAX_SCALE_VAL && nSpacingReduction > 0)
-                    bExportSpaceReduction = true;
-
-                mpFS->singleElementNS(XML_a, XML_normAutofit,
-                    XML_fontScale, 
sax_fastparser::UseIf(OString::number(nFontScale), bExportFontScale),
-                    XML_lnSpcReduction, 
sax_fastparser::UseIf(OString::number(nSpacingReduction), 
bExportSpaceReduction));
-            }
-            else
-            {
-                bool bAutoGrowHeightEnabled = false;
-                const SdrObject* pObj = xShape.is() ? 
SdrObject::getSdrObjectFromXShape(xShape) : nullptr;
-                if (pObj)
-                {
-                    switch (pObj->GetObjIdentifier())
-                    {
-                        case SdrObjKind::NONE:
-                        case SdrObjKind::Text:
-                        case SdrObjKind::TitleText:
-                        case SdrObjKind::OutlineText:
-                        case SdrObjKind::Caption:
-                        case SdrObjKind::CustomShape:
-                            bAutoGrowHeightEnabled = true;
-                            break;
-                        default:
-                            bAutoGrowHeightEnabled = false;
-                    }
-                }
-
-                bool bTextAutoGrowHeight = false;
-                if (bAutoGrowHeightEnabled && GetProperty(rXPropSet, 
u"TextAutoGrowHeight"_ustr))
-                    mAny >>= bTextAutoGrowHeight;
-                mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? 
XML_spAutoFit : XML_noAutofit));
-            }
-        }
-
-        Write3DEffects( rXPropSet, /*bIsText=*/true );
-
-        mpFS->endElementNS((nXmlNamespace ? nXmlNamespace : XML_a), 
XML_bodyPr);
-    }
+        WriteBodyProps(rXIface, rXPropSet, xShape, nXmlNamespace, aWBPInput);
+    } // end of bodyPr
 
     Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
     if( !access.is() || !bText )
@@ -4564,7 +4582,7 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
     if (pTxtObj && mpTextExport)
     {
-e 
... etc. - the rest is truncated

Reply via email to