diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2023-10-27 19:45:09 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2023-11-02 10:47:20 +0100 |
commit | 5726be1314517d47dd733aabe64a3d85cce094c5 (patch) | |
tree | f9cd974c034c48ec10996466fa7a14af5240bc23 /sw | |
parent | 6593d680e21c24501a58bac216de4a7c71541959 (diff) |
tdf#157816 sw: PDF export: filter out links on empty space, INetAttrs
Several problems here:
* As with fields, there may be selection rectangles with no text
* SwRootFrame::CalcFrameRects() adds flys that are anchored in the
selection to the selection
* A fly text portion causes Link annotations to split, but not Link SE
* If a fly only partially overlaps a line vertically, then
CalcFrameRects() produces a full-width half-height rectangle and
another 2 half-width half-height rectangles on both sides.
This is useless, the rectangles must be full line height.
Add some code in CalcFrameRects() to use the fly portions in the
SwParaPortion instead of the fly frame areas.
Change-Id: I93f0c12a5e5a3d5f51fcc4b33052a112e9174863
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158576
Tested-by: Michael Stahl <michael.stahl@allotropia.de>
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/source/core/crsr/viscrs.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/inc/rootfrm.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/layout/trvlfrm.cxx | 49 | ||||
-rw-r--r-- | sw/source/core/text/EnhancedPDFExportHelper.cxx | 18 |
4 files changed, 66 insertions, 9 deletions
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx index da9c043c6581..f681f3a32815 100644 --- a/sw/source/core/crsr/viscrs.cxx +++ b/sw/source/core/crsr/viscrs.cxx @@ -954,7 +954,9 @@ void SwShellCursor::FillRects() (GetMark()->GetNode() == GetPoint()->GetNode() || (GetMark()->GetNode().IsContentNode() && GetMark()->GetNode().GetContentNode()->getLayoutFrame( GetShell()->GetLayout() ) ) )) - GetShell()->GetLayout()->CalcFrameRects( *this ); + { + GetShell()->GetLayout()->CalcFrameRects(*this, *this); + } } void SwShellCursor::Show(SfxViewShell const * pViewShell) diff --git a/sw/source/core/inc/rootfrm.hxx b/sw/source/core/inc/rootfrm.hxx index 29f813360d82..90d18fcf0ee4 100644 --- a/sw/source/core/inc/rootfrm.hxx +++ b/sw/source/core/inc/rootfrm.hxx @@ -20,6 +20,7 @@ #define INCLUDED_SW_SOURCE_CORE_INC_ROOTFRM_HXX #include "layfrm.hxx" +#include <swregion.hxx> #include <viewsh.hxx> #include <doc.hxx> #include <IDocumentTimerAccess.hxx> @@ -343,7 +344,8 @@ public: */ bool IsBetweenPages(const Point& rPt) const; - void CalcFrameRects( SwShellCursor& ); + enum class RectsMode { Default, NoAnchoredFlys }; + void CalcFrameRects(SwShellCursor const&, SwRects &, RectsMode eMode = RectsMode::Default); /** * Calculates the cells included from the current selection diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx index fab57c35c24b..d79ffab813aa 100644 --- a/sw/source/core/layout/trvlfrm.cxx +++ b/sw/source/core/layout/trvlfrm.cxx @@ -47,6 +47,8 @@ #include <fldbas.hxx> #include <frmatr.hxx> #include <frmtool.hxx> +#include "../text/inftxt.hxx" +#include "../text/itrpaint.hxx" #include <ndtxt.hxx> #include <undobj.hxx> @@ -2016,7 +2018,7 @@ static void Add( SwRegionRects& rRegion, const SwRect& rRect ) * rectangles are available for highlighting. * In the end the Flys are cut out of the region. */ -void SwRootFrame::CalcFrameRects(SwShellCursor &rCursor) +void SwRootFrame::CalcFrameRects(SwShellCursor const& rCursor, SwRects & rRects, RectsMode const eMode) { auto [pStartPos, pEndPos] = rCursor.StartEnd(); // SwPosition* @@ -2570,7 +2572,46 @@ void SwRootFrame::CalcFrameRects(SwShellCursor &rCursor) const SwPageFrame *pPage = pStartFrame->FindPageFrame(); const SwPageFrame *pEndPage = pEndFrame->FindPageFrame(); - while ( pPage ) + // for link rectangles: just remove all the fly portions - this prevents + // splitting of portions vertically (causes spurious extra PDF annotations) + if (eMode == RectsMode::NoAnchoredFlys) + { + assert(pStartFrame == pEndFrame); // link or field all in 1 frame + assert(pStartFrame->IsTextFrame()); + SwTextGridItem const*const pGrid(GetGridItem(pStartFrame->FindPageFrame())); + SwTextPaintInfo info(static_cast<SwTextFrame*>(pStartFrame), pStartFrame->FindPageFrame()->getFrameArea()); + SwTextPainter painter(static_cast<SwTextFrame*>(pStartFrame), &info); + // because nothing outside the start/end has been added, it doesn't + // matter to match exactly the start/end, subtracting outside is no-op + painter.CharToLine(static_cast<SwTextFrame*>(pStartFrame)->MapModelToViewPos(*pStartPos)); + do + { + info.SetPos(painter.GetTopLeft()); + bool const bAdjustBaseLine( + painter.GetLineInfo().HasSpecialAlign(pStartFrame->IsVertical()) + || nullptr != pGrid || painter.GetCurr()->GetHangingBaseline()); + SwTwips nAscent, nHeight; + painter.CalcAscentAndHeight(nAscent, nHeight); + SwTwips const nOldY(info.Y()); + for (SwLinePortion const* pLP = painter.GetCurr()->GetFirstPortion(); + pLP; pLP = pLP->GetNextPortion()) + { + if (pLP->IsFlyPortion()) + { + info.Y(info.Y() + (bAdjustBaseLine + ? painter.AdjustBaseLine(*painter.GetCurr(), pLP) + : nAscent)); + SwRect flyPortion; + info.CalcRect(*pLP, &flyPortion); + Sub(aRegion, flyPortion); + info.Y(nOldY); + } + pLP->Move(info); + } + } + while (painter.Next()); + } + else while (pPage) { if ( pPage->GetSortedObjs() ) { @@ -2590,7 +2631,7 @@ void SwRootFrame::CalcFrameRects(SwShellCursor &rCursor) && IsDestroyFrameAnchoredAtChar(*anchoredAt, *pStartPos, *pEndPos)) || (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA && IsSelectFrameAnchoredAtPara(*anchoredAt, *pStartPos, *pEndPos)))); - if( inSelection ) + if (eMode != RectsMode::NoAnchoredFlys && inSelection) Add( aRegion, pFly->getFrameArea() ); else if ( !pFly->IsAnLower( pStartFrame ) && (rSur.GetSurround() != css::text::WrapTextMode_THROUGH && @@ -2642,7 +2683,7 @@ void SwRootFrame::CalcFrameRects(SwShellCursor &rCursor) Sub( aRegion, aDropRect ); } - rCursor.assign( aRegion.begin(), aRegion.end() ); + rRects.assign( aRegion.begin(), aRegion.end() ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx b/sw/source/core/text/EnhancedPDFExportHelper.cxx index 946def82f719..e224d33901a4 100644 --- a/sw/source/core/text/EnhancedPDFExportHelper.cxx +++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx @@ -349,7 +349,9 @@ bool lcl_TryMoveToNonHiddenField(SwEditShell& rShell, const SwTextNode& rNd, con ::std::vector<SwRect> GetCursorRectsContainingText(SwCursorShell const& rShell) { ::std::vector<SwRect> ret; - for (SwRect const& rRect : *rShell.GetCursor_()) + SwRects rects; + rShell.GetLayout()->CalcFrameRects(*rShell.GetCursor_(), rects, SwRootFrame::RectsMode::NoAnchoredFlys); + for (SwRect const& rRect : rects) { Point center(rRect.Center()); SwSpecialPos special; @@ -1824,6 +1826,17 @@ void SwTaggedPDFHelper::BeginInlineStructureElements() aPDFType = aSpanString; break; + case PortionType::Fly: + // if a link is split by a fly overlap, then there will be multiple + // annotations for the link, and hence there must be multiple SEs, + // so every annotation has its own SE. + if (mpPDFExtOutDevData->GetSwPDFState()->m_oCurrentLink) + { + mpPDFExtOutDevData->GetSwPDFState()->m_oCurrentLink.reset(); + EndTag(); + } + break; + case PortionType::Lay : case PortionType::Text : case PortionType::Para : @@ -2193,8 +2206,7 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe // selection can be easily obtained: // Note: We make a copy of the rectangles, because they may // be deleted again in JumpToSwMark. - SwRects aTmp; - aTmp.insert( aTmp.begin(), mrSh.SwCursorShell::GetCursor_()->begin(), mrSh.SwCursorShell::GetCursor_()->end() ); + SwRects const aTmp(GetCursorRectsContainingText(mrSh)); OSL_ENSURE( !aTmp.empty(), "Enhanced pdf export - rectangles are missing" ); OUString const altText(mrSh.GetSelText()); |