diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2024-06-11 10:49:29 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2024-06-11 12:09:51 +0200 |
commit | 013300c751d7a9ede12c1bf1c784254d1c6c5433 (patch) | |
tree | 8490f4e3b20125a97556fc1ee9395413dd238c24 | |
parent | 19e9e49bdaeebc314c892c000385ec778edf759b (diff) |
tdf#161443 DOCX import, table style: handle para border in table cell paras
Open the bugdoc, the in-table paragraphs have some top and bottom
paragraph borders in Word, not in Writer -- because the cell and
paragraph UNO object both have a property named TopBorder as mentioned
in commit 39c54c0ef837e0e23a676a4d1fa5da667e18939c (tdf#161443 DOCX
import, table style: fix para border leaking into cell border,
2024-06-07).
The previous fix avoided the problem that the unwanted border affects,
the cell, but re-routing the property to affect the in-table paragraph
were not done.
Fix the problem by adding 3 new meta-properties with a "Para" prefix for
all 4 border locations (top/left/bottom/right), this way the paragraph
borders defined in a table style can affect the in-table paragraphs, but
not the table cells.
Apart from the border itself, this also affected the border spacing,
which means that the position of all text inside and below the table is
now also correct. Unfortunately this also means we need to move away
from the constexpr frozen container that is only suitable for a limited
number of items:
sw/source/writerfilter/dmapper/PropertyIds.cxx:394:6: error: ‘constexpr’ evaluation operation count exceeds limit of 33554432 (use ‘-fconstexpr-ops-limit=’ to increase the limit)
Returning to std::unordered_map is good enough for our needs.
Change-Id: I478f274800a1d0b200f10226438ab4cfd4957b74
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168659
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r-- | sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx | 24 | ||||
-rw-r--r-- | sw/qa/writerfilter/dmapper/data/table-style-para-border-spacing.docx | bin | 0 -> 12560 bytes | |||
-rw-r--r-- | sw/source/core/unocore/unotext.cxx | 24 | ||||
-rw-r--r-- | sw/source/writerfilter/dmapper/DomainMapper.cxx | 67 | ||||
-rw-r--r-- | sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx | 48 | ||||
-rw-r--r-- | sw/source/writerfilter/dmapper/PropertyIds.cxx | 27 | ||||
-rw-r--r-- | sw/source/writerfilter/dmapper/PropertyIds.hxx | 12 |
7 files changed, 171 insertions, 31 deletions
diff --git a/sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx b/sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx index bfcbf09fe130..4ae51bfc0758 100644 --- a/sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx +++ b/sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx @@ -229,6 +229,30 @@ CPPUNIT_TEST_FIXTURE(Test, testDOCXFloatingTableHeaderBodyOverlap) // Fly bottom was 3063, body text top was 7148. CPPUNIT_ASSERT_LESS(nBodyTextTop, nFlyBottom); } + +CPPUNIT_TEST_FIXTURE(Test, testTableStyleParaBorderSpacing) +{ + // Given a document with a table style, table style defines top and bottom border for + // paragraphs: + // When loading that document: + loadFromFile(u"table-style-para-border-spacing.docx"); + + // Then make sure the in-table paragraph gets its top border: + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xText(xTextDocument->getText(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xText->createEnumeration(); + uno::Reference<text::XTextTable> xPara(xParaEnum->nextElement(), uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xCell(xPara->getCellByName("A1"), uno::UNO_QUERY); + xParaEnum = xCell->createEnumeration(); + uno::Reference<beans::XPropertySet> xParaProps(xParaEnum->nextElement(), uno::UNO_QUERY); + sal_Int32 nTopBorderDistance{}; + xParaProps->getPropertyValue("TopBorderDistance") >>= nTopBorderDistance; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 35 + // - Actual : 0 + // i.e. the top and bottom border and its 1pt spacing was not set on the in-table paragraph. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(35), nTopBorderDistance); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/qa/writerfilter/dmapper/data/table-style-para-border-spacing.docx b/sw/qa/writerfilter/dmapper/data/table-style-para-border-spacing.docx Binary files differnew file mode 100644 index 000000000000..b8382000b2b5 --- /dev/null +++ b/sw/qa/writerfilter/dmapper/data/table-style-para-border-spacing.docx diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx index fd2811f05743..7d0593221201 100644 --- a/sw/source/core/unocore/unotext.cxx +++ b/sw/source/core/unocore/unotext.cxx @@ -2113,6 +2113,18 @@ lcl_ApplyCellProperties( { static const std::initializer_list<std::u16string_view> vDenylist = { u"LeftMargin", + u"ParaTopBorder", + u"ParaTopBorderDistance", + u"ParaTopBorderComplexColor", + u"ParaLeftBorder", + u"ParaLeftBorderDistance", + u"ParaLeftBorderComplexColor", + u"ParaBottomBorder", + u"ParaBottomBorderDistance", + u"ParaBottomBorderComplexColor", + u"ParaRightBorder", + u"ParaRightBorderDistance", + u"ParaRightBorderComplexColor", }; if (std::find(vDenylist.begin(), vDenylist.end(), rName) == vDenylist.end()) { @@ -2250,6 +2262,18 @@ SwXText::convertToTable( u"RightBorder", u"TopBorder", u"VerticalBorder", + u"ParaTopBorder", + u"ParaTopBorderDistance", + u"ParaTopBorderComplexColor", + u"ParaLeftBorder", + u"ParaLeftBorderDistance", + u"ParaLeftBorderComplexColor", + u"ParaBottomBorder", + u"ParaBottomBorderDistance", + u"ParaBottomBorderComplexColor", + u"ParaRightBorder", + u"ParaRightBorderDistance", + u"ParaRightBorderComplexColor", }; if (std::find(vDenylist.begin(), vDenylist.end(), rTableProperty.Name) == vDenylist.end()) { diff --git a/sw/source/writerfilter/dmapper/DomainMapper.cxx b/sw/source/writerfilter/dmapper/DomainMapper.cxx index 30c5f02fb693..d8c6d1ffc5d6 100644 --- a/sw/source/writerfilter/dmapper/DomainMapper.cxx +++ b/sw/source/writerfilter/dmapper/DomainMapper.cxx @@ -1656,34 +1656,65 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) PropertyIds eBorderDistId = PropertyIds::INVALID; const StyleSheetEntryPtr& pEntry = GetStyleSheetTable()->GetCurrentEntry(); - if (pEntry && pEntry->m_nStyleTypeCode == STYLE_TYPE_TABLE) - { - // This would map para borders in table style to cell borders, avoid that till we - // have separate property names for these. - break; - } + bool bInTableStyle = pEntry && pEntry->m_nStyleTypeCode == STYLE_TYPE_TABLE; switch( nSprmId ) { case NS_ooxml::LN_CT_PBdr_top: - eBorderId = PROP_TOP_BORDER; - eBorderComplexColorId = PROP_BORDER_TOP_COMPLEX_COLOR; - eBorderDistId = PROP_TOP_BORDER_DISTANCE; + if (bInTableStyle) + { + eBorderId = PROP_PARA_TOP_BORDER; + eBorderComplexColorId = PROP_PARA_BORDER_TOP_COMPLEX_COLOR; + eBorderDistId = PROP_PARA_TOP_BORDER_DISTANCE; + } + else + { + eBorderId = PROP_TOP_BORDER; + eBorderComplexColorId = PROP_BORDER_TOP_COMPLEX_COLOR; + eBorderDistId = PROP_TOP_BORDER_DISTANCE; + } break; case NS_ooxml::LN_CT_PBdr_left: - eBorderId = PROP_LEFT_BORDER; - eBorderComplexColorId = PROP_BORDER_LEFT_COMPLEX_COLOR; - eBorderDistId = PROP_LEFT_BORDER_DISTANCE; + if (bInTableStyle) + { + eBorderId = PROP_PARA_LEFT_BORDER; + eBorderComplexColorId = PROP_PARA_BORDER_LEFT_COMPLEX_COLOR; + eBorderDistId = PROP_PARA_LEFT_BORDER_DISTANCE; + } + else + { + eBorderId = PROP_LEFT_BORDER; + eBorderComplexColorId = PROP_BORDER_LEFT_COMPLEX_COLOR; + eBorderDistId = PROP_LEFT_BORDER_DISTANCE; + } break; case NS_ooxml::LN_CT_PBdr_bottom: - eBorderId = PROP_BOTTOM_BORDER; - eBorderComplexColorId = PROP_BORDER_BOTTOM_COMPLEX_COLOR; - eBorderDistId = PROP_BOTTOM_BORDER_DISTANCE; + if (bInTableStyle) + { + eBorderId = PROP_PARA_BOTTOM_BORDER; + eBorderComplexColorId = PROP_PARA_BORDER_BOTTOM_COMPLEX_COLOR; + eBorderDistId = PROP_PARA_BOTTOM_BORDER_DISTANCE; + } + else + { + eBorderId = PROP_BOTTOM_BORDER; + eBorderComplexColorId = PROP_BORDER_BOTTOM_COMPLEX_COLOR; + eBorderDistId = PROP_BOTTOM_BORDER_DISTANCE; + } break; case NS_ooxml::LN_CT_PBdr_right: - eBorderId = PROP_RIGHT_BORDER; - eBorderComplexColorId = PROP_BORDER_RIGHT_COMPLEX_COLOR; - eBorderDistId = PROP_RIGHT_BORDER_DISTANCE; + if (bInTableStyle) + { + eBorderId = PROP_PARA_RIGHT_BORDER; + eBorderComplexColorId = PROP_PARA_BORDER_RIGHT_COMPLEX_COLOR; + eBorderDistId = PROP_PARA_RIGHT_BORDER_DISTANCE; + } + else + { + eBorderId = PROP_RIGHT_BORDER; + eBorderComplexColorId = PROP_BORDER_RIGHT_COMPLEX_COLOR; + eBorderDistId = PROP_RIGHT_BORDER_DISTANCE; + } break; case NS_ooxml::LN_CT_PBdr_between: if (m_pImpl->handlePreviousParagraphBorderInBetween()) diff --git a/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx b/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx index e5332fcb79cf..1a366dff4d2c 100644 --- a/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx +++ b/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx @@ -1090,7 +1090,7 @@ void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableParag std::vector<beans::PropertyValue> aProps; std::optional<OUString> oParagraphText; - for( auto const& eId : aAllTableParaProperties ) + for( auto eId : aAllTableParaProperties ) { // apply paragraph and character properties of the table style on table paragraphs // if there is no direct paragraph formatting @@ -1104,7 +1104,51 @@ void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableParag continue; } + PropertyIds eMappedId = eId; + switch (eId) + { + case PROP_PARA_TOP_BORDER: + eMappedId = PROP_TOP_BORDER; + break; + case PROP_PARA_TOP_BORDER_DISTANCE: + eMappedId = PROP_TOP_BORDER_DISTANCE; + break; + case PROP_PARA_BORDER_TOP_COMPLEX_COLOR: + eMappedId = PROP_BORDER_TOP_COMPLEX_COLOR; + break; + case PROP_PARA_LEFT_BORDER: + eMappedId = PROP_LEFT_BORDER; + break; + case PROP_PARA_LEFT_BORDER_DISTANCE: + eMappedId = PROP_LEFT_BORDER_DISTANCE; + break; + case PROP_PARA_BORDER_LEFT_COMPLEX_COLOR: + eMappedId = PROP_BORDER_LEFT_COMPLEX_COLOR; + break; + case PROP_PARA_BOTTOM_BORDER: + eMappedId = PROP_BOTTOM_BORDER; + break; + case PROP_PARA_BOTTOM_BORDER_DISTANCE: + eMappedId = PROP_BOTTOM_BORDER_DISTANCE; + break; + case PROP_PARA_BORDER_BOTTOM_COMPLEX_COLOR: + eMappedId = PROP_BORDER_BOTTOM_COMPLEX_COLOR; + break; + case PROP_PARA_RIGHT_BORDER: + eMappedId = PROP_RIGHT_BORDER; + break; + case PROP_PARA_RIGHT_BORDER_DISTANCE: + eMappedId = PROP_RIGHT_BORDER_DISTANCE; + break; + case PROP_PARA_BORDER_RIGHT_COMPLEX_COLOR: + eMappedId = PROP_BORDER_RIGHT_COMPLEX_COLOR; + break; + default: + break; + } + OUString sPropertyName = getPropertyName(eId); + OUString sMappedPropertyName = getPropertyName(eMappedId); auto pCellProp = std::find_if(rCellProperties.begin(), rCellProperties.end(), [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; }); @@ -1169,7 +1213,7 @@ void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableParag if (!aParaStyle.hasValue() || bDocDefault || bCompatOverride) try { // apply style setting when the paragraph doesn't modify it - aProps.push_back(comphelper::makePropertyValue(sPropertyName, pCellProp->Value)); + aProps.push_back(comphelper::makePropertyValue(sMappedPropertyName, pCellProp->Value)); if (eId == PROP_FILL_COLOR) { // we need this for complete import of table-style based paragraph background color diff --git a/sw/source/writerfilter/dmapper/PropertyIds.cxx b/sw/source/writerfilter/dmapper/PropertyIds.cxx index 5aefa9d3b68b..394a3fd633b5 100644 --- a/sw/source/writerfilter/dmapper/PropertyIds.cxx +++ b/sw/source/writerfilter/dmapper/PropertyIds.cxx @@ -18,16 +18,13 @@ */ #include <rtl/ustring.hxx> #include "PropertyIds.hxx" -#include <frozen/bits/defines.h> -#include <frozen/bits/elsa_std.h> -#include <frozen/unordered_map.h> +#include <unordered_map> namespace writerfilter::dmapper{ -namespace +OUString getPropertyName( PropertyIds eId ) { - constexpr auto constPropertyMap = frozen::make_unordered_map<PropertyIds, std::u16string_view>( - { + static const std::unordered_map<PropertyIds, std::u16string_view> constPropertyMap { { PROP_CHAR_WEIGHT, u"CharWeight"}, { PROP_CHAR_POSTURE, u"CharPosture"}, { PROP_CHAR_STRIKEOUT, u"CharStrikeout"}, @@ -108,6 +105,18 @@ namespace { PROP_PARA_IS_HANGING_PUNCTUATION, u"ParaIsHangingPunctuation"}, { PROP_PARA_LINE_SPACING, u"ParaLineSpacing"}, { PROP_PARA_TAB_STOPS, u"ParaTabStops"}, + { PROP_PARA_TOP_BORDER, u"ParaTopBorder"}, + { PROP_PARA_TOP_BORDER_DISTANCE, u"ParaTopBorderDistance"}, + { PROP_PARA_BORDER_TOP_COMPLEX_COLOR, u"ParaTopBorderComplexColor"}, + { PROP_PARA_LEFT_BORDER, u"ParaLeftBorder"}, + { PROP_PARA_LEFT_BORDER_DISTANCE, u"ParaLeftBorderDistance"}, + { PROP_PARA_BORDER_LEFT_COMPLEX_COLOR, u"ParaLeftBorderComplexColor"}, + { PROP_PARA_BOTTOM_BORDER, u"ParaBottomBorder"}, + { PROP_PARA_BOTTOM_BORDER_DISTANCE, u"ParaBottomBorderDistance"}, + { PROP_PARA_BORDER_BOTTOM_COMPLEX_COLOR, u"ParaBottomBorderComplexColor"}, + { PROP_PARA_RIGHT_BORDER, u"ParaRightBorder"}, + { PROP_PARA_RIGHT_BORDER_DISTANCE, u"ParaRightBorderDistance"}, + { PROP_PARA_BORDER_RIGHT_COMPLEX_COLOR, u"ParaRightBorderComplexColor"}, { PROP_PARA_WIDOWS, u"ParaWidows"}, { PROP_PARA_ORPHANS, u"ParaOrphans"}, { PROP_PARA_LINE_NUMBER_START_VALUE, u"ParaLineNumberStartValue"}, @@ -386,11 +395,7 @@ namespace { PROP_PARA_CONNECT_BORDERS, u"ParaIsConnectBorder"}, { PROP_DECORATIVE, u"Decorative"}, { PROP_PAPER_TRAY, u"PrinterPaperTray"}, - }); -} // end anonymous ns - -OUString getPropertyName( PropertyIds eId ) -{ + }; auto iterator = constPropertyMap.find(eId); if (iterator != constPropertyMap.end()) return OUString(iterator->second); diff --git a/sw/source/writerfilter/dmapper/PropertyIds.hxx b/sw/source/writerfilter/dmapper/PropertyIds.hxx index 724648683335..82ffb1ac35d4 100644 --- a/sw/source/writerfilter/dmapper/PropertyIds.hxx +++ b/sw/source/writerfilter/dmapper/PropertyIds.hxx @@ -263,6 +263,18 @@ enum PropertyIds ,PROP_PARA_TAB_STOPS ,PROP_PARA_TOP_MARGIN ,PROP_PARA_VERT_ALIGNMENT + ,PROP_PARA_TOP_BORDER + ,PROP_PARA_TOP_BORDER_DISTANCE + ,PROP_PARA_BORDER_TOP_COMPLEX_COLOR + ,PROP_PARA_LEFT_BORDER + ,PROP_PARA_LEFT_BORDER_DISTANCE + ,PROP_PARA_BORDER_LEFT_COMPLEX_COLOR + ,PROP_PARA_BOTTOM_BORDER + ,PROP_PARA_BOTTOM_BORDER_DISTANCE + ,PROP_PARA_BORDER_BOTTOM_COMPLEX_COLOR + ,PROP_PARA_RIGHT_BORDER + ,PROP_PARA_RIGHT_BORDER_DISTANCE + ,PROP_PARA_BORDER_RIGHT_COMPLEX_COLOR ,PROP_PARA_WIDOWS ,PROP_PAPER_TRAY ,PROP_PARENT_NUMBERING |