sw/qa/extras/ooxmlexport/data/tdf166325_scheme_color.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx                |   12 ++
 sw/source/filter/ww8/docxattributeoutput.cxx              |   59 +++++++++-----
 3 files changed, 51 insertions(+), 20 deletions(-)

New commits:
commit 43b74c0037b0d1b2ea2f4dc4faa42283addcf483
Author:     Aron Budea <[email protected]>
AuthorDate: Wed Dec 10 13:01:58 2025 +1030
Commit:     Xisco Fauli <[email protected]>
CommitDate: Fri Dec 12 09:01:42 2025 +0100

    tdf#166325 sw: use correct type when exporting scheme color to DOCX
    
    OOXML schemeClr element has a different type (ST_SchemeColorVal)
    compared to themeColor's ST_ThemeColor type, eg. dk1 instead
    of dark1, but commit baf179188d8b9e29188387fd4b7d887dd3168792
    mapped them to the same values on export, causing some affected
    files to become invalid.
    
    Change-Id: Iff63aea8943be905c9afbb68012db320cc94eeb9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195346
    Reviewed-by: Mike Kaganski <[email protected]>
    Tested-by: Jenkins
    Reviewed-by: Aron Budea <[email protected]>
    (cherry picked from commit d5136e0b6059435356351cf2c54af61401e45fc2)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195507
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf166325_scheme_color.docx 
b/sw/qa/extras/ooxmlexport/data/tdf166325_scheme_color.docx
new file mode 100644
index 000000000000..76928834f205
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/tdf166325_scheme_color.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index 0afb04e1ca98..ca5f5d35c0fe 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -1112,6 +1112,18 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf149200)
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r[1]/w:rPr/w:color", 
"themeColor", u"dark1");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf166325_scheme_color)
+{
+    createSwDoc("tdf166325_scheme_color.docx");
+    save(TestFilter::DOCX);
+
+    xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
+    // Without the fix this would be "light2" (type ST_ThemeColor instead of 
ST_SchemeColorVal)
+    assertXPath(pXmlDoc,
+                
"/w:document/w:body/w:p/w:r/w:rPr/w14:textFill/w14:solidFill/w14:schemeClr", 
"val",
+                u"lt2");
+}
+
 DECLARE_OOXMLEXPORT_TEST(testTdf149313, "tdf149313.docx")
 {
     // only 2, but not 3 pages in document
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index f0986e3353de..3fd2af4b63ad 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -301,50 +301,69 @@ auto 
detachFrom(rtl::Reference<sax_fastparser::FastAttributeList>& src)
     return rtl::Reference(std::move(src));
 }
 
-constexpr auto constThemeColorTypeTokenMap = 
frozen::make_unordered_map<model::ThemeColorType, const char*>({
-    { model::ThemeColorType::Dark1, "dark1" },
-    { model::ThemeColorType::Light1, "light1" },
-    { model::ThemeColorType::Dark2, "dark2" },
-    { model::ThemeColorType::Light2, "light2" },
-    { model::ThemeColorType::Accent1, "accent1" },
-    { model::ThemeColorType::Accent2, "accent2" },
-    { model::ThemeColorType::Accent3, "accent3" },
-    { model::ThemeColorType::Accent4, "accent4" },
-    { model::ThemeColorType::Accent5, "accent5" },
-    { model::ThemeColorType::Accent6, "accent6" },
-    { model::ThemeColorType::Hyperlink, "hyperlink" },
-    { model::ThemeColorType::FollowedHyperlink, "followedHyperlink" }
+struct ThemeSchemeName
+{
+    const char* ThemeName;
+    const char* SchemeName;
+};
+
+constexpr auto constThemeColorTypeTokenMap = 
frozen::make_unordered_map<model::ThemeColorType, const ThemeSchemeName>({
+    { model::ThemeColorType::Dark1, { "dark1", "dk1" } },
+    { model::ThemeColorType::Light1, { "light1", "lt1" } },
+    { model::ThemeColorType::Dark2, {"dark2", "dk2" } },
+    { model::ThemeColorType::Light2, {"light2", "lt2" } },
+    { model::ThemeColorType::Accent1, {"accent1", "accent1" } },
+    { model::ThemeColorType::Accent2, {"accent2", "accent2" } },
+    { model::ThemeColorType::Accent3, {"accent3", "accent3" } },
+    { model::ThemeColorType::Accent4, {"accent4", "accent4" } },
+    { model::ThemeColorType::Accent5, {"accent5", "accent5" } },
+    { model::ThemeColorType::Accent6, {"accent6", "accent6" } },
+    { model::ThemeColorType::Hyperlink, {"hyperlink", "hlink" } },
+    { model::ThemeColorType::FollowedHyperlink, {"followedHyperlink", 
"folHlink" } }
 });
 
-OString lclGetSchemeType(model::ComplexColor const& rComplexColor)
+// Returns colors as OOXML ST_ThemeColor or ST_SchemeColorVal types, which are 
very similar
+OString lclGetThemeOrSchemeType(model::ComplexColor const& rComplexColor, bool 
bIsTheme = true)
 {
     const auto iter = 
constThemeColorTypeTokenMap.find(rComplexColor.getThemeColorType());
     assert(iter != constThemeColorTypeTokenMap.end());
-    OString sSchemeType = iter->second;
+    OString sSchemeType = bIsTheme ? iter->second.ThemeName : 
iter->second.SchemeName;
     if (rComplexColor.getThemeColorUsage() == model::ThemeColorUsage::Text)
     {
         if (rComplexColor.getThemeColorType() == model::ThemeColorType::Dark1)
-            sSchemeType = "text1"_ostr;
+            sSchemeType = bIsTheme ? "text1"_ostr : "tx1"_ostr;
         else if (rComplexColor.getThemeColorType() == 
model::ThemeColorType::Dark2)
-            sSchemeType = "text2"_ostr;
+            sSchemeType = bIsTheme ? "text2"_ostr : "tx2"_ostr;
     }
     else if (rComplexColor.getThemeColorUsage() == 
model::ThemeColorUsage::Background)
     {
         if (rComplexColor.getThemeColorType() == model::ThemeColorType::Light1)
-            sSchemeType = "background1"_ostr;
+            sSchemeType = bIsTheme ? "background1"_ostr : "bg1"_ostr;
         else if (rComplexColor.getThemeColorType() == 
model::ThemeColorType::Light2)
-            sSchemeType = "background2"_ostr;
+            sSchemeType = bIsTheme ? "background2"_ostr : "bg2"_ostr;
     }
     return sSchemeType;
 }
 
+// Returns colors as OOXML ST_ThemeColor type
+OString lclGetThemeType(model::ComplexColor const& rComplexColor)
+{
+    return lclGetThemeOrSchemeType(rComplexColor, true);
+}
+
+// Return colors as OOXML ST_SchemeColorVal type for Scheme Color element
+OString lclGetSchemeType(model::ComplexColor const& rComplexColor)
+{
+    return lclGetThemeOrSchemeType(rComplexColor, false);
+}
+
 void lclAddThemeValuesToCustomAttributes(
     rtl::Reference<sax_fastparser::FastAttributeList>& pAttrList, 
model::ComplexColor const& rComplexColor,
     sal_Int32 nThemeAttrId, sal_Int32 nThemeTintAttrId, sal_Int32 
nThemeShadeAttrId)
 {
     if (rComplexColor.isValidThemeType())
     {
-        OString sSchemeType = lclGetSchemeType(rComplexColor);
+        OString sSchemeType = lclGetThemeType(rComplexColor);
 
         DocxAttributeOutput::AddToAttrList(pAttrList, FSNS(XML_w, 
nThemeAttrId), sSchemeType);
 

Reply via email to