sw/source/filter/ww8/docxattributeoutput.cxx          |  162 +++++++++++----
 sw/source/filter/ww8/docxattributeoutput.hxx          |    4 
 sw/source/writerfilter/dmapper/DomainMapper.cxx       |   37 +++
 sw/source/writerfilter/dmapper/TextEffectsHandler.cxx |  190 ++++++++++++++++++
 sw/source/writerfilter/dmapper/TextEffectsHandler.hxx |   16 +
 5 files changed, 365 insertions(+), 44 deletions(-)

New commits:
commit baf179188d8b9e29188387fd4b7d887dd3168792
Author:     Vladislav Tarakanov <vladislav.taraka...@bk.ru>
AuthorDate: Sat Oct 19 00:12:34 2024 +0200
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Sat Oct 19 14:26:23 2024 +0200

    tdf#156333 Adding a tint/shade values to the model
    
    Before implementing text effects from the TextFill tag, their values
    must be directly saved in ComplexColor, without saving in GrabBag.
    To achieve this, DomainMapper has introduced separate processing
    of the LN_textFill_textFill tag using the new TextFillHandler class.
    
    TextFillHandler inherits from TextEffectsHandler. As a parameter in
    the constructor, it receives a reference to the ComplexColor to which
    changes will be added. This is done because some text effects
    (ThemeTint, ThemeShade) can be specified in the <color> tag, so
    TextFill must complement existing transformations. For the same
    reason, when processing LN_EG_RPrBase_color, the ComplexColor
    value is taken from the context if it was placed there previously.
    
    In docx export, existing "Tint" and "Shade" transformations are
    preserved only in <color ThemeTint=...> and <color ThemeShade=...>.
    Because the Tint and Shade values from TextFill must be
    distinguished from the values from color during export, the "Tint"
    and "Shade" transforms have been renamed to "ThemeTint" and
    "ThemeShade". Also added new "Tint" and "Shade" transformations,
    which are currently only saved in TextFill.
    
    Change-Id: I0ebba53eba83ccfc99fa812e60d6cebb2ff6bf0f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157979
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 295c043e3cb9..5d375603e210 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -298,44 +298,50 @@ 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" }
+});
+
+OString lclGetSchemeType(model::ComplexColor const& rComplexColor)
+{
+    const auto iter = 
constThemeColorTypeTokenMap.find(rComplexColor.getThemeColorType());
+    assert(iter != constThemeColorTypeTokenMap.end());
+    OString sSchemeType = iter->second;
+    if (rComplexColor.getThemeColorUsage() == model::ThemeColorUsage::Text)
+    {
+        if (rComplexColor.getThemeColorType() == model::ThemeColorType::Dark1)
+            sSchemeType = "text1"_ostr;
+        else if (rComplexColor.getThemeColorType() == 
model::ThemeColorType::Dark2)
+            sSchemeType = "text2"_ostr;
+    }
+    else if (rComplexColor.getThemeColorUsage() == 
model::ThemeColorUsage::Background)
+    {
+        if (rComplexColor.getThemeColorType() == model::ThemeColorType::Light1)
+            sSchemeType = "background1"_ostr;
+        else if (rComplexColor.getThemeColorType() == 
model::ThemeColorType::Light2)
+            sSchemeType = "background2"_ostr;
+    }
+    return sSchemeType;
+}
+
 void lclAddThemeValuesToCustomAttributes(
     rtl::Reference<sax_fastparser::FastAttributeList>& pAttrList, 
model::ComplexColor const& rComplexColor,
     sal_Int32 nThemeAttrId, sal_Int32 nThemeTintAttrId, sal_Int32 
nThemeShadeAttrId)
 {
-    static 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" }
-    });
-
     if (rComplexColor.isValidThemeType())
     {
-        const auto iter = 
constThemeColorTypeTokenMap.find(rComplexColor.getThemeColorType());
-        assert(iter != constThemeColorTypeTokenMap.end());
-        OString sSchemeType = iter->second;
-        if (rComplexColor.getThemeColorUsage() == model::ThemeColorUsage::Text)
-        {
-            if (rComplexColor.getThemeColorType() == 
model::ThemeColorType::Dark1)
-                sSchemeType = "text1"_ostr;
-            else if (rComplexColor.getThemeColorType() == 
model::ThemeColorType::Dark2)
-                sSchemeType = "text2"_ostr;
-        }
-        else if (rComplexColor.getThemeColorUsage() == 
model::ThemeColorUsage::Background)
-        {
-            if (rComplexColor.getThemeColorType() == 
model::ThemeColorType::Light1)
-                sSchemeType = "background1"_ostr;
-            else if (rComplexColor.getThemeColorType() == 
model::ThemeColorType::Light2)
-                sSchemeType = "background2"_ostr;
-        }
+        OString sSchemeType = lclGetSchemeType(rComplexColor);
 
         DocxAttributeOutput::AddToAttrList(pAttrList, FSNS(XML_w, 
nThemeAttrId), sSchemeType);
 
@@ -400,6 +406,15 @@ void 
lclAddThemeColorAttributes(rtl::Reference<sax_fastparser::FastAttributeList
     lclAddThemeValuesToCustomAttributes(pAttrList, rComplexColor, 
XML_themeColor, XML_themeTint, XML_themeShade);
 }
 
+bool lclHasSolidFillTransformations(const model::ComplexColor& aComplexColor)
+{
+    const std::vector<model::Transformation>& transformations = 
aComplexColor.getTransformations();
+    auto idx = std::find_if(transformations.begin(), transformations.end(), 
[](const model::Transformation& transformation) {
+        return transformation.meType != model::TransformationType::Shade && 
transformation.meType != model::TransformationType::Tint;
+    });
+    return idx != transformations.end();
+}
+
 } // end anonymous namespace
 
 void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 /*nScript*/ )
@@ -3516,7 +3531,18 @@ void lclProcessRecursiveGrabBag(sal_Int32 aElementId, 
const css::uno::Sequence<c
     pSerializer->endElement(aElementId);
 }
 
-}
+constexpr auto constTransformationToTokenId = 
frozen::make_unordered_map<model::TransformationType, sal_Int32>({
+    { model::TransformationType::Tint, XML_tint },
+    { model::TransformationType::Shade, XML_shade },
+    { model::TransformationType::Sat, XML_sat },
+    { model::TransformationType::SatOff, XML_satOff },
+    { model::TransformationType::SatMod, XML_satMod },
+    { model::TransformationType::Lum, XML_lum },
+    { model::TransformationType::LumOff, XML_lumOff },
+    { model::TransformationType::LumMod, XML_lumMod },
+});
+
+} // end anonymous namepsace
 
 void DocxAttributeOutput::WriteCollectedRunProperties()
 {
@@ -3542,35 +3568,81 @@ void DocxAttributeOutput::WriteCollectedRunProperties()
         m_pSerializer->singleElementNS( XML_w, XML_lang, detachFrom( 
m_pCharLangAttrList ) );
     }
 
-    if (m_nCharTransparence != 0 && m_pColorAttrList && 
m_aTextEffectsGrabBag.empty())
+    if ((m_nCharTransparence != 0 || 
lclHasSolidFillTransformations(m_aComplexColor))
+            && m_pColorAttrList.is()
+            && m_aTextFillGrabBag.empty())
     {
         std::string_view pVal;
         m_pColorAttrList->getAsView(FSNS(XML_w, XML_val), pVal);
+
         if (!pVal.empty() && pVal != "auto")
         {
             m_pSerializer->startElementNS(XML_w14, XML_textFill);
             m_pSerializer->startElementNS(XML_w14, XML_solidFill);
-            m_pSerializer->startElementNS(XML_w14, XML_srgbClr, FSNS(XML_w14, 
XML_val), pVal.data());
-            sal_Int32 nTransparence = m_nCharTransparence * 
oox::drawingml::MAX_PERCENT / 255.0;
-            m_pSerializer->singleElementNS(XML_w14, XML_alpha, FSNS(XML_w14, 
XML_val), OString::number(nTransparence));
-            m_pSerializer->endElementNS(XML_w14, XML_srgbClr);
+
+            if (m_aComplexColor.isValidThemeType())
+            {
+                OString sSchemeType = lclGetSchemeType(m_aComplexColor);
+                m_pSerializer->startElementNS(XML_w14, XML_schemeClr, 
FSNS(XML_w14, XML_val), sSchemeType);
+            }
+            else
+            {
+                m_pSerializer->startElementNS(XML_w14, XML_srgbClr, 
FSNS(XML_w14, XML_val), pVal.data());
+            }
+
+            if (m_nCharTransparence != 0)
+            {
+                sal_Int32 nTransparence = basegfx::fround(m_nCharTransparence 
/ 255.0 * 100.0) * oox::drawingml::PER_PERCENT;
+                m_pSerializer->singleElementNS(XML_w14, XML_alpha, 
FSNS(XML_w14, XML_val), OString::number(nTransparence));
+            }
+
+            for (const model::Transformation & transformation : 
m_aComplexColor.getTransformations())
+            {
+                sal_Int32 nValue = transformation.mnValue * 
drawingml::PER_PERCENT;
+                const auto iter = 
constTransformationToTokenId.find(transformation.meType);
+                if (iter != constTransformationToTokenId.end())
+                {
+                    sal_Int32 nElement = iter->second;
+                    m_pSerializer->singleElementNS(XML_w14, nElement, 
FSNS(XML_w14, XML_val), OString::number(nValue));
+                }
+            }
+
+            if (m_aComplexColor.isValidThemeType())
+            {
+                m_pSerializer->endElementNS(XML_w14, XML_schemeClr);
+            }
+            else
+            {
+                m_pSerializer->endElementNS(XML_w14, XML_srgbClr);
+            }
             m_pSerializer->endElementNS(XML_w14, XML_solidFill);
             m_pSerializer->endElementNS(XML_w14, XML_textFill);
             m_nCharTransparence = 0;
         }
     }
     m_pColorAttrList.clear();
-    for (const beans::PropertyValue & i : m_aTextEffectsGrabBag)
+
+    auto processGrabBag = [this](const beans::PropertyValue& prop)
     {
-        std::optional<sal_Int32> aElementId = lclGetElementIdForName(i.Name);
+        std::optional<sal_Int32> aElementId = 
lclGetElementIdForName(prop.Name);
         if(aElementId)
         {
             uno::Sequence<beans::PropertyValue> aGrabBagSeq;
-            i.Value >>= aGrabBagSeq;
+            prop.Value >>= aGrabBagSeq;
             lclProcessRecursiveGrabBag(*aElementId, aGrabBagSeq, 
m_pSerializer);
         }
+    };
+
+    for (const beans::PropertyValue & i : m_aTextEffectsGrabBag)
+    {
+        processGrabBag(i);
+    }
+    for (const beans::PropertyValue & i : m_aTextFillGrabBag)
+    {
+        processGrabBag(i);
     }
     m_aTextEffectsGrabBag.clear();
+    m_aTextFillGrabBag.clear();
 }
 
 void DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
@@ -7830,6 +7902,7 @@ void DocxAttributeOutput::CharColor(const SvxColorItem& 
rColorItem)
 
     AddToAttrList(m_pColorAttrList, FSNS(XML_w, XML_val), aColorString);
     m_nCharTransparence = 255 - aColor.GetAlpha();
+    m_aComplexColor = aComplexColor;
 }
 
 void DocxAttributeOutput::CharContour( const SvxContourItem& rContour )
@@ -10199,7 +10272,6 @@ void DocxAttributeOutput::CharGrabBag( const 
SfxGrabBagItem& rItem )
                 rGrabBagElement.first == "CharShadowTextEffect" ||
                 rGrabBagElement.first == "CharReflectionTextEffect" ||
                 rGrabBagElement.first == "CharTextOutlineTextEffect" ||
-                rGrabBagElement.first == "CharTextFillTextEffect" ||
                 rGrabBagElement.first == "CharScene3DTextEffect" ||
                 rGrabBagElement.first == "CharProps3DTextEffect" ||
                 rGrabBagElement.first == "CharLigaturesTextEffect" ||
@@ -10212,6 +10284,12 @@ void DocxAttributeOutput::CharGrabBag( const 
SfxGrabBagItem& rItem )
             rGrabBagElement.second >>= aPropertyValue;
             m_aTextEffectsGrabBag.push_back(aPropertyValue);
         }
+        else if (rGrabBagElement.first == "CharTextFillTextEffect")
+        {
+            beans::PropertyValue aPropertyValue;
+            rGrabBagElement.second >>= aPropertyValue;
+            m_aTextFillGrabBag.push_back(aPropertyValue);
+        }
         else if (rGrabBagElement.first == "SdtEndBefore")
         {
             if (m_aRunSdt.m_bStartedSdt)
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx 
b/sw/source/filter/ww8/docxattributeoutput.hxx
index 1dd29a81dbe8..c6626051f332 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -836,6 +836,7 @@ private:
     /// Attributes of the run color
     rtl::Reference<sax_fastparser::FastAttributeList> m_pColorAttrList;
     sal_uInt8 m_nCharTransparence = 0;
+    model::ComplexColor m_aComplexColor;
     /// Attributes of the paragraph background
     rtl::Reference<sax_fastparser::FastAttributeList> m_pBackgroundAttrList;
     OUString m_sOriginalBackgroundColor;
@@ -931,6 +932,9 @@ private:
     /// GrabBag for text effects like glow, shadow, ...
     std::vector<css::beans::PropertyValue> m_aTextEffectsGrabBag;
 
+    /// GrabBag for text fill effects
+    std::vector<css::beans::PropertyValue> m_aTextFillGrabBag;
+
     /// The current table helper
     std::unique_ptr<SwWriteTable> m_xTableWrt;
 
diff --git a/sw/source/writerfilter/dmapper/DomainMapper.cxx 
b/sw/source/writerfilter/dmapper/DomainMapper.cxx
index b03ef9364cfe..5d4a0c3b5c14 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper.cxx
@@ -2373,6 +2373,11 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
             {
                 m_pImpl->GetTopContext()->Insert(PROP_CHAR_COLOR, 
uno::Any(pThemeColorHandler->mnColor));
 
+                // ComplexColor can be set in LN_textFill_textFill which has 
priority
+                auto aAnyComplexColor = 
m_pImpl->GetTopContext()->getProperty(PROP_CHAR_COMPLEX_COLOR);
+                if (aAnyComplexColor.has_value())
+                    return;
+
                 auto eType = 
TDefTableHandler::getThemeColorTypeIndex(pThemeColorHandler->mnIndex);
                 if (eType != model::ThemeColorType::Unknown)
                 {
@@ -3435,11 +3440,41 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
     case NS_ooxml::LN_tcEnd:
         m_pImpl->m_StreamStateStack.top().nTableCellDepth--;
     break;
+    case NS_ooxml::LN_textFill_textFill:
+    {
+        model::ComplexColor aComplexColor;
+        tools::SvRef<TextFillHandler> pHandlerPtr(new TextFillHandler(nSprmId, 
aComplexColor));
+        std::optional<PropertyIds> aPropertyId = 
pHandlerPtr->getGrabBagPropertyId();
+        if (aPropertyId)
+        {
+            writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+            pProperties->resolve(*pHandlerPtr);
+            // Saving a ComplexColor (w14:solidFill) in context
+            auto xComplexColor = 
model::color::createXComplexColor(aComplexColor);
+            rContext->Insert(PROP_CHAR_COMPLEX_COLOR, uno::Any(xComplexColor));
+            beans::PropertyValue aGrabBag = pHandlerPtr->getInteropGrabBag();
+
+            for (auto const& transform : aComplexColor.getTransformations())
+            {
+                if (transform.meType == model::TransformationType::Alpha)
+                {
+                    sal_Int16 nTransparency = transform.mnValue;
+                    rContext->Insert(PROP_CHAR_TRANSPARENCE, 
uno::Any(nTransparency));
+                }
+            }
+
+            if (!pHandlerPtr->mbIsHandled)
+            {
+                rContext->Insert(*aPropertyId, uno::Any(aGrabBag), true, 
CHAR_GRAB_BAG);
+            }
+        }
+    }
+    break;
+
     case NS_ooxml::LN_glow_glow:
     case NS_ooxml::LN_shadow_shadow:
     case NS_ooxml::LN_reflection_reflection:
     case NS_ooxml::LN_textOutline_textOutline:
-    case NS_ooxml::LN_textFill_textFill:
     case NS_ooxml::LN_scene3d_scene3d:
     case NS_ooxml::LN_props3d_props3d:
     case NS_ooxml::LN_ligatures_ligatures:
diff --git a/sw/source/writerfilter/dmapper/TextEffectsHandler.cxx 
b/sw/source/writerfilter/dmapper/TextEffectsHandler.cxx
index 6988ea593974..38fddf9ce006 100644
--- a/sw/source/writerfilter/dmapper/TextEffectsHandler.cxx
+++ b/sw/source/writerfilter/dmapper/TextEffectsHandler.cxx
@@ -19,6 +19,11 @@
 #include <ooxml/resourceids.hxx>
 #include <comphelper/sequenceashashmap.hxx>
 #include <oox/drawingml/drawingmltypes.hxx>
+#include <oox/drawingml/color.hxx>
+
+#include <frozen/bits/defines.h>
+#include <frozen/bits/elsa_std.h>
+#include <frozen/unordered_map.h>
 
 namespace writerfilter::dmapper
 {
@@ -73,6 +78,43 @@ OUString lclGetNameForElementId(sal_uInt32 aId)
 
 constexpr OUString constAttributesSequenceName = u"attributes"_ustr;
 
+constexpr auto constThemeTypeMap = 
frozen::make_unordered_map<std::u16string_view, model::ThemeColorType>({
+    { u"dk1", model::ThemeColorType::Dark1 },
+    { u"lt1", model::ThemeColorType::Light1 },
+    { u"dk2", model::ThemeColorType::Dark2 },
+    { u"lt2", model::ThemeColorType::Light2 },
+    { u"accent1", model::ThemeColorType::Accent1 },
+    { u"accent2", model::ThemeColorType::Accent2 },
+    { u"accent3", model::ThemeColorType::Accent3 },
+    { u"accent4", model::ThemeColorType::Accent4 },
+    { u"accent5", model::ThemeColorType::Accent5 },
+    { u"accent6", model::ThemeColorType::Accent6 },
+    { u"hlink", model::ThemeColorType::Hyperlink },
+    { u"folHlink", model::ThemeColorType::FollowedHyperlink },
+    { u"tx1", model::ThemeColorType::Dark1 },
+    { u"bg1", model::ThemeColorType::Light1 },
+    { u"tx2", model::ThemeColorType::Dark2 },
+    { u"bg2", model::ThemeColorType::Light2 },
+    { u"dark1", model::ThemeColorType::Dark1},
+    { u"light1", model::ThemeColorType::Light1},
+    { u"dark2", model::ThemeColorType::Dark2 },
+    { u"light2", model::ThemeColorType::Light2 },
+    { u"text1", model::ThemeColorType::Dark1 },
+    { u"background1", model::ThemeColorType::Light1 },
+    { u"text2", model::ThemeColorType::Dark2 },
+    { u"background2", model::ThemeColorType::Light2 },
+    { u"hyperlink", model::ThemeColorType::Hyperlink },
+    { u"followedHyperlink", model::ThemeColorType::FollowedHyperlink }
+});
+
+model::ThemeColorType lclGetThemeTypeByName(const OUString& name)
+{
+    auto it = constThemeTypeMap.find(name);
+    if (it == constThemeTypeMap.end())
+        return model::ThemeColorType::Unknown;
+    return it->second;
+}
+
 }
 
 OUString TextEffectsHandler::getSchemeColorValTypeString(sal_Int32 nType)
@@ -801,6 +843,154 @@ sal_uInt8 
TextEffectsHandler::GetTextFillSolidFillAlpha(const css::beans::Proper
     return nVal / oox::drawingml::PER_PERCENT;
 }
 
+TextFillHandler::TextFillHandler(sal_uInt32 aElementId, model::ComplexColor& 
aComplexColor)
+    : TextEffectsHandler(aElementId)
+    , maComplexColor(aComplexColor)
+    , mbIsHandled(false)
+{
+}
+
+void TextFillHandler::lcl_sprm(Sprm &rSprm)
+{
+    if (mpGrabBagStack->getCurrentName() == constAttributesSequenceName)
+        mpGrabBagStack->pop();
+    sal_uInt32 nSprmId = rSprm.getId();
+    OUString aElementName = lclGetNameForElementId(nSprmId);
+    if(aElementName.isEmpty())
+    {
+        // Element is unknown -> leave.
+        return;
+    }
+    switch (nSprmId)
+    {
+        case NS_ooxml::LN_EG_FillProperties_solidFill:
+        {
+            mbIsHandled = true;
+            writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+            if( !pProperties )
+                return;
+            tools::SvRef<TextFillHandler> pTextEffectsHandlerPtr( new 
TextFillHandler(nSprmId, maComplexColor) );
+            pProperties->resolve( *pTextEffectsHandlerPtr );
+            pTextEffectsHandlerPtr->updateComplexColor();
+        }
+        break;
+        default:
+        {
+            mpGrabBagStack->push(aElementName);
+            writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+            if( !pProperties )
+                return;
+            pProperties->resolve( *this );
+            if (mpGrabBagStack->getCurrentName() == 
constAttributesSequenceName)
+                mpGrabBagStack->pop();
+            mpGrabBagStack->pop();
+        }
+    }
+}
+
+void TextFillHandler::updateComplexColor()
+{
+    auto getValue = [](const comphelper::SequenceAsHashMap& root)
+    {
+        auto it = root.find("attributes");
+        if (it == root.end())
+        {
+            return static_cast<sal_Int32>(0);
+        }
+        comphelper::SequenceAsHashMap aAttributesMap(it->second);
+        it = aAttributesMap.find("val");
+        if (it == aAttributesMap.end())
+        {
+            return static_cast<sal_Int32>(0);
+        }
+        sal_Int32 nVal = 0;
+        it->second >>= nVal;
+        return nVal;
+    };
+    auto fillProps = getInteropGrabBag();
+    uno::Sequence<beans::PropertyValue> aPropertyValues;
+    fillProps.Value >>= aPropertyValues;
+    comphelper::SequenceAsHashMap aSolidFillMap(aPropertyValues);
+    auto it = aSolidFillMap.find("srgbClr");
+    if (it == aSolidFillMap.end())
+    {
+        it = aSolidFillMap.find("schemeClr");
+        if (it == aSolidFillMap.end())
+        {
+            return;
+        }
+        else
+        {
+            oox::drawingml::Color clr;
+            comphelper::SequenceAsHashMap aSchemeClrMap(it->second);
+            auto schemeIt = aSchemeClrMap.find("attributes");
+            if (schemeIt != aSchemeClrMap.end())
+            {
+                comphelper::SequenceAsHashMap aAttributesMap(schemeIt->second);
+                schemeIt = aAttributesMap.find("val");
+                if (schemeIt != aAttributesMap.end())
+                {
+                    OUString name;
+                    schemeIt->second >>= name;
+                    if (name.getLength() > 0)
+                    {
+                        
maComplexColor.setThemeColor(lclGetThemeTypeByName(name));
+                    }
+                }
+            }
+        }
+    }
+    comphelper::SequenceAsHashMap aSrgbClrMap(it->second);
+    for (auto const& prop : aSrgbClrMap)
+    {
+        if (prop.first.maString == "alpha")
+        {
+            sal_Int16 nAlpha = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            
maComplexColor.addTransformation({model::TransformationType::Alpha, nAlpha});
+        }
+        else if (prop.first.maString == "tint")
+        {
+            sal_Int16 nTint = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            maComplexColor.addTransformation({model::TransformationType::Tint, 
nTint});
+        }
+        else if (prop.first.maString == "shade")
+        {
+            sal_Int16 nShade = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            
maComplexColor.addTransformation({model::TransformationType::Shade, nShade});
+        }
+        else if (prop.first.maString == "sat")
+        {
+            sal_Int16 nSat = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            maComplexColor.addTransformation({model::TransformationType::Sat, 
nSat});
+        }
+        else if (prop.first.maString == "satOff")
+        {
+            sal_Int16 nSatOff = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            
maComplexColor.addTransformation({model::TransformationType::SatOff, nSatOff});
+        }
+        else if (prop.first.maString == "satMod")
+        {
+            sal_Int16 nSatMod = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            
maComplexColor.addTransformation({model::TransformationType::SatMod, nSatMod});
+        }
+        else if (prop.first.maString == "lum")
+        {
+            sal_Int16 nLum = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            maComplexColor.addTransformation({model::TransformationType::Lum, 
nLum});
+        }
+        else if (prop.first.maString == "lumOff")
+        {
+            sal_Int16 nLumOff = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            
maComplexColor.addTransformation({model::TransformationType::LumOff, nLumOff});
+        }
+        else if (prop.first.maString == "lumMod")
+        {
+            sal_Int16 nLumMod = static_cast<sal_Int16>(getValue(prop.second) / 
oox::drawingml::PER_PERCENT);
+            
maComplexColor.addTransformation({model::TransformationType::LumMod, nLumMod});
+        }
+    }
+}
+
 } // namespace
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/writerfilter/dmapper/TextEffectsHandler.hxx 
b/sw/source/writerfilter/dmapper/TextEffectsHandler.hxx
index f442745e5aeb..e64c2a403434 100644
--- a/sw/source/writerfilter/dmapper/TextEffectsHandler.hxx
+++ b/sw/source/writerfilter/dmapper/TextEffectsHandler.hxx
@@ -14,6 +14,8 @@
 
 #include <com/sun/star/beans/PropertyValue.hpp>
 
+#include <docmodel/color/ComplexColor.hxx>
+
 #include "PropertyIds.hxx"
 
 #include <oox/helper/grabbagstack.hxx>
@@ -26,7 +28,7 @@ namespace writerfilter::dmapper
 /// Class to process all text effects like glow, textOutline, ...
 class TextEffectsHandler : public LoggedProperties
 {
-private:
+protected:
     std::optional<PropertyIds> maPropertyId;
     OUString maElementName;
     std::unique_ptr<oox::GrabBagStack> mpGrabBagStack;
@@ -64,6 +66,18 @@ public:
     virtual void lcl_attribute(Id aName, const Value& aValue) override;
     virtual void lcl_sprm(Sprm& sprm) override;
 };
+
+class TextFillHandler : public TextEffectsHandler
+{
+    void updateComplexColor();
+    model::ComplexColor& maComplexColor;
+
+public:
+    bool mbIsHandled;
+    TextFillHandler(sal_uInt32 aElementId, model::ComplexColor& aComplexColor);
+    // LoggedProperties
+    virtual void lcl_sprm(Sprm& rSprm) override;
+};
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to