include/oox/drawingml/color.hxx | 2 include/oox/helper/graphichelper.hxx | 2 include/oox/ppt/pptimport.hxx | 1 include/oox/ppt/presentationfragmenthandler.hxx | 1 oox/source/drawingml/color.cxx | 15 ++++ oox/source/drawingml/fillproperties.cxx | 8 ++ oox/source/drawingml/textcharacterproperties.cxx | 8 ++ oox/source/helper/graphichelper.cxx | 2 oox/source/ppt/pptimport.cxx | 28 ++++++++ oox/source/ppt/presentationfragmenthandler.cxx | 56 ++++++++++++++++ sd/qa/unit/data/pptx/tdf160591.pptx |binary sd/qa/unit/export-tests-ooxml4.cxx | 23 ++++++ sd/source/filter/eppt/pptx-epptooxml.cxx | 80 ++++++++++++++++++----- 13 files changed, 212 insertions(+), 14 deletions(-)
New commits: commit dd42aa47b2d7d105aed2d3f4a458b76d4dcde70b Author: Tibor Nagy <tibor.nagy.ext...@allotropia.de> AuthorDate: Thu Jun 6 19:47:45 2024 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Oct 4 09:40:15 2024 +0200 tdf#160591 PPTX export: fix colormap mapping in slide master Change-Id: I154f0ff1769fbda361ec62f1dd589ca0d7686bd9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168506 Tested-by: Jenkins Reviewed-by: Nagy Tibor <tibor.nagy.ext...@allotropia.de> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174440 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Justin Luth <jl...@mail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/include/oox/drawingml/color.hxx b/include/oox/drawingml/color.hxx index ea02ef8a03e4..dc8be778f665 100644 --- a/include/oox/drawingml/color.hxx +++ b/include/oox/drawingml/color.hxx @@ -122,6 +122,8 @@ public: static OUString getColorTransformationName( sal_Int32 nElement ); /** Translates between color transformation token names and the corresponding token */ static sal_Int32 getColorTransformationToken( std::u16string_view sName ); + /** Translates between ColorMap token names and the corresponding token */ + static sal_Int32 getColorMapToken(std::u16string_view sName); /// Compares this color with rOther. bool equals(const Color& rOther, const GraphicHelper& rGraphicHelper, ::Color nPhClr) const; diff --git a/include/oox/helper/graphichelper.hxx b/include/oox/helper/graphichelper.hxx index 0d0b69216617..906d7330dff3 100644 --- a/include/oox/helper/graphichelper.hxx +++ b/include/oox/helper/graphichelper.hxx @@ -77,6 +77,8 @@ public: ::Color getSystemColor( sal_Int32 nToken, ::Color nDefaultRgb = API_RGB_TRANSPARENT ) const; /** Derived classes may implement to resolve a scheme color from the passed XML token identifier. */ virtual ::Color getSchemeColor( sal_Int32 nToken ) const; + /** Derived classes may implement to resolve a ColorMap token from the passed XML token identifier. */ + virtual void getSchemeColorToken(sal_Int32& nToken) const; /** Derived classes may implement to resolve a palette index to an RGB color. */ virtual ::Color getPaletteColor( sal_Int32 nPaletteIdx ) const; diff --git a/include/oox/ppt/pptimport.hxx b/include/oox/ppt/pptimport.hxx index 2d7367c4c63e..9591560d0326 100644 --- a/include/oox/ppt/pptimport.hxx +++ b/include/oox/ppt/pptimport.hxx @@ -74,6 +74,7 @@ public: virtual sal_Bool SAL_CALL filter( const css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ) override; + void getSchemeColorToken(sal_Int32& nToken) const; ::Color getSchemeColor( sal_Int32 nToken ) const; virtual std::shared_ptr<::oox::drawingml::Theme> getCurrentThemePtr() const override; diff --git a/include/oox/ppt/presentationfragmenthandler.hxx b/include/oox/ppt/presentationfragmenthandler.hxx index 20fc521ae8c5..29e7bcf12bfc 100644 --- a/include/oox/ppt/presentationfragmenthandler.hxx +++ b/include/oox/ppt/presentationfragmenthandler.hxx @@ -57,6 +57,7 @@ private: ::oox::ppt::PowerPointImport& rFilter, const OUString& rMasterFragmentPath); void saveThemeToGrabBag(const oox::drawingml::ThemePtr& pThemePtr, sal_Int32 nThemeIdx); + void saveColorMapToGrabBag(const oox::drawingml::ClrMapPtr& pClrMapPtr); void importCustomSlideShow(std::vector<CustomShow>& rCustomShowList); static void importSlideNames(::oox::core::XmlFilterBase& rFilter, const std::vector<SlidePersistPtr>& rSlidePersist); diff --git a/oox/source/drawingml/color.cxx b/oox/source/drawingml/color.cxx index 9462fc03095c..fea1dd0766a1 100644 --- a/oox/source/drawingml/color.cxx +++ b/oox/source/drawingml/color.cxx @@ -455,6 +455,21 @@ void Color::clearTransformations() clearTransparence(); } +constexpr frozen::unordered_map<std::u16string_view, sal_Int32, 12> constColorMapTokenMap + = { { u"bg1", XML_bg1 }, { u"tx1", XML_tx1 }, { u"bg2", XML_bg2 }, + { u"tx2", XML_tx2 }, { u"accent1", XML_accent1 }, { u"accent2", XML_accent2 }, + { u"accent3", XML_accent3 }, { u"accent4", XML_accent4 }, { u"accent5", XML_accent5 }, + { u"accent6", XML_accent6 }, { u"hlink", XML_hlink }, { u"folHlink", XML_folHlink } }; + +sal_Int32 Color::getColorMapToken(std::u16string_view sName) +{ + auto aIterator = constColorMapTokenMap.find(sName); + if (aIterator == constColorMapTokenMap.end()) + return XML_TOKEN_INVALID; + else + return aIterator->second; +} + OUString Color::getColorTransformationName( sal_Int32 nElement ) { switch( nElement ) diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx index dec9ab9672cc..e0e30a54bd96 100644 --- a/oox/source/drawingml/fillproperties.cxx +++ b/oox/source/drawingml/fillproperties.cxx @@ -441,6 +441,14 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp else { aComplexColor = maFillColor.getComplexColor(); + OUString sColorName = getBestSolidColor().getSchemeColorName(); + sal_Int32 nToken = Color::getColorMapToken(sColorName); + if (nToken != -1) + { + rGraphicHelper.getSchemeColorToken(nToken); + model::ThemeColorType eThemeColorType = schemeTokenToThemeColorType(nToken); + aComplexColor.setThemeColor(eThemeColorType); + } } rPropMap.setProperty(PROP_FillComplexColor, model::color::createXComplexColor(aComplexColor)); diff --git a/oox/source/drawingml/textcharacterproperties.cxx b/oox/source/drawingml/textcharacterproperties.cxx index d123f3607208..31be8a63a609 100644 --- a/oox/source/drawingml/textcharacterproperties.cxx +++ b/oox/source/drawingml/textcharacterproperties.cxx @@ -29,6 +29,7 @@ #include <docmodel/uno/UnoComplexColor.hxx> #include <oox/helper/helper.hxx> #include <oox/helper/propertyset.hxx> +#include <oox/helper/graphichelper.hxx> #include <oox/core/xmlfilterbase.hxx> #include <oox/drawingml/drawingmltypes.hxx> #include <oox/token/properties.hxx> @@ -137,6 +138,13 @@ void TextCharacterProperties::pushToPropMap( PropertyMap& rPropMap, const XmlFil // set theme color model::ComplexColor aComplexColor = aColor.getComplexColor(); + sal_Int32 nToken = Color::getColorMapToken(aColor.getSchemeColorName()); + if (nToken != -1) + { + rFilter.getGraphicHelper().getSchemeColorToken(nToken); + model::ThemeColorType eThemeColorType = schemeTokenToThemeColorType(nToken); + aComplexColor.setThemeColor(eThemeColorType); + } rPropMap.setProperty(PROP_CharComplexColor, model::color::createXComplexColor(aComplexColor)); rPropMap.setProperty(PROP_CharContoured, bContoured); diff --git a/oox/source/helper/graphichelper.cxx b/oox/source/helper/graphichelper.cxx index 830f0131284b..1d728afa8bca 100644 --- a/oox/source/helper/graphichelper.cxx +++ b/oox/source/helper/graphichelper.cxx @@ -122,6 +122,8 @@ GraphicHelper::~GraphicHelper() return ContainerHelper::getMapElement( maSystemPalette, nToken, nDefaultRgb ); } +void GraphicHelper::getSchemeColorToken(sal_Int32& /*nToken*/) const {} + ::Color GraphicHelper::getSchemeColor( sal_Int32 /*nToken*/ ) const { OSL_FAIL( "GraphicHelper::getSchemeColor - scheme colors not implemented" ); diff --git a/oox/source/ppt/pptimport.cxx b/oox/source/ppt/pptimport.cxx index 55e094db652f..3df9a7264cba 100644 --- a/oox/source/ppt/pptimport.cxx +++ b/oox/source/ppt/pptimport.cxx @@ -143,6 +143,28 @@ bool PowerPointImport::exportDocument() noexcept return false; } +void PowerPointImport::getSchemeColorToken(sal_Int32& nToken) const +{ + if (mpActualSlidePersist) + { + bool bColorMapped = false; + oox::drawingml::ClrMapPtr pClrMapPtr(mpActualSlidePersist->getClrMap()); + if (pClrMapPtr) + bColorMapped = pClrMapPtr->getColorMap(nToken); + + if (!bColorMapped) // try masterpage mapping + { + SlidePersistPtr pMasterPersist = mpActualSlidePersist->getMasterPersist(); + if (pMasterPersist) + { + pClrMapPtr = pMasterPersist->getClrMap(); + if (pClrMapPtr) + pClrMapPtr->getColorMap(nToken); + } + } + } +} + ::Color PowerPointImport::getSchemeColor( sal_Int32 nToken ) const { ::Color nColor; @@ -259,6 +281,7 @@ class PptGraphicHelper : public GraphicHelper public: explicit PptGraphicHelper( const PowerPointImport& rFilter ); virtual ::Color getSchemeColor( sal_Int32 nToken ) const override; + virtual void getSchemeColorToken( sal_Int32& nToken ) const override; virtual sal_Int32 getDefaultChartAreaFillStyle() const override; private: const PowerPointImport& mrFilter; @@ -270,6 +293,11 @@ PptGraphicHelper::PptGraphicHelper( const PowerPointImport& rFilter ) : { } +void PptGraphicHelper::getSchemeColorToken(sal_Int32& nToken) const +{ + return mrFilter.getSchemeColorToken(nToken); +} + ::Color PptGraphicHelper::getSchemeColor( sal_Int32 nToken ) const { return mrFilter.getSchemeColor( nToken ); diff --git a/oox/source/ppt/presentationfragmenthandler.cxx b/oox/source/ppt/presentationfragmenthandler.cxx index 2e0f48bbae98..35f5d378ca9a 100644 --- a/oox/source/ppt/presentationfragmenthandler.cxx +++ b/oox/source/ppt/presentationfragmenthandler.cxx @@ -19,6 +19,7 @@ #include <comphelper/anytostring.hxx> #include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> #include <comphelper/sequenceashashmap.hxx> #include <o3tl/string_view.hxx> #include <sal/log.hxx> @@ -287,6 +288,8 @@ void PresentationFragmentHandler::importMasterSlide(const Reference<frame::XMode pMasterPersistPtr->createBackground( rFilter ); pMasterPersistPtr->createXShapes( rFilter ); + saveColorMapToGrabBag(pMasterPersistPtr->getClrMap()); + uno::Reference< beans::XPropertySet > xSet(pMasterPersistPtr->getPage(), uno::UNO_QUERY_THROW); xSet->setPropertyValue("SlideLayout", Any(pMasterPersistPtr->getLayoutFromValueToken())); @@ -365,6 +368,59 @@ void PresentationFragmentHandler::saveThemeToGrabBag(const oox::drawingml::Theme } } +void PresentationFragmentHandler::saveColorMapToGrabBag(const oox::drawingml::ClrMapPtr& pClrMapPtr) +{ + if (!pClrMapPtr) + return; + + try + { + uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY); + if (xDocProps.is()) + { + uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo(); + + static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr; + if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName)) + { + static const constexpr std::array<sal_Int32, 12> constTokenArray + = { XML_bg1, XML_tx1, XML_bg2, XML_tx2, + XML_accent1, XML_accent2, XML_accent3, XML_accent4, + XML_accent5, XML_accent6, XML_hlink, XML_folHlink }; + + comphelper::SequenceAsHashMap aClrMapHashMap; + comphelper::SequenceAsHashMap aGrabBag( + xDocProps->getPropertyValue(aGrabBagPropName)); + + std::vector<beans::PropertyValue> aClrMapList; + size_t nColorMapSize = constTokenArray.size(); + aClrMapList.reserve(nColorMapSize); + for (size_t i = 0; i < nColorMapSize; ++i) + { + sal_Int32 nToken = constTokenArray[i]; + pClrMapPtr->getColorMap(nToken); + aClrMapList.push_back( + comphelper::makePropertyValue(OUString::number(i), nToken)); + } + + uno::Sequence<beans::PropertyValue> aClrMapPropValue{ comphelper::makePropertyValue( + u"OOXColorMap"_ustr, + uno::Any(comphelper::containerToSequence(aClrMapList))) }; + + aClrMapHashMap << aClrMapPropValue; + aGrabBag.update(aClrMapHashMap); + + xDocProps->setPropertyValue(aGrabBagPropName, + uno::Any(aGrabBag.getAsConstPropertyValueList())); + } + } + } + catch (const uno::Exception&) + { + SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveColorMapToGrabBag, Failed to save grab bag"); + } +} + void PresentationFragmentHandler::importMasterSlides() { OUString aMasterFragmentPath; diff --git a/sd/qa/unit/data/pptx/tdf160591.pptx b/sd/qa/unit/data/pptx/tdf160591.pptx new file mode 100644 index 000000000000..9bc68d6ae4e9 Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf160591.pptx differ diff --git a/sd/qa/unit/export-tests-ooxml4.cxx b/sd/qa/unit/export-tests-ooxml4.cxx index f99a3897b3af..9925038f07b9 100644 --- a/sd/qa/unit/export-tests-ooxml4.cxx +++ b/sd/qa/unit/export-tests-ooxml4.cxx @@ -37,6 +37,29 @@ public: } }; +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf160591) +{ + createSdImpressDoc("pptx/tdf160591.pptx"); + save(u"Impress Office Open XML"_ustr); + + // Char scheme color + xmlDocUniquePtr pXmlDoc1 = parseExport(u"ppt/slides/slide1.xml"_ustr); + assertXPath(pXmlDoc1, + "/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:solidFill/a:schemeClr"_ostr, + "val"_ostr, u"lt2"_ustr); + + // Master slide ColorMap + xmlDocUniquePtr pXmlDoc2 = parseExport(u"ppt/slideMasters/slideMaster1.xml"_ustr); + assertXPath(pXmlDoc2, "/p:sldMaster/p:clrMap"_ostr, "bg1"_ostr, u"dk1"_ustr); + assertXPath(pXmlDoc2, "/p:sldMaster/p:clrMap"_ostr, "tx1"_ostr, u"lt1"_ustr); + assertXPath(pXmlDoc2, "/p:sldMaster/p:clrMap"_ostr, "bg2"_ostr, u"dk2"_ustr); + assertXPath(pXmlDoc2, "/p:sldMaster/p:clrMap"_ostr, "tx2"_ostr, u"lt2"_ustr); + + // Master slide background + assertXPath(pXmlDoc2, "/p:sldMaster/p:cSld/p:bg/p:bgPr/a:solidFill/a:schemeClr"_ostr, + "val"_ostr, u"dk1"_ustr); +} + CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testSmartArtPreserve) { createSdImpressDoc("pptx/smartart-preserve.pptx"); diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx index 96f135ecf585..fa659b432b59 100644 --- a/sd/source/filter/eppt/pptx-epptooxml.cxx +++ b/sd/source/filter/eppt/pptx-epptooxml.cxx @@ -1498,20 +1498,72 @@ void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPro pFS->endElementNS(XML_p, XML_cSld); - // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update - pFS->singleElementNS(XML_p, XML_clrMap, - XML_bg1, "lt1", - XML_bg2, "lt2", - XML_tx1, "dk1", - XML_tx2, "dk2", - XML_accent1, "accent1", - XML_accent2, "accent2", - XML_accent3, "accent3", - XML_accent4, "accent4", - XML_accent5, "accent5", - XML_accent6, "accent6", - XML_hlink, "hlink", - XML_folHlink, "folHlink"); + css::uno::Reference< css::beans::XPropertySet > xDocPropSet(getModel(), uno::UNO_QUERY); + if (xDocPropSet.is()) + { + uno::Sequence<beans::PropertyValue> aGrabBag; + if (xDocPropSet->getPropertySetInfo()->hasPropertyByName(u"InteropGrabBag"_ustr)) + xDocPropSet->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag; + + std::vector<OUString> aClrMap; + aClrMap.reserve(12); + if(aGrabBag.hasElements()) + { + uno::Sequence<beans::PropertyValue> aClrMapPropValue; + for (const auto& rProp : aGrabBag) + { + if (rProp.Name == "OOXColorMap") + { + rProp.Value >>= aClrMapPropValue; + break; + } + } + + OUString sName; + sal_Int32 nToken = XML_TOKEN_INVALID; + for(const auto& item : aClrMapPropValue) + { + item.Value >>= nToken; + switch (nToken) + { + case XML_dk1: sName = u"dk1"_ustr; break; + case XML_lt1: sName = u"lt1"_ustr; break; + case XML_dk2: sName = u"dk2"_ustr; break; + case XML_lt2: sName = u"lt2"_ustr; break; + case XML_accent1: sName = u"accent1"_ustr; break; + case XML_accent2: sName = u"accent2"_ustr; break; + case XML_accent3: sName = u"accent3"_ustr; break; + case XML_accent4: sName = u"accent4"_ustr; break; + case XML_accent5: sName = u"accent5"_ustr; break; + case XML_accent6: sName = u"accent6"_ustr; break; + case XML_hlink: sName = u"hlink"_ustr; break; + case XML_folHlink: sName = u"folHlink"_ustr; break; + } + aClrMap.push_back(sName); + } + } + else + { + // default clrMap to export ".odp" files to ".pptx" + aClrMap = { u"lt1"_ustr, u"dk1"_ustr, u"lt2"_ustr, u"dk2"_ustr, + u"accent1"_ustr, u"accent2"_ustr, u"accent3"_ustr, u"accent4"_ustr, + u"accent5"_ustr, u"accent6"_ustr, u"hlink"_ustr, u"folHlink"_ustr }; + } + + pFS->singleElementNS(XML_p, XML_clrMap, + XML_bg1, aClrMap[0], + XML_tx1, aClrMap[1], + XML_bg2, aClrMap[2], + XML_tx2, aClrMap[3], + XML_accent1, aClrMap[4], + XML_accent2, aClrMap[5], + XML_accent3, aClrMap[6], + XML_accent4, aClrMap[7], + XML_accent5, aClrMap[8], + XML_accent6, aClrMap[9], + XML_hlink, aClrMap[10], + XML_folHlink, aClrMap[11]); + } // use master's id type as they have same range, mso does that as well pFS->startElementNS(XML_p, XML_sldLayoutIdLst);