From 3010ee15889a52b23aef278300e29f06739882d6 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 8 Feb 2021 16:49:45 +0100 Subject: tdf#91920 sw page gutter margin: handle mirrored margins - SwPageDesc::Mirror: generate "right gutter margin" from gutter margin for mirrored pages, we just lost the gutter margin here previously - SwBorderAttrs::CalcRight: handle right gutter margin, so gutter increases the right margin, not the left margin on mirrored pages - lcl_CalcBorderRect: similar to left and top margins, compensate for right margin gutter as well, so borders are independent from the gutter margin (Word compat) (cherry picked from commit ffe7fd5c3f3de474b201fbb1e25b8251cb13574d) Conflicts: editeng/source/items/frmitems.cxx include/editeng/lrspitem.hxx sw/source/core/layout/paintfrm.cxx Change-Id: Ie4d3459ab6edcc60b20c2fed08dbf45060ca9828 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110692 Tested-by: Jenkins CollaboraOffice Reviewed-by: Miklos Vajna --- editeng/source/items/frmitems.cxx | 5 +++++ include/editeng/lrspitem.hxx | 4 ++++ sw/qa/core/layout/layout.cxx | 33 +++++++++++++++++++++++++++++++++ sw/source/core/layout/frmtool.cxx | 13 +++++++++++++ sw/source/core/layout/pagedesc.cxx | 1 + sw/source/core/layout/paintfrm.cxx | 21 +++++++++++++++------ 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx index 0de646470ecb..36b32996c0db 100644 --- a/editeng/source/items/frmitems.cxx +++ b/editeng/source/items/frmitems.cxx @@ -309,6 +309,7 @@ SvxLRSpaceItem::SvxLRSpaceItem( const sal_uInt16 nId ) : nLeftMargin ( 0 ), nRightMargin ( 0 ), m_nGutterMargin(0), + m_nRightGutterMargin(0), nPropFirstLineOfst( 100 ), nPropLeftMargin( 100 ), nPropRightMargin( 100 ), @@ -329,6 +330,7 @@ SvxLRSpaceItem::SvxLRSpaceItem( const long nLeft, const long nRight, nLeftMargin ( nLeft ), nRightMargin ( nRight ), m_nGutterMargin(0), + m_nRightGutterMargin(0), nPropFirstLineOfst( 100 ), nPropLeftMargin( 100 ), nPropRightMargin( 100 ), @@ -503,6 +505,7 @@ bool SvxLRSpaceItem::operator==( const SfxPoolItem& rAttr ) const nFirstLineOfst == rOther.GetTextFirstLineOfst() && nTxtLeft == rOther.GetTextLeft() && m_nGutterMargin == rOther.GetGutterMargin() && + m_nRightGutterMargin == rOther.GetRightGutterMargin() && nLeftMargin == rOther.GetLeft() && nRightMargin == rOther.GetRight() && nPropFirstLineOfst == rOther.GetPropTextFirstLineOfst() && @@ -629,6 +632,8 @@ void SvxLRSpaceItem::dumpAsXml(xmlTextWriterPtr pWriter) const xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nRightMargin"), BAD_CAST(OString::number(nRightMargin).getStr())); xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nGutterMargin"), BAD_CAST(OString::number(m_nGutterMargin).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nRightGutterMargin"), + BAD_CAST(OString::number(m_nRightGutterMargin).getStr())); xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nPropFirstLineOfst"), BAD_CAST(OString::number(nPropFirstLineOfst).getStr())); xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nPropLeftMargin"), BAD_CAST(OString::number(nPropLeftMargin).getStr())); xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nPropRightMargin"), BAD_CAST(OString::number(nPropRightMargin).getStr())); diff --git a/include/editeng/lrspitem.hxx b/include/editeng/lrspitem.hxx index b31a5c6de1d6..ce3f23f0d89f 100644 --- a/include/editeng/lrspitem.hxx +++ b/include/editeng/lrspitem.hxx @@ -53,6 +53,8 @@ class EDITENG_DLLPUBLIC SvxLRSpaceItem final : public SfxPoolItem long nRightMargin; // The unproblematic right edge /// The amount of extra space added to the left margin. long m_nGutterMargin; + /// The amount of extra space added to the right margin, on mirrored pages. + long m_nRightGutterMargin; sal_uInt16 nPropFirstLineOfst, nPropLeftMargin, nPropRightMargin; short nFirstLineOfst; // First-line indent _always_ relative to nTxtLeft @@ -120,6 +122,8 @@ public: { nFirstLineOfst = nValue; } void SetGutterMargin(const long nGutterMargin) { m_nGutterMargin = nGutterMargin; } long GetGutterMargin() const { return m_nGutterMargin; } + void SetRightGutterMargin(const long nRightGutterMargin) { m_nRightGutterMargin = nRightGutterMargin; } + long GetRightGutterMargin() const { return m_nRightGutterMargin; } void dumpAsXml(xmlTextWriterPtr pWriter) const override; virtual boost::property_tree::ptree dumpAsJSON() const override; diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx index 33642b84776d..b98360353dc5 100644 --- a/sw/qa/core/layout/layout.cxx +++ b/sw/qa/core/layout/layout.cxx @@ -9,6 +9,8 @@ #include +#include + #include #include #include @@ -132,6 +134,37 @@ CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testGutterTopMargin) CPPUNIT_ASSERT_EQUAL(nGutterTwips, nNewTop - nOldTop); } +CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testGutterMirrorMargin) +{ + loadURL("private:factory/swriter", nullptr); + SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + SwDocShell* pDocShell = pDoc->GetDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + pWrtShell->InsertPageBreak(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + SwFrame* pPage = pLayout->GetLower(); + long nOldLeft = pPage->getFramePrintArea().Left(); + SwFrame* pPage2 = pPage->GetNext(); + long nOldRight = pPage2->getFramePrintArea().Right(); + + uno::Reference xStandard(getStyles("PageStyles")->getByName("Standard"), + uno::UNO_QUERY); + xStandard->setPropertyValue("PageStyleLayout", uno::makeAny(style::PageStyleLayout_MIRRORED)); + sal_Int32 nGutterMm100 = 2000; + xStandard->setPropertyValue("GutterMargin", uno::makeAny(nGutterMm100)); + + long nNewLeft = pPage->getFramePrintArea().Left(); + long nGutterTwips = convertMm100ToTwip(nGutterMm100); + CPPUNIT_ASSERT_EQUAL(nGutterTwips, nNewLeft - nOldLeft); + long nNewRight = pPage2->getFramePrintArea().Right(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1134 + // - Actual : 0 + // i.e. the gutter was missing on the second, mirrored page. + CPPUNIT_ASSERT_EQUAL(nGutterTwips, nOldRight - nNewRight); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index 550e54c05f70..fa8603bcc9b3 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -2252,6 +2252,19 @@ long SwBorderAttrs::CalcRight( const SwFrame* pCaller ) const nRight += static_cast(pCaller)->GetTextNodeForParaProps()->GetLeftMarginWithNum(); } + if (pCaller->IsPageFrame() && m_rLR) + { + const auto pPageFrame = static_cast(pCaller); + bool bGutterAtTop = pPageFrame->GetFormat()->getIDocumentSettingAccess().get( + DocumentSettingId::GUTTER_AT_TOP); + if (!bGutterAtTop) + { + // Decrease the print area: the right space is the sum of right and right gutter + // margins. + nRight += m_rLR->GetRightGutterMargin(); + } + } + return nRight; } diff --git a/sw/source/core/layout/pagedesc.cxx b/sw/source/core/layout/pagedesc.cxx index 06c28a3e5a40..2e472d10ad14 100644 --- a/sw/source/core/layout/pagedesc.cxx +++ b/sw/source/core/layout/pagedesc.cxx @@ -153,6 +153,7 @@ void SwPageDesc::Mirror() const SvxLRSpaceItem &rLR = m_Master.GetLRSpace(); aLR.SetLeft( rLR.GetRight() ); aLR.SetRight( rLR.GetLeft() ); + aLR.SetRightGutterMargin(rLR.GetGutterMargin()); SfxItemSet aSet( *m_Master.GetAttrSet().GetPool(), m_Master.GetAttrSet().GetRanges() ); diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 6563256804f9..921699234913 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -1269,19 +1269,28 @@ static void lcl_CalcBorderRect( SwRect &rRect, const SwFrame *pFrame, if (pFrame->IsPageFrame() && rAttrs.GetLRSpace()) { long nGutterMargin = rAttrs.GetLRSpace()->GetGutterMargin(); + long nRightGutterMargin = rAttrs.GetLRSpace()->GetRightGutterMargin(); const auto pPageFrame = static_cast(pFrame); bool bGutterAtTop = pPageFrame->GetFormat()->getIDocumentSettingAccess().get( DocumentSettingId::GUTTER_AT_TOP); - if (nGutterMargin && !bGutterAtTop) - { - // Paint the left border based on the left margin, ignoring the gutter margin. - (rRect.*fnRect->fnSubLeft)(nGutterMargin); - } - else if (nGutterMargin) + if (bGutterAtTop) { // Paint the top border based on the top margin, ignoring the gutter margin. (rRect.*fnRect->fnSubTop)(nGutterMargin); } + else + { + if (nGutterMargin) + { + // Paint the left border based on the left margin, ignoring the gutter margin. + (rRect.*fnRect->fnSubLeft)(nGutterMargin); + } + if (nRightGutterMargin) + { + // Paint the right border based on the right margin, ignoring the gutter margin. + (rRect.*fnRect->fnAddRight)(nRightGutterMargin); + } + } } const SvxBoxItem &rBox = rAttrs.GetBox(); -- cgit v1.2.3