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

Reply via email to