include/docmodel/color/ComplexColor.hxx |    5 ++
 include/oox/export/ColorExportUtils.hxx |   55 ++++++++++++++++++++++++++++++++
 sc/qa/unit/ThemeImportExportTest.cxx    |   18 +++++-----
 sc/qa/unit/subsequent_export_test.cxx   |   16 ++++++---
 sc/source/filter/excel/xestream.cxx     |   19 ++++++-----
 sc/source/filter/excel/xestyle.cxx      |   40 ++++++++++++++++++-----
 6 files changed, 125 insertions(+), 28 deletions(-)

New commits:
commit 1d627c6f15bddc94189f6018c0cc6d48335695e3
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Fri Jun 30 01:39:50 2023 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Tue Jul 4 10:37:56 2023 +0200

    sc: OOXML export of theme colors for text and background
    
    Change-Id: Ifd0d8184c9210caa5ca099767baa5dbbf8783f36
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153785
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    (cherry picked from commit 82f60df96c5e7f7ad92c49cbbdbb0619f4e5e8a2)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153919

diff --git a/include/docmodel/color/ComplexColor.hxx 
b/include/docmodel/color/ComplexColor.hxx
index 4952d91ac217..e9597b15186b 100644
--- a/include/docmodel/color/ComplexColor.hxx
+++ b/include/docmodel/color/ComplexColor.hxx
@@ -100,6 +100,11 @@ public:
 
     ThemeColorType getSchemeType() const { return meSchemeType; }
 
+    bool isValidSchemeType() const
+    {
+        return meType == model::ColorType::Scheme && meSchemeType != 
ThemeColorType::Unknown;
+    }
+
     Color getRGBColor() const { return Color(mnComponent1, mnComponent2, 
mnComponent3); }
 
     std::vector<Transformation> const& getTransformations() const { return 
maTransformations; }
diff --git a/include/oox/export/ColorExportUtils.hxx 
b/include/oox/export/ColorExportUtils.hxx
new file mode 100644
index 000000000000..63716a10839d
--- /dev/null
+++ b/include/oox/export/ColorExportUtils.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <docmodel/color/ComplexColor.hxx>
+
+namespace oox
+{
+static double convertColorTransformsToTintOrShade(model::ComplexColor const& 
rComplexColor)
+{
+    sal_Int16 nLumMod = 10'000;
+    sal_Int16 nLumOff = 0;
+
+    for (auto const& rTransform : rComplexColor.getTransformations())
+    {
+        if (rTransform.meType == model::TransformationType::LumMod)
+            nLumMod = rTransform.mnValue;
+        if (rTransform.meType == model::TransformationType::LumOff)
+            nLumOff = rTransform.mnValue;
+    }
+
+    if (nLumMod == 10'000 && nLumOff == 0)
+        return 0.0;
+
+    double fTint = 0.0;
+
+    if (nLumOff > 0) // tint
+        fTint = double(nLumOff) / 10'000.0;
+    else
+        fTint = -double(10'000 - nLumMod) / 10'000.0;
+
+    return fTint;
+}
+
+static sal_Int32 convertThemeColorTypeToExcelThemeNumber(model::ThemeColorType 
eType)
+{
+    if (eType == model::ThemeColorType::Unknown)
+        return -1;
+
+    constexpr std::array<sal_Int32, 12> constMap = { 1, 0, 3, 2, 4, 5, 6, 7, 
8, 9, 10, 11 };
+
+    return constMap[sal_Int32(eType)];
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/qa/unit/ThemeImportExportTest.cxx 
b/sc/qa/unit/ThemeImportExportTest.cxx
index 106471f9a816..95e6d0e2351e 100644
--- a/sc/qa/unit/ThemeImportExportTest.cxx
+++ b/sc/qa/unit/ThemeImportExportTest.cxx
@@ -41,11 +41,9 @@ CPPUNIT_TEST_FIXTURE(ThemeImportExportTest, testThemeExport)
     // Fonts
     assertXPath(pXmlDoc, "/x:styleSheet/x:fonts/x:font", 6);
 
-    assertXPath(pXmlDoc, "/x:styleSheet/x:fonts/x:font[5]/x:color", "rgb",
-                "FFFFC000"); // need to be theme probably
+    assertXPath(pXmlDoc, "/x:styleSheet/x:fonts/x:font[5]/x:color", "theme", 
"7");
 
-    assertXPath(pXmlDoc, "/x:styleSheet/x:fonts/x:font[6]/x:color", "rgb",
-                "FF9C5700"); // need to be theme probably
+    assertXPath(pXmlDoc, "/x:styleSheet/x:fonts/x:font[6]/x:color", "rgb", 
"FF9C5700");
 
     // Fills
     assertXPath(pXmlDoc, "/x:styleSheet/x:fills/x:fill", 4);
@@ -92,9 +90,9 @@ void checkCellBackgroundThemeColor(ScDocument* pDoc)
         auto& rTransformations = aComplexColor.getTransformations();
         CPPUNIT_ASSERT_EQUAL(size_t(2), rTransformations.size());
         CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumMod, 
rTransformations[0].meType);
-        CPPUNIT_ASSERT_EQUAL(sal_Int16(2000), rTransformations[0].mnValue);
+        CPPUNIT_ASSERT_EQUAL(20, 
sal_Int32(std::round(rTransformations[0].mnValue / 100.0)));
         CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumOff, 
rTransformations[1].meType);
-        CPPUNIT_ASSERT_EQUAL(sal_Int16(7999), rTransformations[1].mnValue);
+        CPPUNIT_ASSERT_EQUAL(80, 
sal_Int32(std::round(rTransformations[1].mnValue / 100.0)));
     }
 
     // A3
@@ -119,6 +117,8 @@ CPPUNIT_TEST_FIXTURE(ThemeImportExportTest, 
testCellBackgroundThemeColor)
 {
     loadFromURL(u"xlsx/Test_ThemeColor_Text_Background_Border.xlsx");
     checkCellBackgroundThemeColor(getScDoc());
+    saveAndReload("Calc Office Open XML");
+    checkCellBackgroundThemeColor(getScDoc());
 }
 
 void checkCellTextThemeColor(ScDocument* pDoc)
@@ -151,9 +151,9 @@ void checkCellTextThemeColor(ScDocument* pDoc)
         auto& rTransformations = aComplexColor.getTransformations();
         CPPUNIT_ASSERT_EQUAL(size_t(2), rTransformations.size());
         CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumMod, 
rTransformations[0].meType);
-        CPPUNIT_ASSERT_EQUAL(sal_Int16(6000), rTransformations[0].mnValue);
+        CPPUNIT_ASSERT_EQUAL(60, 
sal_Int32(std::round(rTransformations[0].mnValue / 100.0)));
         CPPUNIT_ASSERT_EQUAL(model::TransformationType::LumOff, 
rTransformations[1].meType);
-        CPPUNIT_ASSERT_EQUAL(sal_Int16(3999), rTransformations[1].mnValue);
+        CPPUNIT_ASSERT_EQUAL(40, 
sal_Int32(std::round(rTransformations[1].mnValue / 100.0)));
     }
 
     // B3
@@ -178,6 +178,8 @@ CPPUNIT_TEST_FIXTURE(ThemeImportExportTest, 
testCellTextThemeColor)
 {
     loadFromURL(u"xlsx/Test_ThemeColor_Text_Background_Border.xlsx");
     checkCellTextThemeColor(getScDoc());
+    saveAndReload("Calc Office Open XML");
+    checkCellTextThemeColor(getScDoc());
 }
 
 void checkCellBorderThemeColor(ScDocument* pDoc)
diff --git a/sc/qa/unit/subsequent_export_test.cxx 
b/sc/qa/unit/subsequent_export_test.cxx
index e528e3fc679c..1ce8ef99c926 100644
--- a/sc/qa/unit/subsequent_export_test.cxx
+++ b/sc/qa/unit/subsequent_export_test.cxx
@@ -105,8 +105,13 @@ CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf139167)
                 "FFFFFF00");
 }
 
-CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf113271)
+CPPUNIT_TEST_FIXTURE(ScExportTest, testFontColorWithMultipleAttributesDefined)
 {
+    // Related: TDF #113271
+    // Test font color where "rgb" and "theme" attribute is defined and
+    // is imported and exported correctly. Theme should have priority,
+    // so LO is fine to ignore "rgb" at export.
+
     createScDoc("xlsx/tdf113271.xlsx");
 
     save("Calc Office Open XML");
@@ -115,10 +120,11 @@ CPPUNIT_TEST_FIXTURE(ScExportTest, testTdf113271)
 
     assertXPath(pDoc, "/x:styleSheet/x:fonts", "count", "6");
 
-    // Without the fix in place, this test would have failed with
-    // - Expected: FF000000
-    // - Actual  : FFFFFFFF
-    assertXPath(pDoc, "/x:styleSheet/x:fonts/x:font[1]/x:color", "rgb", 
"FF000000");
+    // Expect "theme" attribute to be set correctly
+    assertXPath(pDoc, "/x:styleSheet/x:fonts/x:font[1]/x:color", "theme", "1");
+    // We don't export "rgb" attribute
+    assertXPathNoAttribute(pDoc, "/x:styleSheet/x:fonts/x:font[1]/x:color", 
"rgb");
+    // Just making sure the checked font is the correct one
     assertXPath(pDoc, "/x:styleSheet/x:fonts/x:font[1]/x:name", "val", 
"Calibri");
 }
 
diff --git a/sc/source/filter/excel/xestream.cxx 
b/sc/source/filter/excel/xestream.cxx
index 81e7472ab414..b10e958e04c5 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -64,6 +64,7 @@
 #include <oox/token/relationship.hxx>
 #include <oox/export/drawingml.hxx>
 #include <oox/export/utils.hxx>
+#include <oox/export/ColorExportUtils.hxx>
 #include <formula/grammar.hxx>
 #include <oox/ole/vbaexport.hxx>
 #include <excelvbaproject.hxx>
@@ -884,15 +885,19 @@ sax_fastparser::FSHelperPtr XclXmlUtils::WriteFontData( 
sax_fastparser::FSHelper
         pStream->singleElement(XML_vertAlign, XML_val, pVertAlign);
     pStream->singleElement(XML_sz, XML_val, OString::number( 
rFontData.mnHeight / 20.0 )); // Twips->Pt
 
-    if (rFontData.maComplexColor.getFinalColor() != Color( ColorAlpha, 0, 
0xFF, 0xFF, 0xFF))
+    auto& rComplexColor = rFontData.maComplexColor;
+    if (rComplexColor.isValidSchemeType())
     {
+        sal_Int32 nTheme = 
oox::convertThemeColorTypeToExcelThemeNumber(rComplexColor.getSchemeType());
+        double fTintShade = 
oox::convertColorTransformsToTintOrShade(rComplexColor);
         pStream->singleElement(XML_color,
-                // OOXTODO: XML_auto,       bool
-                // OOXTODO: XML_indexed,    uint
-                XML_rgb, 
XclXmlUtils::ToOString(rFontData.maComplexColor.getFinalColor())
-                // OOXTODO: XML_theme,      index into <clrScheme/>
-                // OOXTODO: XML_tint,       double
-        );
+            XML_theme, OString::number(nTheme),
+            XML_tint, sax_fastparser::UseIf(OString::number(fTintShade), 
fTintShade != 0.0));
+    }
+    else if (rComplexColor.getFinalColor() != Color( ColorAlpha, 0, 0xFF, 
0xFF, 0xFF))
+    {
+        pStream->singleElement(XML_color,
+            XML_rgb, XclXmlUtils::ToOString(rComplexColor.getFinalColor()));
     }
     pStream->singleElement(nFontId, XML_val, rFontData.maName);
     pStream->singleElement(XML_family, XML_val, OString::number(  
rFontData.mnFamily ));
diff --git a/sc/source/filter/excel/xestyle.cxx 
b/sc/source/filter/excel/xestyle.cxx
index 652e5f77a951..87421c525fa2 100644
--- a/sc/source/filter/excel/xestyle.cxx
+++ b/sc/source/filter/excel/xestyle.cxx
@@ -52,6 +52,7 @@
 
 #include <o3tl/safeint.hxx>
 #include <oox/export/utils.hxx>
+#include <oox/export/ColorExportUtils.hxx>
 #include <oox/token/tokens.hxx>
 #include <oox/token/namespaces.hxx>
 #include <oox/token/relationship.hxx>
@@ -1974,18 +1975,26 @@ void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) 
const
 
         if (maForeColor != COL_TRANSPARENT || maBackColor != COL_TRANSPARENT)
         {
-            if (maForegroundComplexColor.getType() == model::ColorType::Scheme)
+            if (maForegroundComplexColor.isValidSchemeType())
             {
-                rStyleSheet->singleElement(XML_fgColor, XML_theme, 
OString::number(sal_Int32(maForegroundComplexColor.getSchemeType())));
+                sal_Int32 nTheme = 
oox::convertThemeColorTypeToExcelThemeNumber(maForegroundComplexColor.getSchemeType());
+                double fTintShade = 
oox::convertColorTransformsToTintOrShade(maForegroundComplexColor);
+                rStyleSheet->singleElement(XML_fgColor,
+                    XML_theme, OString::number(nTheme),
+                    XML_tint, 
sax_fastparser::UseIf(OString::number(fTintShade), fTintShade != 0.0));
             }
             else if (maForeColor != COL_TRANSPARENT)
             {
                 rStyleSheet->singleElement(XML_fgColor, XML_rgb, 
XclXmlUtils::ToOString(maForeColor));
             }
 
-            if (maBackgroundComplexColor.getType() == model::ColorType::Scheme)
+            if (maBackgroundComplexColor.isValidSchemeType())
             {
-                rStyleSheet->singleElement(XML_fgColor, XML_theme, 
OString::number(sal_Int32(maBackgroundComplexColor.getSchemeType())));
+                sal_Int32 nTheme = 
oox::convertThemeColorTypeToExcelThemeNumber(maBackgroundComplexColor.getSchemeType());
+                double fTintShade = 
oox::convertColorTransformsToTintOrShade(maBackgroundComplexColor);
+                rStyleSheet->singleElement(XML_bgColor,
+                    XML_theme, OString::number(nTheme),
+                    XML_tint, 
sax_fastparser::UseIf(OString::number(fTintShade), fTintShade != 0.0));
             }
             else if (maBackColor != COL_TRANSPARENT)
             {
@@ -1994,9 +2003,14 @@ void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) 
const
         }
         else
         {
-            if (maForegroundComplexColor.getType() == model::ColorType::Scheme)
+            if (maForegroundComplexColor.isValidSchemeType())
             {
-                rStyleSheet->singleElement(XML_fgColor, XML_theme, 
OString::number(sal_Int32(maForegroundComplexColor.getSchemeType())));
+                sal_Int32 nTheme = 
oox::convertThemeColorTypeToExcelThemeNumber(maForegroundComplexColor.getSchemeType());
+                double fTintShade = 
oox::convertColorTransformsToTintOrShade(maForegroundComplexColor);
+
+                rStyleSheet->singleElement(XML_fgColor,
+                    XML_theme, OString::number(nTheme),
+                    XML_tint, 
sax_fastparser::UseIf(OString::number(fTintShade), fTintShade != 0.0));
             }
             else if (mnForeColor != 0)
             {
@@ -2005,7 +2019,11 @@ void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) 
const
 
             if (maBackgroundComplexColor.getType() == model::ColorType::Scheme)
             {
-                rStyleSheet->singleElement(XML_fgColor, XML_theme, 
OString::number(sal_Int32(maBackgroundComplexColor.getSchemeType())));
+                sal_Int32 nTheme = 
oox::convertThemeColorTypeToExcelThemeNumber(maBackgroundComplexColor.getSchemeType());
+                double fTintShade = 
oox::convertColorTransformsToTintOrShade(maBackgroundComplexColor);
+                rStyleSheet->singleElement(XML_bgColor,
+                    XML_theme, OString::number(nTheme),
+                    XML_tint, 
sax_fastparser::UseIf(OString::number(fTintShade), fTintShade != 0.0));
             }
             else if (mnBackColor != 0)
             {
@@ -2037,7 +2055,13 @@ void XclExpColor::SaveXml( XclExpXmlStream& rStrm ) const
     rStyleSheet->startElement(XML_fill);
     rStyleSheet->startElement(XML_patternFill);
     if (maComplexColor.getType() == model::ColorType::Scheme)
-        rStyleSheet->singleElement(XML_bgColor, XML_theme, 
OString::number(sal_Int32(maComplexColor.getSchemeType())));
+    {
+        sal_Int32 nTheme = 
oox::convertThemeColorTypeToExcelThemeNumber(maComplexColor.getSchemeType());
+        double fTintShade = 
oox::convertColorTransformsToTintOrShade(maComplexColor);
+        rStyleSheet->singleElement(XML_bgColor,
+                    XML_theme, OString::number(nTheme),
+                    XML_tint, 
sax_fastparser::UseIf(OString::number(fTintShade), fTintShade != 0.0));
+    }
     else
         rStyleSheet->singleElement(XML_bgColor, XML_rgb, 
XclXmlUtils::ToOString(maColor));
 

Reply via email to