Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx
Warning:line 236, column 32
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name txtfly.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx

/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <vcl/outdev.hxx>
21
22#include <pagefrm.hxx>
23#include <rootfrm.hxx>
24#include <pam.hxx>
25#include <swfont.hxx>
26#include <swregion.hxx>
27#include <dflyobj.hxx>
28#include <drawfont.hxx>
29#include <flyfrm.hxx>
30#include <flyfrms.hxx>
31#include <fmtornt.hxx>
32#include <frmatr.hxx>
33#include <frmtool.hxx>
34#include <ndtxt.hxx>
35#include <txtfly.hxx>
36#include "txtpaint.hxx"
37#include <notxtfrm.hxx>
38#include <fmtcnct.hxx>
39#include <svx/obj3d.hxx>
40#include <editeng/txtrange.hxx>
41#include <editeng/lrspitem.hxx>
42#include <editeng/ulspitem.hxx>
43#include <fmtsrnd.hxx>
44#include <fmtanchr.hxx>
45#include <frmfmt.hxx>
46#include <fmtfollowtextflow.hxx>
47#include <pagedesc.hxx>
48#include <sortedobjs.hxx>
49#include <IDocumentDrawModelAccess.hxx>
50#include <IDocumentSettingAccess.hxx>
51#include <svx/svdoedge.hxx>
52
53#ifdef DBG_UTIL
54#include <viewsh.hxx>
55#include <doc.hxx>
56#endif
57
58using namespace ::com::sun::star;
59
60namespace
61{
62 // #i68520#
63 struct AnchoredObjOrder
64 {
65 bool mbR2L;
66 SwRectFn mfnRect;
67
68 AnchoredObjOrder( const bool bR2L,
69 SwRectFn fnRect )
70 : mbR2L( bR2L ),
71 mfnRect( fnRect )
72 {}
73
74 bool operator()( const SwAnchoredObject* pListedAnchoredObj,
75 const SwAnchoredObject* pNewAnchoredObj )
76 {
77 const SwRect& aBoundRectOfListedObj( pListedAnchoredObj->GetObjRectWithSpaces() );
78 const SwRect& aBoundRectOfNewObj( pNewAnchoredObj->GetObjRectWithSpaces() );
79 if ( ( mbR2L &&
80 ( (aBoundRectOfListedObj.*mfnRect->fnGetRight)() ==
81 (aBoundRectOfNewObj.*mfnRect->fnGetRight)() ) ) ||
82 ( !mbR2L &&
83 ( (aBoundRectOfListedObj.*mfnRect->fnGetLeft)() ==
84 (aBoundRectOfNewObj.*mfnRect->fnGetLeft)() ) ) )
85 {
86 SwTwips nTopDiff =
87 (*mfnRect->fnYDiff)( (aBoundRectOfNewObj.*mfnRect->fnGetTop)(),
88 (aBoundRectOfListedObj.*mfnRect->fnGetTop)() );
89 if ( nTopDiff == 0 &&
90 ( ( mbR2L &&
91 ( (aBoundRectOfNewObj.*mfnRect->fnGetLeft)() >
92 (aBoundRectOfListedObj.*mfnRect->fnGetLeft)() ) ) ||
93 ( !mbR2L &&
94 ( (aBoundRectOfNewObj.*mfnRect->fnGetRight)() <
95 (aBoundRectOfListedObj.*mfnRect->fnGetRight)() ) ) ) )
96 {
97 return true;
98 }
99 else if ( nTopDiff > 0 )
100 {
101 return true;
102 }
103 }
104 else if ( ( mbR2L &&
105 ( (aBoundRectOfListedObj.*mfnRect->fnGetRight)() >
106 (aBoundRectOfNewObj.*mfnRect->fnGetRight)() ) ) ||
107 ( !mbR2L &&
108 ( (aBoundRectOfListedObj.*mfnRect->fnGetLeft)() <
109 (aBoundRectOfNewObj.*mfnRect->fnGetLeft)() ) ) )
110 {
111 return true;
112 }
113
114 return false;
115 }
116 };
117}
118
119SwContourCache::SwContourCache() :
120 mnPointCount( 0 )
121{
122}
123
124SwContourCache::~SwContourCache()
125{
126}
127
128void SwContourCache::ClrObject( sal_uInt16 nPos )
129{
130 mnPointCount -= mvItems[ nPos ].mxTextRanger->GetPointCount();
131 mvItems.erase(mvItems.begin() + nPos);
132}
133
134void ClrContourCache( const SdrObject *pObj )
135{
136 if( pContourCache && pObj )
137 for( sal_uInt16 i = 0; i < pContourCache->GetCount(); ++i )
138 if( pObj == pContourCache->GetObject( i ) )
139 {
140 pContourCache->ClrObject( i );
141 break;
142 }
143}
144
145void ClrContourCache()
146{
147 if( pContourCache )
148 {
149 pContourCache->mvItems.clear();
150 pContourCache->mnPointCount = 0;
151 }
152}
153
154// #i68520#
155SwRect SwContourCache::CalcBoundRect( const SwAnchoredObject* pAnchoredObj,
156 const SwRect &rLine,
157 const SwTextFrame* pFrame,
158 const long nXPos,
159 const bool bRight )
160{
161 SwRect aRet;
162 const SwFrameFormat* pFormat = &(pAnchoredObj->GetFrameFormat());
163 bool bHandleContour(pFormat->GetSurround().IsContour());
164
165 if(!bHandleContour)
26
Assuming 'bHandleContour' is true
27
Taking false branch
166 {
167 // RotateFlyFrame3: Object has no set contour, but for rotated
168 // FlyFrames we can create a 'default' contour to make text
169 // flow around the free, non-covered
170 const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(pAnchoredObj));
171
172 if(nullptr != pSwFlyFreeFrame && pSwFlyFreeFrame->supportsAutoContour())
173 {
174 bHandleContour = true;
175 }
176 }
177
178 if( bHandleContour
27.1
'bHandleContour' is true
27.1
'bHandleContour' is true
&&
33
Taking true branch
179 ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) == nullptr ||
180 ( static_cast<const SwFlyFrame*>(pAnchoredObj)->Lower() &&
28
Assuming the condition is true
181 static_cast<const SwFlyFrame*>(pAnchoredObj)->Lower()->IsNoTextFrame() ) ) )
29
Calling 'SwFrame::IsNoTextFrame'
32
Returning from 'SwFrame::IsNoTextFrame'
182 {
183 aRet = pAnchoredObj->GetObjRectWithSpaces();
34
Value assigned to field 'mpDrawObj'
184 if( aRet.IsOver( rLine ) )
35
Assuming the condition is true
36
Taking true branch
185 {
186 if( !pContourCache )
37
Assuming 'pContourCache' is non-null
38
Taking false branch
187 pContourCache = new SwContourCache;
188
189 aRet = pContourCache->ContourRect(
40
Calling 'SwContourCache::ContourRect'
190 pFormat, pAnchoredObj->GetDrawObj(), pFrame, rLine, nXPos, bRight );
39
Passing value via 2nd parameter 'pObj'
191 }
192 else
193 aRet.Width( 0 );
194 }
195 else
196 {
197 aRet = pAnchoredObj->GetObjRectWithSpaces();
198 }
199
200 return aRet;
201}
202
203SwRect SwContourCache::ContourRect( const SwFormat* pFormat,
204 const SdrObject* pObj, const SwTextFrame* pFrame, const SwRect &rLine,
205 const long nXPos, const bool bRight )
206{
207 SwRect aRet;
208 sal_uInt16 nPos = 0; // Search in the Cache
209 while( nPos < GetCount() && pObj != mvItems[ nPos ].mpSdrObj )
41
Assuming the condition is false
210 ++nPos;
211 if( GetCount() == nPos ) // Not found
42
Assuming the condition is true
43
Taking true branch
212 {
213 if( GetCount() == POLY_CNT20 )
44
Assuming the condition is false
45
Taking false branch
214 {
215 mnPointCount -= mvItems.back().mxTextRanger->GetPointCount();
216 mvItems.pop_back();
217 }
218 ::basegfx::B2DPolyPolygon aPolyPolygon;
219 std::unique_ptr<::basegfx::B2DPolyPolygon> pPolyPolygon;
220
221 if ( auto pVirtFlyDrawObj = dynamic_cast< const SwVirtFlyDrawObj *>( pObj ) )
46
Assuming 'pVirtFlyDrawObj' is null
47
Assuming pointer value is null
48
Taking false branch
222 {
223 // GetContour() causes the graphic to be loaded, which may cause
224 // the graphic to change its size, call ClrObject()
225 tools::PolyPolygon aPoly;
226 if( !pVirtFlyDrawObj->GetFlyFrame()->GetContour( aPoly ) )
227 aPoly = tools::PolyPolygon( static_cast<const SwVirtFlyDrawObj*>(pObj)->
228 GetFlyFrame()->getFrameArea().SVRect() );
229 aPolyPolygon.clear();
230 aPolyPolygon.append(aPoly.getB2DPolyPolygon());
231 }
232 else
233 {
234 if( dynamic_cast< const E3dObject *>( pObj ) == nullptr )
49
Taking true branch
235 {
236 aPolyPolygon = pObj->TakeXorPoly();
50
Called C++ object pointer is null
237 }
238
239 ::basegfx::B2DPolyPolygon aContourPoly(pObj->TakeContour());
240 pPolyPolygon.reset(new ::basegfx::B2DPolyPolygon(aContourPoly));
241 }
242 const SvxLRSpaceItem &rLRSpace = pFormat->GetLRSpace();
243 const SvxULSpaceItem &rULSpace = pFormat->GetULSpace();
244 CacheItem item {
245 pObj, // due to #37347 the Object must be entered only after GetContour()
246 std::make_unique<TextRanger>( aPolyPolygon, pPolyPolygon.get(), 20,
247 static_cast<sal_uInt16>(rLRSpace.GetLeft()), static_cast<sal_uInt16>(rLRSpace.GetRight()),
248 pFormat->GetSurround().IsOutside(), false, pFrame->IsVertical() )
249 };
250 mvItems.insert(mvItems.begin(), std::move(item));
251 mvItems[0].mxTextRanger->SetUpper( rULSpace.GetUpper() );
252 mvItems[0].mxTextRanger->SetLower( rULSpace.GetLower() );
253
254 pPolyPolygon.reset();
255
256 mnPointCount += mvItems[0].mxTextRanger->GetPointCount();
257 while( mnPointCount > POLY_MAX4000 && mvItems.size() > POLY_MIN5 )
258 {
259 mnPointCount -= mvItems.back().mxTextRanger->GetPointCount();
260 mvItems.pop_back();
261 }
262 }
263 else if( nPos )
264 {
265 CacheItem item = std::move(mvItems[nPos]);
266 mvItems.erase(mvItems.begin() + nPos);
267 mvItems.insert(mvItems.begin(), std::move(item));
268 }
269 SwRectFnSet aRectFnSet(pFrame);
270 long nTmpTop = aRectFnSet.GetTop(rLine);
271 // fnGetBottom is top + height
272 long nTmpBottom = aRectFnSet.GetBottom(rLine);
273
274 Range aRange( std::min( nTmpTop, nTmpBottom ), std::max( nTmpTop, nTmpBottom ) );
275
276 std::deque<long>* pTmp = mvItems[0].mxTextRanger->GetTextRanges( aRange );
277
278 const size_t nCount = pTmp->size();
279 if( 0 != nCount )
280 {
281 size_t nIdx = 0;
282 while( nIdx < nCount && (*pTmp)[ nIdx ] < nXPos )
283 ++nIdx;
284 bool bOdd = nIdx % 2;
285 bool bSet = true;
286 if( bOdd )
287 --nIdx; // within interval
288 else if( ! bRight && ( nIdx >= nCount || (*pTmp)[ nIdx ] != nXPos ) )
289 {
290 if( nIdx )
291 nIdx -= 2; // an interval to the left
292 else
293 bSet = false; // before the first interval
294 }
295
296 if( bSet && nIdx < nCount )
297 {
298 aRectFnSet.SetTopAndHeight( aRet, aRectFnSet.GetTop(rLine),
299 aRectFnSet.GetHeight(rLine) );
300 aRectFnSet.SetLeft( aRet, (*pTmp)[ nIdx ] );
301 aRectFnSet.SetRight( aRet, (*pTmp)[ nIdx + 1 ] + 1 );
302 }
303 }
304 return aRet;
305}
306
307SwTextFly::SwTextFly()
308 : m_pPage(nullptr)
309 , mpCurrAnchoredObj(nullptr)
310 , m_pCurrFrame(nullptr)
311 , m_pMaster(nullptr)
312 , m_nMinBottom(0)
313 , m_nNextTop(0)
314 , m_nCurrFrameNodeIndex(0)
315 , m_bOn(false)
316 , m_bTopRule(false)
317 , mbIgnoreCurrentFrame(false)
318 , mbIgnoreContour(false)
319 , mbIgnoreObjsInHeaderFooter(false)
320
321{
322}
323
324SwTextFly::SwTextFly( const SwTextFrame *pFrame )
325{
326 CtorInitTextFly( pFrame );
327}
328
329SwTextFly::SwTextFly( const SwTextFly& rTextFly )
330{
331 m_pPage = rTextFly.m_pPage;
332 mpCurrAnchoredObj = rTextFly.mpCurrAnchoredObj;
333 m_pCurrFrame = rTextFly.m_pCurrFrame;
334 m_pMaster = rTextFly.m_pMaster;
335 if( rTextFly.mpAnchoredObjList )
336 {
337 mpAnchoredObjList.reset( new SwAnchoredObjList( *(rTextFly.mpAnchoredObjList) ) );
338 }
339
340 m_bOn = rTextFly.m_bOn;
341 m_bTopRule = rTextFly.m_bTopRule;
342 m_nMinBottom = rTextFly.m_nMinBottom;
343 m_nNextTop = rTextFly.m_nNextTop;
344 m_nCurrFrameNodeIndex = rTextFly.m_nCurrFrameNodeIndex;
345 mbIgnoreCurrentFrame = rTextFly.mbIgnoreCurrentFrame;
346 mbIgnoreContour = rTextFly.mbIgnoreContour;
347 mbIgnoreObjsInHeaderFooter = rTextFly.mbIgnoreObjsInHeaderFooter;
348}
349
350SwTextFly::~SwTextFly()
351{
352}
353
354void SwTextFly::CtorInitTextFly( const SwTextFrame *pFrame )
355{
356 mbIgnoreCurrentFrame = false;
357 mbIgnoreContour = false;
358 mbIgnoreObjsInHeaderFooter = false;
359 m_pPage = pFrame->FindPageFrame();
360 const SwFlyFrame* pTmp = pFrame->FindFlyFrame();
361 // #i68520#
362 mpCurrAnchoredObj = pTmp;
363 m_pCurrFrame = pFrame;
364 m_pMaster = m_pCurrFrame->IsFollow() ? nullptr : m_pCurrFrame;
365 // If we're not overlapped by a frame or if a FlyCollection does not exist
366 // at all, we switch off forever.
367 // It could be, however, that a line is added while formatting, that
368 // extends into a frame.
369 // That's why we do not optimize for: bOn = pSortedFlys && IsAnyFrame();
370 m_bOn = m_pPage->GetSortedObjs() != nullptr;
371 m_bTopRule = true;
372 m_nMinBottom = 0;
373 m_nNextTop = 0;
374 m_nCurrFrameNodeIndex = ULONG_MAX(9223372036854775807L *2UL+1UL);
375}
376
377SwRect SwTextFly::GetFrame_( const SwRect &rRect ) const
378{
379 SwRect aRet;
380 if( ForEach( rRect, &aRet, true ) )
1
Calling 'SwTextFly::ForEach'
381 {
382 SwRectFnSet aRectFnSet(m_pCurrFrame);
383 aRectFnSet.SetTop( aRet, aRectFnSet.GetTop(rRect) );
384
385 // Do not always adapt the bottom
386 const SwTwips nRetBottom = aRectFnSet.GetBottom(aRet);
387 const SwTwips nRectBottom = aRectFnSet.GetBottom(rRect);
388 if ( aRectFnSet.YDiff( nRetBottom, nRectBottom ) > 0 ||
389 aRectFnSet.GetHeight(aRet) < 0 )
390 aRectFnSet.SetBottom( aRet, nRectBottom );
391 }
392 return aRet;
393}
394
395bool SwTextFly::IsAnyFrame() const
396{
397 SwSwapIfSwapped swap(const_cast<SwTextFrame *>(m_pCurrFrame));
398
399 OSL_ENSURE( m_bOn, "IsAnyFrame: Why?" )do { if (true && (!(m_bOn))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "399" ": "), "%s", "IsAnyFrame: Why?"); } } while (false
)
;
400 SwRect aRect(m_pCurrFrame->getFrameArea().Pos() + m_pCurrFrame->getFramePrintArea().Pos(),
401 m_pCurrFrame->getFramePrintArea().SSize());
402
403 return ForEach( aRect, nullptr, false );
404}
405
406bool SwTextFly::IsAnyObj( const SwRect &rRect ) const
407{
408 OSL_ENSURE( m_bOn, "SwTextFly::IsAnyObj: Who's knocking?" )do { if (true && (!(m_bOn))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "408" ": "), "%s", "SwTextFly::IsAnyObj: Who's knocking?"
); } } while (false)
;
409
410 SwRect aRect( rRect );
411 if ( aRect.IsEmpty() )
412 {
413 aRect = SwRect(m_pCurrFrame->getFrameArea().Pos() + m_pCurrFrame->getFramePrintArea().Pos(),
414 m_pCurrFrame->getFramePrintArea().SSize());
415 }
416
417 const SwSortedObjs *pSorted = m_pPage->GetSortedObjs();
418 if( pSorted ) // bOn actually makes sure that we have objects on the side,
419 // but who knows who deleted something in the meantime?
420 {
421 for ( size_t i = 0; i < pSorted->size(); ++i )
422 {
423 const SwAnchoredObject* pObj = (*pSorted)[i];
424
425 const SwRect aBound( pObj->GetObjRectWithSpaces() );
426
427 // Optimization
428 if( pObj->GetObjRect().Left() > aRect.Right() )
429 continue;
430
431 // #i68520#
432 if( mpCurrAnchoredObj != pObj && aBound.IsOver( aRect ) )
433 return true;
434 }
435 }
436 return false;
437}
438
439const SwTextFrame* SwTextFly::GetMaster_()
440{
441 m_pMaster = m_pCurrFrame;
442 while (m_pMaster && m_pMaster->IsFollow())
443 m_pMaster = m_pMaster->FindMaster();
444 return m_pMaster;
445}
446
447void SwTextFly::DrawTextOpaque( SwDrawTextInfo &rInf )
448{
449 SwSaveClip aClipSave( rInf.GetpOut() );
450 SwRect aRect( rInf.GetPos(), rInf.GetSize() );
451 if( rInf.GetSpace() )
452 {
453 TextFrameIndex const nTmpLen = TextFrameIndex(COMPLETE_STRING) == rInf.GetLen()
454 ? TextFrameIndex(rInf.GetText().getLength())
455 : rInf.GetLen();
456 if( rInf.GetSpace() > 0 )
457 {
458 sal_Int32 nSpaceCnt = 0;
459 const TextFrameIndex nEndPos = rInf.GetIdx() + nTmpLen;
460 for (TextFrameIndex nPos = rInf.GetIdx(); nPos < nEndPos; ++nPos)
461 {
462 if (CH_BLANK == rInf.GetText()[sal_Int32(nPos)])
463 ++nSpaceCnt;
464 }
465 if( nSpaceCnt )
466 aRect.Width( aRect.Width() + nSpaceCnt * rInf.GetSpace() );
467 }
468 else
469 aRect.Width( aRect.Width() - sal_Int32(nTmpLen) * rInf.GetSpace() );
470 }
471
472 if( aClipSave.IsOn() && rInf.GetOut().IsClipRegion() )
473 {
474 SwRect aClipRect( rInf.GetOut().GetClipRegion().GetBoundRect() );
475 aRect.Intersection( aClipRect );
476 }
477
478 SwRegionRects aRegion( aRect );
479
480 bool bOpaque = false;
481 // #i68520#
482 const sal_uInt32 nCurrOrd = mpCurrAnchoredObj
483 ? mpCurrAnchoredObj->GetDrawObj()->GetOrdNum()
484 : SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF);
485 OSL_ENSURE( !m_bTopRule, "DrawTextOpaque: Wrong TopRule" )do { if (true && (!(!m_bTopRule))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "485" ": "), "%s", "DrawTextOpaque: Wrong TopRule"); } }
while (false)
;
486
487 // #i68520#
488 const SwAnchoredObjList::size_type nCount( m_bOn ? GetAnchoredObjList()->size() : 0 );
489 if (nCount > 0)
490 {
491 const SdrLayerID nHellId = m_pPage->getRootFrame()->GetCurrShell()->getIDocumentDrawModelAccess().GetHellId();
492 for( SwAnchoredObjList::size_type i = 0; i < nCount; ++i )
493 {
494 // #i68520#
495 const SwAnchoredObject* pTmpAnchoredObj = (*mpAnchoredObjList)[i];
496 if( dynamic_cast<const SwFlyFrame*>(pTmpAnchoredObj) &&
497 mpCurrAnchoredObj != pTmpAnchoredObj )
498 {
499 // #i68520#
500 const SwFlyFrame& rFly = dynamic_cast<const SwFlyFrame&>(*pTmpAnchoredObj);
501 if( aRegion.GetOrigin().IsOver( rFly.getFrameArea() ) )
502 {
503 const SwFrameFormat *pFormat = rFly.GetFormat();
504 const SwFormatSurround &rSur = pFormat->GetSurround();
505 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
506 // Only the ones who are opaque and more to the top
507 if( ! rFly.IsBackgroundTransparent() &&
508 css::text::WrapTextMode_THROUGH == rSur.GetSurround() &&
509 ( !rSur.IsAnchorOnly() ||
510 // #i68520#
511 GetMaster() == rFly.GetAnchorFrame() ||
512 ((RndStdIds::FLY_AT_PARA != rAnchor.GetAnchorId()) &&
513 (RndStdIds::FLY_AT_CHAR != rAnchor.GetAnchorId())
514 )
515 ) &&
516 // #i68520#
517 pTmpAnchoredObj->GetDrawObj()->GetLayer() != nHellId &&
518 nCurrOrd < pTmpAnchoredObj->GetDrawObj()->GetOrdNum()
519 )
520 {
521 // Except for the content is transparent
522 const SwNoTextFrame *pNoText =
523 rFly.Lower() && rFly.Lower()->IsNoTextFrame()
524 ? static_cast<const SwNoTextFrame*>(rFly.Lower())
525 : nullptr;
526 if ( !pNoText ||
527 (!pNoText->IsTransparent() && !rSur.IsContour()) )
528 {
529 bOpaque = true;
530 aRegion -= rFly.getFrameArea();
531 }
532 }
533 }
534 }
535 }
536 }
537
538 Point aPos( rInf.GetPos().X(), rInf.GetPos().Y() + rInf.GetAscent() );
539 const Point aOldPos(rInf.GetPos());
540 rInf.SetPos( aPos );
541
542 if( !bOpaque )
543 {
544 if( rInf.GetKern() )
545 rInf.GetFont()->DrawStretchText_( rInf );
546 else
547 rInf.GetFont()->DrawText_( rInf );
548 rInf.SetPos(aOldPos);
549 return;
550 }
551 else if( !aRegion.empty() )
552 {
553 // What a huge effort ...
554 SwSaveClip aClipVout( rInf.GetpOut() );
555 for( size_t i = 0; i < aRegion.size(); ++i )
556 {
557 SwRect &rRect = aRegion[i];
558 if( rRect != aRegion.GetOrigin() )
559 aClipVout.ChgClip( rRect );
560 if( rInf.GetKern() )
561 rInf.GetFont()->DrawStretchText_( rInf );
562 else
563 rInf.GetFont()->DrawText_( rInf );
564 }
565 }
566 rInf.SetPos(aOldPos);
567}
568
569void SwTextFly::DrawFlyRect( OutputDevice* pOut, const SwRect &rRect )
570{
571 SwRegionRects aRegion( rRect );
572 OSL_ENSURE( !m_bTopRule, "DrawFlyRect: Wrong TopRule" )do { if (true && (!(!m_bTopRule))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "572" ": "), "%s", "DrawFlyRect: Wrong TopRule"); } } while
(false)
;
573 // #i68520#
574 const SwAnchoredObjList::size_type nCount( m_bOn ? GetAnchoredObjList()->size() : 0 );
575 if (nCount > 0)
576 {
577 const SdrLayerID nHellId = m_pPage->getRootFrame()->GetCurrShell()->getIDocumentDrawModelAccess().GetHellId();
578 for( SwAnchoredObjList::size_type i = 0; i < nCount; ++i )
579 {
580 // #i68520#
581 const SwAnchoredObject* pAnchoredObjTmp = (*mpAnchoredObjList)[i];
582 if (mpCurrAnchoredObj == pAnchoredObjTmp)
583 continue;
584
585 // #i68520#
586 const SwFlyFrame* pFly = dynamic_cast<const SwFlyFrame*>(pAnchoredObjTmp);
587 if (pFly)
588 {
589 // #i68520#
590 const SwFormatSurround& rSur = pAnchoredObjTmp->GetFrameFormat().GetSurround();
591
592 // OD 24.01.2003 #106593# - correct clipping of fly frame area.
593 // Consider that fly frame background/shadow can be transparent
594 // and <SwAlignRect(..)> fly frame area
595 // #i47804# - consider transparent graphics
596 // and OLE objects.
597 bool bClipFlyArea =
598 ( ( css::text::WrapTextMode_THROUGH == rSur.GetSurround() )
599 // #i68520#
600 ? (pAnchoredObjTmp->GetDrawObj()->GetLayer() != nHellId)
601 : !rSur.IsContour() ) &&
602 !pFly->IsBackgroundTransparent() &&
603 ( !pFly->Lower() ||
604 !pFly->Lower()->IsNoTextFrame() ||
605 !static_cast<const SwNoTextFrame*>(pFly->Lower())->IsTransparent() );
606 if ( bClipFlyArea )
607 {
608 // #i68520#
609 SwRect aFly( pAnchoredObjTmp->GetObjRect() );
610 // OD 24.01.2003 #106593#
611 ::SwAlignRect( aFly, m_pPage->getRootFrame()->GetCurrShell(), pOut );
612 if( !aFly.IsEmpty() )
613 aRegion -= aFly;
614 }
615 }
616 }
617 }
618
619 for( size_t i = 0; i < aRegion.size(); ++i )
620 {
621 pOut->DrawRect( aRegion[i].SVRect() );
622 }
623}
624
625/**
626 * #i26945# - change first parameter
627 * Now it's the <SwAnchoredObject> instance of the floating screen object
628 */
629bool SwTextFly::GetTop( const SwAnchoredObject* _pAnchoredObj,
630 const bool bInFootnote,
631 const bool bInFooterOrHeader )
632{
633 // #i68520#
634 // <mpCurrAnchoredObj> is set, if <m_pCurrFrame> is inside a fly frame
635 if( _pAnchoredObj != mpCurrAnchoredObj )
636 {
637 // #i26945#
638 const SdrObject* pNew = _pAnchoredObj->GetDrawObj();
639 // #102344# Ignore connectors which have one or more connections
640 if (const SdrEdgeObj* pEdgeObj = dynamic_cast<const SdrEdgeObj*>(pNew))
641 {
642 if (pEdgeObj->GetConnectedNode(true) || pEdgeObj->GetConnectedNode(false))
643 {
644 return false;
645 }
646 }
647
648 if( ( bInFootnote || bInFooterOrHeader ) && m_bTopRule )
649 {
650 // #i26945#
651 const SwFrameFormat& rFrameFormat = _pAnchoredObj->GetFrameFormat();
652 const SwFormatAnchor& rNewA = rFrameFormat.GetAnchor();
653 if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId())
654 {
655 if ( bInFootnote )
656 return false;
657
658 if ( bInFooterOrHeader )
659 {
660 const SwFormatVertOrient& aVert( rFrameFormat.GetVertOrient() );
661 bool bVertPrt = aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ||
662 aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA;
663 if( bVertPrt )
664 return false;
665 }
666 }
667 }
668
669 // #i68520#
670 // bEvade: consider pNew, if we are not inside a fly
671 // consider pNew, if pNew is lower of <mpCurrAnchoredObj>
672 bool bEvade = !mpCurrAnchoredObj ||
673 Is_Lower_Of( dynamic_cast<const SwFlyFrame*>(mpCurrAnchoredObj), pNew);
674
675 if ( !bEvade )
676 {
677 // We are currently inside a fly frame and pNew is not
678 // inside this fly frame. We can do some more checks if
679 // we have to consider pNew.
680
681 // If bTopRule is not set, we ignore the frame types.
682 // We directly check the z-order
683 if ( !m_bTopRule )
684 bEvade = true;
685 else
686 {
687 // Within chained Flys we only avoid Lower
688 // #i68520#
689 const SwFormatChain &rChain = mpCurrAnchoredObj->GetFrameFormat().GetChain();
690 if ( !rChain.GetPrev() && !rChain.GetNext() )
691 {
692 // #i26945#
693 const SwFormatAnchor& rNewA = _pAnchoredObj->GetFrameFormat().GetAnchor();
694 // #i68520#
695 const SwFormatAnchor& rCurrA = mpCurrAnchoredObj->GetFrameFormat().GetAnchor();
696
697 // If <mpCurrAnchoredObj> is anchored as character, its content
698 // does not wrap around pNew
699 if (RndStdIds::FLY_AS_CHAR == rCurrA.GetAnchorId())
700 return false;
701
702 // If pNew is anchored to page and <mpCurrAnchoredObj is not anchored
703 // to page, the content of <mpCurrAnchoredObj> does not wrap around pNew
704 // If both pNew and <mpCurrAnchoredObj> are anchored to page, we can do
705 // some more checks
706 if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId())
707 {
708 if (RndStdIds::FLY_AT_PAGE == rCurrA.GetAnchorId())
709 {
710 bEvade = true;
711 }
712 else
713 return false;
714 }
715 else if (RndStdIds::FLY_AT_PAGE == rCurrA.GetAnchorId())
716 return false; // Page anchored ones only avoid page anchored ones
717 else if (RndStdIds::FLY_AT_FLY == rNewA.GetAnchorId())
718 bEvade = true; // Non-page anchored ones avoid frame anchored ones
719 else if( RndStdIds::FLY_AT_FLY == rCurrA.GetAnchorId() )
720 return false; // Frame anchored ones do not avoid paragraph anchored ones
721 // #i57062#
722 // In order to avoid loop situation, it's decided to adjust
723 // the wrapping behaviour of content of at-paragraph/at-character
724 // anchored objects to one in the page header/footer and
725 // the document body --> content of at-paragraph/at-character
726 // anchored objects doesn't wrap around each other.
727 else
728 return false;
729 }
730 }
731
732 // But: we never avoid a subordinate one and additionally we only avoid when overlapping.
733 // #i68520#
734 bEvade &= ( mpCurrAnchoredObj->GetDrawObj()->GetOrdNum() < pNew->GetOrdNum() );
735 if( bEvade )
736 {
737 // #i68520#
738 const SwRect& aTmp( _pAnchoredObj->GetObjRectWithSpaces() );
739 if ( !aTmp.IsOver( mpCurrAnchoredObj->GetObjRectWithSpaces() ) )
740 bEvade = false;
741 }
742 }
743
744 if ( bEvade )
745 {
746 // #i26945#
747 const SwFormatAnchor& rNewA = _pAnchoredObj->GetFrameFormat().GetAnchor();
748 OSL_ENSURE( RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId(),do { if (true && (!(RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "749" ": "), "%s", "Don't call GetTop with a FlyInContentFrame"
); } } while (false)
749 "Don't call GetTop with a FlyInContentFrame" )do { if (true && (!(RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "749" ": "), "%s", "Don't call GetTop with a FlyInContentFrame"
); } } while (false)
;
750 if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId())
751 return true; // We always avoid page anchored ones
752
753 // If Flys anchored at paragraph are caught in a FlyCnt, then
754 // their influence ends at the borders of the FlyCnt!
755 // If we are currently formatting the text of the FlyCnt, then
756 // it has to get out of the way of the Frame anchored at paragraph!
757 // m_pCurrFrame is the anchor of pNew?
758 // #i26945#
759 const SwFrame* pTmp = _pAnchoredObj->GetAnchorFrame();
760 if (pTmp == m_pCurrFrame)
761 return true;
762 if( pTmp->IsTextFrame() && ( pTmp->IsInFly() || pTmp->IsInFootnote() ) )
763 {
764 // #i26945#
765 Point aPos = _pAnchoredObj->GetObjRect().Pos();
766 pTmp = GetVirtualUpper( pTmp, aPos );
767 }
768 // #i26945#
769 // If <pTmp> is a text frame inside a table, take the upper
770 // of the anchor frame, which contains the anchor position.
771 else if ( pTmp->IsTextFrame() && pTmp->IsInTab() )
772 {
773 pTmp = const_cast<SwAnchoredObject*>(_pAnchoredObj)
774 ->GetAnchorFrameContainingAnchPos()->GetUpper();
775 }
776 // #i28701# - consider all objects in same context,
777 // if wrapping style is considered on object positioning.
778 // Thus, text will wrap around negative positioned objects.
779 // #i3317# - remove condition on checking,
780 // if wrappings style is considered on object positioning.
781 // Thus, text is wrapping around negative positioned objects.
782 // #i35640# - no consideration of negative
783 // positioned objects, if wrapping style isn't considered on
784 // object position and former text wrapping is applied.
785 // This condition is typically for documents imported from the
786 // OpenOffice.org file format.
787 const IDocumentSettingAccess* pIDSA = &m_pCurrFrame->GetDoc().getIDocumentSettingAccess();
788 if ( ( pIDSA->get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) ||
789 !pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) ) &&
790 ::FindContext( pTmp, SwFrameType::None ) == ::FindContext(m_pCurrFrame, SwFrameType::None))
791 {
792 return true;
793 }
794
795 const SwFrame* pHeader = nullptr;
796 if (m_pCurrFrame->GetNext() != pTmp &&
797 (IsFrameInSameContext( pTmp, m_pCurrFrame ) ||
798 // #i13832#, #i24135# wrap around objects in page header
799 ( !pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) &&
800 nullptr != ( pHeader = pTmp->FindFooterOrHeader() ) &&
801 m_pCurrFrame->IsInDocBody())))
802 {
803 if( pHeader || RndStdIds::FLY_AT_FLY == rNewA.GetAnchorId() )
804 return true;
805
806 // Compare indices:
807 // The Index of the other is retrieved from the anchor attr.
808 sal_uLong nTmpIndex = rNewA.GetContentAnchor()->nNode.GetIndex();
809 // Now check whether the current paragraph is before the anchor
810 // of the displaced object in the text, then we don't have to
811 // get out of its way.
812 // If possible determine Index via SwFormatAnchor because
813 // otherwise it's quite expensive.
814 if (ULONG_MAX(9223372036854775807L *2UL+1UL) == m_nCurrFrameNodeIndex)
815 m_nCurrFrameNodeIndex = m_pCurrFrame->GetTextNodeFirst()->GetIndex();
816
817 if (FrameContainsNode(*m_pCurrFrame, nTmpIndex) || nTmpIndex < m_nCurrFrameNodeIndex)
818 return true;
819 }
820 }
821 }
822 return false;
823}
824
825// #i68520#
826SwAnchoredObjList* SwTextFly::InitAnchoredObjList()
827{
828 OSL_ENSURE( m_pCurrFrame, "InitFlyList: No Frame, no FlyList" )do { if (true && (!(m_pCurrFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "828" ": "), "%s", "InitFlyList: No Frame, no FlyList");
} } while (false)
;
829 // #i68520#
830 OSL_ENSURE( !mpAnchoredObjList, "InitFlyList: FlyList already initialized" )do { if (true && (!(!mpAnchoredObjList))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "830" ": "), "%s", "InitFlyList: FlyList already initialized"
); } } while (false)
;
831
832 SwSwapIfSwapped swap(const_cast<SwTextFrame *>(m_pCurrFrame));
833
834 const SwSortedObjs *pSorted = m_pPage->GetSortedObjs();
835 const size_t nCount = pSorted ? pSorted->size() : 0;
836 // --> #108724# Page header/footer content doesn't have to wrap around
837 // floating screen objects
838 // which was added simply to be compatible with MS Office.
839 // MSO still allows text to wrap around in-table-flies in headers/footers/footnotes
840 const bool bFooterHeader = nullptr != m_pCurrFrame->FindFooterOrHeader();
841 const IDocumentSettingAccess* pIDSA = &m_pCurrFrame->GetDoc().getIDocumentSettingAccess();
842 // #i40155# - check, if frame is marked not to wrap
843 const bool bAllowCompatWrap = m_pCurrFrame->IsInTab() && (bFooterHeader || m_pCurrFrame->IsInFootnote());
844 const bool bWrapAllowed = ( pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) ||
845 bAllowCompatWrap ||
846 (!m_pCurrFrame->IsInFootnote() && !bFooterHeader));
847
848 m_bOn = false;
849
850 if( nCount && bWrapAllowed )
851 {
852 // #i68520#
853 mpAnchoredObjList.reset(new SwAnchoredObjList );
854
855 // #i28701# - consider complete frame area for new
856 // text wrapping
857 SwRect aRect;
858 if ( pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) )
859 {
860 aRect = m_pCurrFrame->getFramePrintArea();
861 aRect += m_pCurrFrame->getFrameArea().Pos();
862 }
863 else
864 {
865 aRect = m_pCurrFrame->getFrameArea();
866 }
867 // Make ourselves a little smaller than we are,
868 // so that 1-Twip-overlappings are ignored (#49532)
869 SwRectFnSet aRectFnSet(m_pCurrFrame);
870 const long nRight = aRectFnSet.GetRight(aRect) - 1;
871 const long nLeft = aRectFnSet.GetLeft(aRect) + 1;
872 const bool bR2L = m_pCurrFrame->IsRightToLeft();
873
874 const IDocumentDrawModelAccess& rIDDMA = m_pCurrFrame->GetDoc().getIDocumentDrawModelAccess();
875
876 for( size_t i = 0; i < nCount; ++i )
877 {
878 // #i68520#
879 // do not consider hidden objects
880 // check, if object has to be considered for text wrap
881 // #118809# - If requested, do not consider
882 // objects in page header|footer for text frames not in page
883 // header|footer. This is requested for the calculation of
884 // the base offset for objects <SwTextFrame::CalcBaseOfstForFly()>
885 // #i20505# Do not consider oversized objects
886 SwAnchoredObject* pAnchoredObj = (*pSorted)[ i ];
887 assert(pAnchoredObj)(static_cast <bool> (pAnchoredObj) ? void (0) : __assert_fail
("pAnchoredObj", "/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
, 887, __extension__ __PRETTY_FUNCTION__))
;
888 if ( !pAnchoredObj ||
889 !rIDDMA.IsVisibleLayerId( pAnchoredObj->GetDrawObj()->GetLayer() ) ||
890 !pAnchoredObj->ConsiderForTextWrap() ||
891 ( mbIgnoreObjsInHeaderFooter && !bFooterHeader &&
892 pAnchoredObj->GetAnchorFrame()->FindFooterOrHeader() ) ||
893 ( bAllowCompatWrap && !pAnchoredObj->GetFrameFormat().GetFollowTextFlow().GetValue() )
894 )
895 {
896 continue;
897 }
898
899 const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
900 if ( nRight < aRectFnSet.GetLeft(aBound) ||
901 aRectFnSet.YDiff( aRectFnSet.GetTop(aRect),
902 aRectFnSet.GetBottom(aBound) ) > 0 ||
903 nLeft > aRectFnSet.GetRight(aBound) ||
904 aRectFnSet.GetHeight(aBound) >
905 2 * aRectFnSet.GetHeight(m_pPage->getFrameArea()) )
906 {
907 continue;
908 }
909
910 // #i26945# - pass <pAnchoredObj> to method
911 // <GetTop(..)> instead of only the <SdrObject> instance of the
912 // anchored object
913 if (GetTop(pAnchoredObj, m_pCurrFrame->IsInFootnote(), bFooterHeader))
914 {
915 // OD 11.03.2003 #107862# - adjust insert position:
916 // overlapping objects should be sorted from left to right and
917 // inside left to right sorting from top to bottom.
918 // If objects on the same position are found, they are sorted
919 // on its width.
920 // #i68520#
921 {
922 SwAnchoredObjList::iterator aInsPosIter =
923 std::lower_bound( mpAnchoredObjList->begin(),
924 mpAnchoredObjList->end(),
925 pAnchoredObj,
926 AnchoredObjOrder( bR2L, aRectFnSet.FnRect() ) );
927
928 mpAnchoredObjList->insert( aInsPosIter, pAnchoredObj );
929 }
930
931 const SwFormatSurround &rFlyFormat = pAnchoredObj->GetFrameFormat().GetSurround();
932 // #i68520#
933 if ( rFlyFormat.IsAnchorOnly() &&
934 pAnchoredObj->GetAnchorFrame() == GetMaster() )
935 {
936 const SwFormatVertOrient &rTmpFormat =
937 pAnchoredObj->GetFrameFormat().GetVertOrient();
938 if( text::VertOrientation::BOTTOM != rTmpFormat.GetVertOrient() )
939 m_nMinBottom = ( aRectFnSet.IsVert() && m_nMinBottom ) ?
940 std::min( m_nMinBottom, aBound.Left() ) :
941 std::max( m_nMinBottom, aRectFnSet.GetBottom(aBound) );
942 }
943
944 m_bOn = true;
945 }
946 }
947 if( m_nMinBottom )
948 {
949 SwTwips nMax = aRectFnSet.GetPrtBottom(*m_pCurrFrame->GetUpper());
950 if( aRectFnSet.YDiff( m_nMinBottom, nMax ) > 0 )
951 m_nMinBottom = nMax;
952 }
953 }
954 else
955 {
956 // #i68520#
957 mpAnchoredObjList.reset( new SwAnchoredObjList );
958 }
959
960 // #i68520#
961 return mpAnchoredObjList.get();
962}
963
964SwTwips SwTextFly::CalcMinBottom() const
965{
966 SwTwips nRet = 0;
967 const SwContentFrame *pLclMaster = GetMaster();
968 OSL_ENSURE(pLclMaster, "SwTextFly without master")do { if (true && (!(pLclMaster))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "968" ": "), "%s", "SwTextFly without master"); } } while
(false)
;
969 const SwSortedObjs *pDrawObj = pLclMaster ? pLclMaster->GetDrawObjs() : nullptr;
970 const size_t nCount = pDrawObj ? pDrawObj->size() : 0;
971 if( nCount )
972 {
973 SwTwips nEndOfFrame = m_pCurrFrame->getFrameArea().Bottom();
974 for( size_t i = 0; i < nCount; ++i )
975 {
976 SwAnchoredObject* pAnchoredObj = (*pDrawObj)[ i ];
977 const SwFormatSurround &rFlyFormat = pAnchoredObj->GetFrameFormat().GetSurround();
978 if( rFlyFormat.IsAnchorOnly() )
979 {
980 const SwFormatVertOrient &rTmpFormat =
981 pAnchoredObj->GetFrameFormat().GetVertOrient();
982 if( text::VertOrientation::BOTTOM != rTmpFormat.GetVertOrient() )
983 {
984 const SwRect& aBound( pAnchoredObj->GetObjRectWithSpaces() );
985 if( aBound.Top() < nEndOfFrame )
986 nRet = std::max( nRet, aBound.Bottom() );
987 }
988 }
989 }
990 SwTwips nMax = m_pCurrFrame->GetUpper()->getFrameArea().Top() +
991 m_pCurrFrame->GetUpper()->getFramePrintArea().Bottom();
992 if( nRet > nMax )
993 nRet = nMax;
994 }
995 return nRet;
996}
997
998bool SwTextFly::ForEach( const SwRect &rRect, SwRect* pRect, bool bAvoid ) const
999{
1000 SwSwapIfSwapped swap(const_cast<SwTextFrame *>(m_pCurrFrame));
1001
1002 // Optimization
1003 SwRectFnSet aRectFnSet(m_pCurrFrame);
1004
1005 // tdf#127235 stop if the area is larger than the page
1006 if( aRectFnSet.GetHeight(m_pPage->getFrameArea()) < aRectFnSet.GetHeight(rRect))
2
Assuming the condition is false
3
Taking false branch
1007 {
1008 // get the doc model description
1009 const SwPageDesc* pPageDesc = m_pPage->GetPageDesc();
1010
1011 // if there is no next page style or it is the same as the current
1012 // => stop trying to place the frame (it would end in an infinite loop)
1013 if( pPageDesc &&
1014 ( !pPageDesc->GetFollow() || pPageDesc->GetFollow() == pPageDesc) )
1015 {
1016 return false;
1017 }
1018 }
1019
1020 bool bRet = false;
1021 // #i68520#
1022 const SwAnchoredObjList::size_type nCount( m_bOn ? GetAnchoredObjList()->size() : 0 );
4
Assuming field 'm_bOn' is true
5
'?' condition is true
1023 if (nCount > 0)
6
Assuming 'nCount' is > 0
7
Taking true branch
1024 {
1025 for( SwAnchoredObjList::size_type i = 0; i
7.1
'i' is < 'nCount'
7.1
'i' is < 'nCount'
< nCount; ++i )
8
Loop condition is true. Entering loop body
1026 {
1027 // #i68520#
1028 const SwAnchoredObject* pAnchoredObj = (*mpAnchoredObjList)[i];
1029
1030 SwRect aRect( pAnchoredObj->GetObjRectWithSpaces() );
1031
1032 if( aRectFnSet.GetLeft(aRect) > aRectFnSet.GetRight(rRect) )
9
Assuming the condition is false
10
Taking false branch
1033 break;
1034
1035 // #i68520#
1036 if ( mpCurrAnchoredObj != pAnchoredObj && aRect.IsOver( rRect ) )
11
Assuming 'pAnchoredObj' is not equal to field 'mpCurrAnchoredObj'
12
Assuming the condition is true
13
Taking true branch
1037 {
1038 // #i68520#
1039 const SwFormat* pFormat( &(pAnchoredObj->GetFrameFormat()) );
1040 const SwFormatSurround &rSur = pFormat->GetSurround();
1041 if( bAvoid
13.1
'bAvoid' is true
13.1
'bAvoid' is true
)
14
Taking true branch
1042 {
1043 // If the text flows below, it has no influence on
1044 // formatting. In LineIter::DrawText() it is "just"
1045 // necessary to cleverly set the ClippingRegions
1046 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
1047 if( ( css::text::WrapTextMode_THROUGH == rSur.GetSurround() &&
15
Assuming the condition is false
17
Taking false branch
1048 ( !rSur.IsAnchorOnly() ||
1049 // #i68520#
1050 GetMaster() == pAnchoredObj->GetAnchorFrame() ||
1051 ((RndStdIds::FLY_AT_PARA != rAnchor.GetAnchorId()) &&
1052 (RndStdIds::FLY_AT_CHAR != rAnchor.GetAnchorId())) ) )
1053 || aRect.Top() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) )
16
Assuming the condition is false
1054 continue;
1055 }
1056
1057 // #i58642#
1058 // Compare <GetMaster()> instead of <m_pCurrFrame> with the
1059 // anchor frame of the anchored object, because a follow frame
1060 // has to ignore the anchored objects of its master frame.
1061 // Note: Anchored objects are always registered at the master
1062 // frame, exception are as-character anchored objects,
1063 // but these aren't handled here.
1064 // #i68520#
1065 if ( mbIgnoreCurrentFrame &&
18
Assuming field 'mbIgnoreCurrentFrame' is false
1066 GetMaster() == pAnchoredObj->GetAnchorFrame() )
1067 continue;
1068
1069 if( pRect
18.1
'pRect' is non-null
18.1
'pRect' is non-null
)
19
Taking true branch
1070 {
1071 // #i68520#
1072 SwRect aFly = AnchoredObjToRect( pAnchoredObj, rRect );
20
Calling 'SwTextFly::AnchoredObjToRect'
1073 if( aFly.IsEmpty() || !aFly.IsOver( rRect ) )
1074 continue;
1075 if( !bRet || (
1076 (!m_pCurrFrame->IsRightToLeft() &&
1077 ( aRectFnSet.GetLeft(aFly) <
1078 aRectFnSet.GetLeft(*pRect) ) ) ||
1079 (m_pCurrFrame->IsRightToLeft() &&
1080 ( aRectFnSet.GetRight(aFly) >
1081 aRectFnSet.GetRight(*pRect) ) ) ) )
1082 *pRect = aFly;
1083 if( rSur.IsContour() )
1084 {
1085 bRet = true;
1086 continue;
1087 }
1088 }
1089 bRet = true;
1090 break;
1091 }
1092 }
1093 }
1094
1095 return bRet;
1096}
1097
1098// #i68520#
1099SwAnchoredObjList::size_type SwTextFly::GetPos( const SwAnchoredObject* pAnchoredObj ) const
1100{
1101 SwAnchoredObjList::size_type nCount = GetAnchoredObjList()->size();
1102 SwAnchoredObjList::size_type nRet = 0;
1103 while ( nRet < nCount && pAnchoredObj != (*mpAnchoredObjList)[ nRet ] )
1104 ++nRet;
1105 return nRet;
1106}
1107
1108// #i68520#
1109void SwTextFly::CalcRightMargin( SwRect &rFly,
1110 SwAnchoredObjList::size_type nFlyPos,
1111 const SwRect &rLine ) const
1112{
1113 // Usually the right margin is the right margin of the Printarea
1114 OSL_ENSURE( !m_pCurrFrame->IsVertical() || !m_pCurrFrame->IsSwapped(),do { if (true && (!(!m_pCurrFrame->IsVertical() ||
!m_pCurrFrame->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "1115" ": "), "%s", "SwTextFly::CalcRightMargin with swapped frame"
); } } while (false)
1115 "SwTextFly::CalcRightMargin with swapped frame" )do { if (true && (!(!m_pCurrFrame->IsVertical() ||
!m_pCurrFrame->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "1115" ": "), "%s", "SwTextFly::CalcRightMargin with swapped frame"
); } } while (false)
;
1116 SwRectFnSet aRectFnSet(m_pCurrFrame);
1117 // #118796# - correct determination of right of printing area
1118 SwTwips nRight = aRectFnSet.GetPrtRight(*m_pCurrFrame);
1119 SwTwips nFlyRight = aRectFnSet.GetRight(rFly);
1120 SwRect aLine( rLine );
1121 aRectFnSet.SetRight( aLine, nRight );
1122 aRectFnSet.SetLeft( aLine, aRectFnSet.GetLeft(rFly) );
1123
1124 // It is possible that there is another object that is _above_ us
1125 // and protrudes into the same line.
1126 // Flys with run-through are invisible for those below, i.e., they
1127 // are ignored for computing the margins of other Flys.
1128 // 3301: pNext->getFrameArea().IsOver( rLine ) is necessary
1129 // #i68520#
1130 css::text::WrapTextMode eSurroundForTextWrap;
1131
1132 bool bStop = false;
1133 // #i68520#
1134 SwAnchoredObjList::size_type nPos = 0;
1135
1136 // #i68520#
1137 while( nPos < mpAnchoredObjList->size() && !bStop )
1138 {
1139 if( nPos == nFlyPos )
1140 {
1141 ++nPos;
1142 continue;
1143 }
1144 // #i68520#
1145 const SwAnchoredObject* pNext = (*mpAnchoredObjList)[ nPos++ ];
1146 if ( pNext == mpCurrAnchoredObj )
1147 continue;
1148 eSurroundForTextWrap = GetSurroundForTextWrap( pNext );
1149 if( css::text::WrapTextMode_THROUGH == eSurroundForTextWrap )
1150 continue;
1151
1152 const SwRect aTmp( SwContourCache::CalcBoundRect
1153 ( pNext, aLine, m_pCurrFrame, nFlyRight, true ) );
1154 SwTwips nTmpRight = aRectFnSet.GetRight(aTmp);
1155
1156 // optimization:
1157 // Record in nNextTop at which Y-position frame related changes are
1158 // likely. This is so that, despite only looking at frames in the
1159 // current line height, for frames without wrap the line height is
1160 // incremented so that with a single line the lower border of the frame
1161 // (or possibly the upper border of another frame) is reached.
1162 // Especially in HTML documents there are often (dummy) paragraphs in
1163 // 2 pt font, and they used to only evade big frames after huge numbers
1164 // of empty lines.
1165 const long nTmpTop = aRectFnSet.GetTop(aTmp);
1166 if( aRectFnSet.YDiff( nTmpTop, aRectFnSet.GetTop(aLine) ) > 0 )
1167 {
1168 if( aRectFnSet.YDiff( m_nNextTop, nTmpTop ) > 0 )
1169 SetNextTop( nTmpTop ); // upper border of next frame
1170 }
1171 else if (!aRectFnSet.GetWidth(aTmp)) // typical for Objects with contour wrap
1172 { // For Objects with contour wrap that start before the current
1173 // line, and end below it, but do not actually overlap it, the
1174 // optimization has to be disabled, because the circumstances
1175 // can change in the next line.
1176 if( ! aRectFnSet.GetHeight(aTmp) ||
1177 aRectFnSet.YDiff( aRectFnSet.GetBottom(aTmp),
1178 aRectFnSet.GetTop(aLine) ) > 0 )
1179 SetNextTop( 0 );
1180 }
1181 if( aTmp.IsOver( aLine ) && nTmpRight > nFlyRight )
1182 {
1183 nFlyRight = nTmpRight;
1184 if( css::text::WrapTextMode_RIGHT == eSurroundForTextWrap ||
1185 css::text::WrapTextMode_PARALLEL == eSurroundForTextWrap )
1186 {
1187 // overrule the FlyFrame
1188 if( nRight > nFlyRight )
1189 nRight = nFlyRight;
1190 bStop = true;
1191 }
1192 }
1193 }
1194 aRectFnSet.SetRight( rFly, nRight );
1195}
1196
1197// #i68520#
1198void SwTextFly::CalcLeftMargin( SwRect &rFly,
1199 SwAnchoredObjList::size_type nFlyPos,
1200 const SwRect &rLine ) const
1201{
1202 OSL_ENSURE( !m_pCurrFrame->IsVertical() || !m_pCurrFrame->IsSwapped(),do { if (true && (!(!m_pCurrFrame->IsVertical() ||
!m_pCurrFrame->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "1203" ": "), "%s", "SwTextFly::CalcLeftMargin with swapped frame"
); } } while (false)
1203 "SwTextFly::CalcLeftMargin with swapped frame" )do { if (true && (!(!m_pCurrFrame->IsVertical() ||
!m_pCurrFrame->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "1203" ": "), "%s", "SwTextFly::CalcLeftMargin with swapped frame"
); } } while (false)
;
1204 SwRectFnSet aRectFnSet(m_pCurrFrame);
1205 // #118796# - correct determination of left of printing area
1206 SwTwips nLeft = aRectFnSet.GetPrtLeft(*m_pCurrFrame);
1207 const SwTwips nFlyLeft = aRectFnSet.GetLeft(rFly);
1208
1209 if( nLeft > nFlyLeft )
1210 nLeft = rFly.Left();
1211
1212 SwRect aLine( rLine );
1213 aRectFnSet.SetLeft( aLine, nLeft );
1214
1215 // It is possible that there is another object that is _above_ us
1216 // and protrudes into the same line.
1217 // Flys with run-through are invisible for those below, i.e., they
1218 // are ignored for computing the margins of other Flys.
1219 // 3301: pNext->getFrameArea().IsOver( rLine ) is necessary
1220
1221 // #i68520#
1222 SwAnchoredObjList::size_type nMyPos = nFlyPos;
1223 while( ++nFlyPos < mpAnchoredObjList->size() )
1224 {
1225 // #i68520#
1226 const SwAnchoredObject* pNext = (*mpAnchoredObjList)[ nFlyPos ];
1227 const SwRect& aTmp( pNext->GetObjRectWithSpaces() );
1228 if( aRectFnSet.GetLeft(aTmp) >= nFlyLeft )
1229 break;
1230 }
1231
1232 while( nFlyPos )
1233 {
1234 if( --nFlyPos == nMyPos )
1235 continue;
1236 // #i68520#
1237 const SwAnchoredObject* pNext = (*mpAnchoredObjList)[ nFlyPos ];
1238 if( pNext == mpCurrAnchoredObj )
1239 continue;
1240 css::text::WrapTextMode eSurroundForTextWrap = GetSurroundForTextWrap( pNext );
1241 if( css::text::WrapTextMode_THROUGH == eSurroundForTextWrap )
1242 continue;
1243
1244 const SwRect aTmp( SwContourCache::CalcBoundRect
1245 (pNext, aLine, m_pCurrFrame, nFlyLeft, false) );
1246
1247 if( aRectFnSet.GetLeft(aTmp) < nFlyLeft && aTmp.IsOver( aLine ) )
1248 {
1249 // #118796# - no '+1', because <..fnGetRight>
1250 // returns the correct value.
1251 SwTwips nTmpRight = aRectFnSet.GetRight(aTmp);
1252 if ( nLeft <= nTmpRight )
1253 nLeft = nTmpRight;
1254
1255 break;
1256 }
1257 }
1258 aRectFnSet.SetLeft( rFly, nLeft );
1259}
1260
1261// #i68520#
1262SwRect SwTextFly::AnchoredObjToRect( const SwAnchoredObject* pAnchoredObj,
1263 const SwRect &rLine ) const
1264{
1265 SwRectFnSet aRectFnSet(m_pCurrFrame);
1266
1267 const long nXPos = m_pCurrFrame->IsRightToLeft() ?
21
Assuming the condition is false
22
'?' condition is false
1268 rLine.Right() :
1269 aRectFnSet.GetLeft(rLine);
1270
1271 SwRect aFly = mbIgnoreContour ?
23
Assuming field 'mbIgnoreContour' is false
24
'?' condition is false
1272 pAnchoredObj->GetObjRectWithSpaces() :
1273 SwContourCache::CalcBoundRect(pAnchoredObj, rLine, m_pCurrFrame,
25
Calling 'SwContourCache::CalcBoundRect'
1274 nXPos, !m_pCurrFrame->IsRightToLeft());
1275
1276 if( !aFly.Width() )
1277 return aFly;
1278
1279 // so the line may grow up to the lower edge of the frame
1280 SetNextTop( aRectFnSet.GetBottom(aFly) );
1281 SwAnchoredObjList::size_type nFlyPos = GetPos( pAnchoredObj );
1282
1283 // LEFT and RIGHT, we grow the rectangle.
1284 // We have some problems, when several frames are to be seen.
1285 // At the moment, only the easier case is assumed:
1286 // + LEFT means that the text must flow on the left of the frame,
1287 // that is the frame expands to the right edge of the print area
1288 // or to the next frame.
1289 // + RIGHT is the opposite.
1290 // Otherwise the set distance between text and frame is always
1291 // added up.
1292 switch( GetSurroundForTextWrap( pAnchoredObj ) )
1293 {
1294 case css::text::WrapTextMode_LEFT :
1295 {
1296 CalcRightMargin( aFly, nFlyPos, rLine );
1297 break;
1298 }
1299 case css::text::WrapTextMode_RIGHT :
1300 {
1301 CalcLeftMargin( aFly, nFlyPos, rLine );
1302 break;
1303 }
1304 case css::text::WrapTextMode_NONE :
1305 {
1306 CalcRightMargin( aFly, nFlyPos, rLine );
1307 CalcLeftMargin( aFly, nFlyPos, rLine );
1308 break;
1309 }
1310 default:
1311 break;
1312 }
1313 return aFly;
1314}
1315
1316// #i68520#
1317
1318// Wrap only on sides with at least 2cm space for the text
1319#define TEXT_MIN1134 1134
1320
1321// MS Word wraps on sides with even less space (value guessed).
1322#define TEXT_MIN_SMALL300 300
1323
1324// Wrap on both sides up to a frame width of 1.5cm
1325#define FRAME_MAX850 850
1326
1327css::text::WrapTextMode SwTextFly::GetSurroundForTextWrap( const SwAnchoredObject* pAnchoredObj ) const
1328{
1329 const SwFrameFormat* pFormat = &(pAnchoredObj->GetFrameFormat());
1330 const SwFormatSurround &rFlyFormat = pFormat->GetSurround();
1331 css::text::WrapTextMode eSurroundForTextWrap = rFlyFormat.GetSurround();
1332
1333 if( rFlyFormat.IsAnchorOnly() && pAnchoredObj->GetAnchorFrame() != GetMaster() )
1334 {
1335 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
1336 if ((RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()) ||
1337 (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()))
1338 {
1339 return css::text::WrapTextMode_NONE;
1340 }
1341 }
1342
1343 // in cause of run-through and nowrap ignore smartly
1344 if( css::text::WrapTextMode_THROUGH == eSurroundForTextWrap ||
1345 css::text::WrapTextMode_NONE == eSurroundForTextWrap )
1346 return eSurroundForTextWrap;
1347
1348 // left is left and right is right
1349 if (m_pCurrFrame->IsRightToLeft())
1350 {
1351 if ( css::text::WrapTextMode_LEFT == eSurroundForTextWrap )
1352 eSurroundForTextWrap = css::text::WrapTextMode_RIGHT;
1353 else if ( css::text::WrapTextMode_RIGHT == eSurroundForTextWrap )
1354 eSurroundForTextWrap = css::text::WrapTextMode_LEFT;
1355 }
1356
1357 // "ideal page wrap":
1358 if ( css::text::WrapTextMode_DYNAMIC == eSurroundForTextWrap )
1359 {
1360 SwRectFnSet aRectFnSet(m_pCurrFrame);
1361 const long nCurrLeft = aRectFnSet.GetPrtLeft(*m_pCurrFrame);
1362 const long nCurrRight = aRectFnSet.GetPrtRight(*m_pCurrFrame);
1363 const SwRect& aRect( pAnchoredObj->GetObjRectWithSpaces() );
1364 long nFlyLeft = aRectFnSet.GetLeft(aRect);
1365 long nFlyRight = aRectFnSet.GetRight(aRect);
1366
1367 if ( nFlyRight < nCurrLeft || nFlyLeft > nCurrRight )
1368 eSurroundForTextWrap = css::text::WrapTextMode_PARALLEL;
1369 else
1370 {
1371 long nLeft = nFlyLeft - nCurrLeft;
1372 long nRight = nCurrRight - nFlyRight;
1373 if( nFlyRight - nFlyLeft > FRAME_MAX850 )
1374 {
1375 if( nLeft < nRight )
1376 nLeft = 0;
1377 else
1378 nRight = 0;
1379 }
1380 const int textMin = GetMaster()->GetDoc()
1381 .getIDocumentSettingAccess().get(DocumentSettingId::SURROUND_TEXT_WRAP_SMALL )
1382 ? TEXT_MIN_SMALL300 : TEXT_MIN1134;
1383
1384 // In case there is no space on either side, then css::text::WrapTextMode_PARALLEL
1385 // gives the same result when doing the initial layout or a layout
1386 // update after editing, so prefer that over css::text::WrapTextMode_NONE.
1387 if (nLeft == 0 && nRight == 0)
1388 return css::text::WrapTextMode_PARALLEL;
1389
1390 if( nLeft < textMin )
1391 nLeft = 0;
1392 if( nRight < textMin )
1393 nRight = 0;
1394 if( nLeft )
1395 eSurroundForTextWrap = nRight ? css::text::WrapTextMode_PARALLEL : css::text::WrapTextMode_LEFT;
1396 else
1397 eSurroundForTextWrap = nRight ? css::text::WrapTextMode_RIGHT: css::text::WrapTextMode_NONE;
1398 }
1399 }
1400
1401 return eSurroundForTextWrap;
1402}
1403
1404bool SwTextFly::IsAnyFrame( const SwRect &rLine ) const
1405{
1406
1407 SwSwapIfSwapped swap(const_cast<SwTextFrame *>(m_pCurrFrame));
1408
1409 OSL_ENSURE( m_bOn, "IsAnyFrame: Why?" )do { if (true && (!(m_bOn))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx"
":" "1409" ": "), "%s", "IsAnyFrame: Why?"); } } while (false
)
;
1410
1411 return ForEach( rLine, nullptr, false );
1412}
1413
1414/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/sw/source/core/inc/frame.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#ifndef INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX
21#define INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX
22
23#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
24#include <editeng/borderline.hxx>
25#include <svl/poolitem.hxx>
26#include <swtypes.hxx>
27#include <swrect.hxx>
28#include <calbck.hxx>
29#include <svl/SfxBroadcaster.hxx>
30#include <o3tl/typed_flags_set.hxx>
31#include <com/sun/star/style/TabStop.hpp>
32#include <basegfx/matrix/b2dhommatrix.hxx>
33#include <vcl/outdev.hxx>
34
35#include <memory>
36
37namespace drawinglayer::processor2d { class BaseProcessor2D; }
38
39class SwLayoutFrame;
40class SwRootFrame;
41class SwPageFrame;
42class SwBodyFrame;
43class SwFlyFrame;
44class SwSectionFrame;
45class SwFootnoteFrame;
46class SwFootnoteBossFrame;
47class SwTabFrame;
48class SwRowFrame;
49class SwContentFrame;
50class SwAttrSet;
51class Color;
52class SwBorderAttrs;
53class SwCache;
54class SvxBrushItem;
55class SvxFormatBreakItem;
56class SwFormatPageDesc;
57class SwSelectionList;
58struct SwPosition;
59struct SwCursorMoveState;
60class SwFormat;
61class SwPrintData;
62class SwSortedObjs;
63class SwAnchoredObject;
64enum class SvxFrameDirection;
65class IDocumentDrawModelAccess;
66
67// Each FrameType is represented here as a bit.
68// The bits must be set in a way that it can be determined with masking of
69// which kind of FrameType an instance is _and_ from what classes it was derived.
70// Each frame has in its base class a member that must be set by the
71// constructors accordingly.
72enum class SwFrameType
73{
74 None = 0x0000,
75 Root = 0x0001,
76 Page = 0x0002,
77 Column = 0x0004,
78 Header = 0x0008,
79 Footer = 0x0010,
80 FtnCont = 0x0020,
81 Ftn = 0x0040,
82 Body = 0x0080,
83 Fly = 0x0100,
84 Section = 0x0200,
85// UNUSED 0x0400
86 Tab = 0x0800,
87 Row = 0x1000,
88 Cell = 0x2000,
89 Txt = 0x4000,
90 NoTxt = 0x8000,
91};
92
93namespace o3tl
94{
95 template<> struct typed_flags<SwFrameType> : is_typed_flags<SwFrameType, 0xfbff> {};
96};
97
98// for internal use some common combinations
99#define FRM_LAYOUTSwFrameType(0x3bFF) SwFrameType(0x3bFF)
100#define FRM_ALLSwFrameType(0xfbff) SwFrameType(0xfbff)
101#define FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt) (SwFrameType::Txt | SwFrameType::NoTxt)
102#define FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column) (SwFrameType::Page | SwFrameType::Column)
103#define FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header |
SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType
::Tab | SwFrameType::Cell | SwFrameType::Txt)
(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType::Tab | SwFrameType::Cell | SwFrameType::Txt)
104#define FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell) (SwFrameType::Column | SwFrameType::Cell)
105#define FRM_NOTE_VERT(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section
| SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType
::Txt)
(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType::Txt)
106#define FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer) (SwFrameType::Header | SwFrameType::Footer)
107#define FRM_BODYFTNC(SwFrameType::FtnCont | SwFrameType::Body) (SwFrameType::FtnCont | SwFrameType::Body)
108
109// for GetNextLeaf/GetPrevLeaf.
110enum MakePageType
111{
112 MAKEPAGE_NONE, // do not create page/footnote
113 MAKEPAGE_APPEND, // only append page if needed
114 MAKEPAGE_INSERT, // add or append page if needed
115 MAKEPAGE_FTN, // add footnote if needed
116 MAKEPAGE_NOSECTION // Don't create section frames
117};
118
119namespace drawinglayer::attribute {
120 class SdrAllFillAttributesHelper;
121 typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr;
122}
123
124/// Helper class to isolate geometry-defining members of SwFrame
125/// and to control their accesses. Moved to own class to have no
126/// hidden accesses to 'private' members anymore.
127///
128/// Added most important flags about the state of this geometric
129/// information and if it is valid or not
130class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition
131{
132private:
133 friend void FriendHackInvalidateRowFrame(SwFrameAreaDefinition &);
134
135 // The absolute position and size of the SwFrame in the document.
136 // This values are set by the layouter implementations
137 SwRect maFrameArea;
138
139 // The 'inner' Frame Area defined by a SwRect relative to FrameArea:
140 // When identical to FrameArea, Pos() will be (0, 0) and Size identical.
141 SwRect maFramePrintArea;
142
143 // bitfield
144 bool mbFrameAreaPositionValid : 1;
145 bool mbFrameAreaSizeValid : 1;
146 bool mbFramePrintAreaValid : 1;
147
148 // #i65250#
149 // frame ID is now in general available - used for layout loop control
150 static sal_uInt32 mnLastFrameId;
151 const sal_uInt32 mnFrameId;
152
153protected:
154 // write access to mb*Valid flags
155 void setFrameAreaPositionValid(bool bNew);
156 void setFrameAreaSizeValid(bool bNew);
157 void setFramePrintAreaValid(bool bNew);
158
159public:
160 SwFrameAreaDefinition();
161 virtual ~SwFrameAreaDefinition();
162
163 // read access to mb*Valid flags
164 bool isFrameAreaPositionValid() const { return mbFrameAreaPositionValid; }
165 bool isFrameAreaSizeValid() const { return mbFrameAreaSizeValid; }
166 bool isFramePrintAreaValid() const { return mbFramePrintAreaValid; }
167
168 // syntactic sugar: test whole FrameAreaDefinition
169 bool isFrameAreaDefinitionValid() const { return isFrameAreaPositionValid() && isFrameAreaSizeValid() && isFramePrintAreaValid(); }
170
171 // #i65250#
172 sal_uInt32 GetFrameId() const { return mnFrameId; }
173
174 // read accesses to FrameArea definitions - only const access allowed.
175 // Do *not* const_cast results, it is necessary to track changes. use
176 // the below offered WriteAccess helper classes instead
177 const SwRect& getFrameArea() const { return maFrameArea; }
178 const SwRect& getFramePrintArea() const { return maFramePrintArea; }
179
180 // helper class(es) for FrameArea manipulation. These
181 // have to be used to apply changes to FrameAreas. They hold a copy of the
182 // SwRect for manipulation. It gets written back at destruction. Thus, this
183 // mechanism depends on scope usage, take care. It prevents errors using
184 // different instances of SwFrame in get/set methods which is more safe
185 class FrameAreaWriteAccess : public SwRect
186 {
187 private:
188 SwFrameAreaDefinition& mrTarget;
189
190 FrameAreaWriteAccess(const FrameAreaWriteAccess&) = delete;
191 FrameAreaWriteAccess& operator=(const FrameAreaWriteAccess&) = delete;
192
193 public:
194 FrameAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFrameArea()), mrTarget(rTarget) {}
195 ~FrameAreaWriteAccess();
196 void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; }
197 };
198
199 // same helper for FramePrintArea
200 class FramePrintAreaWriteAccess : public SwRect
201 {
202 private:
203 SwFrameAreaDefinition& mrTarget;
204
205 FramePrintAreaWriteAccess(const FramePrintAreaWriteAccess&) = delete;
206 FramePrintAreaWriteAccess& operator=(const FramePrintAreaWriteAccess&) = delete;
207
208 public:
209 FramePrintAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFramePrintArea()), mrTarget(rTarget) {}
210 ~FramePrintAreaWriteAccess();
211 void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; }
212 };
213
214 // RotateFlyFrame3 - Support for Transformations
215 // Hand out the Transformations for the current FrameAreaDefinition
216 // for the FrameArea and FramePrintArea.
217 // FramePrintArea is not relative to FrameArea in this
218 // transformation representation (to make it easier to use and understand).
219 // There is no 'set' method since SwFrame is a layout object. For
220 // some cases rotation will be included (used for SwGrfNode in inner
221 // SwFrame of a SwFlyFrame)
222 virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const;
223 virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
224
225 // RotateFlyFrame3 - Support for Transformations
226 // Modify current transformations by applying given translation
227 virtual void transform_translate(const Point& rOffset);
228};
229
230/// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate
231/// transformable. It provides some tooling to do so. To use, add as member
232/// (see e.g. SwFlyFreeFrame which uses 'std::unique_ptr< TransformableSwFrame >')
233class TransformableSwFrame
234{
235private:
236 // The SwFrameAreaDefinition to work on
237 SwFrameAreaDefinition& mrSwFrameAreaDefinition;
238
239 // FrameAreaTransformation and FramePrintAreaTransformation
240 // !identity when needed (translate/scale is used (e.g. rotation))
241 basegfx::B2DHomMatrix maFrameAreaTransformation;
242 basegfx::B2DHomMatrix maFramePrintAreaTransformation;
243
244public:
245 TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition)
246 : mrSwFrameAreaDefinition(rSwFrameAreaDefinition),
247 maFrameAreaTransformation(),
248 maFramePrintAreaTransformation()
249 {
250 }
251
252 // get SwFrameArea in transformation form
253 const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const
254 {
255 return maFrameAreaTransformation;
256 }
257
258 // get SwFramePrintArea in transformation form
259 const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const
260 {
261 return maFramePrintAreaTransformation;
262 }
263
264 // Helpers to re-create the untransformed SwRect(s) originally
265 // in the SwFrameAreaDefinition, based on the current Transformations.
266 SwRect getUntransformedFrameArea() const;
267 SwRect getUntransformedFramePrintArea() const;
268
269 // Helper method to re-create FrameAreaTransformations based on the
270 // current FrameAreaDefinition transformed by given rotation and Center
271 void createFrameAreaTransformations(
272 double fRotation,
273 const basegfx::B2DPoint& rCenter);
274
275 // Tooling method to reset the SwRect(s) in the current
276 // SwFrameAreaDefinition which are already adapted to
277 // Transformation back to the untransformed state, using
278 // the getUntransformedFrame*Area calls above when needed.
279 // Only the SwRect(s) are changed back, not the transformations.
280 void restoreFrameAreas();
281
282 // Re-Creates the SwRect(s) as BoundAreas based on the current
283 // set Transformations.
284 void adaptFrameAreasToTransformations();
285
286 // Modify current definitions by applying the given transformation
287 void transform(const basegfx::B2DHomMatrix& aTransform);
288};
289
290/**
291 * Base class of the Writer layout elements.
292 *
293 * This includes not only fly frames, but everything down to the paragraph
294 * level: pages, headers, footers, etc. (Inside a paragraph SwLinePortion
295 * instances are used.)
296 */
297class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwFrame : public SwFrameAreaDefinition, public SwClient, public SfxBroadcaster
298{
299 // the hidden Frame
300 friend class SwFlowFrame;
301 friend class SwLayoutFrame;
302 friend class SwLooping;
303 friend class SwDeletionChecker; // for GetDep()
304
305 // voids lower during creation of a column
306 friend SwFrame *SaveContent( SwLayoutFrame *, SwFrame* pStart );
307 friend void RestoreContent( SwFrame *, SwLayoutFrame *, SwFrame *pSibling );
308
309 // for validating a mistakenly invalidated one in SwContentFrame::MakeAll
310 friend void ValidateSz( SwFrame *pFrame );
311 // implemented in text/txtftn.cxx, prevents Footnote oscillation
312 friend void ValidateText( SwFrame *pFrame );
313
314 friend void MakeNxt( SwFrame *pFrame, SwFrame *pNxt );
315
316 // cache for (border) attributes
317 static SwCache *mpCache;
318
319 SwRootFrame *mpRoot;
320 SwLayoutFrame *mpUpper;
321 SwFrame *mpNext;
322 SwFrame *mpPrev;
323
324 // sw_redlinehide: hide these dangerous SwClient functions
325 using SwClient::GetRegisteredInNonConst;
326 using SwClient::GetRegisteredIn;
327
328 SwFrame *FindNext_();
329 SwFrame *FindPrev_();
330
331 /** method to determine next content frame in the same environment
332 for a flow frame (content frame, table frame, section frame)
333
334 #i27138# - adding documentation:
335 Travelling downwards through the layout to determine the next content
336 frame in the same environment. There are several environments in a
337 document, which form a closed context regarding this function. These
338 environments are:
339 - Each page header
340 - Each page footer
341 - Each unlinked fly frame
342 - Each group of linked fly frames
343 - All footnotes
344 - All document body frames
345 #i27138# - adding parameter <_bInSameFootnote>
346 Its default value is <false>. If its value is <true>, the environment
347 'All footnotes' is no longer treated. Instead each footnote is treated
348 as an own environment.
349
350 @param _bInSameFootnote
351 input parameter - boolean indicating, that the found next content
352 frame has to be in the same footnote frame. This parameter is only
353 relevant for flow frames in footnotes.
354
355 @return SwContentFrame*
356 pointer to the found next content frame. It's NULL, if none exists.
357 */
358 SwContentFrame* FindNextCnt_( const bool _bInSameFootnote );
359
360 /** method to determine previous content frame in the same environment
361 for a flow frame (content frame, table frame, section frame)
362
363 #i27138#
364 Travelling upwards through the layout to determine the previous content
365 frame in the same environment. There are several environments in a
366 document, which form a closed context regarding this function. These
367 environments are:
368 - Each page header
369 - Each page footer
370 - Each unlinked fly frame
371 - Each group of linked fly frames
372 - All footnotes
373 - All document body frames
374 #i27138# - adding parameter <_bInSameFootnote>
375 Its default value is <false>. If its value is <true>, the environment
376 'All footnotes' is no longer treated. Instead each footnote is treated
377 as an own environment.
378
379 The found previous content frame has to be in the same footnote frame. This is only
380 relevant for flow frames in footnotes.
381
382 @return SwContentFrame*
383 pointer to the found previous content frame. It's NULL, if none exists.
384 */
385 SwContentFrame* FindPrevCnt_();
386
387 void UpdateAttrFrame( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 & );
388 SwFrame* GetIndNext_();
389 void SetDirFlags( bool bVert );
390
391 const SwLayoutFrame* ImplGetNextLayoutLeaf( bool bFwd ) const;
392
393 SwPageFrame* ImplFindPageFrame();
394
395protected:
396 std::unique_ptr<SwSortedObjs> m_pDrawObjs; // draw objects, can be null
397 SwFrameType mnFrameType; //Who am I?
398
399 bool mbInDtor : 1;
400 bool mbInvalidR2L : 1;
401 bool mbDerivedR2L : 1;
402 bool mbRightToLeft : 1;
403 bool mbInvalidVert : 1;
404 bool mbDerivedVert : 1;
405 bool mbVertical : 1;
406
407 bool mbVertLR : 1;
408 bool mbVertLRBT : 1;
409
410 bool mbValidLineNum : 1;
411 bool mbFixSize : 1;
412
413 // if true, frame will be painted completely even content was changed
414 // only partially. For ContentFrames a border (from Action) will exclusively
415 // painted if <mbCompletePaint> is true.
416 bool mbCompletePaint : 1;
417
418 bool mbRetouche : 1; // frame is responsible for retouching
419
420 bool mbInfInvalid : 1; // InfoFlags are invalid
421 bool mbInfBody : 1; // Frame is in document body
422 bool mbInfTab : 1; // Frame is in a table
423 bool mbInfFly : 1; // Frame is in a Fly
424 bool mbInfFootnote : 1; // Frame is in a footnote
425 bool mbInfSct : 1; // Frame is in a section
426 bool mbColLocked : 1; // lock Grow/Shrink for column-wise section
427 // or fly frames, will be set in Format
428 bool m_isInDestroy : 1;
429 bool mbForbidDelete : 1;
430
431 void ColLock() { mbColLocked = true; }
432 void ColUnlock() { mbColLocked = false; }
433
434 virtual void DestroyImpl();
435 virtual ~SwFrame() override;
436
437 // Only used by SwRootFrame Ctor to get 'this' into mpRoot...
438 void setRootFrame( SwRootFrame* pRoot ) { mpRoot = pRoot; }
439
440 SwPageFrame *InsertPage( SwPageFrame *pSibling, bool bFootnote );
441 void PrepareMake(vcl::RenderContext* pRenderContext);
442 void OptPrepareMake();
443 virtual void MakePos();
444 // Format next frame of table frame to assure keeping attributes.
445 // In case of nested tables method <SwFrame::MakeAll()> is called to
446 // avoid formatting of superior table frame.
447 friend SwFrame* sw_FormatNextContentForKeep( SwTabFrame* pTabFrame );
448
449 virtual void MakeAll(vcl::RenderContext* pRenderContext) = 0;
450 // adjust frames of a page
451 SwTwips AdjustNeighbourhood( SwTwips nDiff, bool bTst = false );
452
453 // change only frame size not the size of PrtArea
454 virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) = 0;
455 virtual SwTwips GrowFrame ( SwTwips, bool bTst = false, bool bInfo = false ) = 0;
456
457 /// use these so we can grep for SwFrame's GetRegisteredIn accesses
458 /// beware that SwTextFrame may return sw::WriterMultiListener
459 SwModify *GetDep() { return GetRegisteredInNonConst(); }
460 const SwModify *GetDep() const { return GetRegisteredIn(); }
461
462 SwFrame( SwModify*, SwFrame* );
463
464 void CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool bBrowse );
465
466 /** enumeration for the different invalidations
467 #i28701#
468 */
469 enum InvalidationType
470 {
471 INVALID_SIZE, INVALID_PRTAREA, INVALID_POS, INVALID_LINENUM, INVALID_ALL
472 };
473
474 /** method to determine, if an invalidation is allowed.
475 #i28701
476 */
477 virtual bool InvalidationAllowed( const InvalidationType _nInvalid ) const;
478
479 /** method to perform additional actions on an invalidation
480
481 #i28701#
482 Method has *only* to contain actions, which has to be performed on
483 *every* assignment of the corresponding flag to <false>.
484 */
485 virtual void ActionOnInvalidation( const InvalidationType _nInvalid );
486
487 // draw shadow and borders
488 void PaintShadow( const SwRect&, SwRect&, const SwBorderAttrs& ) const;
489 virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override;
490
491 virtual const IDocumentDrawModelAccess& getIDocumentDrawModelAccess( );
492
493public:
494 virtual css::uno::Sequence< css::style::TabStop > GetTabStopInfo( SwTwips )
495 {
496 return css::uno::Sequence< css::style::TabStop >();
497 }
498
499
500 SwFrameType GetType() const { return mnFrameType; }
501
502 static SwCache &GetCache() { return *mpCache; }
503 static SwCache *GetCachePtr() { return mpCache; }
504 static void SetCache( SwCache *pNew ) { mpCache = pNew; }
505
506 // change PrtArea size and FrameSize
507 SwTwips Shrink( SwTwips, bool bTst = false, bool bInfo = false );
508 SwTwips Grow ( SwTwips, bool bTst = false, bool bInfo = false );
509
510 // different methods for inserting in layout tree (for performance reasons)
511
512 // insert before pBehind or at the end of the chain below mpUpper
513 void InsertBefore( SwLayoutFrame* pParent, SwFrame* pBehind );
514 // insert after pBefore or at the beginning of the chain below mpUpper
515 void InsertBehind( SwLayoutFrame *pParent, SwFrame *pBefore );
516 // insert before pBehind or at the end of the chain while considering
517 // the siblings of pSct
518 bool InsertGroupBefore( SwFrame* pParent, SwFrame* pWhere, SwFrame* pSct );
519 void RemoveFromLayout();
520
521 // For internal use only - who ignores this will be put in a sack and has
522 // to stay there for two days
523 // Does special treatment for Get_[Next|Prev]Leaf() (for tables).
524 SwLayoutFrame *GetLeaf( MakePageType eMakePage, bool bFwd );
525 SwLayoutFrame *GetNextLeaf ( MakePageType eMakePage );
526 SwLayoutFrame *GetNextFootnoteLeaf( MakePageType eMakePage );
527 SwLayoutFrame *GetNextSctLeaf( MakePageType eMakePage );
528 SwLayoutFrame *GetNextCellLeaf();
529 SwLayoutFrame *GetPrevLeaf ();
530 SwLayoutFrame *GetPrevFootnoteLeaf( MakePageType eMakeFootnote );
531 SwLayoutFrame *GetPrevSctLeaf();
532 SwLayoutFrame *GetPrevCellLeaf();
533 const SwLayoutFrame *GetLeaf ( MakePageType eMakePage, bool bFwd,
534 const SwFrame *pAnch ) const;
535
536 bool WrongPageDesc( SwPageFrame* pNew );
537
538 //#i28701# - new methods to append/remove drawing objects
539 void AppendDrawObj( SwAnchoredObject& _rNewObj );
540 void RemoveDrawObj( SwAnchoredObject& _rToRemoveObj );
541
542 // work with chain of FlyFrames
543 void AppendFly( SwFlyFrame *pNew );
544 void RemoveFly( SwFlyFrame *pToRemove );
545 const SwSortedObjs *GetDrawObjs() const { return m_pDrawObjs.get(); }
546 SwSortedObjs *GetDrawObjs() { return m_pDrawObjs.get(); }
547 // #i28701# - change purpose of method and adjust its name
548 void InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs = true );
549
550 virtual void PaintSwFrameShadowAndBorder(
551 const SwRect&,
552 const SwPageFrame* pPage,
553 const SwBorderAttrs&) const;
554 void PaintBaBo( const SwRect&, const SwPageFrame *pPage,
555 const bool bOnlyTextBackground = false) const;
556 void PaintSwFrameBackground( const SwRect&, const SwPageFrame *pPage,
557 const SwBorderAttrs &,
558 const bool bLowerMode = false,
559 const bool bLowerBorder = false,
560 const bool bOnlyTextBackground = false ) const;
561 void PaintBorderLine( const SwRect&, const SwRect&, const SwPageFrame*,
562 const Color *pColor,
563 const SvxBorderLineStyle = SvxBorderLineStyle::SOLID ) const;
564
565 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> CreateProcessor2D( ) const;
566 void ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DContainer& rSequence ) const;
567
568 // retouch, not in the area of the given Rect!
569 void Retouch( const SwPageFrame *pPage, const SwRect &rRect ) const;
570
571 bool GetBackgroundBrush(
572 drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes,
573 const SvxBrushItem*& rpBrush,
574 const Color*& rpColor,
575 SwRect &rOrigRect,
576 bool bLowerMode,
577 bool bConsiderTextBox ) const;
578
579 inline void SetCompletePaint() const;
580 inline void ResetCompletePaint() const;
581 bool IsCompletePaint() const { return mbCompletePaint; }
582
583 inline void SetRetouche() const;
584 inline void ResetRetouche() const;
585 bool IsRetouche() const { return mbRetouche; }
586
587 void SetInfFlags();
588 void InvalidateInfFlags() { mbInfInvalid = true; }
589 inline bool IsInDocBody() const; // use InfoFlags, determine flags
590 inline bool IsInFootnote() const; // if necessary
591 inline bool IsInTab() const;
592 inline bool IsInFly() const;
593 inline bool IsInSct() const;
594
595 // If frame is inside a split table row, this function returns
596 // the corresponding row frame in the follow table.
597 const SwRowFrame* IsInSplitTableRow() const;
598
599 // If frame is inside a follow flow row, this function returns
600 // the corresponding row frame master table
601 const SwRowFrame* IsInFollowFlowRow() const;
602
603 bool IsInBalancedSection() const;
604
605 inline bool IsVertical() const;
606 inline bool IsVertLR() const;
607 inline bool IsVertLRBT() const;
608
609 void SetDerivedVert( bool bNew ){ mbDerivedVert = bNew; }
610 void SetInvalidVert( bool bNew) { mbInvalidVert = bNew; }
611 inline bool IsRightToLeft() const;
612 void SetDerivedR2L( bool bNew ) { mbDerivedR2L = bNew; }
613
614 void CheckDirChange();
615 // returns upper left frame position for LTR and
616 // upper right frame position for Asian / RTL frames
617 Point GetFrameAnchorPos( bool bIgnoreFlysAnchoredAtThisFrame ) const;
618
619 /** determine, if frame is moveable in given environment
620
621 method replaced 'old' method <bool IsMoveable() const>.
622 Determines, if frame is moveable in given environment. if no environment
623 is given (parameter _pLayoutFrame == 0), the movability in the actual
624 environment (<GetUpper()) is checked.
625
626 @param _pLayoutFrame
627 input parameter - given environment (layout frame), in which the movability
628 will be checked. If not set ( == 0 ), actual environment is taken.
629
630 @return boolean, indicating, if frame is moveable in given environment
631 */
632 bool IsMoveable( const SwLayoutFrame* _pLayoutFrame = nullptr ) const;
633
634 // Is it permitted for the (Text)Frame to add a footnote in the current
635 // environment (not e.g. for repeating table headlines)
636 bool IsFootnoteAllowed() const;
637
638 virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr );
639
640 virtual void CheckDirection( bool bVert );
641
642 void ReinitializeFrameSizeAttrFlags();
643
644 /// WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for
645 /// SwTextFrame, use GetBreakItem()/GetPageDescItem() instead
646 const SwAttrSet *GetAttrSet() const;
647 virtual const SvxFormatBreakItem& GetBreakItem() const;
648 virtual const SwFormatPageDesc& GetPageDescItem() const;
649
650 bool HasFixSize() const { return mbFixSize; }
651
652 // check all pages (starting from the given) and correct them if needed
653 static void CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields = true, SwPageFrame** ppPrev = nullptr);
654
655 // might return 0, with and without const
656 SwFrame *GetNext() { return mpNext; }
657 SwFrame *GetPrev() { return mpPrev; }
658 SwLayoutFrame *GetUpper() { return mpUpper; }
659 SwRootFrame *getRootFrame(){ return mpRoot; }
660 SwPageFrame *FindPageFrame() { return IsPageFrame() ? reinterpret_cast<SwPageFrame*>(this) : ImplFindPageFrame(); }
661 SwFrame *FindColFrame();
662 SwRowFrame *FindRowFrame();
663 SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnotes = false );
664 SwTabFrame *ImplFindTabFrame();
665 SwFootnoteFrame *ImplFindFootnoteFrame();
666 SwFlyFrame *ImplFindFlyFrame();
667 SwSectionFrame *ImplFindSctFrame();
668 const SwBodyFrame *ImplFindBodyFrame() const;
669 SwFrame *FindFooterOrHeader();
670 SwFrame *GetLower();
671 const SwFrame *GetNext() const { return mpNext; }
672 const SwFrame *GetPrev() const { return mpPrev; }
673 const SwLayoutFrame *GetUpper() const { return mpUpper; }
674 const SwRootFrame *getRootFrame() const { return mpRoot; }
675 inline SwTabFrame *FindTabFrame();
676 inline SwFootnoteFrame *FindFootnoteFrame();
677 inline SwFlyFrame *FindFlyFrame();
678 inline SwSectionFrame *FindSctFrame();
679 inline SwFrame *FindNext();
680 // #i27138# - add parameter <_bInSameFootnote>
681 SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false );
682 inline SwFrame *FindPrev();
683 inline const SwPageFrame *FindPageFrame() const;
684 inline const SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnote = false ) const;
685 inline const SwFrame *FindColFrame() const;
686 inline const SwFrame *FindFooterOrHeader() const;
687 inline const SwTabFrame *FindTabFrame() const;
688 inline const SwFootnoteFrame *FindFootnoteFrame() const;
689 inline const SwFlyFrame *FindFlyFrame() const;
690 inline const SwSectionFrame *FindSctFrame() const;
691 inline const SwBodyFrame *FindBodyFrame() const;
692 inline const SwFrame *FindNext() const;
693 // #i27138# - add parameter <_bInSameFootnote>
694 const SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ) const;
695 inline const SwFrame *FindPrev() const;
696 const SwFrame *GetLower() const;
697
698 SwContentFrame* FindPrevCnt();
699
700 const SwContentFrame* FindPrevCnt() const;
701
702 // #i79774#
703 SwFrame* GetIndPrev_() const;
704 SwFrame* GetIndPrev() const
705 { return ( mpPrev || !IsInSct() ) ? mpPrev : GetIndPrev_(); }
706
707 SwFrame* GetIndNext()
708 { return ( mpNext || !IsInSct() ) ? mpNext : GetIndNext_(); }
709 const SwFrame* GetIndNext() const { return const_cast<SwFrame*>(this)->GetIndNext(); }
710
711 sal_uInt16 GetPhyPageNum() const; // page number without offset
712 sal_uInt16 GetVirtPageNum() const; // page number with offset
713 bool OnRightPage() const { return 0 != GetPhyPageNum() % 2; };
714 bool WannaRightPage() const;
715 bool OnFirstPage() const;
716
717 inline const SwLayoutFrame *GetPrevLayoutLeaf() const;
718 inline const SwLayoutFrame *GetNextLayoutLeaf() const;
719 inline SwLayoutFrame *GetPrevLayoutLeaf();
720 inline SwLayoutFrame *GetNextLayoutLeaf();
721
722 virtual void Calc(vcl::RenderContext* pRenderContext) const; // here might be "formatted"
723 inline void OptCalc() const; // here we assume (for optimization) that
724 // the predecessors are already formatted
725 Point GetRelPos() const;
726
727 // PaintArea is the area where content might be displayed.
728 // The margin of a page or the space between columns belongs to it.
729 SwRect GetPaintArea() const;
730
731 // UnionFrame is the union of Frame- and PrtArea, normally identical
732 // to the FrameArea except in case of negative Prt margins.
733 SwRect UnionFrame( bool bBorder = false ) const;
734
735 virtual Size ChgSize( const Size& aNewSize );
736
737 virtual void Cut() = 0;
738 virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) = 0;
739
740 void ValidateLineNum() { mbValidLineNum = true; }
741
742 bool GetValidLineNumFlag()const { return mbValidLineNum; }
743
744 // Only invalidate Frame
745 // #i28701# - add call to method <ActionOnInvalidation(..)>
746 // for all invalidation methods.
747 // #i28701# - use method <InvalidationAllowed(..)> to
748 // decide, if invalidation will to be performed or not.
749 // #i26945# - no additional invalidation, if it's already
750 // invalidate.
751 void InvalidateSize_()
752 {
753 if ( isFrameAreaSizeValid() && InvalidationAllowed( INVALID_SIZE ) )
754 {
755 setFrameAreaSizeValid(false);
756 ActionOnInvalidation( INVALID_SIZE );
757 }
758 }
759 void InvalidatePrt_()
760 {
761 if ( isFramePrintAreaValid() && InvalidationAllowed( INVALID_PRTAREA ) )
762 {
763 setFramePrintAreaValid(false);
764 ActionOnInvalidation( INVALID_PRTAREA );
765 }
766 }
767 void InvalidatePos_()
768 {
769 if ( isFrameAreaPositionValid() && InvalidationAllowed( INVALID_POS ) )
770 {
771 setFrameAreaPositionValid(false);
772 ActionOnInvalidation( INVALID_POS );
773 }
774 }
775 void InvalidateLineNum_()
776 {
777 if ( mbValidLineNum && InvalidationAllowed( INVALID_LINENUM ) )
778 {
779 mbValidLineNum = false;
780 ActionOnInvalidation( INVALID_LINENUM );
781 }
782 }
783 void InvalidateAll_()
784 {
785 if ( ( isFrameAreaSizeValid() || isFramePrintAreaValid() || isFrameAreaPositionValid() ) && InvalidationAllowed( INVALID_ALL ) )
786 {
787 setFrameAreaSizeValid(false);
788 setFrameAreaPositionValid(false);
789 setFramePrintAreaValid(false);
790 ActionOnInvalidation( INVALID_ALL );
791 }
792 }
793 // also notify page at the same time
794 inline void InvalidateSize();
795 inline void InvalidatePrt();
796 inline void InvalidatePos();
797 inline void InvalidateLineNum();
798 inline void InvalidateAll();
799 void ImplInvalidateSize();
800 void ImplInvalidatePrt();
801 void ImplInvalidatePos();
802 void ImplInvalidateLineNum();
803
804 inline void InvalidateNextPos( bool bNoFootnote = false );
805 void ImplInvalidateNextPos( bool bNoFootnote );
806
807 /** method to invalidate printing area of next frame
808 #i11859#
809 */
810 void InvalidateNextPrtArea();
811
812 void InvalidatePage( const SwPageFrame *pPage = nullptr ) const;
813
814 virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
815
816 virtual bool GetModelPositionForViewPoint( SwPosition *, Point&,
817 SwCursorMoveState* = nullptr, bool bTestBackground = false ) const;
818 virtual bool GetCharRect( SwRect &, const SwPosition&,
819 SwCursorMoveState* = nullptr, bool bAllowFarAway = true ) const;
820 virtual void PaintSwFrame( vcl::RenderContext& rRenderContext, SwRect const&,
821 SwPrintData const*const pPrintData = nullptr ) const;
822
823 // HACK: shortcut between frame and formatting
824 // It's your own fault if you cast void* incorrectly! In any case check
825 // the void* for 0.
826 virtual bool Prepare( const PrepareHint ePrep = PrepareHint::Clear,
827 const void *pVoid = nullptr, bool bNotify = true );
828
829 // true if it is the correct class, false otherwise
830 inline bool IsLayoutFrame() const;
831 inline bool IsRootFrame() const;
832 inline bool IsPageFrame() const;
833 inline bool IsColumnFrame() const;
834 inline bool IsFootnoteBossFrame() const; // footnote bosses might be PageFrames or ColumnFrames
835 inline bool IsHeaderFrame() const;
836 inline bool IsFooterFrame() const;
837 inline bool IsFootnoteContFrame() const;
838 inline bool IsFootnoteFrame() const;
839 inline bool IsBodyFrame() const;
840 inline bool IsColBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above ColumnFrame
841 inline bool IsPageBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above PageFrame
842 inline bool IsFlyFrame() const;
843 inline bool IsSctFrame() const;
844 inline bool IsTabFrame() const;
845 inline bool IsRowFrame() const;
846 inline bool IsCellFrame() const;
847 inline bool IsContentFrame() const;
848 inline bool IsTextFrame() const;
849 inline bool IsNoTextFrame() const;
850 // Frames where its PrtArea depends on their neighbors and that are
851 // positioned in the content flow
852 inline bool IsFlowFrame() const;
853 // Frames that are capable of retouching or that might need to retouch behind
854 // themselves
855 inline bool IsRetoucheFrame() const;
856 inline bool IsAccessibleFrame() const;
857
858 void PrepareCursor(); // CursorShell is allowed to call this
859
860 // Is the Frame (or the section containing it) protected? Same for Fly in
861 // Fly in ... and footnotes
862 bool IsProtected() const;
863
864 bool IsColLocked() const { return mbColLocked; }
865 virtual bool IsDeleteForbidden() const { return mbForbidDelete; }
866
867 /// this is the only way to delete a SwFrame instance
868 static void DestroyFrame(SwFrame *const pFrame);
869
870 bool IsInDtor() const { return mbInDtor; }
871
872 // No inline cause we need the function pointers
873 long GetTopMargin() const;
874 long GetBottomMargin() const;
875 long GetLeftMargin() const;
876 long GetRightMargin() const;
877 void SetTopBottomMargins( long, long );
878 void SetLeftRightMargins( long, long );
879 void SetRightLeftMargins( long, long );
880 long GetPrtLeft() const;
881 long GetPrtBottom() const;
882 long GetPrtRight() const;
883 long GetPrtTop() const;
884 bool SetMinLeft( long );
885 bool SetMaxBottom( long );
886 bool SetMaxRight( long );
887 void MakeBelowPos( const SwFrame*, const SwFrame*, bool );
888 void MakeLeftPos( const SwFrame*, const SwFrame*, bool );
889 void MakeRightPos( const SwFrame*, const SwFrame*, bool );
890 bool IsNeighbourFrame() const
891 { return bool(GetType() & FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell)); }
892
893 // NEW TABLES
894 // Some functions for covered/covering table cells. This way unnecessary
895 // includes can be avoided
896 virtual bool IsLeaveUpperAllowed() const;
897 virtual bool IsCoveredCell() const;
898 bool IsInCoveredCell() const;
899
900 // #i81146# new loop control
901 bool KnowsFormat( const SwFormat& rFormat ) const;
902 void RegisterToFormat( SwFormat& rFormat );
903 void ValidateThisAndAllLowers( const sal_uInt16 nStage );
904
905 void ForbidDelete() { mbForbidDelete = true; }
906 void AllowDelete() { mbForbidDelete = false; }
907
908 drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const;
909 bool supportsFullDrawingLayerFillAttributeSet() const;
910
911public:
912 // if writer is NULL, dumps the layout structure as XML in layout.xml
913 virtual void dumpAsXml(xmlTextWriterPtr writer = nullptr) const;
914 void dumpTopMostAsXml(xmlTextWriterPtr writer = nullptr) const;
915 void dumpInfosAsXml(xmlTextWriterPtr writer) const;
916 virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const;
917 void dumpChildrenAsXml(xmlTextWriterPtr writer) const;
918 bool IsCollapse() const;
919};
920
921inline bool SwFrame::IsInDocBody() const
922{
923 if ( mbInfInvalid )
924 const_cast<SwFrame*>(this)->SetInfFlags();
925 return mbInfBody;
926}
927inline bool SwFrame::IsInFootnote() const
928{
929 if ( mbInfInvalid )
930 const_cast<SwFrame*>(this)->SetInfFlags();
931 return mbInfFootnote;
932}
933inline bool SwFrame::IsInTab() const
934{
935 if ( mbInfInvalid )
936 const_cast<SwFrame*>(this)->SetInfFlags();
937 return mbInfTab;
938}
939inline bool SwFrame::IsInFly() const
940{
941 if ( mbInfInvalid )
942 const_cast<SwFrame*>(this)->SetInfFlags();
943 return mbInfFly;
944}
945inline bool SwFrame::IsInSct() const
946{
947 if ( mbInfInvalid )
948 const_cast<SwFrame*>(this)->SetInfFlags();
949 return mbInfSct;
950}
951bool SwFrame::IsVertical() const
952{
953 if( mbInvalidVert )
954 const_cast<SwFrame*>(this)->SetDirFlags( true );
955 return mbVertical;
956}
957inline bool SwFrame::IsVertLR() const
958{
959 return mbVertLR;
960}
961inline bool SwFrame::IsVertLRBT() const
962{
963 return mbVertLRBT;
964}
965inline bool SwFrame::IsRightToLeft() const
966{
967 if( mbInvalidR2L )
968 const_cast<SwFrame*>(this)->SetDirFlags( false );
969 return mbRightToLeft;
970}
971
972inline void SwFrame::SetCompletePaint() const
973{
974 const_cast<SwFrame*>(this)->mbCompletePaint = true;
975}
976inline void SwFrame::ResetCompletePaint() const
977{
978 const_cast<SwFrame*>(this)->mbCompletePaint = false;
979}
980
981inline void SwFrame::SetRetouche() const
982{
983 const_cast<SwFrame*>(this)->mbRetouche = true;
984}
985inline void SwFrame::ResetRetouche() const
986{
987 const_cast<SwFrame*>(this)->mbRetouche = false;
988}
989
990inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf()
991{
992 return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf());
993}
994inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf()
995{
996 return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf());
997}
998inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const
999{
1000 return ImplGetNextLayoutLeaf( true );
1001}
1002inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const
1003{
1004 return ImplGetNextLayoutLeaf( false );
1005}
1006
1007inline void SwFrame::InvalidateSize()
1008{
1009 if ( isFrameAreaSizeValid() )
1010 {
1011 ImplInvalidateSize();
1012 }
1013}
1014inline void SwFrame::InvalidatePrt()
1015{
1016 if ( isFramePrintAreaValid() )
1017 {
1018 ImplInvalidatePrt();
1019 }
1020}
1021inline void SwFrame::InvalidatePos()
1022{
1023 if ( isFrameAreaPositionValid() )
1024 {
1025 ImplInvalidatePos();
1026 }
1027}
1028inline void SwFrame::InvalidateLineNum()
1029{
1030 if ( mbValidLineNum )
1031 ImplInvalidateLineNum();
1032}
1033inline void SwFrame::InvalidateAll()
1034{
1035 if ( InvalidationAllowed( INVALID_ALL ) )
1036 {
1037 if ( isFrameAreaDefinitionValid() )
1038 {
1039 ImplInvalidatePos();
1040 }
1041
1042 setFrameAreaSizeValid(false);
1043 setFrameAreaPositionValid(false);
1044 setFramePrintAreaValid(false);
1045
1046 // #i28701#
1047 ActionOnInvalidation( INVALID_ALL );
1048 }
1049}
1050inline void SwFrame::InvalidateNextPos( bool bNoFootnote )
1051{
1052 if ( mpNext && !mpNext->IsSctFrame() )
1053 mpNext->InvalidatePos();
1054 else
1055 ImplInvalidateNextPos( bNoFootnote );
1056}
1057
1058inline void SwFrame::OptCalc() const
1059{
1060 if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() )
1061 {
1062 const_cast<SwFrame*>(this)->OptPrepareMake();
1063 }
1064}
1065inline const SwPageFrame *SwFrame::FindPageFrame() const
1066{
1067 return const_cast<SwFrame*>(this)->FindPageFrame();
1068}
1069inline const SwFrame *SwFrame::FindColFrame() const
1070{
1071 return const_cast<SwFrame*>(this)->FindColFrame();
1072}
1073inline const SwFrame *SwFrame::FindFooterOrHeader() const
1074{
1075 return const_cast<SwFrame*>(this)->FindFooterOrHeader();
1076}
1077inline SwTabFrame *SwFrame::FindTabFrame()
1078{
1079 return IsInTab() ? ImplFindTabFrame() : nullptr;
1080}
1081inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const
1082{
1083 return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote );
1084}
1085inline SwFootnoteFrame *SwFrame::FindFootnoteFrame()
1086{
1087 return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr;
1088}
1089inline SwFlyFrame *SwFrame::FindFlyFrame()
1090{
1091 return IsInFly() ? ImplFindFlyFrame() : nullptr;
1092}
1093inline SwSectionFrame *SwFrame::FindSctFrame()
1094{
1095 return IsInSct() ? ImplFindSctFrame() : nullptr;
1096}
1097
1098inline const SwBodyFrame *SwFrame::FindBodyFrame() const
1099{
1100 return IsInDocBody() ? ImplFindBodyFrame() : nullptr;
1101}
1102
1103inline const SwTabFrame *SwFrame::FindTabFrame() const
1104{
1105 return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr;
1106}
1107inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const
1108{
1109 return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr;
1110}
1111inline const SwFlyFrame *SwFrame::FindFlyFrame() const
1112{
1113 return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr;
1114}
1115inline const SwSectionFrame *SwFrame::FindSctFrame() const
1116{
1117 return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr;
1118}
1119inline SwFrame *SwFrame::FindNext()
1120{
1121 if ( mpNext )
1122 return mpNext;
1123 else
1124 return FindNext_();
1125}
1126inline const SwFrame *SwFrame::FindNext() const
1127{
1128 if ( mpNext )
1129 return mpNext;
1130 else
1131 return const_cast<SwFrame*>(this)->FindNext_();
1132}
1133inline SwFrame *SwFrame::FindPrev()
1134{
1135 if ( mpPrev && !mpPrev->IsSctFrame() )
1136 return mpPrev;
1137 else
1138 return FindPrev_();
1139}
1140inline const SwFrame *SwFrame::FindPrev() const
1141{
1142 if ( mpPrev && !mpPrev->IsSctFrame() )
1143 return mpPrev;
1144 else
1145 return const_cast<SwFrame*>(this)->FindPrev_();
1146}
1147
1148inline bool SwFrame::IsLayoutFrame() const
1149{
1150 return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF));
1151}
1152inline bool SwFrame::IsRootFrame() const
1153{
1154 return mnFrameType == SwFrameType::Root;
1155}
1156inline bool SwFrame::IsPageFrame() const
1157{
1158 return mnFrameType == SwFrameType::Page;
1159}
1160inline bool SwFrame::IsColumnFrame() const
1161{
1162 return mnFrameType == SwFrameType::Column;
1163}
1164inline bool SwFrame::IsFootnoteBossFrame() const
1165{
1166 return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column));
1167}
1168inline bool SwFrame::IsHeaderFrame() const
1169{
1170 return mnFrameType == SwFrameType::Header;
1171}
1172inline bool SwFrame::IsFooterFrame() const
1173{
1174 return mnFrameType == SwFrameType::Footer;
1175}
1176inline bool SwFrame::IsFootnoteContFrame() const
1177{
1178 return mnFrameType == SwFrameType::FtnCont;
1179}
1180inline bool SwFrame::IsFootnoteFrame() const
1181{
1182 return mnFrameType == SwFrameType::Ftn;
1183}
1184inline bool SwFrame::IsBodyFrame() const
1185{
1186 return mnFrameType == SwFrameType::Body;
1187}
1188inline bool SwFrame::IsFlyFrame() const
1189{
1190 return mnFrameType == SwFrameType::Fly;
1191}
1192inline bool SwFrame::IsSctFrame() const
1193{
1194 return mnFrameType == SwFrameType::Section;
1195}
1196inline bool SwFrame::IsTabFrame() const
1197{
1198 return mnFrameType == SwFrameType::Tab;
1199}
1200inline bool SwFrame::IsRowFrame() const
1201{
1202 return mnFrameType == SwFrameType::Row;
1203}
1204inline bool SwFrame::IsCellFrame() const
1205{
1206 return mnFrameType == SwFrameType::Cell;
1207}
1208inline bool SwFrame::IsContentFrame() const
1209{
1210 return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt));
1211}
1212inline bool SwFrame::IsTextFrame() const
1213{
1214 return mnFrameType == SwFrameType::Txt;
1215}
1216inline bool SwFrame::IsNoTextFrame() const
1217{
1218 return mnFrameType == SwFrameType::NoTxt;
30
Assuming field 'mnFrameType' is equal to NoTxt
31
Returning the value 1, which participates in a condition later
1219}
1220inline bool SwFrame::IsFlowFrame() const
1221{
1222 return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section));
1223}
1224inline bool SwFrame::IsRetoucheFrame() const
1225{
1226 return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn));
1227}
1228inline bool SwFrame::IsAccessibleFrame() const
1229{
1230 return bool(GetType() & FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header |
SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType
::Tab | SwFrameType::Cell | SwFrameType::Txt)
);
1231}
1232
1233//use this to protect a SwFrame for a given scope from getting deleted
1234class SwFrameDeleteGuard
1235{
1236private:
1237 SwFrame *m_pForbidFrame;
1238public:
1239 //Flag pFrame for SwFrameDeleteGuard lifetime that we shouldn't delete
1240 //it in e.g. SwSectionFrame::MergeNext etc because we will need it
1241 //again after the SwFrameDeleteGuard dtor
1242 explicit SwFrameDeleteGuard(SwFrame* pFrame)
1243 : m_pForbidFrame((pFrame && !pFrame->IsDeleteForbidden()) ?
1244 pFrame : nullptr)
1245 {
1246 if (m_pForbidFrame)
1247 m_pForbidFrame->ForbidDelete();
1248 }
1249
1250 SwFrameDeleteGuard(const SwFrameDeleteGuard&) =delete;
1251
1252 ~SwFrameDeleteGuard()
1253 {
1254 if (m_pForbidFrame)
1255 m_pForbidFrame->AllowDelete();
1256 }
1257
1258 SwFrameDeleteGuard& operator=(const SwFrameDeleteGuard&) =delete;
1259};
1260
1261typedef long (SwFrame::*SwFrameGet)() const;
1262typedef bool (SwFrame::*SwFrameMax)( long );
1263typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool );
1264typedef long (*SwOperator)( long, long );
1265typedef void (SwFrame::*SwFrameSet)( long, long );
1266
1267struct SwRectFnCollection
1268{
1269 SwRectGet fnGetTop;
1270 SwRectGet fnGetBottom;
1271 SwRectGet fnGetLeft;
1272 SwRectGet fnGetRight;
1273 SwRectGet fnGetWidth;
1274 SwRectGet fnGetHeight;
1275 SwRectPoint fnGetPos;
1276 SwRectSize fnGetSize;
1277
1278 SwRectSet fnSetTop;
1279 SwRectSet fnSetBottom;
1280 SwRectSet fnSetLeft;
1281 SwRectSet fnSetRight;
1282 SwRectSet fnSetWidth;
1283 SwRectSet fnSetHeight;
1284
1285 SwRectSet fnSubTop;
1286 SwRectSet fnAddBottom;
1287 SwRectSet fnSubLeft;
1288 SwRectSet fnAddRight;
1289 SwRectSet fnAddWidth;
1290 SwRectSet fnAddHeight;
1291
1292 SwRectSet fnSetPosX;
1293 SwRectSet fnSetPosY;
1294
1295 SwFrameGet fnGetTopMargin;
1296 SwFrameGet fnGetBottomMargin;
1297 SwFrameGet fnGetLeftMargin;
1298 SwFrameGet fnGetRightMargin;
1299 SwFrameSet fnSetXMargins;
1300 SwFrameSet fnSetYMargins;
1301 SwFrameGet fnGetPrtTop;
1302 SwFrameGet fnGetPrtBottom;
1303 SwFrameGet fnGetPrtLeft;
1304 SwFrameGet fnGetPrtRight;
1305 SwRectDist fnTopDist;
1306 SwRectDist fnBottomDist;
1307 SwRectDist fnLeftDist;
1308 SwRectDist fnRightDist;
1309 SwFrameMax fnSetLimit;
1310 SwRectMax fnOverStep;
1311
1312 SwRectSetPos fnSetPos;
1313 SwFrameMakePos fnMakePos;
1314 SwOperator fnXDiff;
1315 SwOperator fnYDiff;
1316 SwOperator fnXInc;
1317 SwOperator fnYInc;
1318
1319 SwRectSetTwice fnSetLeftAndWidth;
1320 SwRectSetTwice fnSetTopAndHeight;
1321};
1322
1323typedef SwRectFnCollection* SwRectFn;
1324
1325// This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical)
1326extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T;
1327class SwRectFnSet {
1328public:
1329 explicit SwRectFnSet(const SwFrame *pFrame)
1330 : m_bVert(pFrame->IsVertical())
1331 , m_bVertL2R(pFrame->IsVertLR())
1332 , m_bVertL2RB2T(pFrame->IsVertLRBT())
1333 {
1334 m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori;
1335 }
1336
1337 void Refresh(const SwFrame *pFrame)
1338 {
1339 m_bVert = pFrame->IsVertical();
1340 m_bVertL2R = pFrame->IsVertLR();
1341 m_bVertL2RB2T = pFrame->IsVertLRBT();
1342 m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori;
1343 }
1344
1345 bool IsVert() const { return m_bVert; }
1346 bool IsVertL2R() const { return m_bVertL2R; }
1347 SwRectFn FnRect() const { return m_fnRect; }
1348
1349 bool PosDiff(const SwRect &rRect1, const SwRect &rRect2) const
1350 {
1351 return ((rRect1.*m_fnRect->fnGetTop)() != (rRect2.*m_fnRect->fnGetTop)()
1352 || (rRect1.*m_fnRect->fnGetLeft)() != (rRect2.*m_fnRect->fnGetLeft)());
1353 }
1354
1355 long GetTop (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetTop) (); }
1356 long GetBottom(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetBottom)(); }
1357 long GetLeft (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetLeft) (); }
1358 long GetRight (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetRight) (); }
1359 long GetWidth (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetWidth) (); }
1360 long GetHeight(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetHeight)(); }
1361 Point GetPos (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetPos) (); }
1362 Size GetSize (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetSize) (); }
1363
1364 void SetTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetTop) (nNew); }
1365 void SetBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetBottom)(nNew); }
1366 void SetLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetLeft) (nNew); }
1367 void SetRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetRight) (nNew); }
1368 void SetWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetWidth) (nNew); }
1369 void SetHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetHeight)(nNew); }
1370
1371 void SubTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubTop) (nNew); }
1372 void AddBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddBottom)(nNew); }
1373 void SubLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubLeft) (nNew); }
1374 void AddRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddRight) (nNew); }
1375 void AddWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddWidth) (nNew); }
1376 void AddHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddHeight)(nNew); }
1377
1378 void SetPosX(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosX)(nNew); }
1379 void SetPosY(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosY)(nNew); }
1380
1381 long GetTopMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetTopMargin) (); }
1382 long GetBottomMargin(const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetBottomMargin)(); }
1383 long GetLeftMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetLeftMargin) (); }
1384 long GetRightMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetRightMargin) (); }
1385 void SetXMargins(SwFrame& rFrame, long nLeft, long nRight) const { (rFrame.*m_fnRect->fnSetXMargins)(nLeft, nRight); }
1386 void SetYMargins(SwFrame& rFrame, long nTop, long nBottom) const { (rFrame.*m_fnRect->fnSetYMargins)(nTop, nBottom); }
1387 long GetPrtTop (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtTop) (); }
1388 long GetPrtBottom (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtBottom) (); }
1389 long GetPrtLeft (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtLeft) (); }
1390 long GetPrtRight (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtRight) (); }
1391 long TopDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnTopDist) (nPos); }
1392 long BottomDist(const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnBottomDist) (nPos); }
1393 long LeftDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnLeftDist) (nPos); }
1394 long RightDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnRightDist) (nPos); }
1395 void SetLimit (SwFrame& rFrame, long nNew) const { (rFrame.*m_fnRect->fnSetLimit) (nNew); }
1396 bool OverStep (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnOverStep) (nPos); }
1397
1398 void SetPos(SwRect& rRect, const Point& rNew) const { (rRect.*m_fnRect->fnSetPos)(rNew); }
1399 void MakePos(SwFrame& rFrame, const SwFrame* pUp, const SwFrame* pPrv, bool bNotify) const { (rFrame.*m_fnRect->fnMakePos)(pUp, pPrv, bNotify); }
1400 long XDiff(long n1, long n2) const { return (m_fnRect->fnXDiff) (n1, n2); }
1401 long YDiff(long n1, long n2) const { return (m_fnRect->fnYDiff) (n1, n2); }
1402 long XInc (long n1, long n2) const { return (m_fnRect->fnXInc) (n1, n2); }
1403 long YInc (long n1, long n2) const { return (m_fnRect->fnYInc) (n1, n2); }
1404
1405 void SetLeftAndWidth(SwRect& rRect, long nLeft, long nWidth) const { (rRect.*m_fnRect->fnSetLeftAndWidth)(nLeft, nWidth); }
1406 void SetTopAndHeight(SwRect& rRect, long nTop, long nHeight) const { (rRect.*m_fnRect->fnSetTopAndHeight)(nTop, nHeight); }
1407
1408private:
1409 bool m_bVert;
1410 bool m_bVertL2R;
1411 bool m_bVertL2RB2T;
1412 SwRectFn m_fnRect;
1413};
1414
1415#endif
1416
1417/* vim:set shiftwidth=4 softtabstop=4 expandtab: */