sw/qa/core/layout/data/double-page-border.docx |binary sw/qa/core/layout/layout.cxx | 48 +++++++++++++++++++++++++ sw/source/core/layout/paintfrm.cxx | 23 +++++++++-- 3 files changed, 66 insertions(+), 5 deletions(-)
New commits: commit 69a036043a1b7ba1cff2e17016a73e94055baced Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Feb 1 15:17:40 2022 +0100 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Feb 11 09:25:53 2022 +0100 sw: fix swapped inner vs outer border for Word-style right/bottom page borders This is similar to commit cf2690ae76b4250af32be7c8980b8d83b3611591 (sw: fix swapped inner vs outer border for Word-style bottom table borders, 2022-01-13), but that was for outer table borders, this one is for page borders. The explicit mirroring is needed because Writer will automatically mirror, but Word mirrors in its document model, so we need to "mirror back" to get the matching rendering. (cherry picked from commit 60a1f07049a817d4d3d7beb6c9b9da2571e2463b) Change-Id: I38fbf8adbc87ecd217a11b177840b0fede4cdf8c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129770 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/core/layout/data/double-page-border.docx b/sw/qa/core/layout/data/double-page-border.docx new file mode 100644 index 000000000000..a706b327cd05 Binary files /dev/null and b/sw/qa/core/layout/data/double-page-border.docx differ diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx index a02e17fb8bde..abd77b3e217d 100644 --- a/sw/qa/core/layout/layout.cxx +++ b/sw/qa/core/layout/layout.cxx @@ -694,6 +694,54 @@ CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testParaBorderInCellClip) assertXPath(pXmlDoc, "//clipregion/polygon", 2); } +CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testDoublePageBorder) +{ + // Given a page with a top and bottom double border, outer is thick, inner is thin: + SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "double-page-border.docx"); + SwDocShell* pShell = pDoc->GetDocShell(); + + // When rendering that document: + std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile(); + + // Then make sure the top border is thick+thing and the bottom border is thin+thick (from top to + // bottom): + MetafileXmlDump dumper; + xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile); + // Collect widths of horizontal lines. + xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, "//polyline[@style='solid']/point"); + xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval; + // Vertical position -> width. + std::map<sal_Int32, sal_Int32> aBorderWidths; + for (int i = 0; i < xmlXPathNodeSetGetLength(pXmlNodes); i += 2) + { + xmlNodePtr pStart = pXmlNodes->nodeTab[i]; + xmlNodePtr pEnd = pXmlNodes->nodeTab[i + 1]; + xmlChar* pStartY = xmlGetProp(pStart, BAD_CAST("y")); + xmlChar* pEndY = xmlGetProp(pEnd, BAD_CAST("y")); + sal_Int32 nStartY = OString(reinterpret_cast<char const*>(pStartY)).toInt32(); + sal_Int32 nEndY = OString(reinterpret_cast<char const*>(pEndY)).toInt32(); + if (nStartY != nEndY) + { + // Vertical border. + continue; + } + xmlChar* pWidth = xmlGetProp(pStart->parent, BAD_CAST("width")); + sal_Int32 nWidth = OString(reinterpret_cast<char const*>(pWidth)).toInt32(); + aBorderWidths[nStartY] = nWidth; + } + xmlXPathFreeObject(pXmlObj); + std::vector<sal_Int32> aBorderWidthVec; + std::transform(aBorderWidths.begin(), aBorderWidths.end(), std::back_inserter(aBorderWidthVec), + [](const std::pair<sal_Int32, sal_Int32>& rPair) { return rPair.second; }); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), aBorderWidthVec.size()); + CPPUNIT_ASSERT_GREATER(aBorderWidthVec[1], aBorderWidthVec[0]); + // Without the accompanying fix in place, this test would have failed with: + // - Expected greater than: 60 + // - Actual : 15 + // i.e. the bottom border was thick+thin, not thin+thick. + CPPUNIT_ASSERT_GREATER(aBorderWidthVec[2], aBorderWidthVec[3]); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 1b2a7379b17f..b1b3bef8e42f 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -5358,14 +5358,14 @@ void SwFrame::PaintSwFrameShadowAndBorder( pBottomBorder = aAccess.Get()->GetBox().GetBottom(); } - bool bWordTableCell = false; + bool bWordBorder = false; SwViewShell* pShell = getRootFrame()->GetCurrShell(); if (pShell) { const IDocumentSettingAccess& rIDSA = pShell->GetDoc()->getIDocumentSettingAccess(); - bWordTableCell = rIDSA.get(DocumentSettingId::TABLE_ROW_KEEP); + bWordBorder = rIDSA.get(DocumentSettingId::TABLE_ROW_KEEP); } - bool bInWordTableCell = IsContentFrame() && GetUpper()->IsCellFrame() && bWordTableCell; + bool bInWordTableCell = IsContentFrame() && GetUpper()->IsCellFrame() && bWordBorder; if (bInWordTableCell) { // Compat mode: don't paint bottom border if we know the bottom of the content was cut @@ -5385,8 +5385,21 @@ void SwFrame::PaintSwFrameShadowAndBorder( aRect.Width(), aRect.Height(), aRect.Left(), aRect.Top())); const svx::frame::Style aStyleTop(pTopBorder, 1.0); - const svx::frame::Style aStyleRight(pRightBorder, 1.0); - const svx::frame::Style aStyleBottom(pBottomBorder, 1.0); + svx::frame::Style aStyleRight(pRightBorder, 1.0); + + // Right/bottom page borders are always mirrored in Word. + if (IsPageFrame() && bWordBorder) + { + aStyleRight.MirrorSelf(); + } + + svx::frame::Style aStyleBottom(pBottomBorder, 1.0); + + if (IsPageFrame() && bWordBorder) + { + aStyleBottom.MirrorSelf(); + } + const svx::frame::Style aStyleLeft(pLeftBorder, 1.0); drawinglayer::primitive2d::Primitive2DContainer aBorderLineTarget;