File: | home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx |
Warning: | line 236, column 32 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 ) && m_bTopRule ) | ||||
649 | { | ||||
650 | // #i26945# | ||||
651 | const SwFrameFormat& rFrameFormat = _pAnchoredObj->GetFrameFormat(); | ||||
652 | const SwFormatAnchor& rNewA = rFrameFormat.GetAnchor(); | ||||
653 | if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId()) | ||||
654 | { | ||||
655 | if ( bInFootnote ) | ||||
656 | return false; | ||||
657 | |||||
658 | if ( bInFooterOrHeader ) | ||||
659 | { | ||||
660 | const SwFormatVertOrient& aVert( rFrameFormat.GetVertOrient() ); | ||||
661 | bool bVertPrt = aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA || | ||||
662 | aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA; | ||||
663 | if( bVertPrt ) | ||||
664 | return false; | ||||
665 | } | ||||
666 | } | ||||
667 | } | ||||
668 | |||||
669 | // #i68520# | ||||
670 | // bEvade: consider pNew, if we are not inside a fly | ||||
671 | // consider pNew, if pNew is lower of <mpCurrAnchoredObj> | ||||
672 | bool bEvade = !mpCurrAnchoredObj || | ||||
673 | Is_Lower_Of( dynamic_cast<const SwFlyFrame*>(mpCurrAnchoredObj), pNew); | ||||
674 | |||||
675 | if ( !bEvade ) | ||||
676 | { | ||||
677 | // We are currently inside a fly frame and pNew is not | ||||
678 | // inside this fly frame. We can do some more checks if | ||||
679 | // we have to consider pNew. | ||||
680 | |||||
681 | // If bTopRule is not set, we ignore the frame types. | ||||
682 | // We directly check the z-order | ||||
683 | if ( !m_bTopRule ) | ||||
684 | bEvade = true; | ||||
685 | else | ||||
686 | { | ||||
687 | // Within chained Flys we only avoid Lower | ||||
688 | // #i68520# | ||||
689 | const SwFormatChain &rChain = mpCurrAnchoredObj->GetFrameFormat().GetChain(); | ||||
690 | if ( !rChain.GetPrev() && !rChain.GetNext() ) | ||||
691 | { | ||||
692 | // #i26945# | ||||
693 | const SwFormatAnchor& rNewA = _pAnchoredObj->GetFrameFormat().GetAnchor(); | ||||
694 | // #i68520# | ||||
695 | const SwFormatAnchor& rCurrA = mpCurrAnchoredObj->GetFrameFormat().GetAnchor(); | ||||
696 | |||||
697 | // If <mpCurrAnchoredObj> is anchored as character, its content | ||||
698 | // does not wrap around pNew | ||||
699 | if (RndStdIds::FLY_AS_CHAR == rCurrA.GetAnchorId()) | ||||
700 | return false; | ||||
701 | |||||
702 | // If pNew is anchored to page and <mpCurrAnchoredObj is not anchored | ||||
703 | // to page, the content of <mpCurrAnchoredObj> does not wrap around pNew | ||||
704 | // If both pNew and <mpCurrAnchoredObj> are anchored to page, we can do | ||||
705 | // some more checks | ||||
706 | if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId()) | ||||
707 | { | ||||
708 | if (RndStdIds::FLY_AT_PAGE == rCurrA.GetAnchorId()) | ||||
709 | { | ||||
710 | bEvade = true; | ||||
711 | } | ||||
712 | else | ||||
713 | return false; | ||||
714 | } | ||||
715 | else if (RndStdIds::FLY_AT_PAGE == rCurrA.GetAnchorId()) | ||||
716 | return false; // Page anchored ones only avoid page anchored ones | ||||
717 | else if (RndStdIds::FLY_AT_FLY == rNewA.GetAnchorId()) | ||||
718 | bEvade = true; // Non-page anchored ones avoid frame anchored ones | ||||
719 | else if( RndStdIds::FLY_AT_FLY == rCurrA.GetAnchorId() ) | ||||
720 | return false; // Frame anchored ones do not avoid paragraph anchored ones | ||||
721 | // #i57062# | ||||
722 | // In order to avoid loop situation, it's decided to adjust | ||||
723 | // the wrapping behaviour of content of at-paragraph/at-character | ||||
724 | // anchored objects to one in the page header/footer and | ||||
725 | // the document body --> content of at-paragraph/at-character | ||||
726 | // anchored objects doesn't wrap around each other. | ||||
727 | else | ||||
728 | return false; | ||||
729 | } | ||||
730 | } | ||||
731 | |||||
732 | // But: we never avoid a subordinate one and additionally we only avoid when overlapping. | ||||
733 | // #i68520# | ||||
734 | bEvade &= ( mpCurrAnchoredObj->GetDrawObj()->GetOrdNum() < pNew->GetOrdNum() ); | ||||
735 | if( bEvade ) | ||||
736 | { | ||||
737 | // #i68520# | ||||
738 | const SwRect& aTmp( _pAnchoredObj->GetObjRectWithSpaces() ); | ||||
739 | if ( !aTmp.IsOver( mpCurrAnchoredObj->GetObjRectWithSpaces() ) ) | ||||
740 | bEvade = false; | ||||
741 | } | ||||
742 | } | ||||
743 | |||||
744 | if ( bEvade ) | ||||
745 | { | ||||
746 | // #i26945# | ||||
747 | const SwFormatAnchor& rNewA = _pAnchoredObj->GetFrameFormat().GetAnchor(); | ||||
748 | OSL_ENSURE( RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId(),do { if (true && (!(RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx" ":" "749" ": "), "%s", "Don't call GetTop with a FlyInContentFrame" ); } } while (false) | ||||
749 | "Don't call GetTop with a FlyInContentFrame" )do { if (true && (!(RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx" ":" "749" ": "), "%s", "Don't call GetTop with a FlyInContentFrame" ); } } while (false); | ||||
750 | if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId()) | ||||
751 | return true; // We always avoid page anchored ones | ||||
752 | |||||
753 | // If Flys anchored at paragraph are caught in a FlyCnt, then | ||||
754 | // their influence ends at the borders of the FlyCnt! | ||||
755 | // If we are currently formatting the text of the FlyCnt, then | ||||
756 | // it has to get out of the way of the Frame anchored at paragraph! | ||||
757 | // m_pCurrFrame is the anchor of pNew? | ||||
758 | // #i26945# | ||||
759 | const SwFrame* pTmp = _pAnchoredObj->GetAnchorFrame(); | ||||
760 | if (pTmp == m_pCurrFrame) | ||||
761 | return true; | ||||
762 | if( pTmp->IsTextFrame() && ( pTmp->IsInFly() || pTmp->IsInFootnote() ) ) | ||||
763 | { | ||||
764 | // #i26945# | ||||
765 | Point aPos = _pAnchoredObj->GetObjRect().Pos(); | ||||
766 | pTmp = GetVirtualUpper( pTmp, aPos ); | ||||
767 | } | ||||
768 | // #i26945# | ||||
769 | // If <pTmp> is a text frame inside a table, take the upper | ||||
770 | // of the anchor frame, which contains the anchor position. | ||||
771 | else if ( pTmp->IsTextFrame() && pTmp->IsInTab() ) | ||||
772 | { | ||||
773 | pTmp = const_cast<SwAnchoredObject*>(_pAnchoredObj) | ||||
774 | ->GetAnchorFrameContainingAnchPos()->GetUpper(); | ||||
775 | } | ||||
776 | // #i28701# - consider all objects in same context, | ||||
777 | // if wrapping style is considered on object positioning. | ||||
778 | // Thus, text will wrap around negative positioned objects. | ||||
779 | // #i3317# - remove condition on checking, | ||||
780 | // if wrappings style is considered on object positioning. | ||||
781 | // Thus, text is wrapping around negative positioned objects. | ||||
782 | // #i35640# - no consideration of negative | ||||
783 | // positioned objects, if wrapping style isn't considered on | ||||
784 | // object position and former text wrapping is applied. | ||||
785 | // This condition is typically for documents imported from the | ||||
786 | // OpenOffice.org file format. | ||||
787 | const IDocumentSettingAccess* pIDSA = &m_pCurrFrame->GetDoc().getIDocumentSettingAccess(); | ||||
788 | if ( ( pIDSA->get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) || | ||||
789 | !pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) ) && | ||||
790 | ::FindContext( pTmp, SwFrameType::None ) == ::FindContext(m_pCurrFrame, SwFrameType::None)) | ||||
791 | { | ||||
792 | return true; | ||||
793 | } | ||||
794 | |||||
795 | const SwFrame* pHeader = nullptr; | ||||
796 | if (m_pCurrFrame->GetNext() != pTmp && | ||||
797 | (IsFrameInSameContext( pTmp, m_pCurrFrame ) || | ||||
798 | // #i13832#, #i24135# wrap around objects in page header | ||||
799 | ( !pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) && | ||||
800 | nullptr != ( pHeader = pTmp->FindFooterOrHeader() ) && | ||||
801 | m_pCurrFrame->IsInDocBody()))) | ||||
802 | { | ||||
803 | if( pHeader || RndStdIds::FLY_AT_FLY == rNewA.GetAnchorId() ) | ||||
804 | return true; | ||||
805 | |||||
806 | // Compare indices: | ||||
807 | // The Index of the other is retrieved from the anchor attr. | ||||
808 | sal_uLong nTmpIndex = rNewA.GetContentAnchor()->nNode.GetIndex(); | ||||
809 | // Now check whether the current paragraph is before the anchor | ||||
810 | // of the displaced object in the text, then we don't have to | ||||
811 | // get out of its way. | ||||
812 | // If possible determine Index via SwFormatAnchor because | ||||
813 | // otherwise it's quite expensive. | ||||
814 | if (ULONG_MAX(9223372036854775807L *2UL+1UL) == m_nCurrFrameNodeIndex) | ||||
815 | m_nCurrFrameNodeIndex = m_pCurrFrame->GetTextNodeFirst()->GetIndex(); | ||||
816 | |||||
817 | if (FrameContainsNode(*m_pCurrFrame, nTmpIndex) || nTmpIndex < m_nCurrFrameNodeIndex) | ||||
818 | return true; | ||||
819 | } | ||||
820 | } | ||||
821 | } | ||||
822 | return false; | ||||
823 | } | ||||
824 | |||||
825 | // #i68520# | ||||
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 < nCount; ++i ) | ||||
877 | { | ||||
878 | // #i68520# | ||||
879 | // do not consider hidden objects | ||||
880 | // check, if object has to be considered for text wrap | ||||
881 | // #118809# - If requested, do not consider | ||||
882 | // objects in page header|footer for text frames not in page | ||||
883 | // header|footer. This is requested for the calculation of | ||||
884 | // the base offset for objects <SwTextFrame::CalcBaseOfstForFly()> | ||||
885 | // #i20505# Do not consider oversized objects | ||||
886 | SwAnchoredObject* pAnchoredObj = (*pSorted)[ i ]; | ||||
887 | assert(pAnchoredObj)(static_cast <bool> (pAnchoredObj) ? void (0) : __assert_fail ("pAnchoredObj", "/home/maarten/src/libreoffice/core/sw/source/core/text/txtfly.cxx" , 887, __extension__ __PRETTY_FUNCTION__)); | ||||
888 | if ( !pAnchoredObj || | ||||
889 | !rIDDMA.IsVisibleLayerId( pAnchoredObj->GetDrawObj()->GetLayer() ) || | ||||
890 | !pAnchoredObj->ConsiderForTextWrap() || | ||||
891 | ( mbIgnoreObjsInHeaderFooter && !bFooterHeader && | ||||
892 | pAnchoredObj->GetAnchorFrame()->FindFooterOrHeader() ) || | ||||
893 | ( bAllowCompatWrap && !pAnchoredObj->GetFrameFormat().GetFollowTextFlow().GetValue() ) | ||||
894 | ) | ||||
895 | { | ||||
896 | continue; | ||||
897 | } | ||||
898 | |||||
899 | const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() ); | ||||
900 | if ( nRight < aRectFnSet.GetLeft(aBound) || | ||||
901 | aRectFnSet.YDiff( aRectFnSet.GetTop(aRect), | ||||
902 | aRectFnSet.GetBottom(aBound) ) > 0 || | ||||
903 | nLeft > aRectFnSet.GetRight(aBound) || | ||||
904 | aRectFnSet.GetHeight(aBound) > | ||||
905 | 2 * aRectFnSet.GetHeight(m_pPage->getFrameArea()) ) | ||||
906 | { | ||||
907 | continue; | ||||
908 | } | ||||
909 | |||||
910 | // #i26945# - pass <pAnchoredObj> to method | ||||
911 | // <GetTop(..)> instead of only the <SdrObject> instance of the | ||||
912 | // anchored object | ||||
913 | if (GetTop(pAnchoredObj, m_pCurrFrame->IsInFootnote(), bFooterHeader)) | ||||
914 | { | ||||
915 | // OD 11.03.2003 #107862# - adjust insert position: | ||||
916 | // overlapping objects should be sorted from left to right and | ||||
917 | // inside left to right sorting from top to bottom. | ||||
918 | // If objects on the same position are found, they are sorted | ||||
919 | // on its width. | ||||
920 | // #i68520# | ||||
921 | { | ||||
922 | SwAnchoredObjList::iterator aInsPosIter = | ||||
923 | std::lower_bound( mpAnchoredObjList->begin(), | ||||
924 | mpAnchoredObjList->end(), | ||||
925 | pAnchoredObj, | ||||
926 | AnchoredObjOrder( bR2L, aRectFnSet.FnRect() ) ); | ||||
927 | |||||
928 | mpAnchoredObjList->insert( aInsPosIter, pAnchoredObj ); | ||||
929 | } | ||||
930 | |||||
931 | const SwFormatSurround &rFlyFormat = pAnchoredObj->GetFrameFormat().GetSurround(); | ||||
932 | // #i68520# | ||||
933 | if ( rFlyFormat.IsAnchorOnly() && | ||||
934 | pAnchoredObj->GetAnchorFrame() == GetMaster() ) | ||||
935 | { | ||||
936 | const SwFormatVertOrient &rTmpFormat = | ||||
937 | pAnchoredObj->GetFrameFormat().GetVertOrient(); | ||||
938 | if( text::VertOrientation::BOTTOM != rTmpFormat.GetVertOrient() ) | ||||
939 | m_nMinBottom = ( aRectFnSet.IsVert() && m_nMinBottom ) ? | ||||
940 | std::min( m_nMinBottom, aBound.Left() ) : | ||||
941 | std::max( m_nMinBottom, aRectFnSet.GetBottom(aBound) ); | ||||
942 | } | ||||
943 | |||||
944 | m_bOn = true; | ||||
945 | } | ||||
946 | } | ||||
947 | if( m_nMinBottom ) | ||||
948 | { | ||||
949 | SwTwips nMax = aRectFnSet.GetPrtBottom(*m_pCurrFrame->GetUpper()); | ||||
950 | if( aRectFnSet.YDiff( m_nMinBottom, nMax ) > 0 ) | ||||
951 | m_nMinBottom = nMax; | ||||
952 | } | ||||
953 | } | ||||
954 | else | ||||
955 | { | ||||
956 | // #i68520# | ||||
957 | mpAnchoredObjList.reset( new SwAnchoredObjList ); | ||||
958 | } | ||||
959 | |||||
960 | // #i68520# | ||||
961 | return mpAnchoredObjList.get(); | ||||
962 | } | ||||
963 | |||||
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
| ||||
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 | |
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: */ |