chart2/inc/ChartModel.hxx                       |    3 
 chart2/qa/extras/chart2export.cxx               |   11 +++
 chart2/qa/extras/data/xlsx/column-style.xlsx    |binary
 chart2/source/model/main/ChartModel.cxx         |   16 ++++
 docmodel/Library_docmodel.mk                    |    3 
 docmodel/source/styles/ChartColorStyle.cxx      |   21 ++++++
 docmodel/source/uno/UnoChartColorStyle.cxx      |   40 ++++++++++++
 include/docmodel/styles/ChartColorStyle.hxx     |   64 +++++++++++++++++++
 include/docmodel/uno/UnoChartColorStyle.hxx     |   45 +++++++++++++
 include/oox/drawingml/chart/chartconverter.hxx  |   24 +++++++
 offapi/UnoApi_offapi.mk                         |    1 
 offapi/com/sun/star/chart2/XChartColorStyle.idl |   24 +++++++
 offapi/com/sun/star/chart2/XChartDocument.idl   |    5 +
 oox/inc/drawingml/chart/colorsmodel.hxx         |   33 ++++++++++
 oox/inc/drawingml/chart/stylefragment.hxx       |   15 ++++
 oox/inc/drawingml/colorchoicecontext.hxx        |   18 +++++
 oox/source/drawingml/chart/chartconverter.cxx   |   24 +++++++
 oox/source/drawingml/chart/colorsmodel.cxx      |   51 +++++++++++++++
 oox/source/drawingml/chart/stylefragment.cxx    |   79 ++++++++++++++++++++++++
 oox/source/drawingml/colorchoicecontext.cxx     |   32 +++++++++
 oox/source/drawingml/shape.cxx                  |   18 +++++
 oox/source/export/chartexport.cxx               |   52 +++++++++++++--
 oox/source/token/tokens.txt                     |    1 
 23 files changed, 572 insertions(+), 8 deletions(-)

New commits:
commit 0686b1972806fe8b711de5ba64039fb38cd14889
Author:     Kurt Nordback <[email protected]>
AuthorDate: Thu Dec 4 22:16:26 2025 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Fri Dec 5 02:12:41 2025 +0100

    tdf#167941 - Chart color sequence OOXML import/export
    
    Support import, storage, and export of OOXML chart color styles
    (color sequence). In OOXML, chart color styles are in files such
    as colors1.xml, and conform to the chartStyle schema. This commit
    supports I/O of color styles, and provides supports storing them
    in the chart document model. It does not include any features for
    using or modifying the color styles, so at this point it has no
    appreciable effect on users.
    
    Change-Id: I5c02137ebf9c25e11951eea55c4c77fda35b0e80
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194998
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <[email protected]>

diff --git a/chart2/inc/ChartModel.hxx b/chart2/inc/ChartModel.hxx
index b24c5c459d79..428cfe7e297e 100644
--- a/chart2/inc/ChartModel.hxx
+++ b/chart2/inc/ChartModel.hxx
@@ -71,6 +71,7 @@ class SvNumberFormatter;
 class SvNumberFormatsSupplierObj;
 
 class UnoChartStyle;
+class UnoChartColorStyle;
 
 namespace model { class Theme; }
 
@@ -191,6 +192,7 @@ private:
     std::optional<css::util::DateTime> m_aNullDate;
 
     rtl::Reference<UnoChartStyle> m_aStyles;
+    rtl::Reference<UnoChartColorStyle> m_aColorStyles;
 
 private:
     //private methods
@@ -386,6 +388,7 @@ public:
     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::chart2::XChartColorStyle> SAL_CALL 
getColorStyles() override;
     virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
         getPageBackground() override;
 
diff --git a/chart2/qa/extras/chart2export.cxx 
b/chart2/qa/extras/chart2export.cxx
index 84cf592be6eb..bed05f40097c 100644
--- a/chart2/qa/extras/chart2export.cxx
+++ b/chart2/qa/extras/chart2export.cxx
@@ -1386,6 +1386,17 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest, 
testStyleImportExport)
     assertXPath(pXmlDoc, "/cs:chartStyle/cs:axisTitle/cs:fontRef", "idx", 
std::u16string_view(u"major"));
 }
 
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testColorStyleImportExport)
+{
+    loadFromFile(std::u16string_view(u"xlsx/column-style.xlsx"));
+
+    save(TestFilter::XLSX);
+    xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/colors1.xml");
+    CPPUNIT_ASSERT(pXmlDoc);
+    assertXPath(pXmlDoc, "/cs:colorStyle", "meth", u"acrossLinear");
+    assertXPath(pXmlDoc, "/cs:colorStyle/a:schemeClr", "val", u"dk2");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* 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 087102a0ec85..802a42ff85ad 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/chart2/source/model/main/ChartModel.cxx 
b/chart2/source/model/main/ChartModel.cxx
index 4fd9041f67f3..96fe84cc99dc 100644
--- a/chart2/source/model/main/ChartModel.cxx
+++ b/chart2/source/model/main/ChartModel.cxx
@@ -78,6 +78,7 @@
 #include <docmodel/uno/UnoTheme.hxx>
 #include <docmodel/theme/Theme.hxx>
 #include <docmodel/uno/UnoChartStyle.hxx>
+#include <docmodel/uno/UnoChartColorStyle.hxx>
 
 using ::com::sun::star::uno::Sequence;
 using ::com::sun::star::uno::Reference;
@@ -130,6 +131,7 @@ 
ChartModel::ChartModel(uno::Reference<uno::XComponentContext > xContext)
     , m_eColorPaletteType(ChartColorPaletteType::Unknown)
     , m_nColorPaletteIndex(0)
     , m_aStyles(new UnoChartStyle)
+    , m_aColorStyles(new UnoChartColorStyle)
     , mnStart(0)
     , mnEnd(0)
 {
@@ -143,6 +145,7 @@ 
ChartModel::ChartModel(uno::Reference<uno::XComponentContext > xContext)
         m_xPageBackground->addModifyListener( this );
 #if 0 // TODO
         m_aStyles->addModifyListener( this );
+        m_aColorStyles->addModifyListener( this );
 #endif
         m_xChartTypeManager = new ::chart::ChartTypeManager( m_xContext );
     }
@@ -191,6 +194,8 @@ ChartModel::ChartModel( const ChartModel & rOther )
             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<UnoChartColorStyle> xNewChartColorStyle = new
+            UnoChartColorStyle(*rOther.m_aColorStyles);
 
         {
             rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager; // 
does not implement XCloneable
@@ -203,6 +208,7 @@ ChartModel::ChartModel( const ChartModel & rOther )
                 m_xDiagram = xNewDiagram;
                 m_xPageBackground = xNewPageBackground;
                 m_aStyles = xNewChartStyle;
+                m_aColorStyles = xNewChartColorStyle;
                 m_xChartTypeManager = std::move(xChartTypeManager);
                 m_xXMLNamespaceMap = std::move(xXMLNamespaceMap);
             }
@@ -217,6 +223,9 @@ ChartModel::ChartModel( const ChartModel & rOther )
         if( xNewChartStyle && xListener) {
             xNewChartStyle->addModifyListener( xListener );
         }
+        if( xNewChartColorStyle && xListener) {
+            xNewChartColorStyle->addModifyListener( xListener );
+        }
 #endif
         xListener.clear();
     }
@@ -598,6 +607,7 @@ void SAL_CALL ChartModel::dispose()
     m_xPageBackground.clear();
     m_xXMLNamespaceMap.clear();
     m_aStyles.clear();
+    m_aColorStyles.clear();
 
     m_xStorage.clear();
         // just clear, don't dispose - we're not the owner
@@ -831,6 +841,12 @@ uno::Reference< chart2::XChartStyle > SAL_CALL 
ChartModel::getStyles()
     return m_aStyles;
 }
 
+uno::Reference< chart2::XChartColorStyle > SAL_CALL 
ChartModel::getColorStyles()
+{
+    MutexGuard aGuard( m_aModelMutex );
+    return m_aColorStyles;
+}
+
 // ____ 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 83a4cadcbcee..1de5c254a110 100644
--- a/docmodel/Library_docmodel.mk
+++ b/docmodel/Library_docmodel.mk
@@ -12,12 +12,14 @@ $(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/UnoChartColorStyle \
     docmodel/source/uno/UnoGradientTools \
     docmodel/source/uno/UnoTheme \
     docmodel/source/theme/ColorSet \
     docmodel/source/theme/Theme \
     docmodel/source/color/ComplexColorJSON \
     docmodel/source/styles/ChartStyle \
+    docmodel/source/styles/ChartColorStyle \
 ))
 
 $(eval $(call gb_Library_set_include,docmodel,\
@@ -28,6 +30,7 @@ $(eval $(call gb_Library_set_include,docmodel,\
 $(eval $(call gb_Library_use_externals,docmodel,\
     libxml2 \
     boost_headers \
+    frozen \
 ))
 
 $(eval $(call gb_Library_add_defs,docmodel,\
diff --git a/docmodel/source/styles/ChartColorStyle.cxx 
b/docmodel/source/styles/ChartColorStyle.cxx
new file mode 100644
index 000000000000..297e2afa1077
--- /dev/null
+++ b/docmodel/source/styles/ChartColorStyle.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/ChartColorStyle.hxx>
+#include <utility>
+
+using namespace model;
+
+void ColorStyleSet::addEntry(std::vector<model::ComplexColor>& aComplexColors,
+                             ColorStyleMethod eMethod, sal_Int32 nId)
+{
+    maEntryList.emplace_front(aComplexColors, eMethod, nId);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/docmodel/source/uno/UnoChartColorStyle.cxx 
b/docmodel/source/uno/UnoChartColorStyle.cxx
new file mode 100644
index 000000000000..2bf4d02cd743
--- /dev/null
+++ b/docmodel/source/uno/UnoChartColorStyle.cxx
@@ -0,0 +1,40 @@
+/* -*- 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/UnoChartColorStyle.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+using namespace css;
+
+namespace model::style
+{
+uno::Reference<chart2::XChartColorStyle>
+createXChartColorStyle(model::ColorStyleSet const& rColorStyle)
+{
+    return new UnoChartColorStyle(rColorStyle);
+}
+
+model::ColorStyleSet*
+getFromXChartColorStyle(uno::Reference<chart2::XChartColorStyle> const& 
rxColorStyle)
+{
+    UnoChartColorStyle* pUnoChartColorStyle = 
static_cast<UnoChartColorStyle*>(rxColorStyle.get());
+
+    if (pUnoChartColorStyle)
+    {
+        return &pUnoChartColorStyle->getChartColorStyle();
+    }
+    else
+    {
+        return nullptr;
+    }
+}
+
+} // end model::style
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/docmodel/styles/ChartColorStyle.hxx 
b/include/docmodel/styles/ChartColorStyle.hxx
new file mode 100644
index 000000000000..99606aaff8ab
--- /dev/null
+++ b/include/docmodel/styles/ChartColorStyle.hxx
@@ -0,0 +1,64 @@
+/* -*- 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 <com/sun/star/uno/Reference.hxx>
+
+#include <docmodel/color/ComplexColor.hxx>
+#include <comphelper/string.hxx>
+#include <rtl/ustring.hxx>
+#include <memory>
+#include <forward_list>
+
+namespace com::sun::star::beans
+{
+class XPropertySet;
+}
+
+using namespace com::sun::star;
+
+namespace model
+{
+enum class ColorStyleMethod
+{
+    CYCLE,
+    WITHIN_LINEAR,
+    ACROSS_LINEAR,
+    WITHIN_LINEAR_REVERSED,
+    ACROSS_LINEAR_REVERSED
+};
+
+struct DOCMODEL_DLLPUBLIC ColorStyleEntry
+{
+    std::vector<model::ComplexColor> maComplexColors;
+    ColorStyleMethod meMethod;
+    sal_Int32 mnId;
+
+    ColorStyleEntry(std::vector<model::ComplexColor>& aCColors, 
ColorStyleMethod eMethod,
+                    sal_Int32 nId)
+        : maComplexColors(std::move(aCColors))
+        , meMethod(eMethod)
+        , mnId(nId)
+    {
+    }
+};
+
+struct DOCMODEL_DLLPUBLIC ColorStyleSet
+{
+    std::forward_list<ColorStyleEntry> maEntryList;
+
+    void addEntry(std::vector<model::ComplexColor>& aComplexColors, 
ColorStyleMethod eMethod,
+                  sal_Int32 nId);
+};
+
+} // namespace model
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/docmodel/uno/UnoChartColorStyle.hxx 
b/include/docmodel/uno/UnoChartColorStyle.hxx
new file mode 100644
index 000000000000..7b2201716a57
--- /dev/null
+++ b/include/docmodel/uno/UnoChartColorStyle.hxx
@@ -0,0 +1,45 @@
+/* -*- 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/chart2/XChartColorStyle.hpp>
+
+#include <docmodel/dllapi.h>
+#include <docmodel/styles/ChartColorStyle.hxx>
+
+class UNLESS_MERGELIBS(DOCMODEL_DLLPUBLIC) UnoChartColorStyle final
+    : public cppu::WeakImplHelper<css::chart2::XChartColorStyle>
+{
+private:
+    model::ColorStyleSet maColorStyle;
+
+public:
+    UnoChartColorStyle() = default;
+
+    UnoChartColorStyle(model::ColorStyleSet const& rStyle)
+        : maColorStyle(rStyle)
+    {
+    }
+
+    model::ColorStyleSet& getChartColorStyle() { return maColorStyle; }
+};
+
+namespace model::style
+{
+DOCMODEL_DLLPUBLIC css::uno::Reference<css::chart2::XChartColorStyle>
+createXChartColorStyle(model::ColorStyleSet const& rColorStyle);
+DOCMODEL_DLLPUBLIC model::ColorStyleSet*
+getFromXChartColorStyle(css::uno::Reference<css::chart2::XChartColorStyle> 
const& rxColorStyle);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/oox/drawingml/chart/chartconverter.hxx 
b/include/oox/drawingml/chart/chartconverter.hxx
index 0e97752d5f22..d83520381090 100644
--- a/include/oox/drawingml/chart/chartconverter.hxx
+++ b/include/oox/drawingml/chart/chartconverter.hxx
@@ -32,6 +32,7 @@ namespace com::sun::star {
     namespace drawing { class XShapes; }
     namespace chart2 { class XChartDocument; }
     namespace chart2 { class XChartStyle; }
+    namespace chart2 { class XChartColorStyle; }
     namespace chart2::data { class XDataProvider; }
     namespace chart2::data { class XDataSequence; }
 }
@@ -43,6 +44,7 @@ namespace oox::drawingml::chart {
 struct ChartSpaceModel;
 struct DataSequenceModel;
 struct StyleModel;
+struct ColorStyleModel;
 struct StyleEntryModel;
 typedef ModelRef< StyleEntryModel >      StyleEntryRef;
 
@@ -120,6 +122,28 @@ private:
     ChartStyleConverter&     operator=( const ChartStyleConverter& ) = delete;
 };
 
+class OOX_DLLPUBLIC ChartColorStyleConverter
+{
+public:
+    explicit    ChartColorStyleConverter() = default;
+
+    /** Converts the passed ChartColorStyleModel to the passed chart2
+     * XChartColorStyle.
+
+        @param rChartColorStyleModel  The filled chart colorstyle model 
structure.
+
+        @param rxColorChartStyle  The UNO chart colorstyle structure to be 
initialized.
+
+     */
+    static void convertFromModel(
+                    oox::core::XmlFilterBase& rFilter,
+                    ColorStyleModel& rChartColorStyleModel,
+                    const css::uno::Reference< css::chart2::XChartColorStyle 
>& rxChartColorStyle);
+private:
+    ChartColorStyleConverter( const ChartColorStyleConverter& ) = delete;
+    ChartColorStyleConverter&     operator=( const ChartColorStyleConverter& ) 
= delete;
+};
+
 
 } // namespace oox::drawingml::chart
 
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 9ea3611da259..b200f0e02541 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -1992,6 +1992,7 @@ $(eval $(call 
gb_UnoApi_add_idlfiles,offapi,com/sun/star/chart2,\
        TransparencyStyle \
        XAnyDescriptionAccess \
        XAxis \
+    XChartColorStyle \
        XChartDocument \
        XChartShape \
        XChartShapeContainer \
diff --git a/offapi/com/sun/star/chart2/XChartColorStyle.idl 
b/offapi/com/sun/star/chart2/XChartColorStyle.idl
new file mode 100644
index 000000000000..54e8cd7e4eec
--- /dev/null
+++ b/offapi/com/sun/star/chart2/XChartColorStyle.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 {
+
+/** Interface for chart colors
+
+    @since LibreOffice 26.2
+*/
+
+interface XChartColorStyle : com::sun::star::uno::XInterface
+{
+};
+
+}; }; }; };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/offapi/com/sun/star/chart2/XChartDocument.idl 
b/offapi/com/sun/star/chart2/XChartDocument.idl
index d75fb65af4f6..881078db5d14 100644
--- a/offapi/com/sun/star/chart2/XChartDocument.idl
+++ b/offapi/com/sun/star/chart2/XChartDocument.idl
@@ -123,6 +123,11 @@ interface XChartDocument : ::com::sun::star::frame::XModel
         @since LibreOffice 26.02
      */
     XChartStyle getStyles();
+
+    /** Get colorstyle information
+        @since LibreOffice 26.02
+     */
+    XChartColorStyle getColorStyles();
 };
 
 } ; // chart2
diff --git a/oox/inc/drawingml/chart/colorsmodel.hxx 
b/oox/inc/drawingml/chart/colorsmodel.hxx
new file mode 100644
index 000000000000..1972cba650dd
--- /dev/null
+++ b/oox/inc/drawingml/chart/colorsmodel.hxx
@@ -0,0 +1,33 @@
+/* -*- 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 <docmodel/styles/ChartColorStyle.hxx>
+
+namespace oox::drawingml::chart
+{
+// Holds the contents of a cs:CT_ColorStyle
+struct ColorStyleModel
+{
+    std::vector<Color> maColors;
+    std::vector<model::ComplexColor> maComplexColors;
+    ::model::ColorStyleMethod meMethod;
+    sal_Int32 mnId;
+};
+
+} // namespace oox::drawingml::chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/inc/drawingml/chart/stylefragment.hxx 
b/oox/inc/drawingml/chart/stylefragment.hxx
index 9adbea526aba..71875479092b 100644
--- a/oox/inc/drawingml/chart/stylefragment.hxx
+++ b/oox/inc/drawingml/chart/stylefragment.hxx
@@ -85,6 +85,21 @@ public:
                                                            const 
AttributeList& rAttribs) override;
 };
 
+struct ColorStyleModel;
+
+/** Handler for a color fragment (cs:colorStyle root element).
+ */
+class ColorsFragment final : public FragmentBase<ColorStyleModel>
+{
+public:
+    explicit ColorsFragment(::oox::core::XmlFilterBase& rFilter, const 
OUString& rFragmentPath,
+                            ColorStyleModel& rModel);
+    virtual ~ColorsFragment() 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/colorchoicecontext.hxx 
b/oox/inc/drawingml/colorchoicecontext.hxx
index c3736bfbb46b..4c46d5f7be50 100644
--- a/oox/inc/drawingml/colorchoicecontext.hxx
+++ b/oox/inc/drawingml/colorchoicecontext.hxx
@@ -64,6 +64,24 @@ protected:
     ::model::ComplexColor* mpComplexColor;
 };
 
+/** Context handler for cs:variation elements, which describe transformations 
on
+ * colours.
+ */
+class VariationContext : public ColorValueContext
+{
+public:
+    explicit VariationContext(::oox::core::ContextHandler2Helper const & 
rParent,
+            Color* pColor, ::model::ComplexColor* pComplexColor);
+
+    virtual ::oox::core::ContextHandlerRef onCreateContext(
+            sal_Int32 nElement, const ::oox::AttributeList& rAttribs) override;
+
+private:
+    Color* mpColor;
+    ::model::ComplexColor* mpComplexColor;
+};
+
+
 /// Same as ColorContext, but handles multiple colors.
 class ColorsContext final : public ::oox::core::ContextHandler2
 {
diff --git a/oox/source/drawingml/chart/chartconverter.cxx 
b/oox/source/drawingml/chart/chartconverter.cxx
index 1b281bd6cbc5..db4291acb929 100644
--- a/oox/source/drawingml/chart/chartconverter.cxx
+++ b/oox/source/drawingml/chart/chartconverter.cxx
@@ -23,8 +23,11 @@
 #include <drawingml/chart/chartspaceconverter.hxx>
 #include <drawingml/chart/chartspacemodel.hxx>
 #include <drawingml/chart/stylemodel.hxx>
+#include <drawingml/chart/colorsmodel.hxx>
 #include <docmodel/uno/UnoChartStyle.hxx>
+#include <docmodel/uno/UnoChartColorStyle.hxx>
 #include <docmodel/styles/ChartStyle.hxx>
+#include <docmodel/styles/ChartColorStyle.hxx>
 #include <oox/helper/containerhelper.hxx>
 #include <oox/core/xmlfilterbase.hxx>
 #include <osl/diagnose.h>
@@ -175,6 +178,27 @@ void ChartStyleConverter::convertFromModel(XmlFilterBase& 
rFilter,
     aStyles.mnId = rChartStyleModel.mnId;
 }
 
+// ===========
+// ChartColorStyleConverter
+// ===========
+void ChartColorStyleConverter::convertFromModel([[maybe_unused]] 
XmlFilterBase& rFilter,
+        ColorStyleModel& rChartColorStyleModel,
+        const Reference< XChartColorStyle >& rxChartColorStyle)
+{
+    OSL_ENSURE( rxChartColorStyle.is(), 
"ChartColorStyleConverter::convertFromModel - missing chart colorstyle" );
+    if (!rxChartColorStyle.is()) return;
+
+    UnoChartColorStyle *pUnoCS = 
static_cast<UnoChartColorStyle*>(rxChartColorStyle.get());
+    assert(pUnoCS);
+
+    model::ColorStyleSet& aColorStyles = pUnoCS->getChartColorStyle();
+
+    if (!rChartColorStyleModel.maComplexColors.empty()) {
+        aColorStyles.addEntry(rChartColorStyleModel.maComplexColors,
+                rChartColorStyleModel.meMethod, rChartColorStyleModel.mnId);
+    }
+}
+
 
 } // namespace oox::drawingml::chart
 
diff --git a/oox/source/drawingml/chart/colorsmodel.cxx 
b/oox/source/drawingml/chart/colorsmodel.cxx
new file mode 100644
index 000000000000..8c026ed2af33
--- /dev/null
+++ b/oox/source/drawingml/chart/colorsmodel.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/.
+ */
+
+#include <tools/gen.hxx>
+#include <drawingml/chart/stylemodel.hxx>
+#include <docmodel/text/TextBodyProps.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace com::sun::star;
+
+namespace oox::drawingml::chart
+{
+model::StyleEntry StyleEntryModel::toStyleEntry([[maybe_unused]] 
oox::core::XmlFilterBase& rFilter)
+{
+    std::shared_ptr<model::ShapeBase> pShapePr;
+    // Down-cast to ShapeBase* and deep copy so the shared_ptr can have 
ownership
+    if (mxShapeProp)
+    {
+        pShapePr = std::make_shared<model::ShapeBase>(
+            *static_cast<model::ShapeBase*>(mxShapeProp.get()));
+    }
+
+    std::shared_ptr<model::TextCharPropsBase> pCharPr;
+    // Down-cast to TextCharPropsBase* and deep copy so the shared_ptr can 
have ownership
+    if (mrTextCharacterProperties)
+    {
+        pCharPr = std::make_shared<model::TextCharPropsBase>(
+            
*static_cast<model::TextCharPropsBase*>(mrTextCharacterProperties.get()));
+    }
+
+    std::shared_ptr<model::TextBodyProps> pBodyPr;
+    if (mxBodyPr)
+    {
+        // Down-cast to TextBodyProps* and deep copy so the shared_ptr can 
have ownership
+        pBodyPr = std::make_shared<model::TextBodyProps>(
+            *static_cast<model::TextBodyProps*>(mxBodyPr.get()));
+    }
+
+    return model::StyleEntry(mxLnRef, mfLineWidthScale, mxFillRef, 
mxEffectRef, mxFontRef,
+                             std::move(pShapePr), std::move(pCharPr), 
std::move(pBodyPr));
+}
+
+} // namespace oox::drawingml::chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/chart/stylefragment.cxx 
b/oox/source/drawingml/chart/stylefragment.cxx
index 90f3fdcc7481..262ce7c79ad1 100644
--- a/oox/source/drawingml/chart/stylefragment.cxx
+++ b/oox/source/drawingml/chart/stylefragment.cxx
@@ -26,6 +26,7 @@
 #include <drawingml/textbodypropertiescontext.hxx>
 #include <drawingml/textcharacterpropertiescontext.hxx>
 #include <drawingml/chart/stylemodel.hxx>
+#include <drawingml/chart/colorsmodel.hxx>
 #include <drawingml/colorchoicecontext.hxx>
 #include <docmodel/styles/ChartStyle.hxx>
 #include <oox/drawingml/color.hxx>
@@ -34,6 +35,8 @@
 #include <oox/token/namespaces.hxx>
 #include <oox/token/tokens.hxx>
 
+#include <tools/UnitConversion.hxx>
+
 namespace oox::drawingml::chart
 {
 using namespace ::oox::core;
@@ -258,6 +261,82 @@ ContextHandlerRef StyleFragment::onCreateContext(sal_Int32 
nElement, const Attri
     return nullptr;
 }
 
+//=======
+// ColorsFragment
+//=======
+ColorsFragment::ColorsFragment(XmlFilterBase& rFilter, const OUString& 
rFragmentPath,
+                               ColorStyleModel& rModel)
+    : FragmentBase<ColorStyleModel>(rFilter, rFragmentPath, rModel)
+{
+}
+
+ColorsFragment::~ColorsFragment() {}
+
+ContextHandlerRef ColorsFragment::onCreateContext(sal_Int32 nElement, const 
AttributeList& rAttribs)
+{
+    switch (getCurrentElement())
+    {
+        case XML_ROOT_CONTEXT:
+            switch (nElement)
+            {
+                case CS_TOKEN(colorStyle):
+                    mrModel.mnId = rAttribs.getInteger(XML_id, -1);
+                    std::optional<OUString> sMethod = 
rAttribs.getString(XML_meth);
+                    if (sMethod)
+                    {
+                        if (*sMethod == "cycle")
+                        {
+                            mrModel.meMethod = ColorStyleMethod::CYCLE;
+                        }
+                        else if (*sMethod == "withinLinear")
+                        {
+                            mrModel.meMethod = ColorStyleMethod::WITHIN_LINEAR;
+                        }
+                        else if (*sMethod == "acrossLinear")
+                        {
+                            mrModel.meMethod = ColorStyleMethod::ACROSS_LINEAR;
+                        }
+                        else if (*sMethod == "withinLinearReversed")
+                        {
+                            mrModel.meMethod = 
ColorStyleMethod::WITHIN_LINEAR_REVERSED;
+                        }
+                        else if (*sMethod == "acrossLinearReversed")
+                        {
+                            mrModel.meMethod = 
ColorStyleMethod::ACROSS_LINEAR_REVERSED;
+                        }
+                        else
+                        {
+                            assert(false);
+                        }
+                    }
+                    return this;
+            }
+            break;
+
+        case CS_TOKEN(colorStyle):
+            switch (nElement)
+            {
+                case A_TOKEN(scrgbClr):
+                case A_TOKEN(srgbClr):
+                case A_TOKEN(hslClr):
+                case A_TOKEN(sysClr):
+                case A_TOKEN(schemeClr):
+                case A_TOKEN(prstClr):
+                    mrModel.maColors.emplace_back();
+                    mrModel.maComplexColors.emplace_back();
+                    return new ColorValueContext(*this, 
&mrModel.maColors.back(),
+                                                 
&mrModel.maComplexColors.back());
+
+                case CS_TOKEN(variation):
+                    // "variation"s presumably apply to the preceding color 
entry
+                    return new VariationContext(*this, 
&mrModel.maColors.back(),
+                                                
&mrModel.maComplexColors.back());
+            }
+            break;
+    }
+    return nullptr;
+}
+
 } // namespace oox::drawingml::chart
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/colorchoicecontext.cxx 
b/oox/source/drawingml/colorchoicecontext.cxx
index 41c2180a1a87..3122d7917f4f 100644
--- a/oox/source/drawingml/colorchoicecontext.cxx
+++ b/oox/source/drawingml/colorchoicecontext.cxx
@@ -282,6 +282,38 @@ ColorContext::ColorContext(ContextHandler2Helper const & 
rParent, Color* pColor,
     return nullptr;
 }
 
+//===========
+// VariationContext
+//===========
+
+VariationContext::VariationContext(ContextHandler2Helper const & rParent,
+        Color* pColor, model::ComplexColor* pComplexColor)
+    : ColorValueContext(rParent, pColor, pComplexColor)
+    , mpColor(pColor)
+    , mpComplexColor(pComplexColor)
+{
+}
+
+::oox::core::ContextHandlerRef VariationContext::onCreateContext(
+        sal_Int32 nElement, const AttributeList& )
+{
+    switch( nElement )
+    {
+        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, mpColor, mpComplexColor);
+    }
+    return nullptr;
+}
+
+//===========
+// ColorsContext
+//===========
+
 ColorsContext::ColorsContext(ContextHandler2Helper const& rParent, 
std::vector<Color>& rColors)
     : ContextHandler2(rParent)
     , mrColors(rColors)
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index dedfffde0f48..ff2d2edabea7 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -39,6 +39,7 @@
 #include <drawingml/chart/chartspacefragment.hxx>
 #include <drawingml/chart/stylefragment.hxx>
 #include <drawingml/chart/stylemodel.hxx>
+#include <drawingml/chart/colorsmodel.hxx>
 #include <drawingml/chart/chartspacemodel.hxx>
 #include <o3tl/safeint.hxx>
 #include <o3tl/unit_conversion.hxx>
@@ -91,6 +92,7 @@
 #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/chart2/XChartColorStyle.hpp>
 #include <com/sun/star/style/ParagraphAdjust.hpp>
 #include <com/sun/star/io/XOutputStream.hpp>
 #include <com/sun/star/lang/Locale.hpp>
@@ -2660,6 +2662,19 @@ void Shape::finalizeXShape( XmlFilterBase& rFilter, 
const Reference< XShapes >&
                         rFilter, sStylePath, aStyleModel );
                 rFilter.importFragment( pStyleFragment );
 
+                // Import colors file.
+                OUString sColorPath(pFPath, nLastSlash + 1);
+                sColorPath += u"colors"_ustr;
+                sChartFName = sFullPath.copy(nLastSlash + 1, 
sFullPath.getLength() - nLastSlash - 1);
+                sColorPath += sNumber;
+                sColorPath += u".xml"_ustr;
+
+                chart::ColorStyleModel aColorsModel;
+                rtl::Reference<chart::ColorsFragment> pColorsFragment =
+                    new chart::ColorsFragment( rFilter, sColorPath, 
aColorsModel );
+                rFilter.importFragment( pColorsFragment );
+
+
                 // The original theme.
                 ThemePtr pTheme;
                 const OUString aThemeOverrideFragmentPath( 
pChartSpaceFragment->
@@ -2708,6 +2723,9 @@ void Shape::finalizeXShape( XmlFilterBase& rFilter, const 
Reference< XShapes >&
                 // convert chart style model to docmodel style data
                 Reference<com::sun::star::chart2::XChartStyle> xStyle = 
xChartDoc->getStyles();
                 
oox::drawingml::chart::ChartStyleConverter::convertFromModel(rFilter, 
aStyleModel, xStyle);
+                // convert color style model to docmodel colors data
+                Reference<com::sun::star::chart2::XChartColorStyle> xCStyle = 
xChartDoc->getColorStyles();
+                
oox::drawingml::chart::ChartColorStyleConverter::convertFromModel(rFilter, 
aColorsModel, xCStyle);
 
                 if (pPowerPointImport)
                 {
diff --git a/oox/source/export/chartexport.cxx 
b/oox/source/export/chartexport.cxx
index ad4141186896..083b304f5ec4 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -32,6 +32,8 @@
 #include <cstdio>
 #include <limits>
 
+#include <tools/UnitConversion.hxx>
+
 #include <com/sun/star/awt/Gradient2.hpp>
 #include <com/sun/star/chart/XChartDocument.hpp>
 #include <com/sun/star/chart/ChartLegendPosition.hpp>
@@ -115,9 +117,12 @@
 
 #include <o3tl/temporary.hxx>
 #include <o3tl/sorted_vector.hxx>
+#include <o3tl/enumrange.hxx>
 
 #include <docmodel/styles/ChartStyle.hxx>
 #include <docmodel/uno/UnoChartStyle.hxx>
+#include <docmodel/styles/ChartColorStyle.hxx>
+#include <docmodel/uno/UnoChartColorStyle.hxx>
 
 #include <oox/export/ThemeExport.hxx>
 
@@ -1282,16 +1287,47 @@ void ChartExport::WriteChartObj( const Reference< 
XShape >& xShape, sal_Int32 nI
     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 */);
+    Reference<com::sun::star::chart2::XChartColorStyle> xColorStyle = 
xChartDoc->getColorStyles();
+    model::ColorStyleSet* aCSS = 
model::style::getFromXChartColorStyle(xColorStyle);
+
+    if (!aCSS->maEntryList.empty()) {
+        // use the stored data in the document model
+
+        static const std::map<model::ColorStyleMethod, std::string> aMethMap {
+                { model::ColorStyleMethod::CYCLE, "cycle" },
+                { model::ColorStyleMethod::WITHIN_LINEAR, "withinLinear" },
+                { model::ColorStyleMethod::ACROSS_LINEAR, "acrossLinear" },
+                { model::ColorStyleMethod::WITHIN_LINEAR_REVERSED, 
"withinLinearReversed" },
+                { model::ColorStyleMethod::ACROSS_LINEAR_REVERSED, 
"acrossLinearReversed" }
+        };
+
+        for (const model::ColorStyleEntry& rCStyleEntry : aCSS->maEntryList) {
+            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, aMethMap.at(rCStyleEntry.meMethod).c_str(),
+                    XML_id, OUString::number(rCStyleEntry.mnId));
+
+            ThemeExport aTE(mpFB, GetDocumentType(), pFS);
+            for (const model::ComplexColor& rColor : 
rCStyleEntry.maComplexColors) {
+                aTE.writeComplexColor(rColor);
+            }
 
-    pFS->singleElement(FSNS(XML_a, XML_schemeClr),
-            XML_val, "accent1");
+            pFS->endElement(FSNS(XML_cs, XML_colorStyle));
+        }
+    } else {
+        // output a default value to make MS Office happy
+        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->endElement(FSNS(XML_cs, XML_colorStyle));
+        pFS->singleElement(FSNS(XML_a, XML_schemeClr),
+                XML_val, "accent1");
+
+        pFS->endElement(FSNS(XML_cs, XML_colorStyle));
+    }
 
     pColorStyle->endDocument();
 
diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt
index 900cc8c74ecc..25b7aa189190 100644
--- a/oox/source/token/tokens.txt
+++ b/oox/source/token/tokens.txt
@@ -5727,6 +5727,7 @@ varScale
 varSubtotal
 variable
 variant
+variation
 varp
 varyColors
 vbProcedure

Reply via email to