sw/qa/extras/ooxmlexport/data/tdf158044.odt       |binary
 sw/qa/extras/ooxmlexport/ooxmlexport20.cxx        |   34 ++++
 sw/qa/extras/ooxmlimport/data/tdf154370.docx      |binary
 sw/qa/extras/ooxmlimport/ooxmlimport2.cxx         |   77 ++++++++++
 sw/source/filter/ww8/wrtw8nds.cxx                 |  152 +++++++++++++++++---
 sw/source/filter/ww8/wrtww8.hxx                   |    2 
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |  160 +++++++++++++++++++++-
 writerfilter/source/dmapper/DomainMapper_Impl.hxx |    4 
 8 files changed, 403 insertions(+), 26 deletions(-)

New commits:
commit 9e127010a86b3521c803ac86c0b5f58dc8e2966b
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Tue Dec 5 13:28:36 2023 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Tue Dec 19 20:53:12 2023 +0100

    tdf#158044 writerfilter: handle toggle properties in import/export
    
    DOCX has some odd properties (bold, italic, shadowed, hidden ...),
    which switch on/off if they are applied multiple times, e.g. with
    paragraph and character styles. To fix that, a hard attribute has to
    switch off the attribute in that occasion on import and on export a
    hard attribute switches it on in Word.
    
    Includes partial fix for tdf#154370.
    
    Change-Id: Ie4c317cf9b7d02efd89b9d6a9996143585d7e937
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160343
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf158044.odt 
b/sw/qa/extras/ooxmlexport/data/tdf158044.odt
new file mode 100755
index 000000000000..ca17b6625674
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf158044.odt differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport20.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport20.cxx
index fb780b983bb2..191497cce760 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport20.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport20.cxx
@@ -1006,6 +1006,40 @@ CPPUNIT_TEST_FIXTURE(Test, testSvgExtensionsSupport)
     assertXPath(pXmlDocContent, aPath + "/a:extLst/a:ext/asvg:svgBlip"_ostr, 
"embed"_ostr, "rId3");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testtdf158044)
+{
+    loadAndSave("tdf158044.odt");
+    // write hard attributes to prevent multiple toggle attributes from 
vanishing
+    xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
+
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:rStyle[1]"_ostr, "val"_ostr,
+                "BoldItalicCapsEmbossedStrike");
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:b[1]"_ostr);
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:bCs[1]"_ostr);
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:i[1]"_ostr);
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:iCs[1]"_ostr);
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:strike[1]"_ostr);
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:emboss[1]"_ostr);
+
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[3]/w:r[4]/w:rPr[1]/w:rStyle[1]"_ostr, "val"_ostr,
+                "SmallcapsImprint");
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[3]/w:r[4]/w:rPr[1]/w:imprint[1]"_ostr);
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[3]/w:r[4]/w:rPr[1]/w:smallCaps[1]"_ostr);
+
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[4]/w:r[2]/w:rPr[1]/w:rStyle[1]"_ostr, "val"_ostr,
+                "AllCaps");
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[4]/w:r[2]/w:rPr[1]/w:caps[1]"_ostr);
+
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[6]/w:r[2]/w:rPr[1]/w:rStyle[1]"_ostr, "val"_ostr,
+                "Hidden");
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[6]/w:r[2]/w:rPr[1]/w:vanish[1]"_ostr);
+
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[8]/w:r[4]/w:rPr[1]/w:rStyle[1]"_ostr, "val"_ostr,
+                "OutlineShadow");
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[8]/w:r[4]/w:rPr[1]/w:outline[1]"_ostr);
+    assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[8]/w:r[4]/w:rPr[1]/w:shadow[1]"_ostr);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/ooxmlimport/data/tdf154370.docx 
b/sw/qa/extras/ooxmlimport/data/tdf154370.docx
new file mode 100755
index 000000000000..ba72724593b2
Binary files /dev/null and b/sw/qa/extras/ooxmlimport/data/tdf154370.docx differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx 
b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index 553fbebbc6e3..0c29484d765e 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -1188,6 +1188,83 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf141969)
     CPPUNIT_ASSERT_EQUAL(8.0f, getProperty<float>(xRun, "CharHeight"));
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf154370)
+{
+    // Import a file with pargraph and character styles containing toggle 
properties applied to the end of
+    // the paragraphs. Should result in hard attributes resetting the 
properties
+    createSwDoc("tdf154370.docx");
+    {
+        auto xPara(getParagraph(2));
+        auto xRun = getRun(xPara, 2);
+
+        OUString rangeText = xRun->getString();
+        CPPUNIT_ASSERT_EQUAL(OUString("CharStyle 
BoldItalicCapsEmbossedStrike"), rangeText);
+
+        const uno::Reference<beans::XPropertyState> xRangePropState(xRun, 
uno::UNO_QUERY_THROW);
+        beans::PropertyState ePropertyState = 
xRangePropState->getPropertyState("CharWeight");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = 
xRangePropState->getPropertyState("CharWeightComplex");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = xRangePropState->getPropertyState("CharWeightAsian");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = xRangePropState->getPropertyState("CharPosture");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = xRangePropState->getPropertyState("CharPostureAsian");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = xRangePropState->getPropertyState("CharCaseMap");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = xRangePropState->getPropertyState("CharRelief");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = xRangePropState->getPropertyState("CharStrikeout");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+    }
+    {
+        auto xPara(getParagraph(3));
+        auto xRun = getRun(xPara, 2);
+
+        OUString rangeText = xRun->getString();
+        CPPUNIT_ASSERT_EQUAL(OUString("CharStyle SmallcapsImprint"), 
rangeText);
+
+        const uno::Reference<beans::XPropertyState> xRangePropState(xRun, 
uno::UNO_QUERY_THROW);
+        beans::PropertyState ePropertyState = 
xRangePropState->getPropertyState("CharCaseMap");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = xRangePropState->getPropertyState("CharRelief");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+    }
+    {
+        auto xPara(getParagraph(5));
+        auto xRun = getRun(xPara, 2);
+
+        OUString rangeText = xRun->getString();
+        CPPUNIT_ASSERT_EQUAL(OUString("CharStyle Hidden"), rangeText);
+
+        const uno::Reference<beans::XPropertyState> xRangePropState(xRun, 
uno::UNO_QUERY_THROW);
+        beans::PropertyState ePropertyState = 
xRangePropState->getPropertyState("CharHidden");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+    }
+    {
+        auto xPara(getParagraph(7));
+        auto xRun = getRun(xPara, 2);
+
+        OUString rangeText = xRun->getString();
+        CPPUNIT_ASSERT_EQUAL(OUString("OutlineShadow"), rangeText);
+
+        const uno::Reference<beans::XPropertyState> xRangePropState(xRun, 
uno::UNO_QUERY_THROW);
+        beans::PropertyState ePropertyState = 
xRangePropState->getPropertyState("CharContoured");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+
+        ePropertyState = xRangePropState->getPropertyState("CharShadowed");
+        CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, 
ePropertyState);
+    }
+}
 // tests should only be added to ooxmlIMPORT *if* they fail round-tripping in 
ooxmlEXPORT
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx 
b/sw/source/filter/ww8/wrtw8nds.cxx
index 74e53d2fec0b..c70c78121b8b 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -33,12 +33,18 @@
 #include <editeng/svxfont.hxx>
 #include <editeng/lrspitem.hxx>
 #include <editeng/brushitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/crossedoutitem.hxx>
 #include <editeng/fontitem.hxx>
 #include <editeng/keepitem.hxx>
 #include <editeng/fhgtitem.hxx>
 #include <editeng/ulspitem.hxx>
 #include <editeng/formatbreakitem.hxx>
 #include <editeng/frmdiritem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/shdditem.hxx>
 #include <editeng/tstpitem.hxx>
 #include <editeng/wghtitem.hxx>
 #include <svl/grabbagitem.hxx>
@@ -77,11 +83,14 @@
 #include <txtatr.hxx>
 #include <cellatr.hxx>
 #include <fmtrowsplt.hxx>
+#include <com/sun/star/awt/FontRelief.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
 #include <com/sun/star/drawing/XShape.hpp>
 #include <com/sun/star/i18n/BreakIterator.hpp>
 #include <com/sun/star/i18n/ScriptType.hpp>
 #include <com/sun/star/i18n/WordType.hpp>
 #include <com/sun/star/text/RubyPosition.hpp>
+#include <com/sun/star/style/CaseMap.hpp>
 #include <oox/export/vmlexport.hxx>
 #include <sal/log.hxx>
 #include <comphelper/propertysequence.hxx>
@@ -479,9 +488,9 @@ void SwWW8AttrIter::OutAttr(sal_Int32 nSwPos, bool 
bWriteCombChars)
         ClearOverridesFromSet( *pCharFormatItem, aExportSet );
 
     // check toggle properties in DOCX output
+    if (pCharFormatItem)
     {
-        SvxWeightItem aBoldProperty(WEIGHT_BOLD, RES_CHRATR_WEIGHT);
-        handleToggleProperty(aExportSet, pCharFormatItem, RES_CHRATR_WEIGHT, 
&aBoldProperty);
+        handleToggleProperty(aExportSet, *pCharFormatItem);
     }
 
     // tdf#113790: AutoFormat style overwrites char style, so remove all
@@ -558,29 +567,82 @@ void SwWW8AttrIter::OutAttr(sal_Int32 nSwPos, bool 
bWriteCombChars)
 // i.e., the effective value to be applied to the content shall be true if its 
effective value is true for
 // an odd number of levels of the style hierarchy.
 //
-// To prevent such logic inside output, it is required to write inline w:b 
token on content level.
-void SwWW8AttrIter::handleToggleProperty(SfxItemSet& rExportSet, const 
SwFormatCharFormat* pCharFormatItem,
-    sal_uInt16 nWhich, const SfxPoolItem* pValue)
-{
-    if (rExportSet.HasItem(nWhich) || !pValue)
+// To prevent such logic inside output, it is required to write inline 
attribute tokens on content level.
+void SwWW8AttrIter::handleToggleProperty(SfxItemSet& rExportSet, const 
SwFormatCharFormat& rCharFormatItem)
+{
+    if (rExportSet.HasItem(RES_CHRATR_WEIGHT) || 
rExportSet.HasItem(RES_CHRATR_POSTURE)  ||
+        rExportSet.HasItem(RES_CHRATR_CTL_WEIGHT) || 
rExportSet.HasItem(RES_CHRATR_CTL_POSTURE)  ||
+        rExportSet.HasItem(RES_CHRATR_CONTOUR) || 
rExportSet.HasItem(RES_CHRATR_CASEMAP) ||
+        rExportSet.HasItem(RES_CHRATR_RELIEF) || 
rExportSet.HasItem(RES_CHRATR_SHADOWED) ||
+        rExportSet.HasItem(RES_CHRATR_CROSSEDOUT) || 
rExportSet.HasItem(RES_CHRATR_HIDDEN))
         return;
 
-    bool hasPropertyInCharStyle = false;
-    bool hasPropertyInParaStyle = false;
+    SvxWeightItem aBoldProperty(WEIGHT_BOLD, RES_CHRATR_WEIGHT);
+    SvxPostureItem aPostureProperty(ITALIC_NORMAL, RES_CHRATR_POSTURE);
+    SvxContourItem aContouredProperty(true, RES_CHRATR_CONTOUR);
+    SvxCaseMapItem aCaseMapCapsProperty(SvxCaseMap::Uppercase, 
RES_CHRATR_CASEMAP);
+    SvxCaseMapItem aCaseMapSmallProperty(SvxCaseMap::SmallCaps, 
RES_CHRATR_CASEMAP);
+    SvxCharReliefItem aEmbossedProperty(FontRelief::Embossed, 
RES_CHRATR_RELIEF);
+    SvxCharReliefItem aImprintProperty(FontRelief::Engraved, 
RES_CHRATR_RELIEF);
+    SvxShadowedItem aShadowedProperty(true, RES_CHRATR_SHADOWED);
+    SvxCrossedOutItem aStrikeoutProperty(STRIKEOUT_SINGLE, 
RES_CHRATR_CROSSEDOUT);
+    SvxCharHiddenItem aHiddenProperty(true, RES_CHRATR_HIDDEN);
 
-    // get bold flag from specified character style
-    if (pCharFormatItem)
+    bool hasWeightPropertyInCharStyle = false;
+    bool hasWeightComplexPropertyInCharStyle = false;
+    bool hasPosturePropertyInCharStyle = false;
+    bool hasPostureComplexPropertyInCharStyle = false;
+    bool bHasCapsPropertyInCharStyle = false;
+    bool bHasSmallCapsPropertyInCharStyle = false;
+    bool bHasEmbossedPropertyInCharStyle = false;
+    bool bHasImprintPropertyInCharStyle = false;
+    bool hasContouredPropertyInCharStyle = false;
+    bool hasShadowedPropertyInCharStyle = false;
+    bool hasStrikeoutPropertyInCharStyle = false;
+    bool hasHiddenPropertyInCharStyle = false;
+
+
+    // get attribute flags from specified character style
+    if (const SwCharFormat* pCharFormat = rCharFormatItem.GetCharFormat())
     {
-        if (const SwCharFormat* pCharFormat = pCharFormatItem->GetCharFormat())
+        if (const SfxPoolItem* pWeightItem = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_WEIGHT))
+            hasWeightPropertyInCharStyle = (*pWeightItem == aBoldProperty);
+
+        if (const SfxPoolItem* pWeightComplexItem = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_CTL_WEIGHT))
+            hasWeightComplexPropertyInCharStyle = (*pWeightComplexItem == 
aBoldProperty);
+
+        if (const SfxPoolItem* pPostureItem = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_POSTURE))
+            hasPosturePropertyInCharStyle = (*pPostureItem == 
aPostureProperty);
+
+        if (const SfxPoolItem* pPostureComplexItem = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_CTL_POSTURE))
+            hasPostureComplexPropertyInCharStyle = (*pPostureComplexItem == 
aPostureProperty);
+
+        if (const SfxPoolItem* pContouredItem = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_CONTOUR))
+            hasContouredPropertyInCharStyle = (*pContouredItem == 
aContouredProperty);
+
+        if (const SfxPoolItem* pShadowedItem = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_SHADOWED))
+            hasShadowedPropertyInCharStyle = (*pShadowedItem == 
aShadowedProperty);
+
+        if (const SfxPoolItem* pStrikeoutItem = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_CROSSEDOUT))
+            hasStrikeoutPropertyInCharStyle = (*pStrikeoutItem == 
aStrikeoutProperty);
+
+        if (const SfxPoolItem* pHiddenItem = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_HIDDEN))
+            hasHiddenPropertyInCharStyle = (*pHiddenItem == aHiddenProperty);
+
+        if (const SfxPoolItem* pCaseMapItem  = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_CASEMAP))
         {
-            if (const SfxPoolItem* pItem = 
pCharFormat->GetAttrSet().GetItem(nWhich))
-            {
-                hasPropertyInCharStyle = (*pItem == *pValue);
-            }
+            bHasCapsPropertyInCharStyle = (*pCaseMapItem == 
aCaseMapCapsProperty);
+            bHasSmallCapsPropertyInCharStyle = (*pCaseMapItem == 
aCaseMapSmallProperty);
+        }
+
+        if (const SfxPoolItem* pReliefItem  = 
pCharFormat->GetAttrSet().GetItem(RES_CHRATR_RELIEF))
+        {
+            bHasEmbossedPropertyInCharStyle = (*pReliefItem == 
aEmbossedProperty);
+            bHasImprintPropertyInCharStyle = (*pReliefItem == 
aImprintProperty);
         }
     }
 
-    // get bold flag from specified paragraph style
+    // get attribute flags from specified paragraph style and apply properties 
if they are set in character and paragraph style
     {
         SwTextFormatColl& rTextColl = static_cast<SwTextFormatColl&>( 
m_rNode.GetAnyFormatColl() );
         sal_uInt16 nStyle = m_rExport.m_pStyles->GetSlot( &rTextColl );
@@ -588,17 +650,59 @@ void SwWW8AttrIter::handleToggleProperty(SfxItemSet& 
rExportSet, const SwFormatC
         const SwFormat* pFormat = m_rExport.m_pStyles->GetSwFormat(nStyle);
         if (pFormat)
         {
-            if (const SfxPoolItem* pItem = 
pFormat->GetAttrSet().GetItem(nWhich))
+            const SfxPoolItem* pItem;
+            if (hasWeightPropertyInCharStyle && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_WEIGHT)) &&
+                (*pItem == aBoldProperty))
+                rExportSet.Put(aBoldProperty);
+
+            if (hasWeightComplexPropertyInCharStyle && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_CTL_WEIGHT)) &&
+                *pItem == aBoldProperty)
+            {
+                rExportSet.Put(aBoldProperty, RES_CHRATR_CTL_WEIGHT);
+            }
+
+            if (hasPosturePropertyInCharStyle && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_POSTURE)) &&
+                *pItem == aPostureProperty)
+                rExportSet.Put(aPostureProperty);
+
+            if (hasPostureComplexPropertyInCharStyle && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_CTL_POSTURE)) &&
+                *pItem == aPostureProperty)
             {
-                hasPropertyInParaStyle = (*pItem == *pValue);
+                rExportSet.Put(aPostureProperty, RES_CHRATR_CTL_POSTURE);
+            }
+
+            if (hasContouredPropertyInCharStyle && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_CONTOUR)) && *pItem == 
aContouredProperty)
+                rExportSet.Put(aContouredProperty);
+
+            if (hasShadowedPropertyInCharStyle && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_SHADOWED)) &&
+                *pItem == aShadowedProperty)
+                rExportSet.Put(aShadowedProperty);
+
+            if (hasStrikeoutPropertyInCharStyle && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_CROSSEDOUT)) &&
+                *pItem == aStrikeoutProperty)
+                rExportSet.Put(aStrikeoutProperty);
+
+            if (hasHiddenPropertyInCharStyle && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_HIDDEN)) &&
+                (*pItem == aHiddenProperty))
+                rExportSet.Put(aHiddenProperty);
+
+            if 
((bHasCapsPropertyInCharStyle||bHasSmallCapsPropertyInCharStyle) && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_CASEMAP)))
+            {
+                if (bHasCapsPropertyInCharStyle && *pItem == 
aCaseMapCapsProperty)
+                    rExportSet.Put(aCaseMapCapsProperty);
+                else if (bHasSmallCapsPropertyInCharStyle && *pItem == 
aCaseMapSmallProperty)
+                    rExportSet.Put(aCaseMapSmallProperty);
+            }
+
+            if 
((bHasEmbossedPropertyInCharStyle||bHasImprintPropertyInCharStyle) && (pItem = 
pFormat->GetAttrSet().GetItem(RES_CHRATR_RELIEF)))
+            {
+                if (bHasEmbossedPropertyInCharStyle && *pItem == 
aEmbossedProperty)
+                    rExportSet.Put(aEmbossedProperty);
+                else if (bHasImprintPropertyInCharStyle && *pItem == 
aImprintProperty)
+                    rExportSet.Put(aImprintProperty);
             }
         }
-    }
 
-    // add inline property
-    if (hasPropertyInCharStyle && hasPropertyInParaStyle)
-    {
-        rExportSet.Put(*pValue);
     }
 }
 
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 04737fb21410..fcc39c44aab4 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -1551,7 +1551,7 @@ private:
     SwWW8AttrIter(const SwWW8AttrIter&) = delete;
     SwWW8AttrIter& operator=(const SwWW8AttrIter&) = delete;
 
-    void handleToggleProperty(SfxItemSet& rExportSet, const 
SwFormatCharFormat* pCharFormatItem, sal_uInt16 nWhich, const SfxPoolItem* 
pValue);
+    void handleToggleProperty(SfxItemSet& rExportSet, const 
SwFormatCharFormat& rCharFormatItem);
 public:
     SwWW8AttrIter( MSWordExportBase& rWr, const SwTextNode& rNd );
 
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 3a0c5a6e10bd..bc6a3dfdf5a1 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -37,6 +37,7 @@
 #include <com/sun/star/i18n/NumberFormatMapper.hpp>
 #include <com/sun/star/i18n/NumberFormatIndex.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/style/CaseMap.hpp>
 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
 #include <com/sun/star/style/LineNumberPosition.hpp>
 #include <com/sun/star/style/LineSpacing.hpp>
@@ -79,6 +80,10 @@
 #include <com/sun/star/text/ControlCharacter.hpp>
 #include <com/sun/star/text/XTextColumns.hpp>
 #include <com/sun/star/awt/CharSet.hpp>
+#include <com/sun/star/awt/FontRelief.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
 #include <com/sun/star/embed/ElementModes.hpp>
@@ -517,6 +522,17 @@ uno::Reference< container::XNameContainer > const &  
DomainMapper_Impl::GetChara
     return m_xCharacterStyles;
 }
 
+uno::Reference<container::XNameContainer> const& 
DomainMapper_Impl::GetParagraphStyles()
+{
+    if (!m_xParagraphStyles.is())
+    {
+        uno::Reference<style::XStyleFamiliesSupplier> 
xSupplier(m_xTextDocument, uno::UNO_QUERY);
+        if (xSupplier.is())
+            xSupplier->getStyleFamilies()->getByName("ParagraphStyles") >>= 
m_xParagraphStyles;
+    }
+    return m_xParagraphStyles;
+}
+
 OUString DomainMapper_Impl::GetUnusedCharacterStyleName()
 {
     static const char cListLabel[] = "ListLabel ";
@@ -3016,7 +3032,148 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
 
 }
 
-void DomainMapper_Impl::appendTextPortion( const OUString& rString, const 
PropertyMapPtr& pPropertyMap )
+void DomainMapper_Impl::applyToggleAttributes(const PropertyMapPtr& 
pPropertyMap)
+{
+    std::optional<PropertyMap::Property> charStyleProperty = 
pPropertyMap->getProperty(PROP_CHAR_STYLE_NAME);
+    if (charStyleProperty.has_value())
+    {
+        OUString sCharStyleName;
+        charStyleProperty->second >>= sCharStyleName;
+        float fCharStyleBold = css::awt::FontWeight::NORMAL;
+        float fCharStyleBoldComplex = css::awt::FontWeight::NORMAL;
+        css::awt::FontSlant eCharStylePosture = css::awt::FontSlant_NONE;
+        css::awt::FontSlant eCharStylePostureComplex = 
css::awt::FontSlant_NONE;
+        sal_Int16 nCharStyleCaseMap = css::style::CaseMap::NONE;
+        sal_Int16 nCharStyleRelief = css::awt::FontRelief::NONE;
+        bool bCharStyleContoured = false;//Outline;
+        bool bCharStyleShadowed = false;
+        sal_Int16 nCharStyleStrikeThrough = awt::FontStrikeout::NONE;
+        bool bCharStyleHidden = false;
+
+        uno::Reference<beans::XPropertySet> xCharStylePropertySet = 
GetCharacterStyles()->getByName(sCharStyleName).get<uno::Reference<beans::XPropertySet>>();
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_WEIGHT)) >>= 
fCharStyleBold;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_WEIGHT_COMPLEX))
 >>= fCharStyleBoldComplex;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_POSTURE)) >>= 
eCharStylePosture;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_POSTURE_COMPLEX))
 >>= eCharStylePostureComplex;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_CASE_MAP)) 
>>= nCharStyleCaseMap;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_RELIEF)) >>= 
nCharStyleRelief;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_CONTOURED)) 
>>= bCharStyleContoured;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_SHADOWED)) 
>>= bCharStyleShadowed;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_STRIKEOUT)) 
>>= nCharStyleStrikeThrough;
+        
xCharStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_HIDDEN)) >>= 
bCharStyleHidden;
+        if (fCharStyleBold > css::awt::FontWeight::NORMAL || eCharStylePosture 
!= css::awt::FontSlant_NONE|| nCharStyleCaseMap != css::style::CaseMap::NONE ||
+            nCharStyleRelief != css::awt::FontRelief::NONE || 
bCharStyleContoured || bCharStyleShadowed ||
+            nCharStyleStrikeThrough == awt::FontStrikeout::SINGLE || 
bCharStyleHidden)
+        {
+            uno::Reference<beans::XPropertySet> xParaStylePropertySet = 
GetParagraphStyles()->getByName(m_sCurrentParaStyleName).get<uno::Reference<beans::XPropertySet>>();
+            float fParaStyleBold = css::awt::FontWeight::NORMAL;
+            float fParaStyleBoldComplex = css::awt::FontWeight::NORMAL;
+            css::awt::FontSlant eParaStylePosture = css::awt::FontSlant_NONE;
+            css::awt::FontSlant eParaStylePostureComplex = 
css::awt::FontSlant_NONE;
+            sal_Int16 nParaStyleCaseMap = css::style::CaseMap::NONE;
+            sal_Int16 nParaStyleRelief = css::awt::FontRelief::NONE;
+            bool bParaStyleContoured = false;
+            bool bParaStyleShadowed = false;
+            sal_Int16 nParaStyleStrikeThrough = awt::FontStrikeout::NONE;
+            bool bParaStyleHidden = false;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_WEIGHT)) >>= 
fParaStyleBold;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_WEIGHT_COMPLEX))
 >>= fParaStyleBoldComplex;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_POSTURE)) >>= 
eParaStylePosture;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_POSTURE_COMPLEX))
 >>= eParaStylePostureComplex;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_CASE_MAP)) 
>>= nParaStyleCaseMap;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_RELIEF)) >>= 
nParaStyleRelief;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_SHADOWED)) 
>>= bParaStyleShadowed;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_CONTOURED)) 
>>= bParaStyleContoured;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_STRIKEOUT)) 
>>= nParaStyleStrikeThrough;
+            
xParaStylePropertySet->getPropertyValue(getPropertyName(PROP_CHAR_HIDDEN)) >>= 
bParaStyleHidden;
+            if (fCharStyleBold > css::awt::FontWeight::NORMAL && 
fParaStyleBold > css::awt::FontWeight::NORMAL)
+            {
+                std::optional<PropertyMap::Property> charBoldProperty = 
pPropertyMap->getProperty(PROP_CHAR_WEIGHT);
+                if (!charBoldProperty.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_WEIGHT, 
uno::Any(css::awt::FontWeight::NORMAL));
+                }
+            }
+            if (fCharStyleBoldComplex > css::awt::FontWeight::NORMAL && 
fParaStyleBoldComplex > css::awt::FontWeight::NORMAL)
+            {
+                std::optional<PropertyMap::Property> charBoldPropertyComplex = 
pPropertyMap->getProperty(PROP_CHAR_WEIGHT_COMPLEX);
+                if (!charBoldPropertyComplex.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_WEIGHT_COMPLEX, 
uno::Any(css::awt::FontWeight::NORMAL));
+                    pPropertyMap->Insert(PROP_CHAR_WEIGHT_ASIAN, 
uno::Any(css::awt::FontWeight::NORMAL));
+                }
+            }
+            if (eCharStylePosture != css::awt::FontSlant_NONE && 
eParaStylePosture != css::awt::FontSlant_NONE)
+            {
+                std::optional<PropertyMap::Property> charItalicProperty = 
pPropertyMap->getProperty(PROP_CHAR_POSTURE);
+                if (!charItalicProperty.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_POSTURE, 
uno::Any(css::awt::FontSlant_NONE));
+                }
+            }
+            if (eCharStylePostureComplex != css::awt::FontSlant_NONE && 
eParaStylePostureComplex != css::awt::FontSlant_NONE)
+            {
+                std::optional<PropertyMap::Property> charItalicPropertyComplex 
= pPropertyMap->getProperty(PROP_CHAR_POSTURE_COMPLEX);
+                if (!charItalicPropertyComplex.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_POSTURE_COMPLEX, 
uno::Any(css::awt::FontSlant_NONE));
+                    pPropertyMap->Insert(PROP_CHAR_POSTURE_ASIAN, 
uno::Any(css::awt::FontSlant_NONE));
+                }
+            }
+            if (nCharStyleCaseMap == nParaStyleCaseMap && nCharStyleCaseMap != 
css::style::CaseMap::NONE)
+            {
+                std::optional<PropertyMap::Property> charCaseMap = 
pPropertyMap->getProperty(PROP_CHAR_CASE_MAP);
+                if (!charCaseMap.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_CASE_MAP, 
uno::Any(css::style::CaseMap::NONE));
+                }
+            }
+            if (nParaStyleRelief != css::awt::FontRelief::NONE && 
nCharStyleRelief == nParaStyleRelief)
+            {
+                std::optional<PropertyMap::Property> charRelief = 
pPropertyMap->getProperty(PROP_CHAR_RELIEF);
+                if (!charRelief.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_RELIEF, 
uno::Any(css::awt::FontRelief::NONE));
+                }
+            }
+            if (bParaStyleContoured && bCharStyleContoured)
+            {
+                std::optional<PropertyMap::Property> charContoured = 
pPropertyMap->getProperty(PROP_CHAR_CONTOURED);
+                if (!charContoured.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_CONTOURED, uno::Any(false));
+                }
+            }
+            if (bParaStyleShadowed && bCharStyleShadowed)
+            {
+                std::optional<PropertyMap::Property> charShadow = 
pPropertyMap->getProperty(PROP_CHAR_SHADOWED);
+                if (!charShadow.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_SHADOWED, uno::Any(false));
+                }
+            }
+            if (nParaStyleStrikeThrough == css::awt::FontStrikeout::SINGLE && 
nParaStyleStrikeThrough == nCharStyleStrikeThrough)
+            {
+                std::optional<PropertyMap::Property> charStrikeThrough = 
pPropertyMap->getProperty(PROP_CHAR_STRIKEOUT);
+                if (!charStrikeThrough.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_STRIKEOUT, 
uno::Any(css::awt::FontStrikeout::NONE));
+                }
+            }
+            if (bParaStyleHidden && bCharStyleHidden)
+            {
+                std::optional<PropertyMap::Property> charHidden = 
pPropertyMap->getProperty(PROP_CHAR_HIDDEN);
+                if (!charHidden.has_value())
+                {
+                    pPropertyMap->Insert(PROP_CHAR_HIDDEN, uno::Any(false));
+                }
+            }
+        }
+    }
+}
+
+
+    void DomainMapper_Impl::appendTextPortion( const OUString& rString, const 
PropertyMapPtr& pPropertyMap )
 {
     if (m_bDiscardHeaderFooter)
         return;
@@ -3033,6 +3190,7 @@ void DomainMapper_Impl::appendTextPortion( const 
OUString& rString, const Proper
 
     try
     {
+        applyToggleAttributes(pPropertyMap);
         // If we are in comments, then disable CharGrabBag, comment text 
doesn't support that.
         uno::Sequence< beans::PropertyValue > aValues = 
pPropertyMap->GetPropertyValues(/*bCharGrabBag=*/!m_bIsInComments);
 
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index fa5182f77e6c..f555dd14c048 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -451,6 +451,8 @@ private:
     // cache next available number, expensive to repeatedly compute
     std::optional<int> m_xNextUnusedPageStyleNo;
     css::uno::Reference<css::container::XNameContainer> m_xCharacterStyles;
+    css::uno::Reference<css::container::XNameContainer> m_xParagraphStyles;
+
     // cache next available number, expensive to repeatedly compute
     std::optional<int> m_xNextUnusedCharacterStyleNo;
     css::uno::Reference<css::text::XText> m_xBodyText;
@@ -660,6 +662,7 @@ public:
     css::uno::Reference<css::container::XNameContainer> const & 
GetPageStyles();
     OUString GetUnusedPageStyleName();
     css::uno::Reference<css::container::XNameContainer> const & 
GetCharacterStyles();
+    css::uno::Reference<css::container::XNameContainer> const& 
GetParagraphStyles();
     OUString GetUnusedCharacterStyleName();
     css::uno::Reference<css::text::XText> const & GetBodyText();
     const css::uno::Reference<css::lang::XMultiServiceFactory>& 
GetTextFactory() const
@@ -759,6 +762,7 @@ public:
     bool isParaSdtEndDeferred() const;
 
     void finishParagraph( const PropertyMapPtr& pPropertyMap, const bool 
bRemove = false, const bool bNoNumbering = false);
+    void applyToggleAttributes( const PropertyMapPtr& pPropertyMap );
     void appendTextPortion( const OUString& rString, const PropertyMapPtr& 
pPropertyMap );
     void appendTextContent(const 
css::uno::Reference<css::text::XTextContent>&, const 
css::uno::Sequence<css::beans::PropertyValue>&);
     void appendOLE( const OUString& rStreamName, const 
std::shared_ptr<OLEHandler>& pOleHandler );

Reply via email to