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())