1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SW_SOURCE_CORE_INC_FRMTOOL_HXX
21 #define INCLUDED_SW_SOURCE_CORE_INC_FRMTOOL_HXX
23 #include <swtypes.hxx>
24 #include <frameformats.hxx>
25 #include <BorderCacheOwner.hxx>
28 #include "swcache.hxx"
29 #include <swatrset.hxx>
50 namespace sw
{ struct Extent
; }
51 namespace basegfx::utils
{ class B2DClipState
; }
53 #define FAR_AWAY (SAL_MAX_INT32 - 20000) // initial position of a Fly
54 constexpr tools::Long BROWSE_HEIGHT
= 56700 * 10; // 10 Meters
57 #define GRFNUM_REPLACE 2
59 void AppendObjs(const sw::FrameFormats
<sw::SpzFrameFormat
*>* pSpz
, SwNodeOffset nIndex
, SwFrame
* pFrame
, SwPageFrame
* pPage
, SwDoc
* doc
);
61 void AppendObjsOfNode(sw::FrameFormats
<sw::SpzFrameFormat
*> const* pTable
, SwNodeOffset nIndex
,
62 SwFrame
* pFrame
, SwPageFrame
* pPage
, SwDoc
* pDoc
,
63 std::vector
<sw::Extent
>::const_iterator
const* pIter
,
64 std::vector
<sw::Extent
>::const_iterator
const* pEnd
,
65 SwTextNode
const* pFirstNode
, SwTextNode
const* pLastNode
);
67 void RemoveHiddenObjsOfNode(SwTextNode
const& rNode
,
68 std::vector
<sw::Extent
>::const_iterator
const* pIter
,
69 std::vector
<sw::Extent
>::const_iterator
const* pEnd
,
70 SwTextNode
const* pFirstNode
, SwTextNode
const* pLastNode
);
72 bool IsAnchoredObjShown(SwTextFrame
const& rFrame
, SwFormatAnchor
const& rAnchor
);
74 void AppendAllObjs(const sw::FrameFormats
<sw::SpzFrameFormat
*>* pSpzs
, const SwFrame
* pSib
);
76 // draw background with brush or graphics
77 // The 6th parameter indicates that the method should consider background
78 // transparency, saved in the color of the brush item.
84 const sal_uInt8 nGrfNum
= GRFNUM_NO
,
85 const bool bConsiderBackgroundTransparency
= false );
86 bool DrawFillAttributes(
87 const drawinglayer::attribute::SdrAllFillAttributesHelperPtr
& rFillAttributes
,
88 const SwRect
& rOriginalLayoutRect
,
89 const SwRegionRects
& rPaintRegion
,
90 const basegfx::utils::B2DClipState
& rClipState
,
91 vcl::RenderContext
& rOut
);
93 // RotGrfFlyFrame: Adapted to rotation
94 void paintGraphicUsingPrimitivesHelper(
95 vcl::RenderContext
& rOutputDevice
,
96 GraphicObject
const& rGraphicObj
,
97 GraphicAttr
const& rGraphicAttr
,
98 const basegfx::B2DHomMatrix
& rGraphicTransform
,
99 const OUString
& rName
,
100 const OUString
& rTitle
,
101 const OUString
& rDescription
);
103 // MM02 new VOC and primitive-based version
104 void paintGraphicUsingPrimitivesHelper(
105 vcl::RenderContext
& rOutputDevice
,
106 drawinglayer::primitive2d::Primitive2DContainer
& rContent
,
107 const basegfx::B2DHomMatrix
& rGraphicTransform
,
108 const OUString
& rName
,
109 const OUString
& rTitle
,
110 const OUString
& rDescription
);
112 // method to align rectangle.
113 // Created declaration here to avoid <extern> declarations
114 void SwAlignRect( SwRect
&rRect
, const SwViewShell
*pSh
, const vcl::RenderContext
* pRenderContext
);
116 // method to align graphic rectangle
117 // Created declaration here to avoid <extern> declarations
118 void SwAlignGrfRect( SwRect
*pGrfRect
, const vcl::RenderContext
&rOut
);
121 * Paint border around a run of characters using frame painting code.
123 * @param[in] rFont font object of actual text, which specify the border
124 * @param[in] rPaintArea rectangle area in which line portion takes place
125 * @param[in] bVerticalLayout corresponding text frame verticality
126 * @param[in] bVerticalLayoutLRBT corresponding text frame verticality (LRBT subset)
127 * @param[in] bJoinWithPrev leave border with which actual border joins to the previous portion
128 * @param[in] bJoinWithNext leave border with which actual border joins to the next portion
130 void PaintCharacterBorder(const SwFont
& rFont
, const SwRect
& rPaintArea
, const bool bVerticalLayout
,
131 const bool bVerticalLayoutLRBT
, const bool bJoinWithPrev
,
132 const bool bJoinWithNext
);
134 // get Fly, if no List is given use the current shell
135 // Implementation in feshview.cxx
136 SwFlyFrame
*GetFlyFromMarked( const SdrMarkList
*pLst
, SwViewShell
*pSh
);
138 SwFrame
*SaveContent( SwLayoutFrame
*pLay
, SwFrame
*pStart
= nullptr );
139 void RestoreContent( SwFrame
*pSav
, SwLayoutFrame
*pParent
, SwFrame
*pSibling
);
141 // Get ContentNodes, create ContentFrames, and add them to LayFrame.
142 void InsertCnt_( SwLayoutFrame
*pLay
, SwDoc
*pDoc
, SwNodeOffset nIndex
,
143 bool bPages
= false, SwNodeOffset nEndIndex
= SwNodeOffset(0),
144 SwFrame
*pPrv
= nullptr, sw::FrameMode eMode
= sw::FrameMode::New
);
146 // Creation of frames for a specific section (uses InsertCnt_)
147 void MakeFrames( SwDoc
*pDoc
, SwNode
&rSttIdx
,
150 extern bool bObjsDirect
;
152 // for FlyCnts, see SwFlyAtContentFrame::MakeAll()
153 extern bool bSetCompletePaintOnInvalidate
;
155 // for table settings via keyboard
156 SwTwips
CalcRowRstHeight( SwLayoutFrame
*pRow
);
157 tools::Long
CalcHeightWithFlys( const SwFrame
*pFrame
);
160 bool HasPageBreakBefore(SwPageFrame
const& rPage
);
161 bool IsRightPageByNumber(SwRootFrame
const& rLayout
, sal_uInt16 nPageNum
);
162 class FlyCreationSuppressor
164 const bool m_wasAlreadySuppressed
;
166 FlyCreationSuppressor(bool isAlreadySuppressedAllowed
= true);
167 ~FlyCreationSuppressor();
171 SwPageFrame
*InsertNewPage( SwPageDesc
&rDesc
, SwFrame
*pUpper
,
172 bool isRightPage
, bool bFirst
, bool bInsertEmpty
, bool bFootnote
,
173 SwFrame
*pSibling
, bool bVeryFirstPage
= false );
175 // connect Flys with page
176 void RegistFlys( SwPageFrame
*, const SwLayoutFrame
* );
178 // notification of Fly's background if needed
179 void Notify( SwFlyFrame
*pFly
, SwPageFrame
*pOld
, const SwRect
&rOld
,
180 const SwRect
* pOldRect
= nullptr );
182 void Notify_Background( const SdrObject
* pObj
,
185 const PrepareHint eHint
,
188 const SwFrame
* GetVirtualUpper( const SwFrame
* pFrame
, const Point
& rPos
);
190 bool Is_Lower_Of( const SwFrame
*pCurrFrame
, const SdrObject
* pObj
);
192 // FIXME: EasyHack (refactoring): rename method and parameter name in all files
193 const SwFrame
*FindContext( const SwFrame
*pFrame
, SwFrameType nAdditionalContextTyp
);
195 bool IsFrameInSameContext( const SwFrame
*pInnerFrame
, const SwFrame
*pFrame
);
197 const SwFrame
* FindPage( const SwRect
&rRect
, const SwFrame
*pPage
);
199 /** @see SwContentNode::getLayoutFrame()
201 Document model position; for a text frame, the returned frame will be
202 one containing this position.
203 @param pViewPosAndCalcFrame
204 First is a point in the document view; the returned frame will be the one
205 with the minimal distance to this point. To get the first frame in the
206 document, pass in a default-initialized Point with coordinates 0,0.
207 Second indicates whether the frames should be formatted before retrieving
208 their position for the test; this cannot be done by every caller so use
211 SwFrame
* GetFrameOfModify( const SwRootFrame
* pLayout
,
212 sw::BroadcastingModify
const&,
213 SwFrameType
const nFrameType
,
214 const SwPosition
*pPos
= nullptr,
215 std::pair
<Point
, bool> const* pViewPosAndCalcFrame
= nullptr);
217 // Should extra data (redline stroke, line numbers) be painted?
218 bool IsExtraData( const SwDoc
*pDoc
);
220 // #i11760# - method declaration <CalcContent(..)>
221 void CalcContent( SwLayoutFrame
*pLay
, bool bNoColl
= false );
223 // Notify classes memorize the current sizes in their constructor and do
224 // the necessary notifications in their destructor if needed
232 const SwRect maFrame
;
234 SwTwips mnFlyAnchorOfst
;
235 SwTwips mnFlyAnchorOfstNoWrap
;
241 SwFrameNotify( SwFrame
*pFrame
);
244 const SwRect
&getFrameArea() const { return maFrame
; }
245 void SetInvaKeep() { mbInvaKeep
= true; }
248 class SwLayNotify
: public SwFrameNotify
250 bool m_bLowersComplete
;
255 SwLayNotify( SwLayoutFrame
*pLayFrame
);
258 void SetLowersComplete( bool b
) { m_bLowersComplete
= b
; }
259 bool IsLowersComplete() const { return m_bLowersComplete
; }
262 class SwFlyNotify
: public SwLayNotify
264 SwPageFrame
*m_pOldPage
;
265 const SwRect m_aFrameAndSpace
;
270 SwFlyNotify( SwFlyFrame
*pFlyFrame
);
274 class SwContentNotify
: public SwFrameNotify
278 bool mbChkHeightOfLastLine
;
279 SwTwips mnHeightOfLastLine
;
282 bool mbInvalidatePrevPrtArea
;
283 bool mbBordersJoinedWithPrev
;
288 SwContentNotify( SwContentFrame
*pContentFrame
);
292 void SetInvalidatePrevPrtArea()
294 mbInvalidatePrevPrtArea
= true;
297 void SetBordersJoinedWithPrev()
299 mbBordersJoinedWithPrev
= true;
303 // SwBorderAttrs encapsulates the calculation for margin attributes including
304 // border. The whole class is cached.
306 // WARNING! If more attributes should be cached also adjust the method
308 class SwBorderAttrs final
: public SwCacheObj
310 const SwAttrSet
&m_rAttrSet
;
311 const SvxULSpaceItem
&m_rUL
;
312 std::unique_ptr
<SvxFirstLineIndentItem
> m_pFirstLineIndent
;
313 std::unique_ptr
<SvxTextLeftMarginItem
> m_pTextLeftMargin
;
314 std::unique_ptr
<SvxRightMarginItem
> m_pRightMargin
;
315 std::shared_ptr
<SvxLRSpaceItem
> m_xLR
;
316 const SvxBoxItem
&m_rBox
;
317 const SvxShadowItem
&m_rShadow
;
318 const Size m_aFrameSize
;
320 // the following bool values set the cached values to INVALID - until they
321 // are calculated for the first time
323 bool m_bBottomLine
: 1;
324 bool m_bLeftLine
: 1;
325 bool m_bRightLine
: 1;
329 bool m_bLineSpacing
: 1;
331 bool m_bIsLine
: 1; // border on at least one side?
333 bool m_bCacheGetLine
: 1; // cache GetTopLine(), GetBottomLine()?
334 bool m_bCachedGetTopLine
: 1; // is GetTopLine() cached?
335 bool m_bCachedGetBottomLine
: 1; // is GetBottomLine() cached?
336 // Booleans indicate that <m_bJoinedWithPrev> and <m_bJoinedWithNext> are
338 // Caching depends on value of <m_bCacheGetLine>.
339 mutable bool m_bCachedJoinedWithPrev
: 1;
340 mutable bool m_bCachedJoinedWithNext
: 1;
341 // Booleans indicate that borders are joined with previous/next frame.
342 bool m_bJoinedWithPrev
:1;
343 bool m_bJoinedWithNext
:1;
345 // The cached values (un-defined until calculated for the first time)
346 sal_uInt16 m_nTopLine
,
356 // only calculate lines and shadow
358 void CalcBottomLine_();
359 void CalcLeftLine_();
360 void CalcRightLine_();
362 // lines + shadow + margin
368 // #i25029# - If <_pPrevFrame> is set, its value is taken for testing, if
369 // borders/shadow have to be joined with previous frame.
370 void GetTopLine_ ( const SwFrame
& _rFrame
,
371 const SwFrame
* _pPrevFrame
);
372 void GetBottomLine_( const SwFrame
& _rFrame
);
374 // calculate cached values <m_bJoinedWithPrev> and <m_bJoinedWithNext>
375 // #i25029# - If <_pPrevFrame> is set, its value is taken for testing, if
376 // borders/shadow have to be joined with previous frame.
377 void CalcJoinedWithPrev( const SwFrame
& _rFrame
,
378 const SwFrame
* _pPrevFrame
);
379 void CalcJoinedWithNext( const SwFrame
& _rFrame
);
381 // internal helper method for CalcJoinedWithPrev and CalcJoinedWithNext
382 bool JoinWithCmp( const SwFrame
& _rCallerFrame
,
383 const SwFrame
& _rCmpFrame
) const;
385 // Are the left and right line and the LRSpace equal?
386 bool CmpLeftRight( const SwBorderAttrs
&rCmpAttrs
,
387 const SwFrame
*pCaller
,
388 const SwFrame
*pCmp
) const;
390 // tdf#125300 line spacing before cell border
391 void CalcLineSpacing_();
394 SwBorderAttrs( const sw::BorderCacheOwner
* pOwner
, const SwFrame
*pConstructor
);
395 virtual ~SwBorderAttrs() override
;
397 const SwAttrSet
&GetAttrSet() const { return m_rAttrSet
; }
398 const SvxULSpaceItem
&GetULSpace() const { return m_rUL
; }
399 const SvxBoxItem
&GetBox() const { return m_rBox
; }
400 const SvxShadowItem
&GetShadow() const { return m_rShadow
; }
402 inline sal_uInt16
CalcTopLine() const;
403 inline sal_uInt16
CalcBottomLine() const;
404 inline sal_uInt16
CalcLeftLine() const;
405 inline sal_uInt16
CalcRightLine() const;
406 inline sal_uInt16
CalcTop() const;
407 inline sal_uInt16
CalcBottom() const;
408 inline sal_uInt16
CalcLineSpacing() const;
409 tools::Long
CalcLeft( const SwFrame
*pCaller
) const;
410 tools::Long
CalcRight( const SwFrame
*pCaller
) const;
412 inline bool IsLine() const;
414 const Size
&GetSize() const { return m_aFrameSize
; }
416 // Should upper (or lower) border be evaluated for this frame?
417 // #i25029# - If <_pPrevFrame> is set, its value is taken for testing, if
418 // borders/shadow have to be joined with previous frame.
419 inline sal_uInt16
GetTopLine ( const SwFrame
& _rFrame
,
420 const SwFrame
* _pPrevFrame
= nullptr ) const;
421 inline sal_uInt16
GetBottomLine( const SwFrame
& _rFrame
) const;
422 inline void SetGetCacheLine( bool bNew
) const;
424 // Accessors for cached values <m_bJoinedWithPrev> and <m_bJoinedWithNext>
425 // #i25029# - If <_pPrevFrame> is set, its value is taken for testing, if
426 // borders/shadow have to be joined with previous frame.
427 bool JoinedWithPrev( const SwFrame
& _rFrame
,
428 const SwFrame
* _pPrevFrame
= nullptr ) const;
429 bool JoinedWithNext( const SwFrame
& _rFrame
) const;
432 class SwBorderAttrAccess final
: public SwCacheAccess
434 const SwFrame
*m_pConstructor
; //opt: for passing on to SwBorderAttrs
436 virtual SwCacheObj
*NewObj() override
;
439 SwBorderAttrAccess( SwCache
&rCache
, const SwFrame
*pOwner
);
441 SwBorderAttrs
*Get();
444 // Iterator for draw objects of a page. The objects will be iterated sorted by
445 // their Z-order. Iterating is not cheap since for each operation the _whole_
446 // SortArray needs to be traversed.
449 const SwPageFrame
*m_pPage
;
450 const SdrObject
*m_pCurrent
;
453 SwOrderIter( const SwPageFrame
*pPage
);
455 void Current( const SdrObject
*pNew
) { m_pCurrent
= pNew
; }
456 const SdrObject
*operator()() const { return m_pCurrent
; }
458 const SdrObject
*Bottom();
459 const SdrObject
*Next();
465 static sal_uInt8 s_nCnt
;
466 static bool s_bLocked
;
471 if ( ++StackHack::s_nCnt
> 50 )
472 StackHack::s_bLocked
= true;
476 if ( --StackHack::s_nCnt
< 5 )
477 StackHack::s_bLocked
= false;
480 static bool IsLocked() { return StackHack::s_bLocked
; }
481 static sal_uInt8
Count() { return StackHack::s_nCnt
; }
484 // Should upper (or lower) border be evaluated for this frame?
485 // #i25029# - If <_pPrevFrame> is set, its value is taken for testing, if
486 // borders/shadow have to be joined with previous frame.
487 inline sal_uInt16
SwBorderAttrs::GetTopLine ( const SwFrame
& _rFrame
,
488 const SwFrame
* _pPrevFrame
) const
490 if ( !m_bCachedGetTopLine
|| _pPrevFrame
)
492 const_cast<SwBorderAttrs
*>(this)->GetTopLine_( _rFrame
, _pPrevFrame
);
494 return m_nGetTopLine
;
496 inline sal_uInt16
SwBorderAttrs::GetBottomLine( const SwFrame
& _rFrame
) const
498 if ( !m_bCachedGetBottomLine
)
499 const_cast<SwBorderAttrs
*>(this)->GetBottomLine_( _rFrame
);
500 return m_nGetBottomLine
;
502 inline void SwBorderAttrs::SetGetCacheLine( bool bNew
) const
504 const_cast<SwBorderAttrs
*>(this)->m_bCacheGetLine
= bNew
;
505 const_cast<SwBorderAttrs
*>(this)->m_bCachedGetBottomLine
=
506 const_cast<SwBorderAttrs
*>(this)->m_bCachedGetTopLine
= false;
507 // invalidate cache for values <m_bJoinedWithPrev> and <m_bJoinedWithNext>
508 m_bCachedJoinedWithPrev
= false;
509 m_bCachedJoinedWithNext
= false;
512 inline sal_uInt16
SwBorderAttrs::CalcTopLine() const
515 const_cast<SwBorderAttrs
*>(this)->CalcTopLine_();
518 inline sal_uInt16
SwBorderAttrs::CalcBottomLine() const
521 const_cast<SwBorderAttrs
*>(this)->CalcBottomLine_();
522 return m_nBottomLine
;
524 inline sal_uInt16
SwBorderAttrs::CalcLeftLine() const
527 const_cast<SwBorderAttrs
*>(this)->CalcLeftLine_();
530 inline sal_uInt16
SwBorderAttrs::CalcRightLine() const
533 const_cast<SwBorderAttrs
*>(this)->CalcRightLine_();
536 inline sal_uInt16
SwBorderAttrs::CalcTop() const
539 const_cast<SwBorderAttrs
*>(this)->CalcTop_();
542 inline sal_uInt16
SwBorderAttrs::CalcBottom() const
545 const_cast<SwBorderAttrs
*>(this)->CalcBottom_();
548 inline sal_uInt16
SwBorderAttrs::CalcLineSpacing() const
550 if ( m_bLineSpacing
)
551 const_cast<SwBorderAttrs
*>(this)->CalcLineSpacing_();
552 return m_nLineSpacing
;
554 inline bool SwBorderAttrs::IsLine() const
557 const_cast<SwBorderAttrs
*>(this)->IsLine_();
561 /** method to determine the spacing values of a frame
564 Values only provided for flow frames (table, section or text frames)
565 Note: line spacing value is only determined for text frames
567 Add output parameter <obIsLineSpacingProportional>
570 input parameter - frame, for which the spacing values are determined.
572 @param onPrevLowerSpacing
573 output parameter - lower spacing of the frame in SwTwips
575 @param onPrevLineSpacing
576 output parameter - line spacing of the frame in SwTwips
578 @param obIsLineSpacingProportional
580 @param bIdenticalStyles true if the styles of the actual and the next paragraphs (text-frames) are the same
582 void GetSpacingValuesOfFrame( const SwFrame
& rFrame
,
583 SwTwips
& onLowerSpacing
,
584 SwTwips
& onLineSpacing
,
585 bool& obIsLineSpacingProportional
,
586 bool bIdenticalStyles
);
588 /** method to get the content of the table cell
590 Content from any nested tables will be omitted.
591 Note: line spacing value is only determined for text frames
594 input parameter - the cell which should be searched for content.
597 pointer to the found content frame or 0
600 const SwContentFrame
* GetCellContent( const SwLayoutFrame
& rCell_
);
602 /** helper class to check if a frame has been deleted during an operation
603 * WARNING! This should only be used as a last and desperate means to make the
607 class SwDeletionChecker
610 const SwFrame
* mpFrame
;
611 const sw::BroadcastingModify
* mpRegIn
;
614 SwDeletionChecker(const SwFrame
* pFrame
);
618 * true if mpFrame != 0 and mpFrame is not client of pRegIn
621 bool HasBeenDeleted() const;
626 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */