chart2/inc/ChartModel.hxx                      |    5 
 chart2/source/model/main/ChartModel.cxx        |   19 +
 docmodel/Library_docmodel.mk                   |    2 
 docmodel/source/styles/ChartStyle.cxx          |   21 +
 docmodel/source/uno/UnoChartStyle.cxx          |   36 +++
 include/docmodel/styles/ChartStyle.hxx         |  117 ++++++++++
 include/docmodel/uno/UnoChartStyle.hxx         |   54 ++++
 include/oox/core/xmlfilterbase.hxx             |    2 
 include/oox/drawingml/chart/chartconverter.hxx |   37 ++-
 offapi/UnoApi_offapi.mk                        |    1 
 offapi/com/sun/star/chart2/XChartDocument.idl  |    5 
 offapi/com/sun/star/chart2/XChartStyle.idl     |   24 ++
 oox/Library_oox.mk                             |    2 
 oox/inc/drawingml/chart/converterbase.hxx      |    4 
 oox/inc/drawingml/chart/stylefragment.hxx      |   76 ++++++
 oox/inc/drawingml/chart/stylemodel.hxx         |   91 ++++++++
 oox/source/core/xmlfilterbase.cxx              |    1 
 oox/source/drawingml/chart/chartconverter.cxx  |   41 +++
 oox/source/drawingml/chart/converterbase.cxx   |   10 
 oox/source/drawingml/chart/stylefragment.cxx   |  278 +++++++++++++++++++++++++
 oox/source/drawingml/chart/stylemodel.cxx      |   51 ++++
 oox/source/drawingml/shape.cxx                 |   32 ++
 oox/source/drawingml/textbodyproperties.cxx    |    3 
 oox/source/token/namespaces-strict.txt         |    1 
 oox/source/token/namespaces.hxx.tail           |    1 
 oox/source/token/namespaces.txt                |    1 
 oox/source/token/tokens.txt                    |    3 
 sc/source/filter/inc/excelchartconverter.hxx   |    5 
 sc/source/filter/oox/excelchartconverter.cxx   |    5 
 29 files changed, 905 insertions(+), 23 deletions(-)

New commits:
commit 33bbf0bd20fc9ac999bcd743535236b2b91c07cd
Author:     Kurt Nordback <kurt.nordb...@collabora.com>
AuthorDate: Wed Aug 13 12:53:46 2025 -0600
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Wed Sep 3 16:54:45 2025 +0200

    tdf#167941 - Chart style file is not supported in OOXML
    
    Parse the style*.xml file in the OOXML package, and store the imported
    styles in XChartDocument via a new XChartStyle. Some areas are yet to be
    fleshed out, but the intent here is to get a review of the general approach
    and architecture. This includes no work on the export side (or the UI and
    application of styles to a chart, which is a separate but related project).
    
    Change-Id: I9d5b9f5aa44fb7944b2d971edc26e04dc2256c7f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189531
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/chart2/inc/ChartModel.hxx b/chart2/inc/ChartModel.hxx
index 0860ed82c26d..b24c5c459d79 100644
--- a/chart2/inc/ChartModel.hxx
+++ b/chart2/inc/ChartModel.hxx
@@ -70,6 +70,8 @@ namespace com::sun::star::uno { class XComponentContext; }
 class SvNumberFormatter;
 class SvNumberFormatsSupplierObj;
 
+class UnoChartStyle;
+
 namespace model { class Theme; }
 
 namespace chart
@@ -188,6 +190,8 @@ private:
 
     std::optional<css::util::DateTime> m_aNullDate;
 
+    rtl::Reference<UnoChartStyle> m_aStyles;
+
 private:
     //private methods
 
@@ -381,6 +385,7 @@ public:
         setChartTypeManager( const css::uno::Reference< 
css::chart2::XChartTypeManager >& xNewManager ) override;
     virtual css::uno::Reference< css::chart2::XChartTypeManager > SAL_CALL
         getChartTypeManager() override;
+    virtual css::uno::Reference< css::chart2::XChartStyle> SAL_CALL 
getStyles() override;
     virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
         getPageBackground() override;
 
diff --git a/chart2/source/model/main/ChartModel.cxx 
b/chart2/source/model/main/ChartModel.cxx
index 2bf22ae82b2b..b360e934e2c0 100644
--- a/chart2/source/model/main/ChartModel.cxx
+++ b/chart2/source/model/main/ChartModel.cxx
@@ -77,6 +77,7 @@
 #include <com/sun/star/util/XTheme.hpp>
 #include <docmodel/uno/UnoTheme.hxx>
 #include <docmodel/theme/Theme.hxx>
+#include <docmodel/uno/UnoChartStyle.hxx>
 
 using ::com::sun::star::uno::Sequence;
 using ::com::sun::star::uno::Reference;
@@ -128,6 +129,7 @@ 
ChartModel::ChartModel(uno::Reference<uno::XComponentContext > xContext)
     , m_xXMLNamespaceMap( new NameContainer() )
     , m_eColorPaletteType(ChartColorPaletteType::Unknown)
     , m_nColorPaletteIndex(0)
+    , m_aStyles(new UnoChartStyle)
     , mnStart(0)
     , mnEnd(0)
 {
@@ -139,6 +141,9 @@ 
ChartModel::ChartModel(uno::Reference<uno::XComponentContext > xContext)
 
     {
         m_xPageBackground->addModifyListener( this );
+#if 0 // TODO
+        m_aStyles->addModifyListener( this );
+#endif
         m_xChartTypeManager = new ::chart::ChartTypeManager( m_xContext );
     }
     osl_atomic_decrement(&m_refCount);
@@ -185,6 +190,7 @@ ChartModel::ChartModel( const ChartModel & rOther )
         if (rOther.m_xDiagram.is())
             xNewDiagram = new ::chart::Diagram( *rOther.m_xDiagram );
         rtl::Reference< ::chart::PageBackground > xNewPageBackground = new 
PageBackground( *rOther.m_xPageBackground );
+        rtl::Reference<UnoChartStyle> xNewChartStyle = new 
UnoChartStyle(*rOther.m_aStyles);
 
         {
             rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager; // 
does not implement XCloneable
@@ -196,6 +202,7 @@ ChartModel::ChartModel( const ChartModel & rOther )
                 m_xTitle = xNewTitle;
                 m_xDiagram = xNewDiagram;
                 m_xPageBackground = xNewPageBackground;
+                m_aStyles = xNewChartStyle;
                 m_xChartTypeManager = std::move(xChartTypeManager);
                 m_xXMLNamespaceMap = std::move(xXMLNamespaceMap);
             }
@@ -206,6 +213,11 @@ ChartModel::ChartModel( const ChartModel & rOther )
             xNewDiagram->addModifyListener( xListener );
         if( xNewPageBackground && xListener)
             xNewPageBackground->addModifyListener( xListener );
+#if 0 // TODO
+        if( xNewChartStyle && xListener) {
+            xNewChartStyle->addModifyListener( xListener );
+        }
+#endif
         xListener.clear();
     }
     osl_atomic_decrement(&m_refCount);
@@ -585,6 +597,7 @@ void SAL_CALL ChartModel::dispose()
     m_xTitle.clear();
     m_xPageBackground.clear();
     m_xXMLNamespaceMap.clear();
+    m_aStyles.clear();
 
     m_xStorage.clear();
         // just clear, don't dispose - we're not the owner
@@ -812,6 +825,12 @@ uno::Reference< chart2::data::XDataProvider > SAL_CALL 
ChartModel::getDataProvid
     return m_xDataProvider;
 }
 
+uno::Reference< chart2::XChartStyle > SAL_CALL ChartModel::getStyles()
+{
+    MutexGuard aGuard( m_aModelMutex );
+    return m_aStyles;
+}
+
 // ____ XDataReceiver ____
 
 void SAL_CALL ChartModel::attachDataProvider( const uno::Reference< 
chart2::data::XDataProvider >& xDataProvider )
diff --git a/docmodel/Library_docmodel.mk b/docmodel/Library_docmodel.mk
index d5f45316020f..83a4cadcbcee 100644
--- a/docmodel/Library_docmodel.mk
+++ b/docmodel/Library_docmodel.mk
@@ -11,11 +11,13 @@ $(eval $(call gb_Library_Library,docmodel))
 
 $(eval $(call gb_Library_add_exception_objects,docmodel,\
     docmodel/source/uno/UnoComplexColor \
+    docmodel/source/uno/UnoChartStyle \
     docmodel/source/uno/UnoGradientTools \
     docmodel/source/uno/UnoTheme \
     docmodel/source/theme/ColorSet \
     docmodel/source/theme/Theme \
     docmodel/source/color/ComplexColorJSON \
+    docmodel/source/styles/ChartStyle \
 ))
 
 $(eval $(call gb_Library_set_include,docmodel,\
diff --git a/docmodel/source/styles/ChartStyle.cxx 
b/docmodel/source/styles/ChartStyle.cxx
new file mode 100644
index 000000000000..c2d5037e98a8
--- /dev/null
+++ b/docmodel/source/styles/ChartStyle.cxx
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <docmodel/styles/ChartStyle.hxx>
+#include <utility>
+
+using namespace model;
+
+void StyleSet::addEntry(enum StyleEntryType eType, const StyleEntry& aEntry)
+{
+    maEntryMap.emplace(std::make_pair(eType, aEntry));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/docmodel/source/uno/UnoChartStyle.cxx 
b/docmodel/source/uno/UnoChartStyle.cxx
new file mode 100644
index 000000000000..8aeb5cb52b99
--- /dev/null
+++ b/docmodel/source/uno/UnoChartStyle.cxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <docmodel/uno/UnoChartStyle.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+using namespace css;
+
+namespace model::style
+{
+uno::Reference<chart2::XChartStyle> createXChartStyle(model::StyleSet const& 
rStyle)
+{
+    return new UnoChartStyle(rStyle);
+}
+
+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 aChartStyle;
+}
+
+} // end model::style
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/docmodel/styles/ChartStyle.hxx 
b/include/docmodel/styles/ChartStyle.hxx
new file mode 100644
index 000000000000..e455e6e37b1f
--- /dev/null
+++ b/include/docmodel/styles/ChartStyle.hxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <oox/drawingml/color.hxx>
+#include <docmodel/color/ComplexColor.hxx>
+#include <oox/drawingml/shape.hxx>
+#include <oox/helper/propertymap.hxx>
+#include <memory>
+#include <variant>
+
+namespace model
+{
+struct StyleColor
+{
+    enum class StyleColorEnum
+    {
+        AUTO
+    };
+
+    // 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;
+
+    StyleColorVec maStyleClr;
+    sal_Int32 mnIdx;
+    oox::drawingml::Color maColor;
+    model::ComplexColor maComplexColor;
+    // There's also an a:EG_ColorTransform member and a 'mods' member for
+    // StyleColor. Ignore those for now. TODO
+};
+
+struct StyleEntry
+{
+    std::shared_ptr<StyleColor> mxLnClr;
+    double mfLineWidthScale = 1.0;
+    std::shared_ptr<StyleColor> mxFillClr;
+    std::shared_ptr<StyleColor> mxEffectClr;
+    std::shared_ptr<StyleColor> 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,
+               std::shared_ptr<oox::PropertyMap> aCharProps,
+               std::shared_ptr<oox::PropertyMap> aBodyProps)
+        : mxLnClr(aLnClr)
+        , mfLineWidthScale(fLineScale)
+        , mxFillClr(aFillClr)
+        , mxEffectClr(aEffectClr)
+        , mxFontClr(aFontClr)
+        , mxShapePr(aShape)
+        , mrTextCharacterPr(aCharProps)
+        , mxTextBodyPr(aBodyProps)
+    {
+    }
+};
+
+struct DOCMODEL_DLLPUBLIC StyleSet
+{
+    enum class StyleEntryType
+    {
+        AXISTITLE,
+        CATEGORYAXIS,
+        CHARTAREA,
+        DATALABEL,
+        DATALABELCALLOUT,
+        DATAPOINT,
+        DATAPOINT3D,
+        DATAPOINTLINE,
+        DATAPOINTMARKER,
+        DATAPOINTMARKERLAYOUT,
+        DATAPOINTWIREFRAME,
+        DATATABLE,
+        DOWNBAR,
+        DROPLINE,
+        ERRORBAR,
+        FLOOR,
+        GRIDLINEMAJOR,
+        GRIDLINEMINOR,
+        HILOLINE,
+        LEADERLINE,
+        LEGEND,
+        PLOTAREA,
+        PLOTAREA3D,
+        SERIESAXIS,
+        SERIESLINE,
+        TITLE,
+        TRENDLINE,
+        TRENDLINELABEL,
+        UPBAR,
+        VALUEAXIS,
+        WALL
+    };
+
+    std::map<enum StyleEntryType, StyleEntry> maEntryMap;
+
+    sal_Int32 mnId;
+
+    void addEntry(enum StyleEntryType eType, const StyleEntry& aEntry);
+};
+
+} // namespace model
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/docmodel/uno/UnoChartStyle.hxx 
b/include/docmodel/uno/UnoChartStyle.hxx
new file mode 100644
index 000000000000..91588a985c9d
--- /dev/null
+++ b/include/docmodel/uno/UnoChartStyle.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <config_options.h>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+
+#include <com/sun/star/chart2/XChartStyle.hpp>
+
+#include <docmodel/dllapi.h>
+#include <docmodel/styles/ChartStyle.hxx>
+
+class UNLESS_MERGELIBS(DOCMODEL_DLLPUBLIC) UnoChartStyle final
+    : public cppu::WeakImplHelper<css::chart2::XChartStyle>
+#if 0 // TODO
+   ,public css::util::XModifyListener       // I think this is needed
+   ,public css::util::XModifyBroadcaster    // I think this is needed
+#endif
+
+{
+private:
+    model::StyleSet maStyle;
+
+public:
+    UnoChartStyle() = default;
+
+    UnoChartStyle(model::StyleSet const& rStyle)
+        : maStyle(rStyle)
+    {
+    }
+
+    model::StyleSet& getChartStyle() { return maStyle; }
+
+    // XChartStyle
+};
+
+namespace model::style
+{
+DOCMODEL_DLLPUBLIC css::uno::Reference<css::chart2::XChartStyle>
+createXChartStyle(model::StyleSet const& rStyle);
+DOCMODEL_DLLPUBLIC model::StyleSet
+getFromXChartStyle(css::uno::Reference<css::chart2::XChartStyle> const& 
rxStyle);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/oox/core/xmlfilterbase.hxx 
b/include/oox/core/xmlfilterbase.hxx
index 1fcbf06bdaeb..fe69eb7f3c10 100644
--- a/include/oox/core/xmlfilterbase.hxx
+++ b/include/oox/core/xmlfilterbase.hxx
@@ -43,6 +43,7 @@ namespace com::sun::star {
 namespace oox {
     namespace drawingml { class Theme; }
     namespace drawingml::chart { class ChartConverter; }
+    namespace drawingml::chart { class ChartStyleConverter; }
     namespace drawingml::table {
         class TableStyleList;
         typedef std::shared_ptr< TableStyleList > TableStyleListPtr;
@@ -95,6 +96,7 @@ public:
     /** Has to be implemented by each filter, returns a filter-specific chart
         converter object, that should be global per imported document. */
     virtual ::oox::drawingml::chart::ChartConverter* getChartConverter() = 0;
+    //virtual ::oox::drawingml::chart::ChartStyleConverter* 
getChartStyleConverter() = 0;
 
     /** Helper to switch chart data table - specifically for xlsx imports */
     virtual void useInternalChartDataTable( bool /*bInternal*/ ) { }
diff --git a/include/oox/drawingml/chart/chartconverter.hxx 
b/include/oox/drawingml/chart/chartconverter.hxx
index fcf3b2fee3fa..1f41f386988b 100644
--- a/include/oox/drawingml/chart/chartconverter.hxx
+++ b/include/oox/drawingml/chart/chartconverter.hxx
@@ -20,6 +20,8 @@
 #ifndef INCLUDED_OOX_DRAWINGML_CHART_CHARTCONVERTER_HXX
 #define INCLUDED_OOX_DRAWINGML_CHART_CHARTCONVERTER_HXX
 
+#include <oox/core/xmlfilterbase.hxx>
+#include <oox/drawingml/chart/modelbase.hxx>
 #include <com/sun/star/uno/Reference.hxx>
 #include <oox/dllapi.h>
 #include <rtl/ustring.hxx>
@@ -29,6 +31,7 @@ namespace com::sun::star {
     namespace awt { struct Size; }
     namespace drawing { class XShapes; }
     namespace chart2 { class XChartDocument; }
+    namespace chart2 { class XChartStyle; }
     namespace chart2::data { class XDataProvider; }
     namespace chart2::data { class XDataSequence; }
 }
@@ -39,7 +42,9 @@ namespace oox::drawingml::chart {
 
 struct ChartSpaceModel;
 struct DataSequenceModel;
-
+struct StyleModel;
+struct StyleEntryModel;
+typedef ModelRef< StyleEntryModel >      StyleEntryRef;
 
 class OOX_DLLPUBLIC ChartConverter
 {
@@ -72,12 +77,13 @@ public:
                             const css::uno::Reference< 
css::chart2::XChartDocument >& rxChartDoc,
                             const css::uno::Reference< css::drawing::XShapes 
>& rxExternalPage,
                             const css::awt::Point& rChartPos,
-                            const css::awt::Size& rChartSize );
+                            const css::awt::Size& rChartSize ) const;
 
     /** Creates an internal data provider. Derived classes may override this
         function to create an external data provider. */
     virtual void        createDataProvider(
-                            const css::uno::Reference< 
css::chart2::XChartDocument >& rxChartDoc );
+                            const css::uno::Reference<
+                            css::chart2::XChartDocument >& rxChartDoc ) const;
 
     /** Creates a data sequence from a formula. Dummy implementation. Derived
         classes have to override this function to actually parse the formula. 
*/
@@ -85,13 +91,36 @@ public:
         createDataSequence(
             const css::uno::Reference<css::chart2::data::XDataProvider>& 
rxDataProvider,
             const DataSequenceModel& rDataSeq, const OUString& rRole,
-            const OUString& aRoleQualifier );
+            const OUString& aRoleQualifier ) const;
 
 private:
                         ChartConverter( const ChartConverter& ) = delete;
     ChartConverter&     operator=( const ChartConverter& ) = delete;
 };
 
+class OOX_DLLPUBLIC ChartStyleConverter
+{
+public:
+    explicit    ChartStyleConverter() = default;
+    virtual     ~ChartStyleConverter() = default;
+
+    /** Converts the passed ChartStyleModel to the passed chart2 XChartStyle.
+
+        @param rChartStyleModel  The filled chart style model structure.
+
+        @param rxChartStyle  The UNO chart style structure to be initialized.
+
+     */
+    static void convertFromModel(
+                    oox::core::XmlFilterBase& rFilter,
+                    StyleModel& rChartStyleModel,
+                    const css::uno::Reference< css::chart2::XChartStyle >& 
rxChartStyle);
+
+private:
+    ChartStyleConverter( const ChartStyleConverter& ) = delete;
+    ChartStyleConverter&     operator=( const ChartStyleConverter& ) = delete;
+};
+
 
 } // namespace oox::drawingml::chart
 
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 043045367745..e229ad0db8e4 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -1995,6 +1995,7 @@ $(eval $(call 
gb_UnoApi_add_idlfiles,offapi,com/sun/star/chart2,\
        XChartDocument \
        XChartShape \
        XChartShapeContainer \
+    XChartStyle \
        XChartType \
        XChartTypeContainer \
        XChartTypeManager \
diff --git a/offapi/com/sun/star/chart2/XChartDocument.idl 
b/offapi/com/sun/star/chart2/XChartDocument.idl
index 439c90861a27..50236f7be9ab 100644
--- a/offapi/com/sun/star/chart2/XChartDocument.idl
+++ b/offapi/com/sun/star/chart2/XChartDocument.idl
@@ -112,6 +112,11 @@ interface XChartDocument : ::com::sun::star::frame::XModel
         you have to get its wall.  You can get the wall by calling
         XDiagram::getWall().</p>
      */
+
+    /** Get style information
+     */
+    XChartStyle getStyles();
+
     com::sun::star::beans::XPropertySet getPageBackground();
 
     /** Creates a default chart type for a brand-new chart object.
diff --git a/offapi/com/sun/star/chart2/XChartStyle.idl 
b/offapi/com/sun/star/chart2/XChartStyle.idl
new file mode 100644
index 000000000000..0e5645eea25c
--- /dev/null
+++ b/offapi/com/sun/star/chart2/XChartStyle.idl
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+
+module com {  module sun {  module star {  module chart2 {
+
+/** Chart style interface
+
+    @since LibreOffice 26.2
+*/
+
+interface XChartStyle : com::sun::star::uno::XInterface
+{
+};
+
+}; }; }; };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index d1f9933605db..938fac1c8b95 100644
--- a/oox/Library_oox.mk
+++ b/oox/Library_oox.mk
@@ -115,6 +115,8 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
     oox/source/drawingml/chart/seriescontext \
     oox/source/drawingml/chart/seriesconverter \
     oox/source/drawingml/chart/seriesmodel \
+    oox/source/drawingml/chart/stylefragment \
+    oox/source/drawingml/chart/stylemodel \
     oox/source/drawingml/chart/titlecontext \
     oox/source/drawingml/chart/titleconverter \
     oox/source/drawingml/chart/titlemodel \
diff --git a/oox/inc/drawingml/chart/converterbase.hxx 
b/oox/inc/drawingml/chart/converterbase.hxx
index a504764e83e9..3ccb1283019c 100644
--- a/oox/inc/drawingml/chart/converterbase.hxx
+++ b/oox/inc/drawingml/chart/converterbase.hxx
@@ -51,7 +51,7 @@ class ConverterRoot
 public:
     explicit            ConverterRoot(
                             ::oox::core::XmlFilterBase& rFilter,
-                            ChartConverter& rChartConverter,
+                            const ChartConverter& rChartConverter,
                             const ChartSpaceModel& rChartModel,
                             const css::uno::Reference< 
css::chart2::XChartDocument >& rxChartDoc,
                             const css::awt::Size& rChartSize );
@@ -72,7 +72,7 @@ protected:
     /** Returns the filter object of the imported/exported document. */
     ::oox::core::XmlFilterBase& getFilter() const;
     /** Returns the chart converter. */
-    ChartConverter&     getChartConverter() const;
+    const ChartConverter&     getChartConverter() const;
     /** Returns the API chart document model. */
     css::uno::Reference< css::chart2::XChartDocument > const &
                         getChartDocument() const;
diff --git a/oox/inc/drawingml/chart/stylefragment.hxx 
b/oox/inc/drawingml/chart/stylefragment.hxx
new file mode 100644
index 000000000000..aff1f59f870c
--- /dev/null
+++ b/oox/inc/drawingml/chart/stylefragment.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <drawingml/chart/chartcontextbase.hxx>
+
+namespace model
+{
+struct StyleColor;
+}
+
+namespace oox::drawingml::chart
+{
+/** Handler for a cs:CT_StyleReference or cs:CT_FontReference element.
+ */
+class StyleReferenceContext final : public ContextBase<model::StyleColor>
+{
+public:
+    StyleReferenceContext(ContextHandler2Helper& rParent, sal_Int32 nIdx,
+                          model::StyleColor& rModel);
+    virtual ~StyleReferenceContext() override;
+
+    virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement,
+                                                           const 
AttributeList& rAttribs) override;
+};
+
+struct StyleEntryModel;
+
+/** Handler for a cs:CT_StyleEntry element.
+ */
+class StyleEntryContext final : public ContextBase<StyleEntryModel>
+{
+public:
+    StyleEntryContext(ContextHandler2Helper& rParent, StyleEntryModel& rModel);
+    virtual ~StyleEntryContext() override;
+
+    virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement,
+                                                           const 
AttributeList& rAttribs) override;
+    virtual void onCharacters(const OUString& rChars) override;
+};
+
+struct StyleModel;
+
+/** Handler for a style fragment (cs:chartStyle root element).
+ */
+class StyleFragment final : public FragmentBase<StyleModel>
+{
+public:
+    explicit StyleFragment(::oox::core::XmlFilterBase& rFilter, const 
OUString& rFragmentPath,
+                           StyleModel& rModel);
+    virtual ~StyleFragment() override;
+
+    virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement,
+                                                           const 
AttributeList& rAttribs) override;
+};
+
+} // namespace oox::drawingml::chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/inc/drawingml/chart/stylemodel.hxx 
b/oox/inc/drawingml/chart/stylemodel.hxx
new file mode 100644
index 000000000000..d0c1bc92e82f
--- /dev/null
+++ b/oox/inc/drawingml/chart/stylemodel.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <variant>
+
+#include <oox/core/xmlfilterbase.hxx>
+#include <oox/drawingml/chart/modelbase.hxx>
+#include <oox/drawingml/shape.hxx>
+#include <drawingml/textcharacterproperties.hxx>
+#include <drawingml/textbodyproperties.hxx>
+#include <docmodel/styles/ChartStyle.hxx>
+
+namespace oox::drawingml::chart
+{
+// Holds the contents of a cs:CT_StyleEntry
+//
+// CT_StyleReference and CT_FontReference both have the exact same structure,
+// simply with different interpretations of the "idx" attribute. So use this
+// 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<TextCharacterProperties> TextCharacterPropsRef;
+    typedef ModelRef<TextBodyProperties> TextBodyPropsRef;
+    typedef ModelRef<Shape> ShapeRef;
+
+    StyleRef mxLnRef;
+    double mfLineWidthScale = 1.0;
+    StyleRef mxFillRef;
+    StyleRef mxEffectRef;
+    FontRef mxFontRef;
+    ShapeRef mxShapeProp;
+    TextCharacterPropsRef mrTextCharacterProperties;
+    TextBodyPropsRef mxBodyPr;
+
+    model::StyleEntry toStyleEntry(oox::core::XmlFilterBase& rFilter);
+};
+
+// Holds the contents of a cs:CT_ChartStyle
+struct StyleModel
+{
+    typedef ModelRef<StyleEntryModel> StyleEntryRef;
+
+    StyleEntryRef mxAxisTitle;
+    StyleEntryRef mxCategoryAxis;
+    StyleEntryRef mxChartArea;
+    StyleEntryRef mxDataLabel;
+    StyleEntryRef mxDataLabelCallout;
+    StyleEntryRef mxDataPoint;
+    StyleEntryRef mxDataPoint3D;
+    StyleEntryRef mxDataPointLine;
+    StyleEntryRef mxDataPointMarker;
+    StyleEntryRef mxDataPointMarkerLayout;
+    StyleEntryRef mxDataPointWireframe;
+    StyleEntryRef mxDataTable;
+    StyleEntryRef mxDownBar;
+    StyleEntryRef mxDropLine;
+    StyleEntryRef mxErrorBar;
+    StyleEntryRef mxFloor;
+    StyleEntryRef mxGridlineMajor;
+    StyleEntryRef mxGridlineMinor;
+    StyleEntryRef mxHiLoLine;
+    StyleEntryRef mxLeaderLine;
+    StyleEntryRef mxLegend;
+    StyleEntryRef mxPlotArea;
+    StyleEntryRef mxPlotArea3D;
+    StyleEntryRef mxSeriesAxis;
+    StyleEntryRef mxSeriesLine;
+    StyleEntryRef mxTitle;
+    StyleEntryRef mxTrendline;
+    StyleEntryRef mxTrendlineLabel;
+    StyleEntryRef mxUpBar;
+    StyleEntryRef mxValueAxis;
+    StyleEntryRef mxWall;
+
+    sal_Int32 mnId;
+};
+
+} // namespace oox::drawingml::chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/core/xmlfilterbase.cxx 
b/oox/source/core/xmlfilterbase.cxx
index 4bd29f8efc1b..644b7b8cdc56 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -156,6 +156,7 @@ const Sequence< beans::Pair< OUString, sal_Int32 > >& 
NamespaceIds()
             
{u"http://schemas.microsoft.com/office/drawing/2017/decorative"_ustr, 
NMSP_adec},
             
{u"http://schemas.microsoft.com/office/drawing/2016/SVG/main"_ustr, NMSP_asvg},
             {u"http://schemas.microsoft.com/office/drawing/2014/chartex"_ustr, 
NMSP_cx},
+            
{u"http://schemas.microsoft.com/office/drawing/2012/chartStyle"_ustr, NMSP_cs},
         };
     return SINGLETON;
 };
diff --git a/oox/source/drawingml/chart/chartconverter.cxx 
b/oox/source/drawingml/chart/chartconverter.cxx
index 659132eebef2..1b281bd6cbc5 100644
--- a/oox/source/drawingml/chart/chartconverter.cxx
+++ b/oox/source/drawingml/chart/chartconverter.cxx
@@ -17,17 +17,20 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include <oox/drawingml/chart/chartconverter.hxx>
-
 #include <com/sun/star/chart2/XChartDocument.hpp>
 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
 #include <drawingml/chart/chartspaceconverter.hxx>
 #include <drawingml/chart/chartspacemodel.hxx>
+#include <drawingml/chart/stylemodel.hxx>
+#include <docmodel/uno/UnoChartStyle.hxx>
+#include <docmodel/styles/ChartStyle.hxx>
 #include <oox/helper/containerhelper.hxx>
 #include <oox/core/xmlfilterbase.hxx>
 #include <osl/diagnose.h>
 
+#include <oox/drawingml/chart/chartconverter.hxx>
+
 using ::oox::drawingml::chart::DataSequenceModel;
 using ::com::sun::star::uno::Any;
 namespace oox::drawingml::chart {
@@ -78,7 +81,8 @@ ChartConverter::~ChartConverter()
 
 void ChartConverter::convertFromModel( XmlFilterBase& rFilter,
         ChartSpaceModel& rChartModel, const Reference< XChartDocument >& 
rxChartDoc,
-        const Reference< XShapes >& rxExternalPage, const awt::Point& 
rChartPos, const awt::Size& rChartSize )
+        const Reference< XShapes >& rxExternalPage, const awt::Point& 
rChartPos,
+        const awt::Size& rChartSize ) const
 {
     OSL_ENSURE( rxChartDoc.is(), "ChartConverter::convertFromModel - missing 
chart document" );
     if( rxChartDoc.is() )
@@ -94,7 +98,8 @@ void ChartConverter::convertFromModel( XmlFilterBase& rFilter,
     }
 }
 
-void ChartConverter::createDataProvider( const Reference< XChartDocument >& 
rxChartDoc )
+void ChartConverter::createDataProvider( const Reference< XChartDocument >&
+        rxChartDoc ) const
 {
     try
     {
@@ -108,7 +113,7 @@ void ChartConverter::createDataProvider( const Reference< 
XChartDocument >& rxCh
 
 Reference< XDataSequence > ChartConverter::createDataSequence(
     const Reference< XDataProvider >& rxDataProvider, const DataSequenceModel& 
rDataSeq,
-    const OUString& rRole, const OUString& rRoleQualifier )
+    const OUString& rRole, const OUString& rRoleQualifier ) const
 {
     Reference< XDataSequence > xDataSeq;
     if( rxDataProvider.is() )
@@ -145,6 +150,32 @@ Reference< XDataSequence > 
ChartConverter::createDataSequence(
     return nullptr;
 }
 
+// ===========
+// ChartStyleConverter
+// ===========
+void ChartStyleConverter::convertFromModel(XmlFilterBase& rFilter,
+        StyleModel& rChartStyleModel,
+        const Reference< XChartStyle >& rxChartStyle)
+{
+    OSL_ENSURE( rxChartStyle.is(), "ChartStyleConverter::convertFromModel - 
missing chart style" );
+    if (!rxChartStyle.is()) return;
+
+    UnoChartStyle *pUnoCS = static_cast<UnoChartStyle*>(rxChartStyle.get());
+    assert(pUnoCS);
+
+    model::StyleSet& aStyles = pUnoCS->getChartStyle();
+
+    if (rChartStyleModel.mxAxisTitle) {
+        aStyles.addEntry(model::StyleSet::StyleEntryType::AXISTITLE,
+                rChartStyleModel.mxAxisTitle->toStyleEntry(rFilter));
+    }
+    // etc.
+    // TODO: fill in all the stuff
+
+    aStyles.mnId = rChartStyleModel.mnId;
+}
+
+
 } // namespace oox::drawingml::chart
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/chart/converterbase.cxx 
b/oox/source/drawingml/chart/converterbase.cxx
index d7130ec9795d..5e9bd4a8859d 100644
--- a/oox/source/drawingml/chart/converterbase.cxx
+++ b/oox/source/drawingml/chart/converterbase.cxx
@@ -149,13 +149,13 @@ struct ConverterData
     std::map< TitleKey, TitleLayoutInfo >
                         maTitles;
     XmlFilterBase&      mrFilter;
-    ChartConverter&     mrConverter;
+    const ChartConverter&     mrConverter;
     Reference< XChartDocument > mxDoc;
     awt::Size                maSize;
 
     explicit            ConverterData(
                             XmlFilterBase& rFilter,
-                            ChartConverter& rChartConverter,
+                            const ChartConverter& rChartConverter,
                             const ChartSpaceModel& rChartModel,
                             const Reference< XChartDocument >& rxChartDoc,
                             const awt::Size& rChartSize );
@@ -164,7 +164,7 @@ struct ConverterData
 
 ConverterData::ConverterData(
         XmlFilterBase& rFilter,
-        ChartConverter& rChartConverter,
+        const ChartConverter& rChartConverter,
         const ChartSpaceModel& rChartModel,
         const Reference< XChartDocument >& rxChartDoc,
         const awt::Size& rChartSize ) :
@@ -207,7 +207,7 @@ ConverterData::~ConverterData()
 
 ConverterRoot::ConverterRoot(
         XmlFilterBase& rFilter,
-        ChartConverter& rChartConverter,
+        const ChartConverter& rChartConverter,
         const ChartSpaceModel& rChartModel,
         const Reference< XChartDocument >& rxChartDoc,
         const awt::Size& rChartSize ) :
@@ -245,7 +245,7 @@ XmlFilterBase& ConverterRoot::getFilter() const
     return mxData->mrFilter;
 }
 
-ChartConverter& ConverterRoot::getChartConverter() const
+const ChartConverter& ConverterRoot::getChartConverter() const
 {
     return mxData->mrConverter;
 }
diff --git a/oox/source/drawingml/chart/stylefragment.cxx 
b/oox/source/drawingml/chart/stylefragment.cxx
new file mode 100644
index 000000000000..562fe27bda31
--- /dev/null
+++ b/oox/source/drawingml/chart/stylefragment.cxx
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <optional>
+
+#include <drawingml/chart/stylefragment.hxx>
+
+#include <drawingml/shapepropertiescontext.hxx>
+#include <drawingml/textbodycontext.hxx>
+#include <drawingml/textbodypropertiescontext.hxx>
+#include <drawingml/textcharacterpropertiescontext.hxx>
+#include <drawingml/chart/stylemodel.hxx>
+#include <drawingml/colorchoicecontext.hxx>
+#include <docmodel/styles/ChartStyle.hxx>
+#include <oox/drawingml/color.hxx>
+#include <oox/core/xmlfilterbase.hxx>
+#include <oox/helper/attributelist.hxx>
+#include <oox/token/namespaces.hxx>
+#include <oox/token/tokens.hxx>
+
+namespace oox::drawingml::chart
+{
+using namespace ::oox::core;
+using namespace model;
+
+//=======
+// StyleReferenceContext
+//=======
+StyleReferenceContext::StyleReferenceContext(ContextHandler2Helper& rParent, 
sal_Int32 nIdx,
+                                             model::StyleColor& rModel)
+    : ContextBase<StyleColor>(rParent, rModel)
+{
+    mrModel.mnIdx = nIdx;
+}
+
+StyleReferenceContext::~StyleReferenceContext() {}
+
+ContextHandlerRef StyleReferenceContext::onCreateContext(sal_Int32 nElement,
+                                                         const AttributeList& 
rAttribs)
+{
+    if (isRootElement())
+        switch (nElement)
+        {
+            case CS_TOKEN(styleClr):
+            {
+                // The attribute here can be an integer, a string, or "auto" 
(which
+                // of course is also a string, but is considered special). So 
we
+                // need to try to convert the input string to an integer, and 
handle
+                // it as an int if we can. OUString provides toInt(), but it 
returns
+                // 0 in the case of failure, which is eminently unhelpful, 
sinze 0
+                // is a perfectly acceptable value. So convert it to a
+                // std::basic_string, which has stoi(), which throws if it 
can't do
+                // the conversion.
+                //
+                // Unfortunately OUString characters are sal_Unicode which can 
be
+                // uint16_t, and while there's string::stoi() and 
wstring::stoi(),
+                // there's no basic_string<uint16_t>::stoi(). So we use 
wstring and
+                // construct character by character.
+                std::optional<OUString> str = rAttribs.getString(XML_val);
+                if (str)
+                {
+                    StyleColor::StyleColorVal v;
+
+                    const sal_Unicode* pRawStr = str->getStr();
+                    std::wstring sBStr;
+                    sBStr.reserve(str->getLength());
+                    for (const sal_Unicode* pS = pRawStr; pS < pRawStr + 
str->getLength(); ++pS)
+                    {
+                        sBStr.push_back(*pS);
+                    }
+
+                    sal_uInt32 nIntVal = 0;
+                    try
+                    {
+                        nIntVal = stoi(sBStr);
+                        v = nIntVal;
+                    }
+                    catch (std::invalid_argument&)
+                    {
+                        // Not an integer, so see if it's the fixed enum
+                        if (*str == "auto")
+                        {
+                            v = StyleColor::StyleColorEnum::AUTO;
+                        }
+                        else
+                        {
+                            v = *str;
+                        }
+                    }
+                    mrModel.maStyleClr.push_back(v);
+                }
+                return nullptr;
+            }
+            case A_TOKEN(scrgbClr):
+            case A_TOKEN(srgbClr):
+            case A_TOKEN(hslClr):
+            case A_TOKEN(sysClr):
+            case A_TOKEN(schemeClr):
+            case A_TOKEN(prstClr):
+                return new ColorValueContext(*this, mrModel.maColor, 
&mrModel.maComplexColor);
+        }
+    return nullptr;
+}
+
+//=======
+// StyleEntryContext
+//=======
+StyleEntryContext::StyleEntryContext(ContextHandler2Helper& rParent, 
StyleEntryModel& rModel)
+    : ContextBase<StyleEntryModel>(rParent, rModel)
+{
+}
+
+StyleEntryContext::~StyleEntryContext() {}
+
+ContextHandlerRef StyleEntryContext::onCreateContext(sal_Int32 nElement,
+                                                     const AttributeList& 
rAttribs)
+{
+    if (isRootElement())
+        switch (nElement)
+        {
+            case CS_TOKEN(lnRef): // CT_StyleReference
+                return new StyleReferenceContext(*this, 
rAttribs.getInteger(XML_idx, -1),
+                                                 mrModel.mxLnRef.create());
+            case CS_TOKEN(lineWidthScale): // double
+                return this;
+            case CS_TOKEN(fillRef): // CT_StyleReference
+                return new StyleReferenceContext(*this, 
rAttribs.getInteger(XML_idx, -1),
+                                                 mrModel.mxFillRef.create());
+            case CS_TOKEN(effectRef): // CT_StyleReference
+                return new StyleReferenceContext(*this, 
rAttribs.getInteger(XML_idx, -1),
+                                                 mrModel.mxEffectRef.create());
+            case CS_TOKEN(fontRef): // CT_FontReference
+                return new StyleReferenceContext(*this, 
rAttribs.getInteger(XML_idx, -1),
+                                                 mrModel.mxFontRef.create());
+            case CS_TOKEN(spPr): // a:CT_ShapeProperties
+                return new ShapePropertiesContext(*this, 
mrModel.mxShapeProp.create());
+            case CS_TOKEN(defRPr): // a:CT_TextCharacterProperties
+                return new TextCharacterPropertiesContext(
+                    *this, rAttribs, 
mrModel.mrTextCharacterProperties.create());
+            case CS_TOKEN(bodyPr): // a:CT_TextBodyProperties
+                return new TextBodyPropertiesContext(*this, rAttribs, 
mrModel.mxBodyPr.create());
+            case CS_TOKEN(extLst): // a:CT_OfficeArtExtensionList
+                return nullptr;
+        }
+    return nullptr;
+}
+
+void StyleEntryContext::onCharacters(const OUString& rChars)
+{
+    switch (getCurrentElement())
+    {
+        case CS_TOKEN(lineWidthScale):
+            mrModel.mfLineWidthScale = rChars.toDouble();
+            break;
+        default:
+            assert(false);
+    }
+}
+
+//=======
+// StyleFragment
+//=======
+StyleFragment::StyleFragment(XmlFilterBase& rFilter, const OUString& 
rFragmentPath,
+                             StyleModel& rModel)
+    : FragmentBase<StyleModel>(rFilter, rFragmentPath, rModel)
+{
+}
+
+StyleFragment::~StyleFragment() {}
+
+ContextHandlerRef StyleFragment::onCreateContext(sal_Int32 nElement, const 
AttributeList& rAttribs)
+{
+    switch (getCurrentElement())
+    {
+        case XML_ROOT_CONTEXT:
+            switch (nElement)
+            {
+                case CS_TOKEN(chartStyle):
+                    mrModel.mnId = rAttribs.getInteger(XML_id, -1);
+                    return this;
+            }
+            break;
+
+        case CS_TOKEN(chartStyle):
+            switch (nElement)
+            {
+                // All of these have "mods" attributes that aren't currently
+                // handled. TODO
+                case CS_TOKEN(axisTitle):
+                    return new StyleEntryContext(*this, 
mrModel.mxAxisTitle.create());
+                case CS_TOKEN(categoryAxis):
+                    return new StyleEntryContext(*this, 
mrModel.mxCategoryAxis.create());
+                case CS_TOKEN(chartArea):
+                    return new StyleEntryContext(*this, 
mrModel.mxChartArea.create());
+                case CS_TOKEN(dataLabel):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataLabel.create());
+                case CS_TOKEN(dataLabelCallout):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataLabelCallout.create());
+                case CS_TOKEN(dataPoint):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataPoint.create());
+                case CS_TOKEN(dataPoint3D):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataPoint3D.create());
+                case CS_TOKEN(dataPointLine):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataPointLine.create());
+                case CS_TOKEN(dataPointMarker):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataPointMarker.create());
+                case CS_TOKEN(dataPointMarkerLayout):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataPointMarkerLayout.create());
+                case CS_TOKEN(dataPointWireframe):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataPointWireframe.create());
+                case CS_TOKEN(dataTable):
+                    return new StyleEntryContext(*this, 
mrModel.mxDataTable.create());
+                case CS_TOKEN(downBar):
+                    return new StyleEntryContext(*this, 
mrModel.mxDownBar.create());
+                case CS_TOKEN(dropLine):
+                    return new StyleEntryContext(*this, 
mrModel.mxDropLine.create());
+                case CS_TOKEN(errorBar):
+                    return new StyleEntryContext(*this, 
mrModel.mxErrorBar.create());
+                case CS_TOKEN(floor):
+                    return new StyleEntryContext(*this, 
mrModel.mxFloor.create());
+                case CS_TOKEN(gridlineMajor):
+                    return new StyleEntryContext(*this, 
mrModel.mxGridlineMajor.create());
+                case CS_TOKEN(gridlineMinor):
+                    return new StyleEntryContext(*this, 
mrModel.mxGridlineMinor.create());
+                case CS_TOKEN(hiLoLine):
+                    return new StyleEntryContext(*this, 
mrModel.mxHiLoLine.create());
+                case CS_TOKEN(leaderLine):
+                    return new StyleEntryContext(*this, 
mrModel.mxLeaderLine.create());
+                case CS_TOKEN(legend):
+                    return new StyleEntryContext(*this, 
mrModel.mxLegend.create());
+                case CS_TOKEN(plotArea):
+                    return new StyleEntryContext(*this, 
mrModel.mxPlotArea.create());
+                case CS_TOKEN(plotArea3D):
+                    return new StyleEntryContext(*this, 
mrModel.mxPlotArea3D.create());
+                case CS_TOKEN(seriesAxis):
+                    return new StyleEntryContext(*this, 
mrModel.mxSeriesAxis.create());
+                case CS_TOKEN(seriesLine):
+                    return new StyleEntryContext(*this, 
mrModel.mxSeriesLine.create());
+                case CS_TOKEN(title):
+                    return new StyleEntryContext(*this, 
mrModel.mxTitle.create());
+                case CS_TOKEN(trendline):
+                    return new StyleEntryContext(*this, 
mrModel.mxTrendline.create());
+                case CS_TOKEN(trendlineLabel):
+                    return new StyleEntryContext(*this, 
mrModel.mxTrendlineLabel.create());
+                case CS_TOKEN(upBar):
+                    return new StyleEntryContext(*this, 
mrModel.mxUpBar.create());
+                case CS_TOKEN(valueAxis):
+                    return new StyleEntryContext(*this, 
mrModel.mxValueAxis.create());
+                case CS_TOKEN(wall):
+                    return new StyleEntryContext(*this, 
mrModel.mxWall.create());
+                case CS_TOKEN(extLst):
+                    // Don't handle this, at least yet
+                    return nullptr;
+            }
+            break;
+    }
+    return nullptr;
+}
+
+} // namespace oox::drawingml::chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/chart/stylemodel.cxx 
b/oox/source/drawingml/chart/stylemodel.cxx
new file mode 100644
index 000000000000..c72c8391179a
--- /dev/null
+++ b/oox/source/drawingml/chart/stylemodel.cxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tools/gen.hxx>
+#include <drawingml/chart/stylemodel.hxx>
+
+namespace oox::drawingml::chart
+{
+model::StyleEntry StyleEntryModel::toStyleEntry(oox::core::XmlFilterBase& 
rFilter)
+{
+    std::shared_ptr<PropertyMap> aCharMap = std::make_shared<PropertyMap>();
+    if (mrTextCharacterProperties)
+    {
+        mrTextCharacterProperties->pushToPropMap(*aCharMap, rFilter);
+    }
+
+    // Unlike TextCharacterPropsRef, handled above, TextBodyPropsRef does not
+    // have a pushToPropMap() method. It does have a PropertyMap data member,
+    // 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>();
+    if (mxBodyPr)
+    {
+        mxBodyPr->pushTextDistances(Size(0, 0));
+        aBodyMap.reset(&mxBodyPr->maPropertyMap);
+    }
+
+    return model::StyleEntry(mxLnRef, mfLineWidthScale, mxFillRef, 
mxEffectRef, mxFontRef,
+                             mxShapeProp, aCharMap, aBodyMap);
+}
+
+} // namespace oox::drawingml::chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 54b8d91ba663..897a7ac9fc51 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -37,6 +37,8 @@
 #include <drawingml/table/tableproperties.hxx>
 #include <oox/drawingml/chart/chartconverter.hxx>
 #include <drawingml/chart/chartspacefragment.hxx>
+#include <drawingml/chart/stylefragment.hxx>
+#include <drawingml/chart/stylemodel.hxx>
 #include <drawingml/chart/chartspacemodel.hxx>
 #include <o3tl/safeint.hxx>
 #include <o3tl/unit_conversion.hxx>
@@ -87,6 +89,7 @@
 #include <com/sun/star/table/BorderLine2.hpp>
 #include <com/sun/star/table/ShadowFormat.hpp>
 #include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart2/XChartStyle.hpp>
 #include <com/sun/star/style/ParagraphAdjust.hpp>
 #include <com/sun/star/io/XOutputStream.hpp>
 #include <com/sun/star/lang/Locale.hpp>
@@ -2577,12 +2580,22 @@ void Shape::finalizeXShape( XmlFilterBase& rFilter, 
const Reference< XShapes >&
 
                 rtl::Reference<chart::ChartSpaceFragment> pChartSpaceFragment 
= new chart::ChartSpaceFragment(
                         rFilter, mxChartShapeInfo->maFragmentPath, aModel );
-                const OUString aThemeOverrideFragmentPath( 
pChartSpaceFragment->
-                        
getFragmentPathFromFirstTypeFromOfficeDoc(u"themeOverride") );
                 rFilter.importFragment( pChartSpaceFragment );
 
+                // Import styles file
+                sal_Int32 nLastSlash = 
mxChartShapeInfo->maFragmentPath.lastIndexOf('/');
+                const sal_Unicode *pFPath = 
mxChartShapeInfo->maFragmentPath.getStr();
+                OUString sStylePath(pFPath, nLastSlash + 1);
+                sStylePath += u"style1.xml"_ustr;
+                chart::StyleModel aStyleModel;
+                rtl::Reference<chart::StyleFragment> pStyleFragment = new 
chart::StyleFragment(
+                        rFilter, sStylePath, aStyleModel );
+                rFilter.importFragment( pStyleFragment );
+
                 // The original theme.
                 ThemePtr pTheme;
+                const OUString aThemeOverrideFragmentPath( 
pChartSpaceFragment->
+                        
getFragmentPathFromFirstTypeFromOfficeDoc(u"themeOverride") );
 
                 if (!aThemeOverrideFragmentPath.isEmpty() && pPowerPointImport)
                 {
@@ -2601,6 +2614,11 @@ void Shape::finalizeXShape( XmlFilterBase& rFilter, 
const Reference< XShapes >&
                 Reference< drawing::XShapes > xExternalPage;
                 if( !mxChartShapeInfo->mbEmbedShapes )
                     xExternalPage = rxShapes;
+
+                // There are several calls to rFilter.getChartConverter() here.
+                // Doing just one call and storing the result, as in
+                //     chart::ChartConverter *pChartConv = 
rFilter.getChartConverter();
+                // *doesn't work* (tests crash).
                 if( rFilter.getChartConverter() )
                 {
                     rFilter.getChartConverter()->convertFromModel( rFilter, 
aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() );
@@ -2619,6 +2637,16 @@ 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);
+
+
+                }
+
                 if (pPowerPointImport)
                 {
                     if (!aThemeOverrideFragmentPath.isEmpty())
diff --git a/oox/source/drawingml/textbodyproperties.cxx 
b/oox/source/drawingml/textbodyproperties.cxx
index 3b885003fd4f..25a1f0ced330 100644
--- a/oox/source/drawingml/textbodyproperties.cxx
+++ b/oox/source/drawingml/textbodyproperties.cxx
@@ -138,7 +138,8 @@ void TextBodyProperties::pushTextDistances(Size const& 
rTextAreaSize)
 
         // Check if top + bottom is more than text area height.
         // If yes, we need to adjust the values as defined in OOXML.
-        if (nTop + nBottom >= nHeight)
+        // (Overload zero height to mean don't adjust)
+        if (nHeight > 0 && nTop + nBottom >= nHeight)
         {
             double diffFactor = (nTop + nBottom - nHeight) / 2.0;
 
diff --git a/oox/source/token/namespaces-strict.txt 
b/oox/source/token/namespaces-strict.txt
index fbfc7d3e031e..39a7f22c2920 100644
--- a/oox/source/token/namespaces-strict.txt
+++ b/oox/source/token/namespaces-strict.txt
@@ -102,6 +102,7 @@ cs                      
http://schemas.microsoft.com/office/drawing/2012/chartSt
 # MSO 2014 extensions ---------------------------------------------------------
 
 cx                      
http://schemas.microsoft.com/office/drawing/2014/chartex
+cs                      
http://schemas.microsoft.com/office/drawing/2012/chartStyle
 a16                     http://schemas.microsoft.com/office/drawing/2014/main
 
 # extlst namespaces
diff --git a/oox/source/token/namespaces.hxx.tail 
b/oox/source/token/namespaces.hxx.tail
index 0f431907b862..a812725976f0 100644
--- a/oox/source/token/namespaces.hxx.tail
+++ b/oox/source/token/namespaces.hxx.tail
@@ -66,6 +66,7 @@ inline sal_Int32 getNamespace( sal_Int32 nToken ) { return 
nToken & NMSP_MASK; }
 #define XR16_TOKEN(token)       OOX_TOKEN(xr16, token)
 #define WPC_TOKEN(token)        OOX_TOKEN(wpc, token)
 #define CX_TOKEN(token)         OOX_TOKEN(cx, token)
+#define CS_TOKEN(token)         OOX_TOKEN(cs, token)
 
 
 } // namespace oox
diff --git a/oox/source/token/namespaces.txt b/oox/source/token/namespaces.txt
index c691e3ed5162..9617c747360a 100644
--- a/oox/source/token/namespaces.txt
+++ b/oox/source/token/namespaces.txt
@@ -100,6 +100,7 @@ cs                      
http://schemas.microsoft.com/office/drawing/2012/chartSt
 # MSO 2014 extensions ---------------------------------------------------------
 
 cx                      
http://schemas.microsoft.com/office/drawing/2014/chartex
+cs                      
http://schemas.microsoft.com/office/drawing/2012/chartStyle
 a16                     http://schemas.microsoft.com/office/drawing/2014/main
 
 # extlst namespaces
diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt
index 9c35dd0c22f9..ac4c29bb5a6b 100644
--- a/oox/source/token/tokens.txt
+++ b/oox/source/token/tokens.txt
@@ -1669,6 +1669,7 @@ dataField
 dataFields
 dataId
 dataLabel
+dataLabelCallout
 dataLabels
 dataModel
 dataModelExt
@@ -1678,6 +1679,7 @@ dataPoint
 dataPoint3D
 dataPointLine
 dataPointMarker
+dataPointMarkerLayout
 dataPointWireframe
 dataPosition
 dataPt
@@ -3186,6 +3188,7 @@ linePitch
 lineRule
 lineTo
 lineWeight
+lineWidthScale
 lineWrapLikeWord6
 linear
 linen
diff --git a/sc/source/filter/inc/excelchartconverter.hxx 
b/sc/source/filter/inc/excelchartconverter.hxx
index 363966a4c023..140c7d41e646 100644
--- a/sc/source/filter/inc/excelchartconverter.hxx
+++ b/sc/source/filter/inc/excelchartconverter.hxx
@@ -32,14 +32,15 @@ public:
 
     /** Creates an external data provider that is able to use spreadsheet 
data. */
     virtual void        createDataProvider(
-                            const css::uno::Reference< 
css::chart2::XChartDocument >& rxChartDoc ) override;
+                            const css::uno::Reference<
+                            css::chart2::XChartDocument >& rxChartDoc ) const 
override;
 
     /** Creates a data sequence from the passed formula. */
     virtual css::uno::Reference<css::chart2::data::XDataSequence>
         createDataSequence(
             const css::uno::Reference<css::chart2::data::XDataProvider>& 
rxDataProvider,
             const oox::drawingml::chart::DataSequenceModel& rDataSeq, const 
OUString& rRole,
-            const OUString& aRoleQualifier ) override;
+            const OUString& aRoleQualifier ) const override;
 };
 
 } // namespace oox::xls
diff --git a/sc/source/filter/oox/excelchartconverter.cxx 
b/sc/source/filter/oox/excelchartconverter.cxx
index 3800cf68fcfc..ef01d72ab46e 100644
--- a/sc/source/filter/oox/excelchartconverter.cxx
+++ b/sc/source/filter/oox/excelchartconverter.cxx
@@ -48,7 +48,8 @@ ExcelChartConverter::~ExcelChartConverter()
 {
 }
 
-void ExcelChartConverter::createDataProvider( const Reference< XChartDocument 
>& rxChartDoc )
+void ExcelChartConverter::createDataProvider( const Reference< XChartDocument 
>&
+        rxChartDoc ) const
 {
     try
     {
@@ -64,7 +65,7 @@ void ExcelChartConverter::createDataProvider( const 
Reference< XChartDocument >&
 
 Reference< XDataSequence > ExcelChartConverter::createDataSequence(
     const Reference< XDataProvider >& rxDataProvider, const DataSequenceModel& 
rDataSeq,
-    const OUString& /*rRole*/, const OUString& /*aRoleQualifier*/ )
+    const OUString& /*rRole*/, const OUString& /*aRoleQualifier*/ ) const
 {
     Reference< XDataSequence > xDataSeq;
     if (!rxDataProvider.is())

Reply via email to