diff options
author | Oliver Specht <oliver.specht@cib.de> | 2023-12-05 13:28:36 +0100 |
---|---|---|
committer | Thorsten Behrens <thorsten.behrens@allotropia.de> | 2024-02-16 01:27:06 +0100 |
commit | 660f366a78ffcad429458acc429e0579d1af5495 (patch) | |
tree | c0755fd2d6b887f43fbeef03654d70311f353984 | |
parent | Update git submodules (diff) | |
download | core-660f366a78ffcad429458acc429e0579d1af5495.tar.gz core-660f366a78ffcad429458acc429e0579d1af5495.zip |
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.behrens@allotropia.de>
(cherry picked from commit 9e127010a86b3521c803ac86c0b5f58dc8e2966b)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161018
(cherry picked from commit b6c4dd27acdd08fa63f8d75dd09212828e28844f)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163452
-rwxr-xr-x | sw/qa/extras/ooxmlexport/data/tdf158044.odt | bin | 0 -> 14032 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport21.cxx | 32 | ||||
-rwxr-xr-x | sw/qa/extras/ooxmlimport/data/tdf154370.docx | bin | 0 -> 6333 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport2.cxx | 77 | ||||
-rw-r--r-- | sw/source/filter/ww8/wrtw8nds.cxx | 152 | ||||
-rw-r--r-- | sw/source/filter/ww8/wrtww8.hxx | 2 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 160 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 4 |
8 files changed, 401 insertions, 26 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/tdf158044.odt b/sw/qa/extras/ooxmlexport/data/tdf158044.odt Binary files differnew file mode 100755 index 000000000000..ca17b6625674 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf158044.odt diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx index a6df0bff9300..a9d01670aab6 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx @@ -44,6 +44,38 @@ DECLARE_OOXMLEXPORT_TEST(testTdf153909_followTextFlow, "tdf153909_followTextFlow CPPUNIT_ASSERT(nTableTop > nRectBottom); } +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]", "val", + "BoldItalicCapsEmbossedStrike"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:b[1]"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:bCs[1]"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:i[1]"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:iCs[1]"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:strike[1]"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r[2]/w:rPr[1]/w:emboss[1]"); + + assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[4]/w:rPr[1]/w:rStyle[1]", "val", + "SmallcapsImprint"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[4]/w:rPr[1]/w:imprint[1]"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[4]/w:rPr[1]/w:smallCaps[1]"); + + assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r[2]/w:rPr[1]/w:rStyle[1]", "val", "AllCaps"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r[2]/w:rPr[1]/w:caps[1]"); + + assertXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r[2]/w:rPr[1]/w:rStyle[1]", "val", "Hidden"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r[2]/w:rPr[1]/w:vanish[1]"); + + assertXPath(pXmlDoc, "/w:document/w:body/w:p[8]/w:r[4]/w:rPr[1]/w:rStyle[1]", "val", + "OutlineShadow"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[8]/w:r[4]/w:rPr[1]/w:outline[1]"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[8]/w:r[4]/w:rPr[1]/w:shadow[1]"); +} + CPPUNIT_TEST_FIXTURE(Test, testTdf159207_footerFramePrBorder) { loadFromFile(u"tdf159207_footerFramePrBorder.docx"); // re-imports as editeng Frame/Shape diff --git a/sw/qa/extras/ooxmlimport/data/tdf154370.docx b/sw/qa/extras/ooxmlimport/data/tdf154370.docx Binary files differnew file mode 100755 index 000000000000..ba72724593b2 --- /dev/null +++ b/sw/qa/extras/ooxmlimport/data/tdf154370.docx diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx index 6edd873dc7ed..956d6dd3464c 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx @@ -1194,6 +1194,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 d2e57406f8b3..e27137946ef5 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 3aa39a2994b8..5726b3949077 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -1548,7 +1548,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 e1a4d04631db..5fbec2fb965d 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> @@ -78,6 +79,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> @@ -503,6 +508,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 "; @@ -2983,7 +2999,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; @@ -3000,6 +3157,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=*/!IsInComments()); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 2cffecf47fb9..ee17ac183a2a 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -493,6 +493,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; @@ -677,6 +679,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 @@ -771,6 +774,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 ); |