File: | home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx |
Warning: | line 734, column 72 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||||
58 | using namespace ::com::sun::star; | ||||||
59 | |||||||
60 | namespace | ||||||
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 | |||||||
119 | SwContourCache::SwContourCache() : | ||||||
120 | mnPointCount( 0 ) | ||||||
121 | { | ||||||
122 | } | ||||||
123 | |||||||
124 | SwContourCache::~SwContourCache() | ||||||
125 | { | ||||||
126 | } | ||||||
127 | |||||||
128 | void SwContourCache::ClrObject( sal_uInt16 nPos ) | ||||||
129 | { | ||||||
130 | mnPointCount -= mvItems[ nPos ].mxTextRanger->GetPointCount(); | ||||||
131 | mvItems.erase(mvItems.begin() + nPos); | ||||||
132 | } | ||||||
133 | |||||||
134 | void 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 | |||||||
145 | void ClrContourCache() | ||||||
146 | { | ||||||
147 | if( pContourCache ) | ||||||
148 | { | ||||||
149 | pContourCache->mvItems.clear(); | ||||||
150 | pContourCache->mnPointCount = 0; | ||||||
151 | } | ||||||
152 | } | ||||||
153 | |||||||
154 | // #i68520# | ||||||
155 | SwRect 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) | ||||||
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 && | ||||||
179 | ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) == nullptr || | ||||||
180 | ( static_cast<const SwFlyFrame*>(pAnchoredObj)->Lower() && | ||||||
181 | static_cast<const SwFlyFrame*>(pAnchoredObj)->Lower()->IsNoTextFrame() ) ) ) | ||||||
182 | { | ||||||
183 | aRet = pAnchoredObj->GetObjRectWithSpaces(); | ||||||
184 | if( aRet.IsOver( rLine ) ) | ||||||
185 | { | ||||||
186 | if( !pContourCache ) | ||||||
187 | pContourCache = new SwContourCache; | ||||||
188 | |||||||
189 | aRet = pContourCache->ContourRect( | ||||||
190 | pFormat, pAnchoredObj->GetDrawObj(), pFrame, rLine, nXPos, bRight ); | ||||||
191 | } | ||||||
192 | else | ||||||
193 | aRet.Width( 0 ); | ||||||
194 | } | ||||||
195 | else | ||||||
196 | { | ||||||
197 | aRet = pAnchoredObj->GetObjRectWithSpaces(); | ||||||
198 | } | ||||||
199 | |||||||
200 | return aRet; | ||||||
201 | } | ||||||
202 | |||||||
203 | SwRect 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 ) | ||||||
210 | ++nPos; | ||||||
211 | if( GetCount() == nPos ) // Not found | ||||||
212 | { | ||||||
213 | if( GetCount() == POLY_CNT20 ) | ||||||
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 ) ) | ||||||
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 ) | ||||||
235 | { | ||||||
236 | aPolyPolygon = pObj->TakeXorPoly(); | ||||||
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 | |||||||
307 | SwTextFly::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 | |||||||
324 | SwTextFly::SwTextFly( const SwTextFrame *pFrame ) | ||||||
325 | { | ||||||
326 | CtorInitTextFly( pFrame ); | ||||||
327 | } | ||||||
328 | |||||||
329 | SwTextFly::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 | |||||||
350 | SwTextFly::~SwTextFly() | ||||||
351 | { | ||||||
352 | } | ||||||
353 | |||||||
354 | void 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 | |||||||
377 | SwRect SwTextFly::GetFrame_( const SwRect &rRect ) const | ||||||
378 | { | ||||||
379 | SwRect aRet; | ||||||
380 | if( ForEach( rRect, &aRet, true ) ) | ||||||
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 | |||||||
395 | bool 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 | |||||||
406 | bool 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 | |||||||
439 | const 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 | |||||||
447 | void 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 | |||||||
569 | void 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 | */ | ||||||
629 | bool 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
| ||||||
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# | ||||||
826 | SwAnchoredObjList* 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
| ||||||
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
| ||||||
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 | |||||||
964 | SwTwips 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 | |||||||
998 | bool 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)) | ||||||
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 ); | ||||||
1023 | if (nCount > 0) | ||||||
1024 | { | ||||||
1025 | for( SwAnchoredObjList::size_type i = 0; i < nCount; ++i ) | ||||||
1026 | { | ||||||
1027 | // #i68520# | ||||||
1028 | const SwAnchoredObject* pAnchoredObj = (*mpAnchoredObjList)[i]; | ||||||
1029 | |||||||
1030 | SwRect aRect( pAnchoredObj->GetObjRectWithSpaces() ); | ||||||
1031 | |||||||
1032 | if( aRectFnSet.GetLeft(aRect) > aRectFnSet.GetRight(rRect) ) | ||||||
1033 | break; | ||||||
1034 | |||||||
1035 | // #i68520# | ||||||
1036 | if ( mpCurrAnchoredObj != pAnchoredObj && aRect.IsOver( rRect ) ) | ||||||
1037 | { | ||||||
1038 | // #i68520# | ||||||
1039 | const SwFormat* pFormat( &(pAnchoredObj->GetFrameFormat()) ); | ||||||
1040 | const SwFormatSurround &rSur = pFormat->GetSurround(); | ||||||
1041 | if( bAvoid ) | ||||||
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() && | ||||||
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) ) | ||||||
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 && | ||||||
1066 | GetMaster() == pAnchoredObj->GetAnchorFrame() ) | ||||||
1067 | continue; | ||||||
1068 | |||||||
1069 | if( pRect ) | ||||||
1070 | { | ||||||
1071 | // #i68520# | ||||||
1072 | SwRect aFly = AnchoredObjToRect( pAnchoredObj, rRect ); | ||||||
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# | ||||||
1099 | SwAnchoredObjList::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# | ||||||
1109 | void 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# | ||||||
1198 | void 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# | ||||||
1262 | SwRect SwTextFly::AnchoredObjToRect( const SwAnchoredObject* pAnchoredObj, | ||||||
1263 | const SwRect &rLine ) const | ||||||
1264 | { | ||||||
1265 | SwRectFnSet aRectFnSet(m_pCurrFrame); | ||||||
1266 | |||||||
1267 | const long nXPos = m_pCurrFrame->IsRightToLeft() ? | ||||||
1268 | rLine.Right() : | ||||||
1269 | aRectFnSet.GetLeft(rLine); | ||||||
1270 | |||||||
1271 | SwRect aFly = mbIgnoreContour ? | ||||||
1272 | pAnchoredObj->GetObjRectWithSpaces() : | ||||||
1273 | SwContourCache::CalcBoundRect(pAnchoredObj, rLine, m_pCurrFrame, | ||||||
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 | |||||||
1327 | css::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 | |||||||
1404 | bool 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: */ |
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 | #ifndef INCLUDED_SW_SOURCE_CORE_INC_TXTFLY_HXX |
20 | #define INCLUDED_SW_SOURCE_CORE_INC_TXTFLY_HXX |
21 | |
22 | #include <editeng/txtrange.hxx> |
23 | #include <tools/solar.h> |
24 | #include <swtypes.hxx> |
25 | #include <swrect.hxx> |
26 | #include <com/sun/star/text/WrapTextMode.hpp> |
27 | #include <memory> |
28 | #include <vector> |
29 | |
30 | class OutputDevice; |
31 | class SwPageFrame; |
32 | class SdrObject; |
33 | class SwFormat; |
34 | class SwAnchoredObject; |
35 | class SwTextFrame; |
36 | class SwDrawTextInfo; |
37 | class SwContourCache; |
38 | |
39 | typedef std::vector< SwAnchoredObject* > SwAnchoredObjList; |
40 | |
41 | /** Contour-cache global variable, initialized/destroyed in txtinit.cxx |
42 | and needed in txtfly.cxx by text wrapping. |
43 | */ |
44 | extern SwContourCache *pContourCache; |
45 | |
46 | #define POLY_CNT20 20 |
47 | #define POLY_MIN5 5 |
48 | #define POLY_MAX4000 4000 |
49 | |
50 | void ClrContourCache( const SdrObject *pObj ); |
51 | |
52 | class SwContourCache |
53 | { |
54 | friend void ClrContourCache(); |
55 | struct CacheItem |
56 | { |
57 | const SdrObject *mpSdrObj; |
58 | std::unique_ptr<TextRanger> mxTextRanger; |
59 | }; |
60 | std::vector<CacheItem> mvItems; |
61 | long mnPointCount; |
62 | SwRect ContourRect( const SwFormat* pFormat, const SdrObject* pObj, |
63 | const SwTextFrame* pFrame, const SwRect &rLine, const long nXPos, |
64 | const bool bRight ); |
65 | |
66 | public: |
67 | SwContourCache(); |
68 | ~SwContourCache(); |
69 | const SdrObject* GetObject( sal_uInt16 nPos ) const{ return mvItems[ nPos ].mpSdrObj; } |
70 | sal_uInt16 GetCount() const { return mvItems.size(); } |
71 | void ClrObject( sal_uInt16 nPos ); |
72 | |
73 | /** |
74 | Computes the rectangle that will cover the object in the given line. |
75 | |
76 | For _non_ contour-flow objects, this is simply the overlap area of |
77 | BoundRect (including spacing), and the line, for contour-flow, |
78 | the tools::PolyPolygon of the object gets traversed |
79 | */ |
80 | static SwRect CalcBoundRect( const SwAnchoredObject* pAnchoredObj, |
81 | const SwRect &rLine, |
82 | const SwTextFrame* pFrame, |
83 | const long nXPos, |
84 | const bool bRight ); |
85 | }; |
86 | |
87 | /** |
88 | The purpose of this class is to be the universal interface between |
89 | formatting/text output and the possibly overlapping free-flying frames. |
90 | During formatting the formatter gets the information from SwTextFly, whether |
91 | a certain area is present by the attributes of an overlapping frame. |
92 | Such areas are represented by dummy portions. |
93 | |
94 | The whole text output and touch-up is, again, forwarded to a SwTextFly. |
95 | This one decides, whether parts of the text need to be clipped and splits |
96 | the areas for e.g. a DrawRect. |
97 | |
98 | Please note that all free-flying frames are located in a PtrArray, sorted |
99 | by TopLeft. |
100 | |
101 | Internally we always use document-global values. The IN and OUT parameters |
102 | are, however, adjusted to the needs of the LineIter most of the time. That |
103 | is: they are converted to frame- and window-local coordinates. |
104 | If multiple frames with wrap attributes are located on the same line, we get |
105 | the following settings for the text flow: |
106 | |
107 | L/R P L R N |
108 | P -P-P- -P-L -P R- -P N |
109 | L -L P- -L L -L R- -L N |
110 | R R-P- R-L R R- R N |
111 | N N P- N L N R- N N |
112 | |
113 | (P=parallel, L=left, R=right, N=no wrap) |
114 | |
115 | We can describe the behaviour as follows: |
116 | Every frame can push away text, with the restriction that it only has influence |
117 | until the next frame. |
118 | */ |
119 | class SwTextFly |
120 | { |
121 | const SwPageFrame * m_pPage; |
122 | const SwAnchoredObject * mpCurrAnchoredObj; |
123 | const SwTextFrame * m_pCurrFrame; |
124 | const SwTextFrame * m_pMaster; |
125 | std::unique_ptr<SwAnchoredObjList> mpAnchoredObjList; |
126 | |
127 | long m_nMinBottom; |
128 | long m_nNextTop; /// Stores the upper edge of the "next" frame |
129 | sal_uLong m_nCurrFrameNodeIndex; |
130 | |
131 | bool m_bOn : 1; |
132 | bool m_bTopRule: 1; |
133 | bool mbIgnoreCurrentFrame: 1; |
134 | bool mbIgnoreContour: 1; |
135 | |
136 | /** boolean, indicating if objects in page header|footer are considered for |
137 | text frames not in page header|footer. |
138 | */ |
139 | bool mbIgnoreObjsInHeaderFooter: 1; |
140 | |
141 | /** |
142 | This method will be called during the LineIter formatting |
143 | \li to compute the position of the next \c FlyPortion |
144 | \li remember new overlappings after a change of the line height. |
145 | |
146 | \param[in] rPortion |
147 | Scope: document global. |
148 | */ |
149 | SwRect GetFrame_( const SwRect &rPortion ) const; |
150 | |
151 | SwAnchoredObjList* InitAnchoredObjList(); |
152 | |
153 | SwAnchoredObjList* GetAnchoredObjList() const; |
154 | |
155 | /** |
156 | Look for the first object which overlaps with the rectangle. |
157 | Iterates over the anchored object list mpAnchoredObjList. |
158 | */ |
159 | bool ForEach( const SwRect &rRect, SwRect* pRect, bool bAvoid ) const; |
160 | |
161 | /** |
162 | \li There is less than 2cm space on both sides for the text: |
163 | no surround (css::text::WrapTextMode_NONE) |
164 | |
165 | \li There is more than 2cm space on only one side: |
166 | surround on that side (css::text::WrapTextMode_LEFT or css::text::WrapTextMode_RIGHT) |
167 | |
168 | \li There is more than 2cm space on both sides, the object is |
169 | larger than 1.5cm: surround on the wider side |
170 | (css::text::WrapTextMode_LEFT or css::text::WrapTextMode_RIGHT) |
171 | |
172 | \li There is more than 2cm space on both sides and the object |
173 | width is less than 1.5cm: both sides surround (css::text::WrapTextMode_PARALLEL) |
174 | */ |
175 | css::text::WrapTextMode GetSurroundForTextWrap( const SwAnchoredObject* pAnchoredObj ) const; |
176 | |
177 | /** |
178 | The right margin is the right margin or it is determined by the |
179 | next object standing on the line. |
180 | */ |
181 | void CalcRightMargin( SwRect &rFly, |
182 | SwAnchoredObjList::size_type nPos, |
183 | const SwRect &rLine ) const; |
184 | |
185 | /** |
186 | The left margin is the left margin of the current PrintArea or |
187 | it is determined by the last FlyFrame, which stands on the line. |
188 | */ |
189 | void CalcLeftMargin( SwRect &rFly, |
190 | SwAnchoredObjList::size_type nPos, |
191 | const SwRect &rLine ) const; |
192 | |
193 | /** |
194 | \return the position in sorted array |
195 | */ |
196 | SwAnchoredObjList::size_type GetPos( const SwAnchoredObject* pAnchoredObj ) const; |
197 | |
198 | bool GetTop( const SwAnchoredObject* _pAnchoredObj, |
199 | const bool bInFootnote, |
200 | const bool bInFooterOrHeader ); |
201 | |
202 | SwTwips CalcMinBottom() const; |
203 | |
204 | const SwTextFrame* GetMaster_(); |
205 | |
206 | public: |
207 | |
208 | SwTextFly(); |
209 | SwTextFly( const SwTextFrame *pFrame ); |
210 | SwTextFly( const SwTextFly& rTextFly ); |
211 | ~SwTextFly(); |
212 | |
213 | void CtorInitTextFly( const SwTextFrame *pFrame ); |
214 | |
215 | void SetTopRule(); |
216 | |
217 | SwRect GetFrame( const SwRect &rPortion ) const; |
218 | bool IsOn() const; |
219 | |
220 | /** |
221 | If there is no flying object frame standing in rRect (usually the current row), |
222 | then we are turning ourself off. |
223 | |
224 | \param rRect is global to the document! |
225 | */ |
226 | bool Relax( const SwRect &rRect ); |
227 | bool Relax(); |
228 | |
229 | SwTwips GetMinBottom() const; |
230 | const SwTextFrame* GetMaster() const; |
231 | |
232 | // This temporary variable needs to be manipulated in const methods |
233 | long GetNextTop() const; |
234 | void SetNextTop( long nNew ) const; |
235 | |
236 | /** |
237 | Determines the demanded rectangle for an anchored object, |
238 | considering its surround for text wrapping. |
239 | |
240 | \param pAnchoredObj the object for which to get the bounds |
241 | \param rLine the bounds of the line to format |
242 | |
243 | \return the flying object bounds |
244 | */ |
245 | SwRect AnchoredObjToRect( const SwAnchoredObject* pAnchoredObj, |
246 | const SwRect& rRect ) const; |
247 | |
248 | /** |
249 | This method is called by DrawText(). |
250 | |
251 | Ensures that the overlapping frames (except the transparent frames) won't |
252 | be scribbled by setting clip regions so that only the portions that are not |
253 | in the area of FlyFrames that are opaque and above the current frame will |
254 | be output. |
255 | |
256 | DrawText() takes over the on optimization! |
257 | */ |
258 | void DrawTextOpaque( SwDrawTextInfo &rInf ); |
259 | |
260 | /** |
261 | Two subtleties needs to be mentioned: |
262 | \li DrawRect() is allowed over the ClipRects |
263 | \li FlyToRect() returns bigger values than the frame data |
264 | |
265 | Ensure that the overlapping frames (except the transparent frames) |
266 | won't be scribbled |
267 | */ |
268 | void DrawFlyRect( OutputDevice* pOut, const SwRect &rRect ); |
269 | |
270 | /** |
271 | Used to switch off the SwTextFly when there is no overlapping object (Relax). |
272 | |
273 | \param[in] the line area |
274 | \return whether the line will be overlapped by a frame |
275 | */ |
276 | bool IsAnyFrame( const SwRect &rLine ) const; |
277 | |
278 | /** |
279 | Same as IsAnyFrame(const SwRect&), but uses the current frame print |
280 | area |
281 | */ |
282 | bool IsAnyFrame() const; |
283 | |
284 | /** |
285 | true when a frame or DrawObj must be taken in account. The optimizations |
286 | like Paint/FormatEmpty for empty sentences or the virtual OutputDevice can |
287 | be used only when false is returned. |
288 | |
289 | \param rRect |
290 | The rectangle can be empty, the current frame is then used. The value is |
291 | global to the document. |
292 | */ |
293 | bool IsAnyObj( const SwRect& rRect ) const; |
294 | |
295 | void SetIgnoreCurrentFrame( bool bNew ); |
296 | void SetIgnoreContour( bool bNew ); |
297 | |
298 | void SetIgnoreObjsInHeaderFooter( const bool bNew ); |
299 | }; |
300 | |
301 | inline SwAnchoredObjList* SwTextFly::GetAnchoredObjList() const |
302 | { |
303 | return mpAnchoredObjList |
304 | ? mpAnchoredObjList.get() |
305 | : const_cast<SwTextFly*>(this)->InitAnchoredObjList(); |
306 | } |
307 | |
308 | inline void SwTextFly::SetTopRule() |
309 | { |
310 | m_bTopRule = false; |
311 | } |
312 | |
313 | inline bool SwTextFly::IsOn() const |
314 | { |
315 | return m_bOn; |
316 | } |
317 | |
318 | inline bool SwTextFly::Relax( const SwRect &rRect ) |
319 | { |
320 | if (m_bOn) |
321 | { |
322 | m_bOn = IsAnyFrame( rRect ); |
323 | } |
324 | return m_bOn; |
325 | } |
326 | |
327 | inline bool SwTextFly::Relax() |
328 | { |
329 | if (m_bOn) |
330 | { |
331 | m_bOn = IsAnyFrame(); |
332 | } |
333 | return m_bOn; |
334 | } |
335 | |
336 | inline SwTwips SwTextFly::GetMinBottom() const |
337 | { |
338 | return mpAnchoredObjList ? m_nMinBottom : CalcMinBottom(); |
339 | } |
340 | |
341 | inline const SwTextFrame* SwTextFly::GetMaster() const |
342 | { |
343 | return m_pMaster ? m_pMaster : const_cast<SwTextFly*>(this)->GetMaster_(); |
344 | } |
345 | |
346 | inline long SwTextFly::GetNextTop() const |
347 | { |
348 | return m_nNextTop; |
349 | } |
350 | |
351 | inline void SwTextFly::SetNextTop( long nNew ) const |
352 | { |
353 | const_cast<SwTextFly*>(this)->m_nNextTop = nNew; |
354 | } |
355 | |
356 | inline SwRect SwTextFly::GetFrame( const SwRect &rRect ) const |
357 | { |
358 | return m_bOn ? GetFrame_( rRect ) : SwRect(); |
359 | } |
360 | |
361 | inline void SwTextFly::SetIgnoreCurrentFrame( bool bNew ) |
362 | { |
363 | mbIgnoreCurrentFrame = bNew; |
364 | } |
365 | |
366 | inline void SwTextFly::SetIgnoreContour( bool bNew ) |
367 | { |
368 | mbIgnoreContour = bNew; |
369 | } |
370 | |
371 | inline void SwTextFly::SetIgnoreObjsInHeaderFooter( const bool bNew ) |
372 | { |
373 | mbIgnoreObjsInHeaderFooter = bNew; |
374 | } |
375 | |
376 | #endif |
377 | |
378 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | |||||||
37 | namespace drawinglayer::processor2d { class BaseProcessor2D; } | ||||||
38 | |||||||
39 | class SwLayoutFrame; | ||||||
40 | class SwRootFrame; | ||||||
41 | class SwPageFrame; | ||||||
42 | class SwBodyFrame; | ||||||
43 | class SwFlyFrame; | ||||||
44 | class SwSectionFrame; | ||||||
45 | class SwFootnoteFrame; | ||||||
46 | class SwFootnoteBossFrame; | ||||||
47 | class SwTabFrame; | ||||||
48 | class SwRowFrame; | ||||||
49 | class SwContentFrame; | ||||||
50 | class SwAttrSet; | ||||||
51 | class Color; | ||||||
52 | class SwBorderAttrs; | ||||||
53 | class SwCache; | ||||||
54 | class SvxBrushItem; | ||||||
55 | class SvxFormatBreakItem; | ||||||
56 | class SwFormatPageDesc; | ||||||
57 | class SwSelectionList; | ||||||
58 | struct SwPosition; | ||||||
59 | struct SwCursorMoveState; | ||||||
60 | class SwFormat; | ||||||
61 | class SwPrintData; | ||||||
62 | class SwSortedObjs; | ||||||
63 | class SwAnchoredObject; | ||||||
64 | enum class SvxFrameDirection; | ||||||
65 | class 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. | ||||||
72 | enum 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 | |||||||
93 | namespace 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. | ||||||
110 | enum 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 | |||||||
119 | namespace 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 | ||||||
130 | class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition | ||||||
131 | { | ||||||
132 | private: | ||||||
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 | |||||||
153 | protected: | ||||||
154 | // write access to mb*Valid flags | ||||||
155 | void setFrameAreaPositionValid(bool bNew); | ||||||
156 | void setFrameAreaSizeValid(bool bNew); | ||||||
157 | void setFramePrintAreaValid(bool bNew); | ||||||
158 | |||||||
159 | public: | ||||||
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 >') | ||||||
233 | class TransformableSwFrame | ||||||
234 | { | ||||||
235 | private: | ||||||
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 | |||||||
244 | public: | ||||||
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 | */ | ||||||
297 | class 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 | |||||||
395 | protected: | ||||||
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 | |||||||
493 | public: | ||||||
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 | |||||||
911 | public: | ||||||
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 | |||||||
921 | inline bool SwFrame::IsInDocBody() const | ||||||
922 | { | ||||||
923 | if ( mbInfInvalid ) | ||||||
924 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||||
925 | return mbInfBody; | ||||||
926 | } | ||||||
927 | inline bool SwFrame::IsInFootnote() const | ||||||
928 | { | ||||||
929 | if ( mbInfInvalid
| ||||||
930 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||||
931 | return mbInfFootnote; | ||||||
932 | } | ||||||
933 | inline bool SwFrame::IsInTab() const | ||||||
934 | { | ||||||
935 | if ( mbInfInvalid ) | ||||||
936 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||||
937 | return mbInfTab; | ||||||
938 | } | ||||||
939 | inline bool SwFrame::IsInFly() const | ||||||
940 | { | ||||||
941 | if ( mbInfInvalid ) | ||||||
942 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||||
943 | return mbInfFly; | ||||||
944 | } | ||||||
945 | inline bool SwFrame::IsInSct() const | ||||||
946 | { | ||||||
947 | if ( mbInfInvalid ) | ||||||
948 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||||
949 | return mbInfSct; | ||||||
950 | } | ||||||
951 | bool SwFrame::IsVertical() const | ||||||
952 | { | ||||||
953 | if( mbInvalidVert ) | ||||||
954 | const_cast<SwFrame*>(this)->SetDirFlags( true ); | ||||||
955 | return mbVertical; | ||||||
956 | } | ||||||
957 | inline bool SwFrame::IsVertLR() const | ||||||
958 | { | ||||||
959 | return mbVertLR; | ||||||
960 | } | ||||||
961 | inline bool SwFrame::IsVertLRBT() const | ||||||
962 | { | ||||||
963 | return mbVertLRBT; | ||||||
964 | } | ||||||
965 | inline bool SwFrame::IsRightToLeft() const | ||||||
966 | { | ||||||
967 | if( mbInvalidR2L ) | ||||||
968 | const_cast<SwFrame*>(this)->SetDirFlags( false ); | ||||||
969 | return mbRightToLeft; | ||||||
970 | } | ||||||
971 | |||||||
972 | inline void SwFrame::SetCompletePaint() const | ||||||
973 | { | ||||||
974 | const_cast<SwFrame*>(this)->mbCompletePaint = true; | ||||||
975 | } | ||||||
976 | inline void SwFrame::ResetCompletePaint() const | ||||||
977 | { | ||||||
978 | const_cast<SwFrame*>(this)->mbCompletePaint = false; | ||||||
979 | } | ||||||
980 | |||||||
981 | inline void SwFrame::SetRetouche() const | ||||||
982 | { | ||||||
983 | const_cast<SwFrame*>(this)->mbRetouche = true; | ||||||
984 | } | ||||||
985 | inline void SwFrame::ResetRetouche() const | ||||||
986 | { | ||||||
987 | const_cast<SwFrame*>(this)->mbRetouche = false; | ||||||
988 | } | ||||||
989 | |||||||
990 | inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf() | ||||||
991 | { | ||||||
992 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf()); | ||||||
993 | } | ||||||
994 | inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() | ||||||
995 | { | ||||||
996 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf()); | ||||||
997 | } | ||||||
998 | inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const | ||||||
999 | { | ||||||
1000 | return ImplGetNextLayoutLeaf( true ); | ||||||
1001 | } | ||||||
1002 | inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const | ||||||
1003 | { | ||||||
1004 | return ImplGetNextLayoutLeaf( false ); | ||||||
1005 | } | ||||||
1006 | |||||||
1007 | inline void SwFrame::InvalidateSize() | ||||||
1008 | { | ||||||
1009 | if ( isFrameAreaSizeValid() ) | ||||||
1010 | { | ||||||
1011 | ImplInvalidateSize(); | ||||||
1012 | } | ||||||
1013 | } | ||||||
1014 | inline void SwFrame::InvalidatePrt() | ||||||
1015 | { | ||||||
1016 | if ( isFramePrintAreaValid() ) | ||||||
1017 | { | ||||||
1018 | ImplInvalidatePrt(); | ||||||
1019 | } | ||||||
1020 | } | ||||||
1021 | inline void SwFrame::InvalidatePos() | ||||||
1022 | { | ||||||
1023 | if ( isFrameAreaPositionValid() ) | ||||||
1024 | { | ||||||
1025 | ImplInvalidatePos(); | ||||||
1026 | } | ||||||
1027 | } | ||||||
1028 | inline void SwFrame::InvalidateLineNum() | ||||||
1029 | { | ||||||
1030 | if ( mbValidLineNum ) | ||||||
1031 | ImplInvalidateLineNum(); | ||||||
1032 | } | ||||||
1033 | inline 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 | } | ||||||
1050 | inline void SwFrame::InvalidateNextPos( bool bNoFootnote ) | ||||||
1051 | { | ||||||
1052 | if ( mpNext && !mpNext->IsSctFrame() ) | ||||||
1053 | mpNext->InvalidatePos(); | ||||||
1054 | else | ||||||
1055 | ImplInvalidateNextPos( bNoFootnote ); | ||||||
1056 | } | ||||||
1057 | |||||||
1058 | inline void SwFrame::OptCalc() const | ||||||
1059 | { | ||||||
1060 | if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() ) | ||||||
1061 | { | ||||||
1062 | const_cast<SwFrame*>(this)->OptPrepareMake(); | ||||||
1063 | } | ||||||
1064 | } | ||||||
1065 | inline const SwPageFrame *SwFrame::FindPageFrame() const | ||||||
1066 | { | ||||||
1067 | return const_cast<SwFrame*>(this)->FindPageFrame(); | ||||||
1068 | } | ||||||
1069 | inline const SwFrame *SwFrame::FindColFrame() const | ||||||
1070 | { | ||||||
1071 | return const_cast<SwFrame*>(this)->FindColFrame(); | ||||||
1072 | } | ||||||
1073 | inline const SwFrame *SwFrame::FindFooterOrHeader() const | ||||||
1074 | { | ||||||
1075 | return const_cast<SwFrame*>(this)->FindFooterOrHeader(); | ||||||
1076 | } | ||||||
1077 | inline SwTabFrame *SwFrame::FindTabFrame() | ||||||
1078 | { | ||||||
1079 | return IsInTab() ? ImplFindTabFrame() : nullptr; | ||||||
1080 | } | ||||||
1081 | inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const | ||||||
1082 | { | ||||||
1083 | return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote ); | ||||||
1084 | } | ||||||
1085 | inline SwFootnoteFrame *SwFrame::FindFootnoteFrame() | ||||||
1086 | { | ||||||
1087 | return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr; | ||||||
1088 | } | ||||||
1089 | inline SwFlyFrame *SwFrame::FindFlyFrame() | ||||||
1090 | { | ||||||
1091 | return IsInFly() ? ImplFindFlyFrame() : nullptr; | ||||||
1092 | } | ||||||
1093 | inline SwSectionFrame *SwFrame::FindSctFrame() | ||||||
1094 | { | ||||||
1095 | return IsInSct() ? ImplFindSctFrame() : nullptr; | ||||||
1096 | } | ||||||
1097 | |||||||
1098 | inline const SwBodyFrame *SwFrame::FindBodyFrame() const | ||||||
1099 | { | ||||||
1100 | return IsInDocBody() ? ImplFindBodyFrame() : nullptr; | ||||||
1101 | } | ||||||
1102 | |||||||
1103 | inline const SwTabFrame *SwFrame::FindTabFrame() const | ||||||
1104 | { | ||||||
1105 | return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr; | ||||||
1106 | } | ||||||
1107 | inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const | ||||||
1108 | { | ||||||
1109 | return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr; | ||||||
1110 | } | ||||||
1111 | inline const SwFlyFrame *SwFrame::FindFlyFrame() const | ||||||
1112 | { | ||||||
1113 | return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr; | ||||||
1114 | } | ||||||
1115 | inline const SwSectionFrame *SwFrame::FindSctFrame() const | ||||||
1116 | { | ||||||
1117 | return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr; | ||||||
1118 | } | ||||||
1119 | inline SwFrame *SwFrame::FindNext() | ||||||
1120 | { | ||||||
1121 | if ( mpNext ) | ||||||
1122 | return mpNext; | ||||||
1123 | else | ||||||
1124 | return FindNext_(); | ||||||
1125 | } | ||||||
1126 | inline const SwFrame *SwFrame::FindNext() const | ||||||
1127 | { | ||||||
1128 | if ( mpNext ) | ||||||
1129 | return mpNext; | ||||||
1130 | else | ||||||
1131 | return const_cast<SwFrame*>(this)->FindNext_(); | ||||||
1132 | } | ||||||
1133 | inline SwFrame *SwFrame::FindPrev() | ||||||
1134 | { | ||||||
1135 | if ( mpPrev && !mpPrev->IsSctFrame() ) | ||||||
1136 | return mpPrev; | ||||||
1137 | else | ||||||
1138 | return FindPrev_(); | ||||||
1139 | } | ||||||
1140 | inline 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 | |||||||
1148 | inline bool SwFrame::IsLayoutFrame() const | ||||||
1149 | { | ||||||
1150 | return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF)); | ||||||
1151 | } | ||||||
1152 | inline bool SwFrame::IsRootFrame() const | ||||||
1153 | { | ||||||
1154 | return mnFrameType == SwFrameType::Root; | ||||||
1155 | } | ||||||
1156 | inline bool SwFrame::IsPageFrame() const | ||||||
1157 | { | ||||||
1158 | return mnFrameType == SwFrameType::Page; | ||||||
1159 | } | ||||||
1160 | inline bool SwFrame::IsColumnFrame() const | ||||||
1161 | { | ||||||
1162 | return mnFrameType == SwFrameType::Column; | ||||||
1163 | } | ||||||
1164 | inline bool SwFrame::IsFootnoteBossFrame() const | ||||||
1165 | { | ||||||
1166 | return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column)); | ||||||
1167 | } | ||||||
1168 | inline bool SwFrame::IsHeaderFrame() const | ||||||
1169 | { | ||||||
1170 | return mnFrameType == SwFrameType::Header; | ||||||
1171 | } | ||||||
1172 | inline bool SwFrame::IsFooterFrame() const | ||||||
1173 | { | ||||||
1174 | return mnFrameType == SwFrameType::Footer; | ||||||
1175 | } | ||||||
1176 | inline bool SwFrame::IsFootnoteContFrame() const | ||||||
1177 | { | ||||||
1178 | return mnFrameType == SwFrameType::FtnCont; | ||||||
1179 | } | ||||||
1180 | inline bool SwFrame::IsFootnoteFrame() const | ||||||
1181 | { | ||||||
1182 | return mnFrameType == SwFrameType::Ftn; | ||||||
1183 | } | ||||||
1184 | inline bool SwFrame::IsBodyFrame() const | ||||||
1185 | { | ||||||
1186 | return mnFrameType == SwFrameType::Body; | ||||||
1187 | } | ||||||
1188 | inline bool SwFrame::IsFlyFrame() const | ||||||
1189 | { | ||||||
1190 | return mnFrameType == SwFrameType::Fly; | ||||||
1191 | } | ||||||
1192 | inline bool SwFrame::IsSctFrame() const | ||||||
1193 | { | ||||||
1194 | return mnFrameType == SwFrameType::Section; | ||||||
1195 | } | ||||||
1196 | inline bool SwFrame::IsTabFrame() const | ||||||
1197 | { | ||||||
1198 | return mnFrameType == SwFrameType::Tab; | ||||||
1199 | } | ||||||
1200 | inline bool SwFrame::IsRowFrame() const | ||||||
1201 | { | ||||||
1202 | return mnFrameType == SwFrameType::Row; | ||||||
1203 | } | ||||||
1204 | inline bool SwFrame::IsCellFrame() const | ||||||
1205 | { | ||||||
1206 | return mnFrameType == SwFrameType::Cell; | ||||||
1207 | } | ||||||
1208 | inline bool SwFrame::IsContentFrame() const | ||||||
1209 | { | ||||||
1210 | return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)); | ||||||
1211 | } | ||||||
1212 | inline bool SwFrame::IsTextFrame() const | ||||||
1213 | { | ||||||
1214 | return mnFrameType == SwFrameType::Txt; | ||||||
1215 | } | ||||||
1216 | inline bool SwFrame::IsNoTextFrame() const | ||||||
1217 | { | ||||||
1218 | return mnFrameType == SwFrameType::NoTxt; | ||||||
1219 | } | ||||||
1220 | inline bool SwFrame::IsFlowFrame() const | ||||||
1221 | { | ||||||
1222 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section)); | ||||||
1223 | } | ||||||
1224 | inline bool SwFrame::IsRetoucheFrame() const | ||||||
1225 | { | ||||||
1226 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn)); | ||||||
1227 | } | ||||||
1228 | inline 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 | ||||||
1234 | class SwFrameDeleteGuard | ||||||
1235 | { | ||||||
1236 | private: | ||||||
1237 | SwFrame *m_pForbidFrame; | ||||||
1238 | public: | ||||||
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 | |||||||
1261 | typedef long (SwFrame::*SwFrameGet)() const; | ||||||
1262 | typedef bool (SwFrame::*SwFrameMax)( long ); | ||||||
1263 | typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool ); | ||||||
1264 | typedef long (*SwOperator)( long, long ); | ||||||
1265 | typedef void (SwFrame::*SwFrameSet)( long, long ); | ||||||
1266 | |||||||
1267 | struct 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 | |||||||
1323 | typedef SwRectFnCollection* SwRectFn; | ||||||
1324 | |||||||
1325 | // This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical) | ||||||
1326 | extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T; | ||||||
1327 | class SwRectFnSet { | ||||||
1328 | public: | ||||||
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 | |||||||
1408 | private: | ||||||
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: */ |