summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-02-01 15:17:40 +0100
committerMiklos Vajna <vmiklos@collabora.com>2022-02-02 09:09:48 +0100
commit60a1f07049a817d4d3d7beb6c9b9da2571e2463b (patch)
tree74b58403f9e16374fb4d6a6ff7dbfc77fe0abb4c
parent74bcd46bbf4cb88112b054e5b192a995f3ef354a (diff)
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. Change-Id: I38fbf8adbc87ecd217a11b177840b0fede4cdf8c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129281 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--sw/qa/core/layout/data/double-page-border.docxbin0 -> 12053 bytes
-rw-r--r--sw/qa/core/layout/layout.cxx48
-rw-r--r--sw/source/core/layout/paintfrm.cxx23
3 files changed, 66 insertions, 5 deletions
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
--- /dev/null
+++ b/sw/qa/core/layout/data/double-page-border.docx
Binary files differ
diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx
index 8b8174d76941..a31646704cbd 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 868817ff5147..82601c6334f6 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -5360,14 +5360,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
@@ -5387,8 +5387,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;