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 60a1f07049a817d4d3d7beb6c9b9da2571e2463b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Feb 1 15:17:40 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Feb 2 09:09:48 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.
    
    Change-Id: I38fbf8adbc87ecd217a11b177840b0fede4cdf8c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129281
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

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 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;
 

Reply via email to