diff options
author | László Németh <nemeth@numbertext.org> | 2020-02-17 14:34:11 +0100 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2020-02-19 16:46:18 +0100 |
commit | 4d5c0eaf3e0d3d3bcd9e691fffee19b75f3d6631 (patch) | |
tree | 6ed8e4a013884c28db01b9175dfc933141b7c395 | |
parent | faa2e7b7227b6b87379e7e136ea9ab63f37c3fc4 (diff) |
tdf#118812 DOCX import: fix table style preference – part 2
Apply table styles according to OOXML and – in
the case of font sizes – MSO exception
"overrideTableStyleFontSizeAndJustification".
Fix temporary regression in styles of paragraph
portions, table cell regions and nested tables from
commit f15d67442972c5f69c71925a6bfa5aa1a39d54eb
(tdf#129575 DOCX import: fix table style preference).
Unit test document was created by Justin Luth.
Change-Id: I7b076ac27f5b44d44934b7efb18ac4a878f8b596
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88869
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/calendar5.docx | bin | 0 -> 12584 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf118812_tableStyles-comprehensive.docx | bin | 0 -> 12382 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport3.cxx | 25 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport6.cxx | 6 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 77 | ||||
-rw-r--r-- | sw/source/core/unocore/unotbl.cxx | 30 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapperTableHandler.cxx | 150 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapperTableHandler.hxx | 11 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 8 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 7 |
10 files changed, 226 insertions, 88 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/calendar5.docx b/sw/qa/extras/ooxmlexport/data/calendar5.docx Binary files differnew file mode 100644 index 000000000000..a27634673efc --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/calendar5.docx diff --git a/sw/qa/extras/ooxmlexport/data/tdf118812_tableStyles-comprehensive.docx b/sw/qa/extras/ooxmlexport/data/tdf118812_tableStyles-comprehensive.docx Binary files differnew file mode 100644 index 000000000000..e2cbffc20a2b --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf118812_tableStyles-comprehensive.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx index 55337895efb7..d1e62fb62c90 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx @@ -316,8 +316,12 @@ DECLARE_OOXMLEXPORT_TEST(testCalendar3, "calendar3.docx") // TableStyle:firstRow (for header rows 1 and 2) color and size overrides document rPrDefault uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY); uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A2"), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0x5B9BD5), getProperty<sal_Int32>(getRun(xCell,1), "CharColor")); - CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(getRun(xCell,1), "CharHeight")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0x5B9BD5), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell->getText()), 1), "CharColor")); + CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()),1), "CharHeight")); + // direct formatting in A1 + uno::Reference<text::XTextRange> xCell2(xTable->getCellByName("A1"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0x2E74B5), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell2->getText()), 1), "CharColor")); + CPPUNIT_ASSERT_EQUAL(20.f, getProperty<float>(getRun(getParagraphOfText(1, xCell2->getText()),1), "CharHeight")); } DECLARE_OOXMLEXPORT_TEST(testCalendar4, "calendar4.docx") @@ -329,6 +333,23 @@ DECLARE_OOXMLEXPORT_TEST(testCalendar4, "calendar4.docx") CPPUNIT_ASSERT_EQUAL(14.f, getProperty<float>(getRun(xCell,1), "CharHeight")); } +DECLARE_OOXMLEXPORT_TEST(testCalendar5, "calendar5.docx") +{ + // check text portions with and without direct formatting + uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY); + // text portions with direct formatting + CPPUNIT_ASSERT_EQUAL(sal_Int32(0x2E74B5), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell->getText()), 1), "CharColor")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0xFF0000), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell->getText()), 2), "CharColor")); + // default paragraph text color + CPPUNIT_ASSERT_EQUAL(sal_Int32(0x5B9BD5), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell->getText()), 3), "CharColor")); + // text portions with direct formatting + CPPUNIT_ASSERT_EQUAL(20.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()),1), "CharHeight")); + CPPUNIT_ASSERT_EQUAL(10.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()),2), "CharHeight")); + // default paragraph text size + CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()),3), "CharHeight")); +} + DECLARE_OOXMLEXPORT_TEST(testTcBorders, "testTcBorders.docx") { //fdo#76635 : Table borders are not getting preserved. diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx index 45bcc9ac5f27..3b5726dceb28 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx @@ -459,9 +459,9 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf128752, "tdf128752.docx") DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf119054, "tdf119054.docx") { xmlDocPtr pXmlDoc = parseExport(); - // Overwrite applied table style with before and after spacing of Heading2 - assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before", "0"); - assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after", "360"); + // Don't overwrite before and after spacing of Heading2 by table style + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after"); // Use table style based single line spacing instead of the docDefaults' 254 assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "line", "240"); } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index b7f6852a6a23..991916ef6ca8 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -30,7 +30,6 @@ #include <com/sun/star/view/XSelectionSupplier.hpp> #include <com/sun/star/style/LineSpacing.hpp> #include <com/sun/star/style/LineSpacingMode.hpp> -//#include <com/sun/star/drawing/LineStyle.hpp> #include <com/sun/star/style/ParagraphAdjust.hpp> #include <com/sun/star/drawing/XControlShape.hpp> #include <com/sun/star/text/TextContentAnchorType.hpp> @@ -249,6 +248,82 @@ DECLARE_OOXMLEXPORT_TEST(testTdf129575_docDefault, "tdf129575-docDefault.docx") } +DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf118812, "tdf118812_tableStyles-comprehensive.docx") +{ + xmlDocPtr pXmlDoc = parseExport("word/document.xml"); + // cell A1 + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:pStyle", "val", "Normal"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:spacing", "lineRule"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:spacing", "line"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:spacing", "before", "480"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:spacing", "after", "20"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[1]/w:rPr/w:sz", "val", "16"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[2]/w:rPr/w:rStyle", "val", "CharSubStyleDefaults"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[2]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[2]/w:rPr/w:sz", "val", "16"); + // cell A2 + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:pStyle", "val", "Normal"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:spacing", "lineRule"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:spacing", "line"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:spacing", "before", "480"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:spacing", "after", "20"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[1]/w:rPr/w:sz", "val", "16"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[2]/w:rPr/w:rStyle", "val", "ParaSubStyleDefaultsChar"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[2]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[2]/w:rPr/w:sz", "val", "16"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[3]/w:rPr/w:rStyle", "val", "CharSubStyleNormal"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[3]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[3]/w:rPr/w:sz", "val", "16"); + // cell A3 + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:pStyle", "val", "ParaSubStyleNormal"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:spacing", "lineRule"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:spacing", "line"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:spacing", "before", "480"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:spacing", "after", "280"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[1]/w:rPr/w:sz", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[2]/w:rPr/w:rStyle", "val", "CharSubStyleNormal"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[2]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[2]/w:rPr/w:sz", 0); + // cell A4 + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:pStyle", "val", "ParaSubStyleDefaults"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:spacing", "lineRule"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:spacing", "line"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:spacing", "before", "480"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:spacing", "after", "200"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[1]/w:rPr/w:sz", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[2]/w:rPr/w:rStyle", "val", "CharSubStyleDefaults"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[2]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[2]/w:rPr/w:sz", 0); + // cell A5 + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:pStyle", "val", "Normal"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:spacing", "lineRule"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:spacing", "line"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:rPr", "color"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:rPr", "sz"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:spacing", "before", "480"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:spacing", "after", "20"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:r[1]/w:rPr/w:color", 1); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:r[1]/w:rPr/w:color", "val", "AAAA00"); // all text in color + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:r[1]/w:rPr/w:sz", "val", "16"); + // cell A6 + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:pStyle", "val", "Normal"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:spacing", "lineRule"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:spacing", "line"); + assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:rPr", "color"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:rPr/w:sz", "val", "16"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:spacing", "before", "480"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:spacing", "after", "20"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[1]/w:rPr/w:sz", "val", "16"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[2]/w:rPr/w:color", 1); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[2]/w:rPr/w:color", "val", "AAAA00"); + assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[2]/w:rPr/w:sz", "val", "16"); +} + DECLARE_OOXMLEXPORT_TEST(testTdf106970, "tdf106970.docx") { // The second paragraph (first numbered one) had 0 bottom margin: diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx index 79cb240426dd..b51efa908b1b 100644 --- a/sw/source/core/unocore/unotbl.cxx +++ b/sw/source/core/unocore/unotbl.cxx @@ -1003,40 +1003,12 @@ void SwXCell::setPropertyValue(const OUString& rPropertyName, const uno::Any& aV auto pEntry(m_pPropSet->getPropertyMap().getByName(rPropertyName)); if ( !pEntry ) { - // not a table property: if it is a paragraph/character property, consider applying it to the underlying text. + // not a table property: ignore it, if it is a paragraph/character property const SfxItemPropertySet& rParaPropSet = *aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH); pEntry = rParaPropSet.getPropertyMap().getByName(rPropertyName); if ( pEntry ) - { - SwNodeIndex aIdx( *GetStartNode(), 1 ); - const SwNode* pEndNd = aIdx.GetNode().EndOfSectionNode(); - while ( &aIdx.GetNode() != pEndNd ) - { - const SwTextNode* pNd = aIdx.GetNode().GetTextNode(); - if ( pNd ) - { - //point and mark selecting the whole paragraph - SwPaM aPaM(*pNd, 0, *pNd, pNd->GetText().getLength()); - const bool bHasAttrSet = pNd->HasSwAttrSet(); - const SfxItemSet& aSet = pNd->GetSwAttrSet(); - // isPARATR: replace DEFAULT_VALUE properties only - // Require that the property is default in the paragraph style as well, - // unless the style is the default style. - // isCHRATR: change the base/auto SwAttr property, but don't remove the DIRECT hints - bool bCustomParent = false; - if (const SwFormatColl* pFormatColl = pNd->GetFormatColl()) - { - bCustomParent = pFormatColl->GetPoolFormatId() != RES_POOLCOLL_STANDARD; - } - bool bSearchInParent = bCustomParent && !pNd->GetNumRule(); - if ( !bHasAttrSet || SfxItemState::DEFAULT == aSet.GetItemState(pEntry->nWID, bSearchInParent) ) - SwUnoCursorHelper::SetPropertyValue(aPaM, rParaPropSet, rPropertyName, aValue, SetAttrMode::DONTREPLACE); - } - ++aIdx; - } return; - } } if(!pEntry) diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx index ab51d4fdd48d..d02e26abf96e 100644 --- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx +++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx @@ -28,6 +28,10 @@ #include <com/sun/star/text/RelOrientation.hpp> #include <com/sun/star/text/SizeType.hpp> #include <com/sun/star/text/XTextRangeCompare.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> #include "TablePositionHandler.hxx" #include "ConversionHelper.hxx" #include "util.hxx" @@ -1066,59 +1070,65 @@ css::uno::Sequence<css::beans::PropertyValues> DomainMapperTableHandler::endTabl // table style has got bigger precedence than docDefault style, // but lower precedence than the paragraph styles and direct paragraph formatting -void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo) +void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableParagraph rParaProp, std::vector< PropertyIds > aAllTableParaProperties, css::beans::PropertyValues rCellProperties) { - for( auto const& eId : rInfo.aTablePropertyIds ) + for( auto const& eId : aAllTableParaProperties ) { // apply paragraph and character properties of the table style on table paragraphs - if ( isParagraphProperty(eId) || isCharacterProperty(eId) ) + // if there is no direct paragraph formatting + if ( !rParaProp.m_pPropertyMap->isSet(eId) ) { - // check all paragraphs of the table - for (const auto& rParaProp : m_rDMapper_Impl.m_aParagraphsToEndTable) + OUString sPropertyName = getPropertyName(eId); + auto pCellProp = std::find_if(rCellProperties.begin(), rCellProperties.end(), + [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; }); + // this cell applies the table style property + if (pCellProp != rCellProperties.end()) { - // there is no direct paragraph formatting - if (!rParaProp.m_pPropertyMap->isSet(eId)) + bool bDocDefault; + OUString sParaStyleName; + rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName; + StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName); + uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault); + // use table style when no paragraph style setting or a docDefault value is applied instead of it + if ( aParaStyle == uno::Any() || bDocDefault || + // set default behaviour of MSO ("overrideTableStyleFontSizeAndJustification" exception): + // if Normal style defines 11 pt or 12 pt font heights, table style overrides its font size + (eId == PROP_CHAR_HEIGHT && sParaStyleName == "Standard" && (aParaStyle == uno::Any(double(11)) || aParaStyle == uno::Any(double(12))))) try { - bool bDocDefault; - OUString sParaStyleName; - rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName; - StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName); - uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault); - // use table style when a docDefault value is applied instead of it, - // and there is no associated TableStyleSheetEntry - // TODO: replace CNF_ALL with the actual mask - if ( (aParaStyle == uno::Any() || bDocDefault) && !rInfo.pTableStyle->GetProperties(CNF_ALL)->getProperty(eId) ) + // check property state of paragraph + uno::Reference<text::XParagraphCursor> xParagraph( + rParaProp.m_rEndParagraph->getText()->createTextCursorByRange(rParaProp.m_rEndParagraph), uno::UNO_QUERY_THROW ); + // select paragraph + xParagraph->gotoStartOfParagraph( true ); + uno::Reference< beans::XPropertyState > xParaProperties( xParagraph, uno::UNO_QUERY_THROW ); + if ( xParaProperties->getPropertyState(sPropertyName) == css::beans::PropertyState_DEFAULT_VALUE ) { - OUString sPropertyName = getPropertyName(eId); - auto pTableProp = std::find_if(rInfo.aTableProperties.begin(), rInfo.aTableProperties.end(), - [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; }); - if (pTableProp != rInfo.aTableProperties.end()) - { - try - { - rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pTableProp->Value ); - } - catch ( const uno::Exception & ) - { - TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction"); - } - } + // apply style setting when the paragraph doesn't modify it + rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pCellProp->Value ); } - // table style can overwrite paragraph style, when the paragraph style property has a default value, restore it - // TODO remove the associated TableStyleSheetEntry styles, if needed - else if ( aParaStyle != uno::Any() && !bDocDefault ) + else { - OUString sPropertyName = getPropertyName(eId); - try - { - rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, aParaStyle ); - } - catch ( const uno::Exception & ) + // apply style setting only on text portions without direct modification of it + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xParagraph, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration(); + while ( xRunEnum->hasMoreElements() ) { - TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction"); + uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY); + uno::Reference< beans::XPropertyState > xRunProperties( xRun, uno::UNO_QUERY_THROW ); + if ( xRunProperties->getPropertyState(sPropertyName) == css::beans::PropertyState_DEFAULT_VALUE ) + { + uno::Reference< beans::XPropertySet > xRunPropertySet( xRun, uno::UNO_QUERY_THROW ); + xRunPropertySet->setPropertyValue( sPropertyName, pCellProp->Value ); + } } } } + catch ( const uno::Exception & ) + { + TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction"); + } } } } @@ -1153,6 +1163,60 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab uno::Reference<text::XTextRange> xEnd; bool bFloating = !aFrameProperties.empty(); + + // OOXML table style may contain paragraph properties, apply these on cell paragraphs + if ( m_aTableRanges[0].hasElements() && m_aTableRanges[0][0].hasElements() ) + { + // collect all paragraph properties used in table styles + PropertyMapPtr pAllTableProps( new PropertyMap ); + pAllTableProps->InsertProps(aTableInfo.pTableDefaults); + if ( aTableInfo.pTableStyle ) + pAllTableProps->InsertProps(aTableInfo.pTableStyle->GetProperties( CNF_ALL )); + for (const auto& eId : pAllTableProps->GetPropertyIds()) + { + if ( !isParagraphProperty(eId) && !isCharacterProperty(eId) ) + pAllTableProps->Erase(eId); + } + std::vector< PropertyIds > aAllTableParaProperties = pAllTableProps->GetPropertyIds(); + + if ( !aAllTableParaProperties.empty() ) + { + for (size_t nRow = 0; nRow < m_aTableRanges.size(); ++nRow) + { + for (size_t nCell = 0; nCell < m_aTableRanges[nRow].size(); ++nCell) + { + auto rStartPara = m_aTableRanges[nRow][nCell][0]; + auto rEndPara = m_aTableRanges[nRow][nCell][1]; + uno::Reference<text::XTextRangeCompare> xTextRangeCompare(rStartPara->getText(), uno::UNO_QUERY); + bool bApply = false; + // search paragraphs of the cell + std::vector<TableParagraph>::iterator aIt = m_rDMapper_Impl.m_aParagraphsToEndTable.begin(); + while ( aIt != m_rDMapper_Impl.m_aParagraphsToEndTable.end() ) try + { + if (!bApply && xTextRangeCompare->compareRegionStarts(rStartPara, aIt->m_rStartParagraph) == 0) + bApply = true; + if (bApply) + { + bool bEndOfApply = (xTextRangeCompare->compareRegionEnds(rEndPara, aIt->m_rEndParagraph) == 0); + ApplyParagraphPropertiesFromTableStyle(*aIt, aAllTableParaProperties, aCellProperties[nRow][nCell]); + // erase processed paragraph from list of pending paragraphs + aIt = m_rDMapper_Impl.m_aParagraphsToEndTable.erase(aIt); + if (bEndOfApply) + break; + } + else + ++aIt; + } + catch( const lang::IllegalArgumentException & ) + { + // skip compareRegion with nested tables + ++aIt; + } + } + } + } + } + // Additional checks: if we can do this. if (bFloating && m_aTableRanges[0].hasElements() && m_aTableRanges[0][0].hasElements()) { @@ -1221,9 +1285,6 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab } } } - - // OOXML table style may contain paragraph properties, apply these now. - ApplyParagraphPropertiesFromTableStyle(aTableInfo); } } catch ( const lang::IllegalArgumentException & ) @@ -1301,7 +1362,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab m_aCellProperties.clear(); m_aRowProperties.clear(); m_bHadFootOrEndnote = false; - m_rDMapper_Impl.m_aParagraphsToEndTable.clear(); + if (nestedTableLevel <= 1) + m_rDMapper_Impl.m_aParagraphsToEndTable.clear(); #ifdef DBG_UTIL TagLogger::getInstance().endElement(); diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx index b454be94f563..bb0ea2e01804 100644 --- a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx +++ b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx @@ -56,6 +56,15 @@ struct HorizontallyMergedCell } }; +/// Information about a paragraph to be finished after a table end. +struct TableParagraph +{ + css::uno::Reference<css::text::XTextRange> m_rStartParagraph; + css::uno::Reference<css::text::XTextRange> m_rEndParagraph; + PropertyMapPtr m_pPropertyMap; + css::uno::Reference<css::beans::XPropertySet> m_rPropertySet; +}; + /// Class to handle events generated by TableManager::resolveCurrentTable(). class DomainMapperTableHandler final : public virtual SvRefBase { @@ -91,7 +100,7 @@ public: */ void startTable(const TablePropertyMapPtr& pProps); - void ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo); + void ApplyParagraphPropertiesFromTableStyle(TableParagraph rParaProp, std::vector< PropertyIds > aAllTableProperties, css::beans::PropertyValues rCellProperties); /// Handle end of table. void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 259e1ebbf678..0ee4c6d1989d 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1759,7 +1759,13 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con // collect these pending paragraph properties to process in endTable() if (xParaProps && m_nTableDepth > 0) { - TableParagraph aPending{pParaContext, xParaProps}; + uno::Reference<text::XTextCursor> xCur = xTextRange->getText( )->createTextCursor( ); + xCur->gotoEnd(false); + xCur->goLeft(1, false); + uno::Reference<text::XTextCursor> xCur2 = xTextRange->getText()->createTextCursorByRange(xCur); + uno::Reference<text::XParagraphCursor> xParaCursor(xCur2, uno::UNO_QUERY_THROW); + xParaCursor->gotoStartOfParagraph(false); + TableParagraph aPending{xParaCursor, xCur, pParaContext, xParaProps}; m_aParagraphsToEndTable.push_back(aPending); } diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 0fd51ab2298e..6138bb738e56 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -430,13 +430,6 @@ struct SymbolData { } }; -/// Information about a paragraph to be finished after a table end. -struct TableParagraph -{ - PropertyMapPtr m_pPropertyMap; - css::uno::Reference<css::beans::XPropertySet> m_rPropertySet; -}; - class DomainMapper; class DomainMapper_Impl final { |