chart2/qa/extras/chart2export.cxx | 14 chart2/qa/extras/chart2export2.cxx | 2 chart2/qa/extras/charttest.hxx | 13 chart2/qa/extras/data/xlsx/column-style.xlsx |binary docmodel/source/uno/UnoChartStyle.cxx | 11 include/docmodel/styles/ChartStyle.hxx | 158 ------ include/docmodel/uno/UnoChartStyle.hxx | 2 include/oox/export/ThemeExport.hxx | 5 include/oox/export/chartexport.hxx | 15 include/oox/export/drawingml.hxx | 32 - oox/inc/drawingml/chart/stylefragment.hxx | 24 - oox/inc/drawingml/chart/stylemodel.hxx | 4 oox/source/drawingml/chart/stylefragment.cxx | 147 +++--- oox/source/drawingml/chart/stylemodel.cxx | 5 oox/source/drawingml/shape.cxx | 34 - oox/source/export/ThemeExport.cxx | 4 oox/source/export/chartexport.cxx | 620 ++++++++++----------------- oox/source/export/drawingml.cxx | 610 ++++++++++++-------------- test/source/xmltesttools.cxx | 2 19 files changed, 659 insertions(+), 1043 deletions(-)
New commits: commit 1117967e147e760098a7a5e044a8a575b0f922de Author: Kurt Nordback <[email protected]> AuthorDate: Tue Jan 20 09:46:04 2026 -0700 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Jan 26 08:09:52 2026 +0100 Revert "tdf#167941 - Chart style file is not supported in OOXML" This reverts commit 526287a4aa7fe06bcfaa8fedc26106bd1a87fc88. Change-Id: Ie286dea0fb442ba7ce6b396d8ce13696bd3620ac Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197895 Reviewed-by: Tomaž Vajngerl <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/chart2/qa/extras/chart2export.cxx b/chart2/qa/extras/chart2export.cxx index 55f597dbe2f3..291f87586b9f 100644 --- a/chart2/qa/extras/chart2export.cxx +++ b/chart2/qa/extras/chart2export.cxx @@ -1396,20 +1396,6 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testInvertNegative) } } -CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testStyleImportExport) -{ - // column-style.xlsx is a hand-edited test that includes an axisTitle style - // with run property text size 777 (chosen simply as a distinctive number). - // Test that this value round-trips successfully. - loadFromFile(std::u16string_view(u"xlsx/column-style.xlsx")); - - save("Calc Office Open XML"); - xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/style1.xml"); - CPPUNIT_ASSERT(pXmlDoc); - assertXPath(pXmlDoc, "/cs:chartStyle"); - assertXPath(pXmlDoc, "/cs:chartStyle/cs:axisTitle"); - assertXPath(pXmlDoc, "/cs:chartStyle/cs:axisTitle/a:defRPr", "sz", std::u16string_view(u"777")); -} CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/chart2/qa/extras/chart2export2.cxx b/chart2/qa/extras/chart2export2.cxx index 95b03c2b4331..d4881a353a59 100644 --- a/chart2/qa/extras/chart2export2.cxx +++ b/chart2/qa/extras/chart2export2.cxx @@ -963,7 +963,7 @@ CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, test_style) xmlDocUniquePtr pXmlDoc = parseExport(u"xl/charts/chart1.xml"_ustr); CPPUNIT_ASSERT(pXmlDoc); // workaround: use leave-gap instead of zero to show the original line chart - assertXPath(pXmlDoc, "/c:chartSpace/c:style", "val", u"36"); + assertXPath(pXmlDoc, "/c:chartSpace/c:style", "val", u"23"); } CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCustomLabelText) diff --git a/chart2/qa/extras/charttest.hxx b/chart2/qa/extras/charttest.hxx index a8edb86bbde9..696e3c7ab164 100644 --- a/chart2/qa/extras/charttest.hxx +++ b/chart2/qa/extras/charttest.hxx @@ -109,8 +109,6 @@ public: getShapeByName(const uno::Reference<drawing::XShapes>& rShapes, const OUString& rName, const std::function<bool(const uno::Reference<drawing::XShape>&)>& pCondition = nullptr); - Reference<chart2::XChartStyle> - getStyleFromDoc(Reference<chart2::XChartDocument> const& xChartDoc); }; Reference< lang::XComponent > ChartTest::getChartCompFromSheet( sal_Int32 nSheet, sal_Int32 nChart ) @@ -509,15 +507,4 @@ ChartTest::getShapeByName(const uno::Reference<drawing::XShapes>& rShapes, const return uno::Reference<drawing::XShape>(); } -Reference<chart2::XChartStyle> - getStyleFromDoc(Reference<chart2::XChartDocument> const& xChartDoc) -{ - CPPUNIT_ASSERT( xChartDoc.is() ); - - Reference <chart2::XChartStyle > xStyle = xChartDoc->getStyles(); - CPPUNIT_ASSERT( xStyle.is() ); - - return xStyle; -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/qa/extras/data/xlsx/column-style.xlsx b/chart2/qa/extras/data/xlsx/column-style.xlsx index be9e29050d11..95da9c97caa8 100644 Binary files a/chart2/qa/extras/data/xlsx/column-style.xlsx and b/chart2/qa/extras/data/xlsx/column-style.xlsx differ diff --git a/docmodel/source/uno/UnoChartStyle.cxx b/docmodel/source/uno/UnoChartStyle.cxx index d7e9b5019b63..8aeb5cb52b99 100644 --- a/docmodel/source/uno/UnoChartStyle.cxx +++ b/docmodel/source/uno/UnoChartStyle.cxx @@ -20,18 +20,15 @@ uno::Reference<chart2::XChartStyle> createXChartStyle(model::StyleSet const& rSt return new UnoChartStyle(rStyle); } -model::StyleSet* getFromXChartStyle(uno::Reference<chart2::XChartStyle> const& rxStyle) +model::StyleSet getFromXChartStyle(uno::Reference<chart2::XChartStyle> const& rxStyle) { + model::StyleSet aChartStyle; UnoChartStyle* pUnoChartStyle = static_cast<UnoChartStyle*>(rxStyle.get()); - if (pUnoChartStyle) { - return &pUnoChartStyle->getChartStyle(); - } - else - { - return nullptr; + aChartStyle = pUnoChartStyle->getChartStyle(); } + return aChartStyle; } } // end model::style diff --git a/include/docmodel/styles/ChartStyle.hxx b/include/docmodel/styles/ChartStyle.hxx index 18fffdc6b6e9..e455e6e37b1f 100644 --- a/include/docmodel/styles/ChartStyle.hxx +++ b/include/docmodel/styles/ChartStyle.hxx @@ -19,10 +19,8 @@ namespace model { -struct FontOrStyleRef +struct StyleColor { - sal_Int32 mnIdx; // required - enum class StyleColorEnum { AUTO @@ -30,56 +28,32 @@ struct FontOrStyleRef // The schema uses 'union' here. Implement with a std::variant for safety. using StyleColorVal = std::variant<sal_uInt32, enum StyleColorEnum, OUString>; - std::unique_ptr<StyleColorVal> maStyleClr; // optional - - // Get a string version of the ColorVal, for output/streaming - OUString getColorValStr() const - { - OUString sV; - - if (maStyleClr) - { - switch (maStyleClr->index()) - { - case 0: // sal_uInt32, a raw color value - sV = OUString::number(std::get<0>(*maStyleClr)); - break; - case 1: // enum; only value "auto" - sV = "auto"; - break; - case 2: // arbitrary string - sV = std::get<2>(*maStyleClr); - break; - } - } - return sV; - } + typedef std::vector<StyleColorVal> StyleColorVec; - // A child element of cs:CT_FontReference or cs:CT_StyleReference is - // a:EG_ColorChoice. The latter is handled by ColorValueContext. - oox::drawingml::Color maColor; // needed for ColorValueContext - model::ComplexColor maComplexColor; // needed for ColorValueContext + 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 - // FontOrStyleRef. Ignore those for now. TODO + // StyleColor. Ignore those for now. TODO }; struct StyleEntry { - std::shared_ptr<FontOrStyleRef> mxLnClr; + std::shared_ptr<StyleColor> mxLnClr; double mfLineWidthScale = 1.0; - std::shared_ptr<FontOrStyleRef> mxFillClr; - std::shared_ptr<FontOrStyleRef> mxEffectClr; - std::shared_ptr<FontOrStyleRef> mxFontClr; + 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<FontOrStyleRef> aLnClr, double fLineScale, - std::shared_ptr<FontOrStyleRef> aFillClr, std::shared_ptr<FontOrStyleRef> aEffectClr, - std::shared_ptr<FontOrStyleRef> aFontClr, - std::shared_ptr<oox::drawingml::Shape> aShape, + 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) @@ -98,8 +72,7 @@ struct DOCMODEL_DLLPUBLIC StyleSet { enum class StyleEntryType { - BEGIN = 0, // for iteration - AXISTITLE = BEGIN, + AXISTITLE, CATEGORYAXIS, CHARTAREA, DATALABEL, @@ -129,8 +102,7 @@ struct DOCMODEL_DLLPUBLIC StyleSet TRENDLINELABEL, UPBAR, VALUEAXIS, - WALL, - END // for iteration + WALL }; std::map<enum StyleEntryType, StyleEntry> maEntryMap; diff --git a/include/docmodel/uno/UnoChartStyle.hxx b/include/docmodel/uno/UnoChartStyle.hxx index 45bb26811ba8..91588a985c9d 100644 --- a/include/docmodel/uno/UnoChartStyle.hxx +++ b/include/docmodel/uno/UnoChartStyle.hxx @@ -47,7 +47,7 @@ namespace model::style { DOCMODEL_DLLPUBLIC css::uno::Reference<css::chart2::XChartStyle> createXChartStyle(model::StyleSet const& rStyle); -DOCMODEL_DLLPUBLIC model::StyleSet* +DOCMODEL_DLLPUBLIC model::StyleSet getFromXChartStyle(css::uno::Reference<css::chart2::XChartStyle> const& rxStyle); } diff --git a/include/oox/export/ThemeExport.hxx b/include/oox/export/ThemeExport.hxx index 91c4b57ad8e8..c220d2d3037d 100644 --- a/include/oox/export/ThemeExport.hxx +++ b/include/oox/export/ThemeExport.hxx @@ -40,11 +40,9 @@ private: sax_fastparser::FSHelperPtr mpFS; public: - ThemeExport(oox::core::XmlFilterBase* pFilterBase, oox::drawingml::DocumentType eDocumentType, - sax_fastparser::FSHelperPtr pFS = nullptr); + ThemeExport(oox::core::XmlFilterBase* pFilterBase, oox::drawingml::DocumentType eDocumentType); void write(OUString const& rPath, model::Theme const& rTheme); - void writeComplexColor(model::ComplexColor const& rComplexColor); private: bool writeColorSet(model::Theme const& rTheme); @@ -60,6 +58,7 @@ private: void writePatternFill(model::PatternFill const& rPatternFill); void writeGradientFill(model::GradientFill const& rGradientFill); void writeSolidFill(model::SolidFill const& rSolidFill); + void writeComplexColor(model::ComplexColor const& rComplexColor); void writeColorPlaceholder(model::ComplexColor const& rComplexColor); void writeColorSystem(model::ComplexColor const& rComplexColor); void writeColorTheme(model::ComplexColor const& rComplexColor); diff --git a/include/oox/export/chartexport.hxx b/include/oox/export/chartexport.hxx index e2c4d082072f..5900ce9496e4 100644 --- a/include/oox/export/chartexport.hxx +++ b/include/oox/export/chartexport.hxx @@ -69,11 +69,6 @@ namespace core { class XmlFilterBase; }} -namespace model { - struct FontOrStyleRef; - struct StyleEntry; -} - namespace oox::drawingml { struct LabelPlacementParam; @@ -243,7 +238,7 @@ private: void exportSeriesValues( const css::uno::Reference< css::chart2::data::XDataSequence >& xValueSeq, sal_Int32 nValueType = XML_val ); void exportShapeProps( const css::uno::Reference< css::beans::XPropertySet >& xPropSet, - sal_Int32 nNS); + bool bIsChartex); void exportDataPoints( const css::uno::Reference< css::beans::XPropertySet >& xSeriesProperties, sal_Int32 nSeriesLength, sal_Int32 eChartType ); @@ -294,11 +289,6 @@ private: const css::uno::Reference<css::beans::XPropertySet>& xPropSet, const LabelPlacementParam& rLabelParam, sal_Int32 nLabelIndex, DataLabelsRange& rDLblsRange, bool bIsChartex); - // Functions for style file output - void outputStyleEntry(::sax_fastparser::FSHelperPtr pFS, - sal_Int32 nElTokenId, model::StyleEntry& aEntry); - void outputFontOrStyleRef(::sax_fastparser::FSHelperPtr pFS, - sal_Int32 nElTokenId, const model::FontOrStyleRef& aColor); public: diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index 9b5a28eaef1f..aa08f22c5ee7 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -50,8 +50,6 @@ #include <vcl/mapmod.hxx> #include <svx/EnhancedCustomShape2d.hxx> #include <basegfx/utils/bgradient.hxx> -#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> - class Graphic; class SdrObjCustomShape; @@ -293,28 +291,6 @@ struct WriteRunInput css::uno::Reference<css::beans::XPropertySet> xShapePropSet; }; -struct WriteBodyPropsInput -{ - bool bIsFontworkShape = false; - bool bHasWrap = false; - bool bWrap = false; - bool bFromWordArt = false; - sal_Int32 nTop = 0; - sal_Int32 nBottom = 0; - sal_Int32 nLeft = 0; - sal_Int32 nRight = 0; - std::optional<OUString> sHorzOverflow; - std::optional<OUString> sVertOverflow; - const char *sAnchor = nullptr; - bool bAnchorCtr = false; - std::optional<OString> sWritingMode; - std::optional<OString> sIsUpright; - std::optional<OString> sTextRotateAngleMSUnit; - css::uno::Sequence<css::drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentSeq; - OUString sPresetWarp; - OUString sMSWordPresetTextWarp; -}; - class DrawingML { @@ -324,8 +300,6 @@ private: /// Parent exporter, used for text callback. DMLTextExport* mpTextExport; - static constexpr const sal_Int32 mconstDefaultLeftRightInset = 254; - static constexpr const sal_Int32 mconstDefaultTopBottomInset = 127; protected: css::uno::Any mAny; @@ -492,12 +466,6 @@ public: bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, const css::uno::Reference<css::beans::XPropertySet>& rXShapePropSet, sal_Int32 nElement); - void WriteBodyProps( - const css::uno::Reference< css::uno::XInterface >& rXIface, - const css::uno::Reference<css::beans::XPropertySet>& rXPropSet, - const css::uno::Reference<css::drawing::XShape>& xShape, - sal_Int32 nXmlNamespace, const WriteBodyPropsInput& aWBPInput); - /** Populates the lstStyle with the shape's text run and paragraph properties */ void WriteLstStyles(const css::uno::Reference<css::text::XTextContent>& rParagraph, bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, diff --git a/oox/inc/drawingml/chart/stylefragment.hxx b/oox/inc/drawingml/chart/stylefragment.hxx index a7bb698a43e2..aff1f59f870c 100644 --- a/oox/inc/drawingml/chart/stylefragment.hxx +++ b/oox/inc/drawingml/chart/stylefragment.hxx @@ -23,18 +23,18 @@ namespace model { -struct FontOrStyleRef; +struct StyleColor; } namespace oox::drawingml::chart { /** Handler for a cs:CT_StyleReference or cs:CT_FontReference element. */ -class StyleReferenceContext final : public ContextBase<model::FontOrStyleRef> +class StyleReferenceContext final : public ContextBase<model::StyleColor> { public: StyleReferenceContext(ContextHandler2Helper& rParent, sal_Int32 nIdx, - model::FontOrStyleRef& rModel); + model::StyleColor& rModel); virtual ~StyleReferenceContext() override; virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, diff --git a/oox/inc/drawingml/chart/stylemodel.hxx b/oox/inc/drawingml/chart/stylemodel.hxx index ce8c2c8e64d6..d0c1bc92e82f 100644 --- a/oox/inc/drawingml/chart/stylemodel.hxx +++ b/oox/inc/drawingml/chart/stylemodel.hxx @@ -28,8 +28,8 @@ namespace oox::drawingml::chart // model for both. struct StyleEntryModel { - typedef ModelRef<model::FontOrStyleRef> StyleRef; // "idx" is ST_StyleMatrixColumnIndex - typedef ModelRef<model::FontOrStyleRef> FontRef; // "idx" is ST_FontCollectionIndex + 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; diff --git a/oox/source/drawingml/chart/stylefragment.cxx b/oox/source/drawingml/chart/stylefragment.cxx index a353ce445d91..562fe27bda31 100644 --- a/oox/source/drawingml/chart/stylefragment.cxx +++ b/oox/source/drawingml/chart/stylefragment.cxx @@ -43,8 +43,8 @@ using namespace model; // StyleReferenceContext //======= StyleReferenceContext::StyleReferenceContext(ContextHandler2Helper& rParent, sal_Int32 nIdx, - model::FontOrStyleRef& rModel) - : ContextBase<FontOrStyleRef>(rParent, rModel) + model::StyleColor& rModel) + : ContextBase<StyleColor>(rParent, rModel) { mrModel.mnIdx = nIdx; } @@ -75,7 +75,7 @@ ContextHandlerRef StyleReferenceContext::onCreateContext(sal_Int32 nElement, std::optional<OUString> str = rAttribs.getString(XML_val); if (str) { - FontOrStyleRef::StyleColorVal v; + StyleColor::StyleColorVal v; const sal_Unicode* pRawStr = str->getStr(); std::wstring sBStr; @@ -96,14 +96,14 @@ ContextHandlerRef StyleReferenceContext::onCreateContext(sal_Int32 nElement, // Not an integer, so see if it's the fixed enum if (*str == "auto") { - v = FontOrStyleRef::StyleColorEnum::AUTO; + v = StyleColor::StyleColorEnum::AUTO; } else { v = *str; } } - mrModel.maStyleClr = std::make_unique<FontOrStyleRef::StyleColorVal>(v); + mrModel.maStyleClr.push_back(v); } return nullptr; } diff --git a/oox/source/drawingml/chart/stylemodel.cxx b/oox/source/drawingml/chart/stylemodel.cxx index ddfb24d9c35d..c72c8391179a 100644 --- a/oox/source/drawingml/chart/stylemodel.cxx +++ b/oox/source/drawingml/chart/stylemodel.cxx @@ -35,12 +35,11 @@ model::StyleEntry StyleEntryModel::toStyleEntry(oox::core::XmlFilterBase& rFilte // which can be set using pushTextDistances(). I'm not sure why the // interfaces are different, but that's why what's below is not parallel to // the above. - std::shared_ptr<PropertyMap> aBodyMap; + std::shared_ptr<PropertyMap> aBodyMap = std::make_shared<PropertyMap>(); if (mxBodyPr) { mxBodyPr->pushTextDistances(Size(0, 0)); - // Deep copy mxBodyPr->maPropertyMap so the shared_ptr can have ownership - aBodyMap = std::make_shared<PropertyMap>(mxBodyPr->maPropertyMap); + aBodyMap.reset(&mxBodyPr->maPropertyMap); } return model::StyleEntry(mxLnRef, mfLineWidthScale, mxFillRef, mxEffectRef, mxFontRef, diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index 55f0eef8afe4..346722bda6b0 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -2643,31 +2643,11 @@ void Shape::finalizeXShape( XmlFilterBase& rFilter, const Reference< XShapes >& rFilter, mxChartShapeInfo->maFragmentPath, aModel ); rFilter.importFragment( pChartSpaceFragment ); - // Import styles file. - // Create the styles path from the path to the chart*.xml file + // Import styles file sal_Int32 nLastSlash = mxChartShapeInfo->maFragmentPath.lastIndexOf('/'); const sal_Unicode *pFPath = mxChartShapeInfo->maFragmentPath.getStr(); OUString sStylePath(pFPath, nLastSlash + 1); - OUString sFullPath(pFPath); - sStylePath += u"style"_ustr; - OUString sChartFName(sFullPath.copy(nLastSlash + 1, sFullPath.getLength() - nLastSlash - 1)); - OUString sTail; - // Verify that the path is the way we expect it, and extract the - // end bit. Don't put the startsWith() call inside an assert, - // because we don't want it optimized away. - const bool bWellFormed = sChartFName.startsWith(std::u16string_view(u"chart"), &sTail); - if (!bWellFormed) { - assert(false); - } - // We should have something of the form 'chart1234.xml'. We - // want to get the numeric ('1234') part, since it should be - // the same for the style file. - sal_Int32 nPeriod = sTail.indexOf('.'); - OUString sNumber(sTail.copy(0, nPeriod)); - - sStylePath += sNumber; - sStylePath += u".xml"_ustr; - + sStylePath += u"style1.xml"_ustr; chart::StyleModel aStyleModel; rtl::Reference<chart::StyleFragment> pStyleFragment = new chart::StyleFragment( rFilter, sStylePath, aStyleModel ); @@ -2719,8 +2699,14 @@ 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); + 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) { diff --git a/oox/source/export/ThemeExport.cxx b/oox/source/export/ThemeExport.cxx index 64a0d9b5155a..069b38b090dd 100644 --- a/oox/source/export/ThemeExport.cxx +++ b/oox/source/export/ThemeExport.cxx @@ -38,11 +38,9 @@ void writeRelativeRectangle(sax_fastparser::FSHelperPtr pFS, sal_Int32 nToken, } // end anonymous namespace ThemeExport::ThemeExport(oox::core::XmlFilterBase* pFilterBase, - oox::drawingml::DocumentType eDocumentType, - sax_fastparser::FSHelperPtr pFS) + oox::drawingml::DocumentType eDocumentType) : mpFilterBase(pFilterBase) , meDocumentType(eDocumentType) - , mpFS(pFS) { } diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index 056c49c467ab..45c1adcaf7c8 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -115,11 +115,6 @@ #include <o3tl/temporary.hxx> #include <o3tl/sorted_vector.hxx> -#include <docmodel/styles/ChartStyle.hxx> -#include <docmodel/uno/UnoChartStyle.hxx> - -#include <oox/export/ThemeExport.hxx> - using namespace css; using namespace css::uno; using namespace css::drawing; @@ -167,6 +162,75 @@ private: OUString m_aRole; }; +void outputStyleEntry(FSHelperPtr pFS, sal_Int32 nElTokenId) +{ + // Just default values for now + pFS->startElement(FSNS(XML_cs, nElTokenId)); + pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0"); + pFS->singleElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0"); + pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0"); + pFS->singleElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor"); + pFS->endElement(FSNS(XML_cs, nElTokenId)); +} + +void outputChartAreaStyleEntry(FSHelperPtr pFS) +{ + // Just default values for now + pFS->startElement(FSNS(XML_cs, XML_chartArea), XML_mods, "allowNoFillOverride allowNoLineOverride"); + pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0"); + pFS->singleElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0"); + pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0"); + + pFS->startElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor"); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "tx1"); + pFS->endElement(FSNS(XML_cs, XML_fontRef)); + + pFS->startElement(FSNS(XML_cs, XML_spPr)); + + pFS->startElement(FSNS(XML_a, XML_solidFill)); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "bg1"); + pFS->endElement(FSNS(XML_a, XML_solidFill)); + + pFS->startElement(FSNS(XML_a, XML_ln), XML_w, "9525", XML_cap, "flat", + XML_cmpd, "sng", XML_algn, "ctr"); + pFS->startElement(FSNS(XML_a, XML_solidFill)); + pFS->startElement(FSNS(XML_a, XML_schemeClr), XML_val, "tx1"); + pFS->singleElement(FSNS(XML_a, XML_lumMod), XML_val, "15000"); + pFS->singleElement(FSNS(XML_a, XML_lumOff), XML_val, "85000"); + pFS->endElement(FSNS(XML_a, XML_schemeClr)); + pFS->endElement(FSNS(XML_a, XML_solidFill)); + pFS->singleElement(FSNS(XML_a, XML_round)); + pFS->endElement(FSNS(XML_a, XML_ln)); + + pFS->endElement(FSNS(XML_cs, XML_spPr)); + + pFS->endElement(FSNS(XML_cs, XML_chartArea)); +} + +void outputDataPointStyleEntry(FSHelperPtr pFS) +{ + pFS->startElement(FSNS(XML_cs, XML_dataPoint)); + pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0"); + + pFS->startElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0"); + pFS->singleElement(FSNS(XML_cs, XML_styleClr), XML_val, "auto"); + pFS->endElement(FSNS(XML_cs, XML_fillRef)); + + pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0"); + + pFS->startElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor"); + pFS->singleElement(FSNS(XML_cs, XML_schemeClr), XML_val, "tx1"); + pFS->endElement(FSNS(XML_cs, XML_fontRef)); + + pFS->startElement(FSNS(XML_cs, XML_spPr)); + pFS->startElement(FSNS(XML_a, XML_solidFill)); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "phClr"); + pFS->endElement(FSNS(XML_a, XML_solidFill)); + pFS->endElement(FSNS(XML_cs, XML_spPr)); + + pFS->endElement(FSNS(XML_cs, XML_dataPoint)); +} + std::vector<Sequence<Reference<chart2::XDataSeries> > > splitDataSeriesByAxis(const Reference< chart2::XChartType >& xChartType) { std::vector<Sequence<Reference<chart2::XDataSeries> > > aSplitSeries; @@ -844,175 +908,6 @@ OUString ChartExport::parseFormula( const OUString& rRange ) return aResult; } -// Output the chartex AlternateContent fallback path -static void writeChartexAlternateContent(FSHelperPtr pFS) -{ - pFS->startElementNS(XML_mc, XML_Fallback); - pFS->startElementNS(XML_xdr, XML_sp, XML_macro, "", XML_textlink, ""); - pFS->startElementNS(XML_xdr, XML_nvSpPr); - pFS->singleElementNS(XML_xdr, XML_cNvPr, XML_id, "0", XML_name, ""); - pFS->startElementNS(XML_xdr, XML_cNvSpPr); - pFS->singleElementNS(XML_a, XML_spLocks, XML_noTextEdit, "1"); - pFS->endElementNS(XML_xdr, XML_cNvSpPr); - pFS->endElementNS(XML_xdr, XML_nvSpPr); - pFS->startElementNS(XML_xdr, XML_spPr); - pFS->startElementNS(XML_a, XML_xfrm); - pFS->singleElementNS(XML_a, XML_off, XML_x, "6600825", XML_y, "2533650"); - pFS->singleElementNS(XML_a, XML_ext, XML_cx, "4572000", XML_cy, "2743200"); - pFS->endElementNS(XML_a, XML_xfrm); - pFS->startElementNS(XML_a, XML_prstGeom, XML_prst, "rect"); - pFS->singleElementNS(XML_a, XML_avLst); - pFS->endElementNS(XML_a, XML_prstGeom); - pFS->startElementNS(XML_a, XML_solidFill); - pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "white"); - pFS->endElementNS(XML_a, XML_solidFill); - pFS->startElementNS(XML_a, XML_ln, XML_w, "1"); - pFS->startElementNS(XML_a, XML_solidFill); - pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "green"); - pFS->endElementNS(XML_a, XML_solidFill); - pFS->endElementNS(XML_a, XML_ln); - pFS->endElementNS(XML_xdr, XML_spPr); - pFS->startElementNS(XML_xdr, XML_txBody); - pFS->singleElementNS(XML_a, XML_bodyPr, XML_vertOverflow, "clip", XML_horzOverflow, "clip"); - pFS->singleElementNS(XML_a, XML_lstStyle); - pFS->startElementNS(XML_a, XML_p); - pFS->startElementNS(XML_a, XML_r); - pFS->singleElementNS(XML_a, XML_rPr, XML_sz, "1100"); - pFS->startElementNS(XML_a, XML_t); - - const std::string_view sErrTxt("This chart isn't available in your version of Excel. " - "Editing this shape or saving this workbook into a different file format will permanently break the chart."); - pFS->writeEscaped( sErrTxt ); - - pFS->endElementNS(XML_a, XML_t); - pFS->endElementNS(XML_a, XML_r); - pFS->endElementNS(XML_a, XML_p); - pFS->endElementNS(XML_xdr, XML_txBody); - pFS->endElementNS(XML_xdr, XML_sp); -} - -namespace { - -// Map enumerated style entry types to corresponding XML tags -struct styleTag { - model::StyleSet::StyleEntryType meType; - sal_Int32 mnTag; -}; - -std::array<styleTag, static_cast<int>(model::StyleSet::StyleEntryType::END)> styleTagMap {{ - { model::StyleSet::StyleEntryType::AXISTITLE, XML_axisTitle }, - { model::StyleSet::StyleEntryType::CATEGORYAXIS, XML_categoryAxis }, - { model::StyleSet::StyleEntryType::CHARTAREA, XML_chartArea }, - { model::StyleSet::StyleEntryType::DATALABEL, XML_dataLabel }, - { model::StyleSet::StyleEntryType::DATALABELCALLOUT, XML_dataLabelCallout }, - { model::StyleSet::StyleEntryType::DATAPOINT, XML_dataPoint }, - { model::StyleSet::StyleEntryType::DATAPOINT3D, XML_dataPoint3D }, - { model::StyleSet::StyleEntryType::DATAPOINTLINE, XML_dataPointLine }, - { model::StyleSet::StyleEntryType::DATAPOINTMARKER, XML_dataPointMarker }, - { model::StyleSet::StyleEntryType::DATAPOINTMARKERLAYOUT, XML_dataPointMarkerLayout }, - { model::StyleSet::StyleEntryType::DATAPOINTWIREFRAME, XML_dataPointWireframe }, - { model::StyleSet::StyleEntryType::DATATABLE, XML_dataTable }, - { model::StyleSet::StyleEntryType::DOWNBAR, XML_downBar }, - { model::StyleSet::StyleEntryType::DROPLINE, XML_dropLine }, - { model::StyleSet::StyleEntryType::ERRORBAR, XML_errorBar }, - { model::StyleSet::StyleEntryType::FLOOR, XML_floor }, - { model::StyleSet::StyleEntryType::GRIDLINEMAJOR, XML_gridlineMajor }, - { model::StyleSet::StyleEntryType::GRIDLINEMINOR, XML_gridlineMinor }, - { model::StyleSet::StyleEntryType::HILOLINE, XML_hiLoLine }, - { model::StyleSet::StyleEntryType::LEADERLINE, XML_leaderLine }, - { model::StyleSet::StyleEntryType::LEGEND, XML_legend }, - { model::StyleSet::StyleEntryType::PLOTAREA, XML_plotArea }, - { model::StyleSet::StyleEntryType::PLOTAREA3D, XML_plotArea3D }, - { model::StyleSet::StyleEntryType::SERIESAXIS, XML_seriesAxis }, - { model::StyleSet::StyleEntryType::SERIESLINE, XML_seriesLine }, - { model::StyleSet::StyleEntryType::TITLE, XML_title }, - { model::StyleSet::StyleEntryType::TRENDLINE, XML_trendline }, - { model::StyleSet::StyleEntryType::TRENDLINELABEL, XML_trendlineLabel }, - { model::StyleSet::StyleEntryType::UPBAR, XML_upBar }, - { model::StyleSet::StyleEntryType::VALUEAXIS, XML_valueAxis }, - { model::StyleSet::StyleEntryType::WALL, XML_wall } -}}; - -// The following functions are intended to duplicate what appear to be the MS -// Office defaults for various style entries. These are not documented anywhere, -// so far as I can tell. The values here are just derived by looking at some -// files Office creates. It's very possible that things are not as simple as the -// hard-coded values here. - -// All style entries other than the special cases below -void outputDefaultStyleEntry(FSHelperPtr pFS, sal_Int32 nElTokenId) -{ - pFS->startElement(FSNS(XML_cs, nElTokenId)); - pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0"); - pFS->singleElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0"); - pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0"); - pFS->singleElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor"); - pFS->endElement(FSNS(XML_cs, nElTokenId)); -} - -// chartArea entry -void outputDefaultChartAreaStyleEntry(FSHelperPtr pFS) -{ - pFS->startElement(FSNS(XML_cs, XML_chartArea), XML_mods, "allowNoFillOverride allowNoLineOverride"); - pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0"); - pFS->singleElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0"); - pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0"); - - pFS->startElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor"); - pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "tx1"); - pFS->endElement(FSNS(XML_cs, XML_fontRef)); - - pFS->startElement(FSNS(XML_cs, XML_spPr)); - - pFS->startElement(FSNS(XML_a, XML_solidFill)); - pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "bg1"); - pFS->endElement(FSNS(XML_a, XML_solidFill)); - - pFS->startElement(FSNS(XML_a, XML_ln), XML_w, "9525", XML_cap, "flat", - XML_cmpd, "sng", XML_algn, "ctr"); - pFS->startElement(FSNS(XML_a, XML_solidFill)); - pFS->startElement(FSNS(XML_a, XML_schemeClr), XML_val, "tx1"); - pFS->singleElement(FSNS(XML_a, XML_lumMod), XML_val, "15000"); - pFS->singleElement(FSNS(XML_a, XML_lumOff), XML_val, "85000"); - pFS->endElement(FSNS(XML_a, XML_schemeClr)); - pFS->endElement(FSNS(XML_a, XML_solidFill)); - pFS->singleElement(FSNS(XML_a, XML_round)); - pFS->endElement(FSNS(XML_a, XML_ln)); - - pFS->endElement(FSNS(XML_cs, XML_spPr)); - - pFS->endElement(FSNS(XML_cs, XML_chartArea)); -} - -// dataPoint entry -void outputDefaultDataPointStyleEntry(FSHelperPtr pFS) -{ - pFS->startElement(FSNS(XML_cs, XML_dataPoint)); - pFS->singleElement(FSNS(XML_cs, XML_lnRef), XML_idx, "0"); - - pFS->startElement(FSNS(XML_cs, XML_fillRef), XML_idx, "0"); - pFS->singleElement(FSNS(XML_cs, XML_styleClr), XML_val, "auto"); - pFS->endElement(FSNS(XML_cs, XML_fillRef)); - - pFS->singleElement(FSNS(XML_cs, XML_effectRef), XML_idx, "0"); - - pFS->startElement(FSNS(XML_cs, XML_fontRef), XML_idx, "minor"); - pFS->singleElement(FSNS(XML_cs, XML_schemeClr), XML_val, "tx1"); - pFS->endElement(FSNS(XML_cs, XML_fontRef)); - - pFS->startElement(FSNS(XML_cs, XML_spPr)); - pFS->startElement(FSNS(XML_a, XML_solidFill)); - pFS->singleElement(FSNS(XML_a, XML_schemeClr), XML_val, "phClr"); - pFS->endElement(FSNS(XML_a, XML_solidFill)); - pFS->endElement(FSNS(XML_cs, XML_spPr)); - - pFS->endElement(FSNS(XML_cs, XML_dataPoint)); -} - -} // unnamed namespace - - - void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nID, sal_Int32 nChartCount ) { FSHelperPtr pFS = GetFS(); @@ -1174,9 +1069,50 @@ void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nI pFS->endElementNS( mnXmlNamespace, XML_graphicFrame ); if (bIsChartex) { + // Do the AlternateContent fallback path pFS->endElementNS(XML_mc, XML_Choice); - - writeChartexAlternateContent(pFS); + pFS->startElementNS(XML_mc, XML_Fallback); + pFS->startElementNS(XML_xdr, XML_sp, XML_macro, "", XML_textlink, ""); + pFS->startElementNS(XML_xdr, XML_nvSpPr); + pFS->singleElementNS(XML_xdr, XML_cNvPr, XML_id, "0", XML_name, ""); + pFS->startElementNS(XML_xdr, XML_cNvSpPr); + pFS->singleElementNS(XML_a, XML_spLocks, XML_noTextEdit, "1"); + pFS->endElementNS(XML_xdr, XML_cNvSpPr); + pFS->endElementNS(XML_xdr, XML_nvSpPr); + pFS->startElementNS(XML_xdr, XML_spPr); + pFS->startElementNS(XML_a, XML_xfrm); + pFS->singleElementNS(XML_a, XML_off, XML_x, "6600825", XML_y, "2533650"); + pFS->singleElementNS(XML_a, XML_ext, XML_cx, "4572000", XML_cy, "2743200"); + pFS->endElementNS(XML_a, XML_xfrm); + pFS->startElementNS(XML_a, XML_prstGeom, XML_prst, "rect"); + pFS->singleElementNS(XML_a, XML_avLst); + pFS->endElementNS(XML_a, XML_prstGeom); + pFS->startElementNS(XML_a, XML_solidFill); + pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "white"); + pFS->endElementNS(XML_a, XML_solidFill); + pFS->startElementNS(XML_a, XML_ln, XML_w, "1"); + pFS->startElementNS(XML_a, XML_solidFill); + pFS->singleElementNS(XML_a, XML_prstClr, XML_val, "green"); + pFS->endElementNS(XML_a, XML_solidFill); + pFS->endElementNS(XML_a, XML_ln); + pFS->endElementNS(XML_xdr, XML_spPr); + pFS->startElementNS(XML_xdr, XML_txBody); + pFS->singleElementNS(XML_a, XML_bodyPr, XML_vertOverflow, "clip", XML_horzOverflow, "clip"); + pFS->singleElementNS(XML_a, XML_lstStyle); + pFS->startElementNS(XML_a, XML_p); + pFS->startElementNS(XML_a, XML_r); + pFS->singleElementNS(XML_a, XML_rPr, XML_sz, "1100"); + pFS->startElementNS(XML_a, XML_t); + + const std::string_view sErrTxt("This chart isn't available in your version of Excel. " + "Editing this shape or saving this workbook into a different file format will permanently break the chart."); + pFS->writeEscaped( sErrTxt ); + + pFS->endElementNS(XML_a, XML_t); + pFS->endElementNS(XML_a, XML_r); + pFS->endElementNS(XML_a, XML_p); + pFS->endElementNS(XML_xdr, XML_txBody); + pFS->endElementNS(XML_xdr, XML_sp); pFS->endElementNS(XML_mc, XML_Fallback); pFS->endElementNS(XML_mc, XML_AlternateContent); @@ -1185,114 +1121,112 @@ void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nI SetFS( pChart ); ExportContent(); - // output style and colorstyle files + if (bIsChartex) { + SetFS( pChart ); + sRelativePath =""; - SetFS( pChart ); - sRelativePath =""; - - FSHelperPtr pChartFS = GetFS(); - - // first style - static constexpr char sStyleFnamePrefix[] = "style"; - OUStringBuffer sFullStreamBuf; - sFullStreamBuf.appendAscii(sFullPath); - sFullStreamBuf = sFullStreamBuf + sStyleFnamePrefix + OUString::number(nChartCount) + ".xml"; - sFullStream = sFullStreamBuf.makeStringAndClear(); - OUStringBuffer sRelativeStreamBuf; - sRelativeStreamBuf.appendAscii(sRelativePath); - sRelativeStreamBuf = sRelativeStreamBuf + sStyleFnamePrefix + OUString::number(nChartCount) + ".xml"; - sRelativeStream = sRelativeStreamBuf.makeStringAndClear(); - - FSHelperPtr pStyle = CreateOutputStream( - sFullStream, - sRelativeStream, - pChartFS->getOutputStream(), - u"application/vnd.ms-office.chartstyle+xml"_ustr, - oox::getRelationship(Relationship::CHARTSTYLE), - &sId, - true /* for some reason this doesn't have a header line */); - - SetFS( pStyle ); - pFS = GetFS(); - - pFS->startElement(FSNS(XML_cs, XML_chartStyle), - FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)), - FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)), - XML_id, "419" /* no idea what this number is supposed to be */); - - Reference<com::sun::star::chart2::XChartStyle> xStyle = xChartDoc->getStyles(); - model::StyleSet* aSS = model::style::getFromXChartStyle(xStyle); - - for (enum model::StyleSet::StyleEntryType eEType = model::StyleSet::StyleEntryType::BEGIN; - eEType != model::StyleSet::StyleEntryType::END; - eEType = static_cast<model::StyleSet::StyleEntryType>(static_cast<int>(eEType) + 1)) { - auto entryIt = aSS->maEntryMap.find(eEType); - - if (entryIt == aSS->maEntryMap.end()) { - // We haven't stored any style information for this entry type, so - // just output a default value - switch (eEType) { - case model::StyleSet::StyleEntryType::CHARTAREA: - outputDefaultChartAreaStyleEntry(pFS); - break; - case model::StyleSet::StyleEntryType::DATAPOINT: - outputDefaultDataPointStyleEntry(pFS); - break; - case model::StyleSet::StyleEntryType::DATALABELCALLOUT: - // no entry required? - break; - default: - if (styleTagMap[static_cast<int>(eEType)].meType != eEType) { - assert(false); - } - outputDefaultStyleEntry(pFS, styleTagMap[static_cast<int>(eEType)].mnTag); - break; - } - } else { - outputStyleEntry(pFS, styleTagMap[static_cast<int>(eEType)].mnTag, - entryIt->second); - } - } + FSHelperPtr pChartFS = GetFS(); + + // output style and colorstyle files - pFS->endElement(FSNS(XML_cs, XML_chartStyle)); + // first style + static constexpr char sStyleFnamePrefix[] = "style"; + OUStringBuffer sFullStreamBuf; + sFullStreamBuf.appendAscii(sFullPath); + sFullStreamBuf = sFullStreamBuf + sStyleFnamePrefix + OUString::number(nChartCount) + ".xml"; + sFullStream = sFullStreamBuf.makeStringAndClear(); + OUStringBuffer sRelativeStreamBuf; + sRelativeStreamBuf.appendAscii(sRelativePath); + sRelativeStreamBuf = sRelativeStreamBuf + sStyleFnamePrefix + OUString::number(nChartCount) + ".xml"; + sRelativeStream = sRelativeStreamBuf.makeStringAndClear(); - pStyle->endDocument(); + FSHelperPtr pStyle = CreateOutputStream( + sFullStream, + sRelativeStream, + pChartFS->getOutputStream(), + u"application/vnd.ms-office.chartstyle+xml"_ustr, + oox::getRelationship(Relationship::CHARTSTYLE), + &sId, + true /* for some reason this doesn't have a header line */); - // now colorstyle - static constexpr char sColorFnamePrefix[] = "colors"; - sFullStreamBuf = OUStringBuffer(); - sFullStreamBuf.appendAscii(sFullPath); - sFullStreamBuf = sFullStreamBuf + sColorFnamePrefix + OUString::number(nChartCount) + ".xml"; - sFullStream = sFullStreamBuf.makeStringAndClear(); - sRelativeStreamBuf = OUStringBuffer(); - sRelativeStreamBuf.appendAscii(sRelativePath); - sRelativeStreamBuf = sRelativeStreamBuf + sColorFnamePrefix + OUString::number(nChartCount) + ".xml"; - sRelativeStream = sRelativeStreamBuf.makeStringAndClear(); + SetFS( pStyle ); + pFS = GetFS(); - FSHelperPtr pColorStyle = CreateOutputStream( - sFullStream, - sRelativeStream, - pChartFS->getOutputStream(), - u"application/vnd.ms-office.chartcolorstyle+xml"_ustr, - oox::getRelationship(Relationship::CHARTCOLORSTYLE), - &sId, - true /* also no header line */); + pFS->startElement(FSNS(XML_cs, XML_chartStyle), + FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)), + FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)), + XML_id, "419" /* no idea what this number is supposed to be */); + + outputStyleEntry(pFS, XML_axisTitle);; + outputStyleEntry(pFS, XML_categoryAxis); + outputChartAreaStyleEntry(pFS); + outputStyleEntry(pFS, XML_dataLabel); + outputDataPointStyleEntry(pFS); + outputStyleEntry(pFS, XML_dataPoint3D); + outputStyleEntry(pFS, XML_dataPointLine); + outputStyleEntry(pFS, XML_dataPointMarker); + outputStyleEntry(pFS, XML_dataPointWireframe); + outputStyleEntry(pFS, XML_dataTable); + outputStyleEntry(pFS, XML_downBar); + outputStyleEntry(pFS, XML_dropLine); + outputStyleEntry(pFS, XML_errorBar); + outputStyleEntry(pFS, XML_floor); + outputStyleEntry(pFS, XML_gridlineMajor); + outputStyleEntry(pFS, XML_gridlineMinor); + outputStyleEntry(pFS, XML_hiLoLine); + outputStyleEntry(pFS, XML_leaderLine); + outputStyleEntry(pFS, XML_legend); + outputStyleEntry(pFS, XML_plotArea); + outputStyleEntry(pFS, XML_plotArea3D); + outputStyleEntry(pFS, XML_seriesAxis); + outputStyleEntry(pFS, XML_seriesLine); + outputStyleEntry(pFS, XML_title); + outputStyleEntry(pFS, XML_trendline); + outputStyleEntry(pFS, XML_trendlineLabel); + outputStyleEntry(pFS, XML_upBar); + outputStyleEntry(pFS, XML_valueAxis); + outputStyleEntry(pFS, XML_wall); + + pFS->endElement(FSNS(XML_cs, XML_chartStyle)); + + pStyle->endDocument(); + + // now colorstyle + static constexpr char sColorFnamePrefix[] = "colors"; + sFullStreamBuf = OUStringBuffer(); + sFullStreamBuf.appendAscii(sFullPath); + sFullStreamBuf = sFullStreamBuf + sColorFnamePrefix + OUString::number(nChartCount) + ".xml"; + sFullStream = sFullStreamBuf.makeStringAndClear(); + sRelativeStreamBuf = OUStringBuffer(); + sRelativeStreamBuf.appendAscii(sRelativePath); + sRelativeStreamBuf = sRelativeStreamBuf + sColorFnamePrefix + OUString::number(nChartCount) + ".xml"; + sRelativeStream = sRelativeStreamBuf.makeStringAndClear(); + + FSHelperPtr pColorStyle = CreateOutputStream( + sFullStream, + sRelativeStream, + pChartFS->getOutputStream(), + u"application/vnd.ms-office.chartcolorstyle+xml"_ustr, + oox::getRelationship(Relationship::CHARTCOLORSTYLE), + &sId, + true /* also no header line */); - SetFS( pColorStyle ); - pFS = GetFS(); + SetFS( pColorStyle ); + pFS = GetFS(); - pFS->startElement(FSNS(XML_cs, XML_colorStyle), - FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)), - FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)), - XML_meth, "cycle", - XML_id, "10" /* no idea what this number is supposed to be */); + pFS->startElement(FSNS(XML_cs, XML_colorStyle), + FSNS( XML_xmlns, XML_cs ), pFB->getNamespaceURL(OOX_NS(cs)), + FSNS( XML_xmlns, XML_a ), pFB->getNamespaceURL(OOX_NS(dml)), + XML_meth, "cycle", + XML_id, "10" /* no idea what this number is supposed to be */); - pFS->singleElement(FSNS(XML_a, XML_schemeClr), - XML_val, "accent1"); + pFS->singleElement(FSNS(XML_a, XML_schemeClr), + XML_val, "accent1"); - pFS->endElement(FSNS(XML_cs, XML_colorStyle)); + pFS->endElement(FSNS(XML_cs, XML_colorStyle)); - pColorStyle->endDocument(); + pColorStyle->endDocument(); + } pChart->endDocument(); } @@ -1426,7 +1360,7 @@ void ChartExport::exportChartSpace( const Reference< css::chart::XChartDocument // TODO: text properties Reference< XPropertySet > xPropSet = xChartDoc->getArea(); if( xPropSet.is() ) - exportShapeProps( xPropSet, nChartNS ); + exportShapeProps( xPropSet, bIsChartex ); // TODO for chartex if (!bIsChartex) { @@ -1905,7 +1839,7 @@ void ChartExport::exportChart( const Reference< css::chart::XChartDocument >& xC if( xFloor.is() ) { pFS->startElement(FSNS(XML_c, XML_floor)); - exportShapeProps( xFloor, XML_c ); + exportShapeProps( xFloor, false ); pFS->endElement( FSNS( XML_c, XML_floor ) ); } @@ -1916,12 +1850,12 @@ void ChartExport::exportChart( const Reference< css::chart::XChartDocument >& xC { // sideWall pFS->startElement(FSNS(XML_c, XML_sideWall)); - exportShapeProps( xWall, XML_c ); + exportShapeProps( xWall, false ); pFS->endElement( FSNS( XML_c, XML_sideWall ) ); // backWall pFS->startElement(FSNS(XML_c, XML_backWall)); - exportShapeProps( xWall, XML_c ); + exportShapeProps( xWall, false ); pFS->endElement( FSNS( XML_c, XML_backWall ) ); } } @@ -2166,7 +2100,7 @@ void ChartExport::exportLegend( const Reference< css::chart::XChartDocument >& x } // shape properties - exportShapeProps( xProp, bIsChartex ? XML_cx : XML_c ); + exportShapeProps( xProp, bIsChartex ); // draw-chart:txPr text properties exportTextProps( xProp, bIsChartex ); @@ -2232,7 +2166,7 @@ void ChartExport::exportTitle( const Reference< XShape >& xShape, bool bIsCharte // shape properties if( xPropSet.is() ) { - exportShapeProps( xPropSet, bIsChartex ? XML_cx : XML_c ); + exportShapeProps( xPropSet, bIsChartex ); } pFS->startElement(FSNS(XML_cx, XML_txPr)); @@ -2366,7 +2300,7 @@ void ChartExport::exportTitle( const Reference< XShape >& xShape, bool bIsCharte // shape properties if( xPropSet.is() ) { - exportShapeProps( xPropSet, bIsChartex ? XML_cx : XML_c ); + exportShapeProps( xPropSet, bIsChartex ); } } @@ -2584,7 +2518,7 @@ void ChartExport::exportPlotArea(const Reference< css::chart::XChartDocument >& { xWallPropSet->setPropertyValue( u"LineStyle"_ustr, uno::Any(drawing::LineStyle_NONE) ); } - exportShapeProps( xWallPropSet, bIsChartex ? XML_cx : XML_c ); + exportShapeProps( xWallPropSet, bIsChartex ); } } @@ -2910,7 +2844,7 @@ void ChartExport::exportDataTable( ) if (bShowKeys) pFS->singleElement(FSNS(XML_c, XML_showKeys), XML_val, "1"); - exportShapeProps(aPropSet, XML_c); + exportShapeProps(aPropSet, false); exportTextProps(aPropSet, false); pFS->endElement(FSNS(XML_c, XML_dTable)); @@ -3344,7 +3278,7 @@ void ChartExport::exportHiLowLines() return; pFS->startElement(FSNS(XML_c, XML_hiLowLines)); - exportShapeProps( xStockPropSet, XML_c ); + exportShapeProps( xStockPropSet, false ); pFS->endElement( FSNS( XML_c, XML_hiLowLines ) ); } @@ -3372,7 +3306,7 @@ void ChartExport::exportUpDownBars( const Reference< chart2::XChartType >& xChar // so no need to call the exportShapeProps() for LineChart if(xChartType->getChartType() == "com.sun.star.chart2.CandleStickChartType") { - exportShapeProps(xChartPropSet, XML_c); + exportShapeProps(xChartPropSet, false); } pFS->endElement( FSNS( XML_c, XML_upBars ) ); } @@ -3382,7 +3316,7 @@ void ChartExport::exportUpDownBars( const Reference< chart2::XChartType >& xChar pFS->startElement(FSNS(XML_c, XML_downBars)); if(xChartType->getChartType() == "com.sun.star.chart2.CandleStickChartType") { - exportShapeProps(xChartPropSet, XML_c); + exportShapeProps(xChartPropSet, false); } pFS->endElement( FSNS( XML_c, XML_downBars ) ); } @@ -3508,7 +3442,7 @@ void ChartExport::exportSeries_chart( const Reference<chart2::XChartType>& xChar rSeries, getModel() ); if( xOldPropSet.is() ) { - exportShapeProps( xOldPropSet, XML_c ); + exportShapeProps( xOldPropSet, false ); } switch( eChartType ) @@ -3692,7 +3626,7 @@ void ChartExport::exportSeries_chartex( const Reference<chart2::XChartType>& xCh rSeries, getModel() ); if( xOldPropSet.is() ) { - exportShapeProps( xOldPropSet, XML_cx ); + exportShapeProps( xOldPropSet, true ); } DataLabelsRange aDLblsRange; @@ -3960,15 +3894,16 @@ void ChartExport::exportSeriesValues( const Reference< chart2::data::XDataSequen } void ChartExport::exportShapeProps( const Reference< XPropertySet >& xPropSet, - sal_Int32 nNS) + bool bIsChartex) { + sal_Int32 nChartNS = bIsChartex ? XML_cx : XML_c; FSHelperPtr pFS = GetFS(); - pFS->startElement(FSNS(nNS, XML_spPr)); + pFS->startElement(FSNS(nChartNS, XML_spPr)); exportFill( xPropSet ); WriteOutline( xPropSet, getModel() ); - pFS->endElement( FSNS( nNS, XML_spPr ) ); + pFS->endElement( FSNS( nChartNS, XML_spPr ) ); } void ChartExport::exportTextProps(const Reference<XPropertySet>& xPropSet, @@ -4353,7 +4288,7 @@ void ChartExport::exportOneAxis_chart( if( xMajorGrid.is()) { pFS->startElement(FSNS(XML_c, XML_majorGridlines)); - exportShapeProps( xMajorGrid, XML_c ); + exportShapeProps( xMajorGrid, false ); pFS->endElement( FSNS( XML_c, XML_majorGridlines ) ); } @@ -4361,7 +4296,7 @@ void ChartExport::exportOneAxis_chart( if( xMinorGrid.is()) { pFS->startElement(FSNS(XML_c, XML_minorGridlines)); - exportShapeProps( xMinorGrid, XML_c ); + exportShapeProps( xMinorGrid, false ); pFS->endElement( FSNS( XML_c, XML_minorGridlines ) ); } @@ -4433,7 +4368,7 @@ void ChartExport::exportOneAxis_chart( pFS->singleElement(FSNS(XML_c, XML_tickLblPos), XML_val, sTickLblPos); // shape properties - exportShapeProps( xAxisProp, XML_c ); + exportShapeProps( xAxisProp, false ); exportTextProps(xAxisProp, false); @@ -4712,7 +4647,7 @@ void ChartExport::exportOneAxis_chartex( if( xMajorGrid.is()) { pFS->startElement(FSNS(XML_cx, XML_majorGridlines)); - exportShapeProps( xMajorGrid, XML_cx ); + exportShapeProps( xMajorGrid, true ); pFS->endElement( FSNS( XML_cx, XML_majorGridlines ) ); } @@ -4720,7 +4655,7 @@ void ChartExport::exportOneAxis_chartex( if( xMinorGrid.is()) { pFS->startElement(FSNS(XML_cx, XML_minorGridlines)); - exportShapeProps( xMinorGrid, XML_cx ); + exportShapeProps( xMinorGrid, true ); pFS->endElement( FSNS( XML_cx, XML_minorGridlines ) ); } @@ -4766,7 +4701,7 @@ void ChartExport::exportOneAxis_chartex( XML_sourceLinked, bLinkedNumFmt ? "1" : "0"); // ==== spPr - exportShapeProps( xAxisProp, XML_cx ); + exportShapeProps( xAxisProp, true ); // ==== txPr exportTextProps(xAxisProp, true); @@ -5325,7 +5260,7 @@ void ChartExport::exportDataPoints( default: break; } - exportShapeProps( xPropSet, XML_c ); + exportShapeProps( xPropSet, false ); pFS->endElement( FSNS( XML_c, XML_dPt ) ); } @@ -5369,7 +5304,7 @@ void ChartExport::exportDataPoints( case chart::TYPEID_HORBAR: case chart::TYPEID_BAR: pFS->singleElement(FSNS(XML_c, XML_invertIfNegative), XML_val, "0"); - exportShapeProps(xPropSet, XML_c); + exportShapeProps(xPropSet, false); break; case chart::TYPEID_LINE: @@ -5379,7 +5314,7 @@ void ChartExport::exportDataPoints( break; default: - exportShapeProps(xPropSet, XML_c); + exportShapeProps(xPropSet, false); break; } @@ -5499,7 +5434,7 @@ void ChartExport::exportTrendlines( const Reference< chart2::XDataSeries >& xSer pFS->endElement( FSNS( XML_c, XML_name) ); } - exportShapeProps( xProperties, XML_c ); + exportShapeProps( xProperties, false ); if( aService == "com.sun.star.chart2.LinearRegressionCurve" ) { @@ -5819,7 +5754,7 @@ void ChartExport::exportErrorBar(const Reference< XPropertySet>& xErrorBarProps, pFS->singleElement(FSNS(XML_c, XML_val), XML_val, OString::number(nVal)); } - exportShapeProps( xErrorBarProps, XML_c ); + exportShapeProps( xErrorBarProps, false ); pFS->endElement( FSNS( XML_c, XML_errBars) ); } @@ -5987,68 +5922,6 @@ OUString ChartExport::getNumberFormatCode(sal_Int32 nKey) const return aCode; } -// Create cs:CT_FontReference or cs:CT_StyleReference -void ChartExport::outputFontOrStyleRef(FSHelperPtr pFS, sal_Int32 nElTokenId, const - model::FontOrStyleRef& aColor) -{ - pFS->startElement(FSNS(XML_cs, nElTokenId), XML_idx, OUString::number(aColor.mnIdx)); - - ThemeExport aTE(mpFB, GetDocumentType(), pFS); - aTE.writeComplexColor(aColor.maComplexColor); - - // Get the string for the StyleColorVal - OUString sV = aColor.getColorValStr(); - if (!sV.isEmpty()) { - pFS->singleElement(FSNS(XML_cs, XML_styleClr), XML_val, sV); - } - - pFS->endElement(FSNS(XML_cs, nElTokenId)); -} - -// Create cs:CT_StyleEntry -void ChartExport::outputStyleEntry(FSHelperPtr pFS, sal_Int32 nElTokenId, model::StyleEntry& aEntry) -{ - // Just default values for now - pFS->startElement(FSNS(XML_cs, nElTokenId)); - - outputFontOrStyleRef(pFS, FSNS(XML_cs, XML_lnRef), *(aEntry.mxLnClr)); - - pFS->startElement(FSNS(XML_cs, XML_lineWidthScale)); - pFS->write(aEntry.mfLineWidthScale); - pFS->endElement(FSNS(XML_cs, XML_lineWidthScale)); - - outputFontOrStyleRef(pFS, FSNS(XML_cs, XML_fillRef), *(aEntry.mxFillClr)); - outputFontOrStyleRef(pFS, FSNS(XML_cs, XML_effectRef), *(aEntry.mxEffectClr)); - outputFontOrStyleRef(pFS, FSNS(XML_cs, XML_fontRef), *(aEntry.mxFontClr)); - - if (aEntry.mxShapePr) { - exportShapeProps(aEntry.mxShapePr->getShapeProperties().makePropertySet(), XML_cs); - } - - if (aEntry.mrTextCharacterPr) { - PropertyMap *pPM = aEntry.mrTextCharacterPr.get(); - Reference< XPropertySet > rPS = pPM->makePropertySet(); - - WriteRunInput aInput; - aInput.bCheckDirect = false; - aInput.bUseTextSchemeColors = false; - WriteRunProperties(rPS, XML_defRPr, aInput ); - } - - if (aEntry.mxTextBodyPr) { - PropertyMap *pPM = aEntry.mxTextBodyPr.get(); - aEntry.mxTextBodyPr.reset(); - Reference< XPropertySet > rPS = pPM->makePropertySet(); - uno::Reference<drawing::XShape> xShape(rPS, UNO_QUERY); - uno::Reference<XPropertySet> rXPropSet = rPS; - WriteBodyPropsInput aWBPInput; - - WriteBodyProps(rPS, rXPropSet, xShape, XML_cs, aWBPInput); - } - - pFS->endElement(FSNS(XML_cs, nElTokenId)); -} - }// oox /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index f14bd9fd3c21..9790c745150d 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -2632,10 +2632,10 @@ void DrawingML::WriteRunProperties(const Reference<XPropertySet>& rRun, sal_Int3 usLanguage = aLanguageTag.getBcp47MS(); } - if (rXPropState && GetDirectProperty(rXPropSet, rXPropState, u"CharEscapement"_ustr)) + if (GetDirectProperty(rXPropSet, rXPropState, u"CharEscapement"_ustr)) mAny >>= nCharEscapement; - if (rXPropState && GetDirectProperty(rXPropSet, rXPropState, u"CharEscapementHeight"_ustr)) + if (GetDirectProperty(rXPropSet, rXPropState, u"CharEscapementHeight"_ustr)) mAny >>= nCharEscapementHeight; if (DFLT_ESC_AUTO_SUPER == nCharEscapement) @@ -2827,7 +2827,7 @@ void DrawingML::WriteRunProperties(const Reference<XPropertySet>& rRun, sal_Int3 XML_charset, charset ); } - if (rXPropState && GetDirectProperty(rXPropSet, rXPropState, + if (GetDirectProperty(rXPropSet, rXPropState, bComplex ? u"CharFontNameComplex"_ustr : u"CharFontNameAsian"_ustr)) { const char* const pitch = nullptr; @@ -3915,236 +3915,6 @@ bool DrawingML::IsFontworkShape(const css::uno::Reference<css::beans::XPropertyS return bResult; } -// Output text body properties -void DrawingML::WriteBodyProps(const css::uno::Reference< css::uno::XInterface >& rXIface, - const uno::Reference<XPropertySet>& rXPropSet, - const uno::Reference<drawing::XShape>& xShape, - sal_Int32 nXmlNamespace, const WriteBodyPropsInput& aWBPInput) -{ - const char* pWrap = (aWBPInput.bHasWrap && !aWBPInput.bWrap) || aWBPInput.bIsFontworkShape ? "none" : nullptr; - if (GetDocumentType() == DOCUMENT_DOCX) - { - // In case of DOCX, if we want to have the same effect as - // TextShape's automatic word wrapping, then we need to set - // wrapping to square. - uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, uno::UNO_QUERY); - if ((xServiceInfo.is() && xServiceInfo->supportsService(u"com.sun.star.drawing.TextShape"_ustr)) - || aWBPInput.bIsFontworkShape) - pWrap = "square"; - } - - sal_Int16 nCols = 0; - sal_Int32 nColSpacing = -1; - if (GetProperty(rXPropSet, u"TextColumns"_ustr)) - { - if (css::uno::Reference<css::text::XTextColumns> xCols{ mAny, css::uno::UNO_QUERY }) - { - nCols = xCols->getColumnCount(); - if (css::uno::Reference<css::beans::XPropertySet> xProps{ mAny, - css::uno::UNO_QUERY }) - { - if (GetProperty(xProps, u"AutomaticDistance"_ustr)) - mAny >>= nColSpacing; - } - } - } - - std::optional<OUString> sVertOverflow = aWBPInput.sVertOverflow; - - if (!sVertOverflow && GetProperty(rXPropSet, u"TextClipVerticalOverflow"_ustr) && mAny.get<bool>()) - { - sVertOverflow = "clip"; - } - - // tdf#151134 When writing placeholder shapes, inset must be explicitly specified - bool bRequireInset = GetProperty(rXPropSet, u"IsPresentationObject"_ustr) && rXPropSet->getPropertyValue(u"IsPresentationObject"_ustr).get<bool>(); - - mpFS->startElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr, - XML_numCol, sax_fastparser::UseIf(OString::number(nCols), nCols > 0), - XML_spcCol, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nColSpacing)), nCols > 0 && nColSpacing >= 0), - XML_wrap, pWrap, - XML_horzOverflow, aWBPInput.sHorzOverflow, - XML_vertOverflow, sVertOverflow, - XML_fromWordArt, sax_fastparser::UseIf("1", - aWBPInput.bFromWordArt), - XML_lIns, - sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(aWBPInput.nLeft)), - bRequireInset || - aWBPInput.nLeft != mconstDefaultLeftRightInset), - XML_tIns, - sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(aWBPInput.nTop)), - bRequireInset || - aWBPInput.nTop != mconstDefaultTopBottomInset), - XML_rIns, - sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(aWBPInput.nRight)), - bRequireInset || - aWBPInput.nRight != mconstDefaultLeftRightInset), - XML_bIns, - sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(aWBPInput.nBottom)), - bRequireInset || - aWBPInput.nBottom != mconstDefaultTopBottomInset), - XML_anchor, aWBPInput.sAnchor, - XML_anchorCtr, sax_fastparser::UseIf("1", aWBPInput.bAnchorCtr), - XML_vert, aWBPInput.sWritingMode, - XML_upright, aWBPInput.sIsUpright, - XML_rot, aWBPInput.sTextRotateAngleMSUnit); - - if (aWBPInput.bIsFontworkShape) - { - if (aWBPInput.aAdjustmentSeq.hasElements()) - { - mpFS->startElementNS(XML_a, XML_prstTxWarp, XML_prst, aWBPInput.sPresetWarp); - mpFS->startElementNS(XML_a, XML_avLst); - bool bHasTwoHandles( - aWBPInput.sPresetWarp == "textArchDownPour" || aWBPInput.sPresetWarp == "textArchUpPour" - || aWBPInput.sPresetWarp == "textButtonPour" || aWBPInput.sPresetWarp == "textCirclePour" - || aWBPInput.sPresetWarp == "textDoubleWave1" || aWBPInput.sPresetWarp == "textWave1" - || aWBPInput.sPresetWarp == "textWave2" || aWBPInput.sPresetWarp == "textWave4"); - for (sal_Int32 i = 0, nElems = aWBPInput.aAdjustmentSeq.getLength(); i < nElems; ++i ) - { - OString sName = "adj" + (bHasTwoHandles ? OString::number(i + 1) : OString()); - double fValue(0.0); - if (aWBPInput.aAdjustmentSeq[i].Value.getValueTypeClass() == TypeClass_DOUBLE) - aWBPInput.aAdjustmentSeq[i].Value >>= fValue; - else - { - sal_Int32 nNumber(0); - aWBPInput.aAdjustmentSeq[i].Value >>= nNumber; - fValue = static_cast<double>(nNumber); - } - // Convert from binary coordinate system with viewBox "0 0 21600 21600" and simple degree - // to DrawingML with coordinate range 0..100000 and angle in 1/60000 degree. - // Reverse to conversion in lcl_createPresetShape in drawingml/shape.cxx on import. - if (aWBPInput.sPresetWarp == "textArchDown" || aWBPInput.sPresetWarp == "textArchUp" - || aWBPInput.sPresetWarp == "textButton" || aWBPInput.sPresetWarp == "textCircle" - || ((i == 0) - && (aWBPInput.sPresetWarp == "textArchDownPour" || - aWBPInput.sPresetWarp == "textArchUpPour" - || aWBPInput.sPresetWarp == "textButtonPour" || - aWBPInput.sPresetWarp == "textCirclePour"))) - { - fValue *= 60000.0; - if (fValue < 0) - fValue += 21600000; - } - else if ((i == 1) - && (aWBPInput.sPresetWarp == "textDoubleWave1" || - aWBPInput.sPresetWarp == "textWave1" - || aWBPInput.sPresetWarp == "textWave2" || aWBPInput.sPresetWarp == "textWave4")) - { - fValue = fValue / 0.216 - 50000.0; - } - else if ((i == 1) - && (aWBPInput.sPresetWarp == "textArchDownPour" - || aWBPInput.sPresetWarp == "textArchUpPour" - || aWBPInput.sPresetWarp == "textButtonPour" - || aWBPInput.sPresetWarp == "textCirclePour")) - { - fValue /= 0.108; - } - else - { - fValue /= 0.216; - } - OString sFmla = "val " + OString::number(std::lround(fValue)); - mpFS->singleElementNS(XML_a, XML_gd, XML_name, sName, XML_fmla, sFmla); - // There exists faulty Favorite shapes with one handle but two adjustment values. - if (!bHasTwoHandles) - break; - } - mpFS->endElementNS(XML_a, XML_avLst); - mpFS->endElementNS(XML_a, XML_prstTxWarp); - } - else - { - mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, aWBPInput.sPresetWarp); - } - } - else if (GetDocumentType() == DOCUMENT_DOCX) - { - // interim solution for fdo#80897, roundtrip DOCX > LO > DOCX - if (!aWBPInput.sMSWordPresetTextWarp.isEmpty()) - mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, aWBPInput.sMSWordPresetTextWarp); - } - - if (GetDocumentType() == DOCUMENT_DOCX || GetDocumentType() == DOCUMENT_XLSX) - { - // tdf#112312: only custom shapes obey the TextAutoGrowHeight option - bool bTextAutoGrowHeight = false; - auto pSdrObjCustomShape = xShape.is() ? dynamic_cast<SdrObjCustomShape*>(SdrObject::getSdrObjectFromXShape(xShape)) : nullptr; - if (pSdrObjCustomShape && GetProperty(rXPropSet, u"TextAutoGrowHeight"_ustr)) - { - mAny >>= bTextAutoGrowHeight; - } - mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : XML_noAutofit)); - } - if (GetDocumentType() == DOCUMENT_PPTX) - { - TextFitToSizeType eFit = TextFitToSizeType_NONE; - if (GetProperty(rXPropSet, u"TextFitToSize"_ustr)) - mAny >>= eFit; - - if (eFit == TextFitToSizeType_AUTOFIT) - { - const sal_Int32 MAX_SCALE_VAL = 100000; - sal_Int32 nFontScale = MAX_SCALE_VAL; - sal_Int32 nSpacingReduction = 0; - SvxShapeText* pTextShape = dynamic_cast<SvxShapeText*>(rXIface.get()); - if (pTextShape) - { - SdrTextObj* pTextObject = DynCastSdrTextObj(pTextShape->GetSdrObject()); - if (pTextObject) - { - nFontScale = sal_Int32(pTextObject->GetFontScale() * 100000.0); - nSpacingReduction = sal_Int32((1.0 - pTextObject->GetSpacingScale()) * 100000.0); - } - } - - bool bExportFontScale = false; - if (nFontScale < MAX_SCALE_VAL && nFontScale > 0) - bExportFontScale = true; - - bool bExportSpaceReduction = false; - if (nSpacingReduction < MAX_SCALE_VAL && nSpacingReduction > 0) - bExportSpaceReduction = true; - - mpFS->singleElementNS(XML_a, XML_normAutofit, - XML_fontScale, sax_fastparser::UseIf(OString::number(nFontScale), bExportFontScale), - XML_lnSpcReduction, sax_fastparser::UseIf(OString::number(nSpacingReduction), bExportSpaceReduction)); - } - else - { - bool bAutoGrowHeightEnabled = false; - const SdrObject* pObj = xShape.is() ? SdrObject::getSdrObjectFromXShape(xShape) : nullptr; - if (pObj) - { - switch (pObj->GetObjIdentifier()) - { - case SdrObjKind::NONE: - case SdrObjKind::Text: - case SdrObjKind::TitleText: - case SdrObjKind::OutlineText: - case SdrObjKind::Caption: - case SdrObjKind::CustomShape: - bAutoGrowHeightEnabled = true; - break; - default: - bAutoGrowHeightEnabled = false; - } - } - - bool bTextAutoGrowHeight = false; - if (bAutoGrowHeightEnabled && GetProperty(rXPropSet, u"TextAutoGrowHeight"_ustr)) - mAny >>= bTextAutoGrowHeight; - mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : XML_noAutofit)); - } - } - - Write3DEffects( rXPropSet, /*bIsText=*/true ); - - mpFS->endElementNS((nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr); -} - void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles) { @@ -4153,28 +3923,26 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo if( !xXText.is() ) return; - WriteBodyPropsInput aWBPInput; - uno::Reference<drawing::XShape> xShape(rXIface, UNO_QUERY); uno::Reference<XPropertySet> rXPropSet(rXIface, UNO_QUERY); constexpr const sal_Int32 constDefaultLeftRightInset = 254; constexpr const sal_Int32 constDefaultTopBottomInset = 127; - aWBPInput.nLeft = constDefaultLeftRightInset; - aWBPInput.nRight = constDefaultLeftRightInset; - aWBPInput.nTop = constDefaultTopBottomInset; - aWBPInput.nBottom = constDefaultTopBottomInset; + sal_Int32 nLeft = constDefaultLeftRightInset; + sal_Int32 nRight = constDefaultLeftRightInset; + sal_Int32 nTop = constDefaultTopBottomInset; + sal_Int32 nBottom = constDefaultTopBottomInset; // top inset looks a bit different compared to ppt export // check if something related doesn't work as expected if (GetProperty(rXPropSet, u"TextLeftDistance"_ustr)) - mAny >>= aWBPInput.nLeft; + mAny >>= nLeft; if (GetProperty(rXPropSet, u"TextRightDistance"_ustr)) - mAny >>= aWBPInput.nRight; + mAny >>= nRight; if (GetProperty(rXPropSet, u"TextUpperDistance"_ustr)) - mAny >>= aWBPInput.nTop; + mAny >>= nTop; if (GetProperty(rXPropSet, u"TextLowerDistance"_ustr)) - mAny >>= aWBPInput.nBottom; + mAny >>= nBottom; // Transform the text distance values so they are compatible with OOXML insets if (xShape.is()) @@ -4192,22 +3960,23 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo nTextHeight = convertTwipToMm100(nTextHeight); } - if (aWBPInput.nTop + aWBPInput.nBottom >= nTextHeight) + if (nTop + nBottom >= nTextHeight) { // Effective bottom would be above effective top of text area. LO normalizes the // effective text area in such case implicitly for rendering. MS needs indents so that // the result is the normalized effective text area. - std::swap(aWBPInput.nTop, aWBPInput.nBottom); - aWBPInput.nTop = nTextHeight - aWBPInput.nTop; - aWBPInput.nBottom = nTextHeight - aWBPInput.nBottom; + std::swap(nTop, nBottom); + nTop = nTextHeight - nTop; + nBottom = nTextHeight - nBottom; } } + std::optional<OString> sWritingMode; if (GetProperty(rXPropSet, u"TextWritingMode"_ustr)) { WritingMode eMode; if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL ) - aWBPInput.sWritingMode = "eaVert"; + sWritingMode = "eaVert"; } if (GetProperty(rXPropSet, u"WritingMode"_ustr)) { @@ -4215,22 +3984,24 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo if (mAny >>= nWritingMode) { if (nWritingMode == text::WritingMode2::TB_RL) - aWBPInput.sWritingMode = "eaVert"; + sWritingMode = "eaVert"; else if (nWritingMode == text::WritingMode2::BT_LR) - aWBPInput.sWritingMode = "vert270"; + sWritingMode = "vert270"; else if (nWritingMode == text::WritingMode2::TB_RL90) - aWBPInput.sWritingMode = "vert"; + sWritingMode = "vert"; else if (nWritingMode == text::WritingMode2::TB_LR) - aWBPInput.sWritingMode = "mongolianVert"; + sWritingMode = "mongolianVert"; else if (nWritingMode == text::WritingMode2::STACKED) - aWBPInput.sWritingMode = "wordArtVert"; + sWritingMode = "wordArtVert"; } } // read values from CustomShapeGeometry + Sequence<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentSeq; uno::Sequence<beans::PropertyValue> aTextPathSeq; bool bScaleX(false); OUString sShapeType(u"non-primitive"_ustr); + OUString sMSWordPresetTextWarp; sal_Int32 nTextPreRotateAngle = 0; // degree std::optional<Degree100> nTextRotateAngleDeg100; // text area rotation @@ -4244,7 +4015,7 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo if (rProp.Name == "TextPreRotateAngle") rProp.Value >>= nTextPreRotateAngle; else if (rProp.Name == "AdjustmentValues") - rProp.Value >>= aWBPInput.aAdjustmentSeq; + rProp.Value >>= aAdjustmentSeq; else if (rProp.Name == "TextRotateAngle") { double fTextRotateAngle = 0; // degree @@ -4263,7 +4034,7 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo } } else if (rProp.Name == "PresetTextWarp") - rProp.Value >>= aWBPInput.sMSWordPresetTextWarp; + rProp.Value >>= sMSWordPresetTextWarp; } } } @@ -4284,16 +4055,16 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo switch (nWritingMode) { case WritingMode2::TB_RL: - aWBPInput.sWritingMode = "eaVert"; + sWritingMode = "eaVert"; break; case WritingMode2::BT_LR: - aWBPInput.sWritingMode = "vert270"; + sWritingMode = "vert270"; break; case WritingMode2::TB_RL90: - aWBPInput.sWritingMode = "vert"; + sWritingMode = "vert"; break; case WritingMode2::TB_LR: - aWBPInput.sWritingMode = "mongolianVert"; + sWritingMode = "mongolianVert"; break; default: break; @@ -4305,7 +4076,10 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo } // read InteropGrabBag if any + std::optional<OUString> sHorzOverflow; + std::optional<OUString> sVertOverflow; bool bUpright = false; + std::optional<OString> isUpright; if (rXPropSet->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr)) { uno::Sequence<beans::PropertyValue> aGrabBag; @@ -4315,42 +4089,40 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo if (aProp.Name == "Upright") { aProp.Value >>= bUpright; - aWBPInput.sIsUpright = OString(bUpright ? "1" : "0"); + isUpright = OString(bUpright ? "1" : "0"); } else if (aProp.Name == "horzOverflow") { OUString sValue; aProp.Value >>= sValue; - aWBPInput.sHorzOverflow = sValue; + sHorzOverflow = sValue; } else if (aProp.Name == "vertOverflow") { OUString sValue; aProp.Value >>= sValue; - aWBPInput.sVertOverflow = sValue; + sVertOverflow = sValue; } } } - aWBPInput.bIsFontworkShape = IsFontworkShape(rXPropSet); - aWBPInput.sPresetWarp = PresetGeometryTypeNames::GetMsoName(sShapeType); + bool bIsFontworkShape(IsFontworkShape(rXPropSet)); + OUString sPresetWarp(PresetGeometryTypeNames::GetMsoName(sShapeType)); // ODF may have user defined TextPath, use "textPlain" as ersatz. - if (aWBPInput.sPresetWarp.isEmpty()) - aWBPInput.sPresetWarp = aWBPInput.bIsFontworkShape ? std::u16string_view(u"textPlain") : std::u16string_view(u"textNoShape"); + if (sPresetWarp.isEmpty()) + sPresetWarp = bIsFontworkShape ? std::u16string_view(u"textPlain") : std::u16string_view(u"textNoShape"); - aWBPInput.bFromWordArt = !bScaleX - && ( aWBPInput.sPresetWarp == "textArchDown" || - aWBPInput.sPresetWarp == "textArchUp" - || aWBPInput.sPresetWarp == "textButton" || - aWBPInput.sPresetWarp == "textCircle"); + bool bFromWordArt = !bScaleX + && ( sPresetWarp == "textArchDown" || sPresetWarp == "textArchUp" + || sPresetWarp == "textButton" || sPresetWarp == "textCircle"); // Fontwork shapes in LO ignore insets in rendering, Word interprets them. - if (GetDocumentType() == DOCUMENT_DOCX && aWBPInput.bIsFontworkShape) + if (GetDocumentType() == DOCUMENT_DOCX && bIsFontworkShape) { - aWBPInput.nLeft = 0; - aWBPInput.nRight = 0; - aWBPInput.nTop = 0; - aWBPInput.nBottom = 0; + nLeft = 0; + nRight = 0; + nTop = 0; + nBottom = 0; } if (bUpright) @@ -4381,7 +4153,7 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo else { // User changes. Keep current angles. - aWBPInput.sIsUpright.reset(); + isUpright.reset(); if (bWasAngleChanged) { nTextPreRotateAngle += 90; @@ -4392,12 +4164,12 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo // ToDo: Unsure about this. Need to investigate shapes from diagram import, especially diagrams // with vertical text directions. - if (nTextPreRotateAngle != 0 && !aWBPInput.sWritingMode) + if (nTextPreRotateAngle != 0 && !sWritingMode) { if (nTextPreRotateAngle == -90 || nTextPreRotateAngle == 270) - aWBPInput.sWritingMode = "vert"; + sWritingMode = "vert"; else if (nTextPreRotateAngle == -270 || nTextPreRotateAngle == 90) - aWBPInput.sWritingMode = "vert270"; + sWritingMode = "vert270"; else if (nTextPreRotateAngle == -180 || nTextPreRotateAngle == 180) { #if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 @@ -4414,7 +4186,7 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo else SAL_WARN("oox", "unsuitable value for TextPreRotateAngle:" << nTextPreRotateAngle); } - else if (nTextPreRotateAngle != 0 && aWBPInput.sWritingMode && aWBPInput.sWritingMode.value() == "eaVert") + else if (nTextPreRotateAngle != 0 && sWritingMode && sWritingMode.value() == "eaVert") { // ToDo: eaVert plus 270deg clockwise rotation has to be written with vert="horz" // plus attribute 'normalEastAsianFlow="1"' on the <wps:wsp> element. @@ -4423,37 +4195,38 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo // Our WritingMode introduces text pre rotation which includes padding, MSO vert does not include // padding. Therefore set padding so, that is looks the same in MSO as in LO. - if (aWBPInput.sWritingMode) + if (sWritingMode) { - if (aWBPInput.sWritingMode.value() == "vert" || aWBPInput.sWritingMode.value() == "eaVert") + if (sWritingMode.value() == "vert" || sWritingMode.value() == "eaVert") { - sal_Int32 nHelp = aWBPInput.nLeft; - aWBPInput.nLeft = aWBPInput.nBottom; - aWBPInput.nBottom = aWBPInput.nRight; - aWBPInput.nRight = aWBPInput.nTop; - aWBPInput.nTop = nHelp; + sal_Int32 nHelp = nLeft; + nLeft = nBottom; + nBottom = nRight; + nRight = nTop; + nTop = nHelp; } - else if (aWBPInput.sWritingMode.value() == "vert270") + else if (sWritingMode.value() == "vert270") { - sal_Int32 nHelp = aWBPInput.nLeft; - aWBPInput.nLeft = aWBPInput.nTop; - aWBPInput.nTop = aWBPInput.nRight; - aWBPInput.nRight = aWBPInput.nBottom; - aWBPInput.nBottom = nHelp; + sal_Int32 nHelp = nLeft; + nLeft = nTop; + nTop = nRight; + nRight = nBottom; + nBottom = nHelp; } - else if (aWBPInput.sWritingMode.value() == "mongolianVert") + else if (sWritingMode.value() == "mongolianVert") { // ToDo: Examine padding } } + std::optional<OString> sTextRotateAngleMSUnit; if (nTextRotateAngleDeg100.has_value()) #if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif - aWBPInput.sTextRotateAngleMSUnit + sTextRotateAngleMSUnit = oox::drawingml::calcRotationValue(nTextRotateAngleDeg100.value().get()); #if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12 #pragma GCC diagnostic pop @@ -4469,40 +4242,42 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo if (GetProperty(rXPropSet, u"TextHorizontalAdjust"_ustr)) mAny >>= eHorizontalAlignment; - if (aWBPInput.sWritingMode.has_value() - && (aWBPInput.sWritingMode.value() == "eaVert" || aWBPInput.sWritingMode.value() == "mongolianVert")) + const char* sAnchor = nullptr; + bool bAnchorCtr = false; + if (sWritingMode.has_value() + && (sWritingMode.value() == "eaVert" || sWritingMode.value() == "mongolianVert")) { - aWBPInput.bAnchorCtr = eVerticalAlignment == TextVerticalAdjust_CENTER + bAnchorCtr = eVerticalAlignment == TextVerticalAdjust_CENTER || eVerticalAlignment == TextVerticalAdjust_BOTTOM || eVerticalAlignment == TextVerticalAdjust_BLOCK; switch (eHorizontalAlignment) { case TextHorizontalAdjust_CENTER: - aWBPInput.sAnchor = "ctr"; + sAnchor = "ctr"; break; case TextHorizontalAdjust_LEFT: - aWBPInput.sAnchor = aWBPInput.sWritingMode.value() == "eaVert" ? "b" : "t"; + sAnchor = sWritingMode.value() == "eaVert" ? "b" : "t"; break; case TextHorizontalAdjust_RIGHT: default: // TextHorizontalAdjust_BLOCK, should not happen - aWBPInput.sAnchor = aWBPInput.sWritingMode.value() == "eaVert" ? "t" : "b"; + sAnchor = sWritingMode.value() == "eaVert" ? "t" : "b"; break; } } else { - aWBPInput.bAnchorCtr = eHorizontalAlignment == TextHorizontalAdjust_CENTER + bAnchorCtr = eHorizontalAlignment == TextHorizontalAdjust_CENTER || eHorizontalAlignment == TextHorizontalAdjust_RIGHT; - aWBPInput.sAnchor = GetTextVerticalAdjust(eVerticalAlignment); + sAnchor = GetTextVerticalAdjust(eVerticalAlignment); } - aWBPInput.bHasWrap = false; - aWBPInput.bWrap = false; + bool bHasWrap = false; + bool bWrap = false; // Only custom shapes obey the TextWordWrap option, normal text always wraps. if (dynamic_cast<SvxCustomShape*>(rXIface.get()) && GetProperty(rXPropSet, u"TextWordWrap"_ustr)) { - mAny >>= aWBPInput.bWrap; - aWBPInput.bHasWrap = true; + mAny >>= bWrap; + bHasWrap = true; } // tdf#134401: If AUTOGROWWIDTH and AUTOGROWHEIGHT are set, then export it as TextWordWrap @@ -4516,15 +4291,222 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo if (rSdrTextFitWidth.GetValue() == true && rSdrTextFitHeight.GetValue() == true) { - aWBPInput.bHasWrap = true; - aWBPInput.bWrap = false; + bHasWrap = true; + bWrap = false; } } if (bBodyPr) { - WriteBodyProps(rXIface, rXPropSet, xShape, nXmlNamespace, aWBPInput); - } // end of bodyPr + const char* pWrap = (bHasWrap && !bWrap) || bIsFontworkShape ? "none" : nullptr; + if (GetDocumentType() == DOCUMENT_DOCX) + { + // In case of DOCX, if we want to have the same effect as + // TextShape's automatic word wrapping, then we need to set + // wrapping to square. + uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, uno::UNO_QUERY); + if ((xServiceInfo.is() && xServiceInfo->supportsService(u"com.sun.star.drawing.TextShape"_ustr)) + || bIsFontworkShape) + pWrap = "square"; + } + + sal_Int16 nCols = 0; + sal_Int32 nColSpacing = -1; + if (GetProperty(rXPropSet, u"TextColumns"_ustr)) + { + if (css::uno::Reference<css::text::XTextColumns> xCols{ mAny, css::uno::UNO_QUERY }) + { + nCols = xCols->getColumnCount(); + if (css::uno::Reference<css::beans::XPropertySet> xProps{ mAny, + css::uno::UNO_QUERY }) + { + if (GetProperty(xProps, u"AutomaticDistance"_ustr)) + mAny >>= nColSpacing; + } + } + } + + if (!sVertOverflow && GetProperty(rXPropSet, u"TextClipVerticalOverflow"_ustr) && mAny.get<bool>()) + { + sVertOverflow = "clip"; + } + + // tdf#151134 When writing placeholder shapes, inset must be explicitly specified + bool bRequireInset = GetProperty(rXPropSet, u"IsPresentationObject"_ustr) && rXPropSet->getPropertyValue(u"IsPresentationObject"_ustr).get<bool>(); + + mpFS->startElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr, + XML_numCol, sax_fastparser::UseIf(OString::number(nCols), nCols > 0), + XML_spcCol, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nColSpacing)), nCols > 0 && nColSpacing >= 0), + XML_wrap, pWrap, + XML_horzOverflow, sHorzOverflow, + XML_vertOverflow, sVertOverflow, + XML_fromWordArt, sax_fastparser::UseIf("1", bFromWordArt), + XML_lIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nLeft)), + bRequireInset || nLeft != constDefaultLeftRightInset), + XML_tIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nTop)), + bRequireInset || nTop != constDefaultTopBottomInset), + XML_rIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nRight)), + bRequireInset || nRight != constDefaultLeftRightInset), + XML_bIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nBottom)), + bRequireInset || nBottom != constDefaultTopBottomInset), + XML_anchor, sAnchor, + XML_anchorCtr, sax_fastparser::UseIf("1", bAnchorCtr), + XML_vert, sWritingMode, + XML_upright, isUpright, + XML_rot, sTextRotateAngleMSUnit); + + if (bIsFontworkShape) + { + if (aAdjustmentSeq.hasElements()) + { + mpFS->startElementNS(XML_a, XML_prstTxWarp, XML_prst, sPresetWarp); + mpFS->startElementNS(XML_a, XML_avLst); + bool bHasTwoHandles( + sPresetWarp == "textArchDownPour" || sPresetWarp == "textArchUpPour" + || sPresetWarp == "textButtonPour" || sPresetWarp == "textCirclePour" + || sPresetWarp == "textDoubleWave1" || sPresetWarp == "textWave1" + || sPresetWarp == "textWave2" || sPresetWarp == "textWave4"); + for (sal_Int32 i = 0, nElems = aAdjustmentSeq.getLength(); i < nElems; ++i ) + { + OString sName = "adj" + (bHasTwoHandles ? OString::number(i + 1) : OString()); + double fValue(0.0); + if (aAdjustmentSeq[i].Value.getValueTypeClass() == TypeClass_DOUBLE) + aAdjustmentSeq[i].Value >>= fValue; + else + { + sal_Int32 nNumber(0); + aAdjustmentSeq[i].Value >>= nNumber; + fValue = static_cast<double>(nNumber); + } + // Convert from binary coordinate system with viewBox "0 0 21600 21600" and simple degree + // to DrawingML with coordinate range 0..100000 and angle in 1/60000 degree. + // Reverse to conversion in lcl_createPresetShape in drawingml/shape.cxx on import. + if (sPresetWarp == "textArchDown" || sPresetWarp == "textArchUp" + || sPresetWarp == "textButton" || sPresetWarp == "textCircle" + || ((i == 0) + && (sPresetWarp == "textArchDownPour" || sPresetWarp == "textArchUpPour" + || sPresetWarp == "textButtonPour" || sPresetWarp == "textCirclePour"))) + { + fValue *= 60000.0; + if (fValue < 0) + fValue += 21600000; + } + else if ((i == 1) + && (sPresetWarp == "textDoubleWave1" || sPresetWarp == "textWave1" + || sPresetWarp == "textWave2" || sPresetWarp == "textWave4")) + { + fValue = fValue / 0.216 - 50000.0; + } + else if ((i == 1) + && (sPresetWarp == "textArchDownPour" + || sPresetWarp == "textArchUpPour" + || sPresetWarp == "textButtonPour" + || sPresetWarp == "textCirclePour")) + { + fValue /= 0.108; + } + else + { + fValue /= 0.216; + } + OString sFmla = "val " + OString::number(std::lround(fValue)); + mpFS->singleElementNS(XML_a, XML_gd, XML_name, sName, XML_fmla, sFmla); + // There exists faulty Favorite shapes with one handle but two adjustment values. + if (!bHasTwoHandles) + break; + } + mpFS->endElementNS(XML_a, XML_avLst); + mpFS->endElementNS(XML_a, XML_prstTxWarp); + } + else + { + mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, sPresetWarp); + } + } + else if (GetDocumentType() == DOCUMENT_DOCX) + { + // interim solution for fdo#80897, roundtrip DOCX > LO > DOCX + if (!sMSWordPresetTextWarp.isEmpty()) + mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, sMSWordPresetTextWarp); + } + + if (GetDocumentType() == DOCUMENT_DOCX || GetDocumentType() == DOCUMENT_XLSX) + { + // tdf#112312: only custom shapes obey the TextAutoGrowHeight option + bool bTextAutoGrowHeight = false; + auto pSdrObjCustomShape = xShape.is() ? dynamic_cast<SdrObjCustomShape*>(SdrObject::getSdrObjectFromXShape(xShape)) : nullptr; + if (pSdrObjCustomShape && GetProperty(rXPropSet, u"TextAutoGrowHeight"_ustr)) + { + mAny >>= bTextAutoGrowHeight; + } + mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : XML_noAutofit)); + } + if (GetDocumentType() == DOCUMENT_PPTX) + { + TextFitToSizeType eFit = TextFitToSizeType_NONE; + if (GetProperty(rXPropSet, u"TextFitToSize"_ustr)) + mAny >>= eFit; + + if (eFit == TextFitToSizeType_AUTOFIT) + { + const sal_Int32 MAX_SCALE_VAL = 100000; + sal_Int32 nFontScale = MAX_SCALE_VAL; + sal_Int32 nSpacingReduction = 0; + SvxShapeText* pTextShape = dynamic_cast<SvxShapeText*>(rXIface.get()); + if (pTextShape) + { + SdrTextObj* pTextObject = DynCastSdrTextObj(pTextShape->GetSdrObject()); + if (pTextObject) + { + nFontScale = sal_Int32(pTextObject->GetFontScale() * 100000.0); + nSpacingReduction = sal_Int32((1.0 - pTextObject->GetSpacingScale()) * 100000.0); + } + } + + bool bExportFontScale = false; + if (nFontScale < MAX_SCALE_VAL && nFontScale > 0) + bExportFontScale = true; + + bool bExportSpaceReduction = false; + if (nSpacingReduction < MAX_SCALE_VAL && nSpacingReduction > 0) + bExportSpaceReduction = true; + + mpFS->singleElementNS(XML_a, XML_normAutofit, + XML_fontScale, sax_fastparser::UseIf(OString::number(nFontScale), bExportFontScale), + XML_lnSpcReduction, sax_fastparser::UseIf(OString::number(nSpacingReduction), bExportSpaceReduction)); + } + else + { + bool bAutoGrowHeightEnabled = false; + const SdrObject* pObj = xShape.is() ? SdrObject::getSdrObjectFromXShape(xShape) : nullptr; + if (pObj) + { + switch (pObj->GetObjIdentifier()) + { + case SdrObjKind::NONE: + case SdrObjKind::Text: + case SdrObjKind::TitleText: + case SdrObjKind::OutlineText: + case SdrObjKind::Caption: + case SdrObjKind::CustomShape: + bAutoGrowHeightEnabled = true; + break; + default: + bAutoGrowHeightEnabled = false; + } + } + + bool bTextAutoGrowHeight = false; + if (bAutoGrowHeightEnabled && GetProperty(rXPropSet, u"TextAutoGrowHeight"_ustr)) + mAny >>= bTextAutoGrowHeight; + mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : XML_noAutofit)); + } + } + + Write3DEffects( rXPropSet, /*bIsText=*/true ); + + mpFS->endElementNS((nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr); + } Reference< XEnumerationAccess > access( xXText, UNO_QUERY ); if( !access.is() || !bText ) @@ -4539,7 +4521,7 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo if (pTxtObj && mpTextExport) { std::vector<beans::PropertyValue> aOldCharFillPropVec; - if (aWBPInput.bIsFontworkShape) + if (bIsFontworkShape) { // Users may have set the character fill properties for more convenient editing. // Save the properties before changing them for Fontwork export. -e ... etc. - the rest is truncated
