summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2024-06-11 10:49:29 +0200
committerMiklos Vajna <vmiklos@collabora.com>2024-06-11 12:09:51 +0200
commit013300c751d7a9ede12c1bf1c784254d1c6c5433 (patch)
tree8490f4e3b20125a97556fc1ee9395413dd238c24
parent19e9e49bdaeebc314c892c000385ec778edf759b (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.cxx24
-rw-r--r--sw/qa/writerfilter/dmapper/data/table-style-para-border-spacing.docxbin0 -> 12560 bytes
-rw-r--r--sw/source/core/unocore/unotext.cxx24
-rw-r--r--sw/source/writerfilter/dmapper/DomainMapper.cxx67
-rw-r--r--sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx48
-rw-r--r--sw/source/writerfilter/dmapper/PropertyIds.cxx27
-rw-r--r--sw/source/writerfilter/dmapper/PropertyIds.hxx12
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
new file mode 100644
index 000000000000..b8382000b2b5
--- /dev/null
+++ b/sw/qa/writerfilter/dmapper/data/table-style-para-border-spacing.docx
Binary files differ
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