diff options
-rw-r--r-- | sw/inc/viewsh.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/inc/hffrm.hxx | 6 | ||||
-rw-r--r-- | sw/source/core/inc/pagefrm.hxx | 3 | ||||
-rw-r--r-- | sw/source/core/layout/paintfrm.cxx | 156 | ||||
-rw-r--r-- | sw/source/core/view/viewsh.cxx | 18 |
5 files changed, 144 insertions, 41 deletions
diff --git a/sw/inc/viewsh.hxx b/sw/inc/viewsh.hxx index 8976452a0dc4..66eec0f5060e 100644 --- a/sw/inc/viewsh.hxx +++ b/sw/inc/viewsh.hxx @@ -188,6 +188,8 @@ class SW_DLLPUBLIC SwViewShell : public sw::Ring<SwViewShell> SAL_DLLPRIVATE void InvalidateAll(std::vector<LockPaintReason>& rReasons); + SAL_DLLPRIVATE void InvalidatePageAndHFSubsidiaryLines(); + protected: static ShellResource* spShellRes; ///< Resources for the Shell. static vcl::DeleteOnDeinit< std::shared_ptr<weld::Window> > spCareDialog; ///< Avoid this window. diff --git a/sw/source/core/inc/hffrm.hxx b/sw/source/core/inc/hffrm.hxx index 32af4dab9e30..4fed2517db1e 100644 --- a/sw/source/core/inc/hffrm.hxx +++ b/sw/source/core/inc/hffrm.hxx @@ -22,8 +22,13 @@ #include "layfrm.hxx" +class SwViewShell; + class SwHeadFootFrame : public SwLayoutFrame { +private: + std::vector<basegfx::B2DPolygon> GetSubsidiaryLinesPolygons(const SwViewShell& rViewShell) const; + protected: void FormatSize(SwTwips nUL, const SwBorderAttrs * pAttrs); void FormatPrt(SwTwips & nUL, const SwBorderAttrs * pAttrs); @@ -37,6 +42,7 @@ public: virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) override; virtual void PaintSubsidiaryLines( const SwPageFrame*, const SwRect& ) const override; + void AddSubsidiaryLinesBounds(const SwViewShell& rViewShell, RectangleVector& rRects) const; }; /// Header in the document layout, inside a page. diff --git a/sw/source/core/inc/pagefrm.hxx b/sw/source/core/inc/pagefrm.hxx index d85ddaecd116..53bf27a24bbc 100644 --- a/sw/source/core/inc/pagefrm.hxx +++ b/sw/source/core/inc/pagefrm.hxx @@ -123,6 +123,8 @@ class SW_DLLPUBLIC SwPageFrame final: public SwFootnoteBossFrame /// Calculate the content height of a page (without columns). size_t GetContentHeight(const tools::Long nTop, const tools::Long nBottom) const; + std::vector<basegfx::B2DPolygon> GetSubsidiaryLinesPolygons(const SwViewShell& rViewShell) const; + public: SwPageFrame( SwFrameFormat*, SwFrame*, SwPageDesc* ); @@ -189,6 +191,7 @@ public: void PaintDecorators( ) const; virtual void PaintSubsidiaryLines( const SwPageFrame*, const SwRect& ) const override; + void AddSubsidiaryLinesBounds(const SwViewShell& rShell, RectangleVector& rRects) const; virtual void PaintBreak() const override; /// Paint line number etc. diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 117ac8eb5e61..7c757e4d19ca 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -18,6 +18,7 @@ */ #include <utility> +#include <vcl/canvastools.hxx> #include <vcl/lazydelete.hxx> #include <sfx2/docfile.hxx> #include <sfx2/printer.hxx> @@ -6969,12 +6970,10 @@ static void lcl_RefreshLine( const SwLayoutFrame *pLay, } } -static drawinglayer::primitive2d::Primitive2DContainer lcl_CreatePageAreaDelimiterPrimitives( - const SwRect& rRect ) +static std::vector<basegfx::B2DPolygon> lcl_CreatePageAreaDelimiterPolygons(const SwRect& rRect) { - drawinglayer::primitive2d::Primitive2DContainer aSeq( 4 ); + std::vector<basegfx::B2DPolygon> aPolygons; - basegfx::BColor aLineColor = SwViewOption::GetCurrentViewOptions().GetDocBoundariesColor().getBColor(); double nLineLength = 200.0; // in Twips Point aPoints[] = { rRect.TopLeft(), rRect.TopRight(), rRect.BottomRight(), rRect.BottomLeft() }; @@ -6994,30 +6993,39 @@ static drawinglayer::primitive2d::Primitive2DContainer lcl_CreatePageAreaDelimit aPolygon.append( aBPoint ); aPolygon.append( aBPoint + aVertVector * nLineLength ); - aSeq[i] = new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( - std::move(aPolygon), aLineColor ); + aPolygons.emplace_back(aPolygon); } - return aSeq; + return aPolygons; } -static drawinglayer::primitive2d::Primitive2DContainer lcl_CreateRectangleDelimiterPrimitives ( - const SwRect& rRect ) +static drawinglayer::primitive2d::Primitive2DContainer lcl_CreateDelimiterPrimitives( + const std::vector<basegfx::B2DPolygon>& rPolygons) { - drawinglayer::primitive2d::Primitive2DContainer aSeq( 1 ); + drawinglayer::primitive2d::Primitive2DContainer aSeq(rPolygons.size()); + basegfx::BColor aLineColor = SwViewOption::GetCurrentViewOptions().GetDocBoundariesColor().getBColor(); + for (size_t i = 0; i < rPolygons.size(); ++i) + aSeq[i] = new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(rPolygons[i], aLineColor); - basegfx::B2DPolygon aPolygon; - aPolygon.append( basegfx::B2DPoint( rRect.Left(), rRect.Top() ) ); - aPolygon.append( basegfx::B2DPoint( rRect.Right(), rRect.Top() ) ); - aPolygon.append( basegfx::B2DPoint( rRect.Right(), rRect.Bottom() ) ); - aPolygon.append( basegfx::B2DPoint( rRect.Left(), rRect.Bottom() ) ); - aPolygon.setClosed( true ); + return aSeq; +} - aSeq[0] = new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( - std::move(aPolygon), aLineColor ); +static std::vector<basegfx::B2DPolygon> lcl_CreateRectangleDelimiterPolygons(const SwRect& rRect) +{ + std::vector<basegfx::B2DPolygon> aRet(1); + aRet[0].append( basegfx::B2DPoint( rRect.Left(), rRect.Top() ) ); + aRet[0].append( basegfx::B2DPoint( rRect.Right(), rRect.Top() ) ); + aRet[0].append( basegfx::B2DPoint( rRect.Right(), rRect.Bottom() ) ); + aRet[0].append( basegfx::B2DPoint( rRect.Left(), rRect.Bottom() ) ); + aRet[0].setClosed( true ); + return aRet; +} - return aSeq; +static drawinglayer::primitive2d::Primitive2DContainer lcl_CreateRectangleDelimiterPrimitives ( + const SwRect& rRect ) +{ + return lcl_CreateDelimiterPrimitives(lcl_CreateRectangleDelimiterPolygons(rRect)); } static drawinglayer::primitive2d::Primitive2DContainer lcl_CreateColumnAreaDelimiterPrimitives( @@ -7052,14 +7060,12 @@ static drawinglayer::primitive2d::Primitive2DContainer lcl_CreateColumnAreaDelim return aSeq; } -void SwPageFrame::PaintSubsidiaryLines( const SwPageFrame *, - const SwRect & ) const +std::vector<basegfx::B2DPolygon> SwPageFrame::GetSubsidiaryLinesPolygons(const SwViewShell& rViewShell) const { - if (!gProp.pSGlobalShell->GetViewOptions()->IsDocBoundaries()) - return; + std::vector<basegfx::B2DPolygon> aPolygons; - if ( gProp.pSGlobalShell->IsHeaderFooterEdit() ) - return; + if (!rViewShell.GetViewOptions()->IsDocBoundaries()) + return aPolygons; const SwFrame* pLay = Lower(); const SwFrame* pFootnoteCont = nullptr; @@ -7079,10 +7085,64 @@ void SwPageFrame::PaintSubsidiaryLines( const SwPageFrame *, if ( pFootnoteCont ) aArea.AddBottom( pFootnoteCont->getFrameArea().Bottom() - aArea.Bottom() ); - if ( !gProp.pSGlobalShell->GetViewOptions()->IsViewMetaChars( ) ) - ProcessPrimitives( lcl_CreatePageAreaDelimiterPrimitives( aArea ) ); + if (aArea.IsEmpty()) + return aPolygons; + + if (!rViewShell.GetViewOptions()->IsViewMetaChars()) + aPolygons = lcl_CreatePageAreaDelimiterPolygons(aArea); else - ProcessPrimitives( lcl_CreateRectangleDelimiterPrimitives( aArea ) ); + aPolygons = lcl_CreateRectangleDelimiterPolygons(aArea); + + return aPolygons; +} + +void SwPageFrame::PaintSubsidiaryLines(const SwPageFrame*, const SwRect&) const +{ + if (gProp.pSGlobalShell->IsHeaderFooterEdit()) + return; + + std::vector<basegfx::B2DPolygon> aPolygons = GetSubsidiaryLinesPolygons(*gProp.pSGlobalShell); + if (aPolygons.empty()) + return; + + ProcessPrimitives(lcl_CreateDelimiterPrimitives(aPolygons)); +} + +static void lclAddSubsidiaryLinesBounds(const std::vector<basegfx::B2DPolygon>& rPolygons, RectangleVector& rRects) +{ + for (const auto& rPolygon : rPolygons) + { + tools::Rectangle aRect(vcl::unotools::rectangleFromB2DRectangle(rPolygon.getB2DRange())); + aRect.expand(1); + if (basegfx::utils::isRectangle(rPolygon) && aRect.GetWidth() > 4 && aRect.GetHeight() > 4) + { + // turn hairline rectangle into four non-overlapping blocks that cover the borders + rRects.emplace_back(tools::Rectangle(Point(aRect.Left(), aRect.Top()), Size(aRect.GetWidth(), 2))); + rRects.emplace_back(tools::Rectangle(Point(aRect.Left(), aRect.Top() + 2), Size(2, aRect.GetHeight() - 4))); + rRects.emplace_back(tools::Rectangle(Point(aRect.Right() - 2, aRect.Top() + 2), Size(2, aRect.GetHeight() - 4))); + rRects.emplace_back(tools::Rectangle(Point(aRect.Left(), aRect.Top() + aRect.GetHeight() - 2), Size(aRect.GetWidth(), 2))); + } + else + rRects.emplace_back(aRect); + } +} + +void SwPageFrame::AddSubsidiaryLinesBounds(const SwViewShell& rViewShell, RectangleVector& rRects) const +{ + lclAddSubsidiaryLinesBounds(GetSubsidiaryLinesPolygons(rViewShell), rRects); + + const SwFrame *pLow = Lower(); + while (pLow) + { + if (pLow->getFrameArea().HasArea()) + { + if (pLow->IsHeaderFrame() || pLow->IsFooterFrame()) + { + static_cast<const SwHeadFootFrame*>(pLow)->AddSubsidiaryLinesBounds(rViewShell, rRects); + } + } + pLow = pLow->GetNext(); + } } void SwColumnFrame::PaintSubsidiaryLines( const SwPageFrame *, @@ -7148,20 +7208,38 @@ void SwBodyFrame::PaintSubsidiaryLines( const SwPageFrame *, { } -void SwHeadFootFrame::PaintSubsidiaryLines( const SwPageFrame *, const SwRect & ) const +std::vector<basegfx::B2DPolygon> SwHeadFootFrame::GetSubsidiaryLinesPolygons(const SwViewShell& rViewShell) const +{ + std::vector<basegfx::B2DPolygon> aPolygons; + + if (!rViewShell.GetViewOptions()->IsDocBoundaries()) + return aPolygons; + + SwRect aArea( getFramePrintArea() ); + aArea.Pos() += getFrameArea().Pos(); + if (!rViewShell.GetViewOptions()->IsViewMetaChars( )) + aPolygons = lcl_CreatePageAreaDelimiterPolygons(aArea); + else + aPolygons = lcl_CreateRectangleDelimiterPolygons(aArea); + + return aPolygons; +} + +void SwHeadFootFrame::PaintSubsidiaryLines(const SwPageFrame*, const SwRect&) const { - if (!gProp.pSGlobalShell->GetViewOptions()->IsDocBoundaries()) + if (!gProp.pSGlobalShell->IsHeaderFooterEdit()) return; - if ( gProp.pSGlobalShell->IsHeaderFooterEdit() ) - { - SwRect aArea( getFramePrintArea() ); - aArea.Pos() += getFrameArea().Pos(); - if ( !gProp.pSGlobalShell->GetViewOptions()->IsViewMetaChars( ) ) - ProcessPrimitives( lcl_CreatePageAreaDelimiterPrimitives( aArea ) ); - else - ProcessPrimitives( lcl_CreateRectangleDelimiterPrimitives( aArea ) ); - } + std::vector<basegfx::B2DPolygon> aPolygons = GetSubsidiaryLinesPolygons(*gProp.pSGlobalShell); + if (aPolygons.empty()) + return; + + ProcessPrimitives(lcl_CreateDelimiterPrimitives(aPolygons)); +} + +void SwHeadFootFrame::AddSubsidiaryLinesBounds(const SwViewShell& rViewShell, RectangleVector& rRects) const +{ + lclAddSubsidiaryLinesBounds(GetSubsidiaryLinesPolygons(rViewShell), rRects); } /** diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx index 9074f43ab8b4..a77d0ccc8bcf 100644 --- a/sw/source/core/view/viewsh.cxx +++ b/sw/source/core/view/viewsh.cxx @@ -126,8 +126,22 @@ void SwViewShell::ToggleHeaderFooterEdit() mbHeaderFooterEdit = false; } - // Repaint everything - GetWin()->Invalidate(); + InvalidatePageAndHFSubsidiaryLines(); +} + +// Invalidate Subsidiary Lines around headers/footers and page frames to repaint +void SwViewShell::InvalidatePageAndHFSubsidiaryLines() +{ + RectangleVector aInvalidRects; + SwPageFrame *pPg = static_cast<SwPageFrame*>(GetLayout()->Lower()); + while (pPg) + { + pPg->AddSubsidiaryLinesBounds(*this, aInvalidRects); + pPg = static_cast<SwPageFrame*>(pPg->GetNext()); + } + + for (const auto &rRect : aInvalidRects) + GetWin()->Invalidate(rRect); } void SwViewShell::setOutputToWindow(bool bOutputToWindow) |