summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-01-18 17:04:14 +0100
committerMike Kaganski <mike.kaganski@collabora.com>2022-02-11 09:23:54 +0100
commit797aa8d22b8c5cdc7400c1853695a587dd3f03ae (patch)
treed0556878a53f11fa84b2cb07a49c0a7f82649e76
parentsw: fix swapped inner vs outer border for Word-style bottom table borders (diff)
downloadcore-797aa8d22b8c5cdc7400c1853695a587dd3f03ae.tar.gz
core-797aa8d22b8c5cdc7400c1853695a587dd3f03ae.zip
sw: fix unexpected paragraph border inside table cells
The bug document has a table cell, which contains a paragraph with borders. Its left/right/bottom borders are rendered in Writer, but not in Word. The reason for the left/right border is that it's outside the paragraph's frame area, which is not rendered in Word. Fix this by clipping the rendered borders so they don't go outside the paragraph's frame area. (Normally the frame area is the larger rectangle, and then margins may cause a smaller "print area", but in this case we have a negative right margin, so clipping the print area to fit into the frame area actually does something.) This is quite similar to what commit 1e21902106cbe57658bed03ed24d4d0863685cfd (tdf#117884: intersect border with paint area of upper frame., 2018-05-26) did for table borders. The bottom border is a different problem: the cell has a fixed height and enough content so the paragraph is cut off vertically. This means that technically the bottom border would be inside the frame area, but Word cuts it off, because they apply clipping on the not-yet-cut-off rectangle. Fix this by dropping the bottom margin when the frame is cut off. (cherry picked from commit 4a7281fa206c0a82cfc2ba23f25c31ae775d8777) Change-Id: I7f65b68997330b247db65839db8a484e74f78c64 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129769 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--sw/qa/core/layout/data/para-border-in-cell-clip.docxbin0 -> 12524 bytes
-rw-r--r--sw/qa/core/layout/layout.cxx20
-rw-r--r--sw/source/core/layout/paintfrm.cxx40
3 files changed, 57 insertions, 3 deletions
diff --git a/sw/qa/core/layout/data/para-border-in-cell-clip.docx b/sw/qa/core/layout/data/para-border-in-cell-clip.docx
new file mode 100644
index 000000000000..7c516853648c
--- /dev/null
+++ b/sw/qa/core/layout/data/para-border-in-cell-clip.docx
Binary files differ
diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx
index 4ed97597ffcc..a02e17fb8bde 100644
--- a/sw/qa/core/layout/layout.cxx
+++ b/sw/qa/core/layout/layout.cxx
@@ -674,6 +674,26 @@ CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testDoubleBorderHorizontal)
CPPUNIT_ASSERT_GREATER(aBorderWidthVec[3], aBorderWidthVec[2]);
}
+CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testParaBorderInCellClip)
+{
+ // Given a document which has outside-cell borders defined, which should not be visible:
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "para-border-in-cell-clip.docx");
+ SwDocShell* pShell = pDoc->GetDocShell();
+
+ // When rendering those borders:
+ std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
+
+ // Then make sure that we have clipping setup for both paragraphs inside the table cell:
+ MetafileXmlDump dumper;
+ xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 2
+ // - Actual : 0
+ // - XPath '//clipregion/polygon' number of nodes is incorrect
+ // i.e. there was no clipping applied, leading to unexpected left/right borders.
+ assertXPath(pXmlDoc, "//clipregion/polygon", 2);
+}
+
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 656646420dc5..1b2a7379b17f 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -118,6 +118,7 @@
#include <comphelper/lok.hxx>
#include <svtools/optionsdrawinglayer.hxx>
#include <vcl/GraphicLoader.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
using namespace ::editeng;
using namespace ::com::sun::star;
@@ -5357,6 +5358,25 @@ void SwFrame::PaintSwFrameShadowAndBorder(
pBottomBorder = aAccess.Get()->GetBox().GetBottom();
}
+ bool bWordTableCell = false;
+ SwViewShell* pShell = getRootFrame()->GetCurrShell();
+ if (pShell)
+ {
+ const IDocumentSettingAccess& rIDSA = pShell->GetDoc()->getIDocumentSettingAccess();
+ bWordTableCell = rIDSA.get(DocumentSettingId::TABLE_ROW_KEEP);
+ }
+ bool bInWordTableCell = IsContentFrame() && GetUpper()->IsCellFrame() && bWordTableCell;
+ if (bInWordTableCell)
+ {
+ // Compat mode: don't paint bottom border if we know the bottom of the content was cut
+ // off.
+ auto pContentFrame = static_cast<const SwContentFrame*>(this);
+ if (pContentFrame->IsUndersized())
+ {
+ pBottomBorder = nullptr;
+ }
+ }
+
if(nullptr != pLeftBorder || nullptr != pRightBorder || nullptr != pTopBorder || nullptr != pBottomBorder)
{
// now we have all SvxBorderLine(s) sorted out, create geometry
@@ -5370,14 +5390,28 @@ void SwFrame::PaintSwFrameShadowAndBorder(
const svx::frame::Style aStyleLeft(pLeftBorder, 1.0);
drawinglayer::primitive2d::Primitive2DContainer aBorderLineTarget;
- aBorderLineTarget.append(
- drawinglayer::primitive2d::Primitive2DReference(
+ drawinglayer::primitive2d::Primitive2DReference aRetval(
new drawinglayer::primitive2d::SwBorderRectanglePrimitive2D(
aBorderTransform,
aStyleTop,
aStyleRight,
aStyleBottom,
- aStyleLeft)));
+ aStyleLeft));
+
+ if (bInWordTableCell)
+ {
+ // Compat mode: cut off the borders which are outside of our own area.
+ const SwRect& rClip = getFrameArea();
+ basegfx::B2DRectangle aClip(rClip.Left(), rClip.Top(), rClip.Right(),
+ rClip.Bottom());
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::utils::createPolygonFromRect(aClip));
+ const drawinglayer::primitive2d::Primitive2DReference xClipped(
+ new drawinglayer::primitive2d::MaskPrimitive2D(aPolyPolygon, { aRetval }));
+ aRetval = xClipped;
+ }
+
+ aBorderLineTarget.append(aRetval);
gProp.pBLines->AddBorderLines(std::move(aBorderLineTarget));
}
}