File: | home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx |
Warning: | line 1445, column 31 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 <pagefrm.hxx> | |||
21 | #include <rootfrm.hxx> | |||
22 | #include <cntfrm.hxx> | |||
23 | #include <dflyobj.hxx> | |||
24 | #include <dcontact.hxx> | |||
25 | #include <ftnfrm.hxx> | |||
26 | #include <frmatr.hxx> | |||
27 | #include <frmtool.hxx> | |||
28 | #include <hints.hxx> | |||
29 | #include <sectfrm.hxx> | |||
30 | #include <notxtfrm.hxx> | |||
31 | #include <txtfly.hxx> | |||
32 | ||||
33 | #include <svx/svdpage.hxx> | |||
34 | #include <editeng/ulspitem.hxx> | |||
35 | #include <fmtornt.hxx> | |||
36 | #include <fmtfsize.hxx> | |||
37 | #include <ndole.hxx> | |||
38 | #include <tabfrm.hxx> | |||
39 | #include <flyfrms.hxx> | |||
40 | #include <fmtfollowtextflow.hxx> | |||
41 | #include <environmentofanchoredobject.hxx> | |||
42 | #include <sortedobjs.hxx> | |||
43 | #include <viewimp.hxx> | |||
44 | #include <IDocumentSettingAccess.hxx> | |||
45 | #include <IDocumentDrawModelAccess.hxx> | |||
46 | #include <pam.hxx> | |||
47 | #include <ndindex.hxx> | |||
48 | #include <basegfx/matrix/b2dhommatrixtools.hxx> | |||
49 | #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx> | |||
50 | ||||
51 | using namespace ::com::sun::star; | |||
52 | ||||
53 | SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) | |||
54 | : SwFlyFrame( pFormat, pSib, pAnch ), | |||
55 | // #i34753# | |||
56 | mbNoMakePos( false ), | |||
57 | // #i37068# | |||
58 | mbNoMoveOnCheckClip( false ), | |||
59 | maUnclippedFrame(), | |||
60 | // RotateFlyFrame3 | |||
61 | mpTransformableSwFrame() | |||
62 | { | |||
63 | } | |||
64 | ||||
65 | void SwFlyFreeFrame::DestroyImpl() | |||
66 | { | |||
67 | // #i28701# - use new method <GetPageFrame()> | |||
68 | if( GetPageFrame() ) | |||
69 | { | |||
70 | if( GetFormat()->GetDoc()->IsInDtor() ) | |||
71 | { | |||
72 | // #i29879# - remove also to-frame anchored Writer | |||
73 | // fly frame from page. | |||
74 | const bool bRemoveFromPage = | |||
75 | GetPageFrame()->GetSortedObjs() && | |||
76 | ( IsFlyAtContentFrame() || | |||
77 | ( GetAnchorFrame() && GetAnchorFrame()->IsFlyFrame() ) ); | |||
78 | if ( bRemoveFromPage ) | |||
79 | { | |||
80 | GetPageFrame()->GetSortedObjs()->Remove( *this ); | |||
81 | } | |||
82 | } | |||
83 | else | |||
84 | { | |||
85 | SwRect aTmp( GetObjRectWithSpaces() ); | |||
86 | SwFlyFreeFrame::NotifyBackground( GetPageFrame(), aTmp, PrepareHint::FlyFrameLeave ); | |||
87 | } | |||
88 | } | |||
89 | ||||
90 | SwFlyFrame::DestroyImpl(); | |||
91 | } | |||
92 | ||||
93 | SwFlyFreeFrame::~SwFlyFreeFrame() | |||
94 | { | |||
95 | #if 0 | |||
96 | // we are possibly in ContourCache, make sure we vanish | |||
97 | ::ClrContourCache(GetVirtDrawObj()); | |||
98 | #endif | |||
99 | } | |||
100 | ||||
101 | // #i28701# | |||
102 | /** Notifies the background (all ContentFrames that currently are overlapping). | |||
103 | * | |||
104 | * Additionally, the window is also directly invalidated (especially where | |||
105 | * there are no overlapping ContentFrames). | |||
106 | * This also takes ContentFrames within other Flys into account. | |||
107 | */ | |||
108 | void SwFlyFreeFrame::NotifyBackground( SwPageFrame *pPageFrame, | |||
109 | const SwRect& rRect, PrepareHint eHint ) | |||
110 | { | |||
111 | ::Notify_Background( GetVirtDrawObj(), pPageFrame, rRect, eHint, true ); | |||
112 | } | |||
113 | ||||
114 | void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) | |||
115 | { | |||
116 | if ( !GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) ) | |||
117 | { | |||
118 | return; | |||
119 | } | |||
120 | ||||
121 | if ( !GetAnchorFrame() || IsLocked() || IsColLocked() ) | |||
122 | { | |||
123 | return; | |||
124 | } | |||
125 | ||||
126 | // #i28701# - use new method <GetPageFrame()> | |||
127 | if( !GetPageFrame() && GetAnchorFrame()->IsInFly() ) | |||
128 | { | |||
129 | SwFlyFrame* pFly = AnchorFrame()->FindFlyFrame(); | |||
130 | SwPageFrame *pPageFrame = pFly ? pFly->FindPageFrame() : nullptr; | |||
131 | if( pPageFrame ) | |||
132 | pPageFrame->AppendFlyToPage( this ); | |||
133 | } | |||
134 | ||||
135 | if( !GetPageFrame() ) | |||
136 | { | |||
137 | return; | |||
138 | } | |||
139 | ||||
140 | Lock(); // The curtain drops | |||
141 | ||||
142 | // takes care of the notification in the dtor | |||
143 | const SwFlyNotify aNotify( this ); | |||
144 | ||||
145 | if ( IsClipped() ) | |||
146 | { | |||
147 | setFrameAreaSizeValid(false); | |||
148 | m_bHeightClipped = m_bWidthClipped = false; | |||
149 | // no invalidation of position, | |||
150 | // if anchored object is anchored inside a Writer fly frame, | |||
151 | // its position is already locked, and it follows the text flow. | |||
152 | // #i34753# - add condition: | |||
153 | // no invalidation of position, if no direct move is requested in <CheckClip(..)> | |||
154 | if ( !IsNoMoveOnCheckClip() && | |||
155 | !( PositionLocked() && | |||
156 | GetAnchorFrame()->IsInFly() && | |||
157 | GetFrameFormat().GetFollowTextFlow().GetValue() ) ) | |||
158 | { | |||
159 | setFrameAreaPositionValid(false); | |||
160 | } | |||
161 | } | |||
162 | ||||
163 | // #i81146# new loop control | |||
164 | int nLoopControlRuns = 0; | |||
165 | const int nLoopControlMax = 10; | |||
166 | ||||
167 | // RotateFlyFrame3 - outer frame | |||
168 | const double fRotation(getLocalFrameRotation()); | |||
169 | const bool bRotated(!basegfx::fTools::equalZero(fRotation)); | |||
170 | ||||
171 | if(bRotated) | |||
172 | { | |||
173 | // Re-layout may be partially (see all isFrameAreaDefinitionValid() flags), | |||
174 | // so resetting the local SwFrame(s) in the local SwFrameAreaDefinition is | |||
175 | // needed. Reset to BoundAreas will be done below automatically | |||
176 | if(isTransformableSwFrame()) | |||
177 | { | |||
178 | getTransformableSwFrame()->restoreFrameAreas(); | |||
179 | } | |||
180 | } | |||
181 | ||||
182 | while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() || m_bFormatHeightOnly || !m_bValidContentPos ) | |||
183 | { | |||
184 | SwRectFnSet aRectFnSet(this); | |||
185 | const SwFormatFrameSize *pSz; | |||
186 | { // Additional scope, so aAccess will be destroyed before the check! | |||
187 | ||||
188 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), this ); | |||
189 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
190 | pSz = &rAttrs.GetAttrSet().GetFrameSize(); | |||
191 | ||||
192 | // Only set when the flag is set! | |||
193 | if ( !isFrameAreaSizeValid() ) | |||
194 | { | |||
195 | setFramePrintAreaValid(false); | |||
196 | } | |||
197 | ||||
198 | if ( !isFramePrintAreaValid() ) | |||
199 | { | |||
200 | MakePrtArea( rAttrs ); | |||
201 | m_bValidContentPos = false; | |||
202 | } | |||
203 | ||||
204 | if ( !isFrameAreaSizeValid() || m_bFormatHeightOnly ) | |||
205 | { | |||
206 | setFrameAreaSizeValid(false); | |||
207 | Format( getRootFrame()->GetCurrShell()->GetOut(), &rAttrs ); | |||
208 | m_bFormatHeightOnly = false; | |||
209 | } | |||
210 | } | |||
211 | ||||
212 | if ( !isFrameAreaPositionValid() ) | |||
213 | { | |||
214 | const Point aOldPos( aRectFnSet.GetPos(getFrameArea()) ); | |||
215 | // #i26791# - use new method <MakeObjPos()> | |||
216 | // #i34753# - no positioning, if requested. | |||
217 | if ( IsNoMakePos() ) | |||
218 | { | |||
219 | setFrameAreaPositionValid(true); | |||
220 | } | |||
221 | else | |||
222 | // #i26791# - use new method <MakeObjPos()> | |||
223 | MakeObjPos(); | |||
224 | if( aOldPos == aRectFnSet.GetPos(getFrameArea()) ) | |||
225 | { | |||
226 | if( !isFrameAreaPositionValid() && GetAnchorFrame()->IsInSct() && | |||
227 | !GetAnchorFrame()->FindSctFrame()->isFrameAreaDefinitionValid() ) | |||
228 | { | |||
229 | setFrameAreaPositionValid(true); | |||
230 | } | |||
231 | } | |||
232 | else | |||
233 | { | |||
234 | setFrameAreaSizeValid(false); | |||
235 | } | |||
236 | } | |||
237 | ||||
238 | if ( !m_bValidContentPos ) | |||
239 | { | |||
240 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), this ); | |||
241 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
242 | MakeContentPos( rAttrs ); | |||
243 | } | |||
244 | ||||
245 | if ( isFrameAreaPositionValid() && isFrameAreaSizeValid() ) | |||
246 | { | |||
247 | ++nLoopControlRuns; | |||
248 | ||||
249 | OSL_ENSURE( nLoopControlRuns < nLoopControlMax, "LoopControl in SwFlyFreeFrame::MakeAll" )do { if (true && (!(nLoopControlRuns < nLoopControlMax ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "249" ": "), "%s", "LoopControl in SwFlyFreeFrame::MakeAll" ); } } while (false); | |||
250 | ||||
251 | if ( nLoopControlRuns < nLoopControlMax ) | |||
252 | CheckClip( *pSz ); | |||
253 | } | |||
254 | else | |||
255 | nLoopControlRuns = 0; | |||
256 | } | |||
257 | ||||
258 | // RotateFlyFrame3 - outer frame | |||
259 | // Do not refresh transforms/Areas self here, this will be done | |||
260 | // when inner and outer frame are layouted, in SwNoTextFrame::MakeAll | |||
261 | if(bRotated) | |||
262 | { | |||
263 | // RotateFlyFrame3: Safe changes locally | |||
264 | // get center from outer frame (layout frame) to be on the safe side | |||
265 | const Point aCenter(getFrameArea().Center()); | |||
266 | const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y()); | |||
267 | ||||
268 | if(!mpTransformableSwFrame) | |||
269 | { | |||
270 | mpTransformableSwFrame.reset(new TransformableSwFrame(*this)); | |||
271 | } | |||
272 | ||||
273 | getTransformableSwFrame()->createFrameAreaTransformations( | |||
274 | fRotation, | |||
275 | aB2DCenter); | |||
276 | getTransformableSwFrame()->adaptFrameAreasToTransformations(); | |||
277 | } | |||
278 | else | |||
279 | { | |||
280 | // RotateFlyFrame3: Also need to clear ContourCache (if used), | |||
281 | // usually done in SwFlyFrame::NotifyDrawObj, but there relies on | |||
282 | // being in transform mode which is already reset then | |||
283 | if(isTransformableSwFrame()) | |||
284 | { | |||
285 | ::ClrContourCache(GetVirtDrawObj()); | |||
286 | } | |||
287 | ||||
288 | // reset transformations to show that they are not used | |||
289 | mpTransformableSwFrame.reset(); | |||
290 | } | |||
291 | ||||
292 | Unlock(); | |||
293 | ||||
294 | #if OSL_DEBUG_LEVEL1 > 0 | |||
295 | SwRectFnSet aRectFnSet(this); | |||
296 | OSL_ENSURE( m_bHeightClipped || ( aRectFnSet.GetHeight(getFrameArea()) > 0 &&do { if (true && (!(m_bHeightClipped || ( aRectFnSet. GetHeight(getFrameArea()) > 0 && aRectFnSet.GetHeight (getFramePrintArea()) > 0)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "298" ": "), "%s", "SwFlyFreeFrame::Format(), flipping Fly." ); } } while (false) | |||
297 | aRectFnSet.GetHeight(getFramePrintArea()) > 0),do { if (true && (!(m_bHeightClipped || ( aRectFnSet. GetHeight(getFrameArea()) > 0 && aRectFnSet.GetHeight (getFramePrintArea()) > 0)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "298" ": "), "%s", "SwFlyFreeFrame::Format(), flipping Fly." ); } } while (false) | |||
298 | "SwFlyFreeFrame::Format(), flipping Fly." )do { if (true && (!(m_bHeightClipped || ( aRectFnSet. GetHeight(getFrameArea()) > 0 && aRectFnSet.GetHeight (getFramePrintArea()) > 0)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "298" ": "), "%s", "SwFlyFreeFrame::Format(), flipping Fly." ); } } while (false); | |||
299 | ||||
300 | #endif | |||
301 | } | |||
302 | ||||
303 | bool SwFlyFreeFrame::supportsAutoContour() const | |||
304 | { | |||
305 | static bool bOverrideHandleContourToAlwaysOff(true); // loplugin:constvars:ignore | |||
306 | ||||
307 | // RotateFlyFrameFix: For LO6.0 we need to deactivate the AutoContour feature again, it is simply | |||
308 | // not clear how/if to use and save/load it in ODF. This has to be discussed. | |||
309 | // The reason not to remove is that this may be used as-is now, using a new switch. | |||
310 | // Even when not, the detection if it is possible will be needed in any case later. | |||
311 | if(bOverrideHandleContourToAlwaysOff) | |||
312 | { | |||
313 | return false; | |||
314 | } | |||
315 | ||||
316 | if(!isTransformableSwFrame()) | |||
317 | { | |||
318 | // support only when transformed, else there is no free space | |||
319 | return false; | |||
320 | } | |||
321 | ||||
322 | // Check for Borders. If we have Borders, do (currently) not support, | |||
323 | // since borders do not transform with the object. | |||
324 | // (Will need to be enhanced to take into account if we have Borders and if these | |||
325 | // transform with the object) | |||
326 | SwBorderAttrAccess aAccess(SwFrame::GetCache(), this); | |||
327 | const SwBorderAttrs &rAttrs(*aAccess.Get()); | |||
328 | ||||
329 | if(rAttrs.IsLine()) | |||
330 | { | |||
331 | return false; | |||
332 | } | |||
333 | ||||
334 | // Check for Padding. Do not support when padding is used, this will | |||
335 | // produce a covered space around the object (filled with fill defines) | |||
336 | const SfxPoolItem* pItem(nullptr); | |||
337 | ||||
338 | if(GetFormat() && SfxItemState::SET == GetFormat()->GetItemState(RES_BOX, false, &pItem)) | |||
339 | { | |||
340 | const SvxBoxItem& rBox = *static_cast< const SvxBoxItem* >(pItem); | |||
341 | ||||
342 | if(rBox.HasBorder(/*bTreatPaddingAsBorder*/true)) | |||
343 | { | |||
344 | return false; | |||
345 | } | |||
346 | } | |||
347 | ||||
348 | // check for Fill - if we have fill, it will fill the gaps and we will not | |||
349 | // support AutoContour | |||
350 | if(GetFormat() && GetFormat()->supportsFullDrawingLayerFillAttributeSet()) | |||
351 | { | |||
352 | const drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(GetFormat()->getSdrAllFillAttributesHelper()); | |||
353 | ||||
354 | if(aFillAttributes && aFillAttributes->isUsed()) | |||
355 | { | |||
356 | return false; | |||
357 | } | |||
358 | } | |||
359 | else | |||
360 | { | |||
361 | const std::unique_ptr<SvxBrushItem> aBack(GetFormat()->makeBackgroundBrushItem()); | |||
362 | ||||
363 | if(aBack && aBack->isUsed()) | |||
364 | { | |||
365 | return false; | |||
366 | } | |||
367 | } | |||
368 | ||||
369 | // else, support | |||
370 | return true; | |||
371 | } | |||
372 | ||||
373 | // RotateFlyFrame3 - Support for Transformations - outer frame | |||
374 | basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const | |||
375 | { | |||
376 | if(isTransformableSwFrame()) | |||
377 | { | |||
378 | // use pre-created transformation | |||
379 | return getTransformableSwFrame()->getLocalFrameAreaTransformation(); | |||
380 | } | |||
381 | ||||
382 | // call parent | |||
383 | return SwFlyFrame::getFrameAreaTransformation(); | |||
384 | } | |||
385 | ||||
386 | basegfx::B2DHomMatrix SwFlyFreeFrame::getFramePrintAreaTransformation() const | |||
387 | { | |||
388 | if(isTransformableSwFrame()) | |||
389 | { | |||
390 | // use pre-created transformation | |||
391 | return getTransformableSwFrame()->getLocalFramePrintAreaTransformation(); | |||
392 | } | |||
393 | ||||
394 | // call parent | |||
395 | return SwFlyFrame::getFramePrintAreaTransformation(); | |||
396 | } | |||
397 | ||||
398 | // RotateFlyFrame3 - Support for Transformations | |||
399 | void SwFlyFreeFrame::transform_translate(const Point& rOffset) | |||
400 | { | |||
401 | // call parent - this will do the basic transform for SwRect(s) | |||
402 | // in the SwFrameAreaDefinition | |||
403 | SwFlyFrame::transform_translate(rOffset); | |||
404 | ||||
405 | // check if the Transformations need to be adapted | |||
406 | if(isTransformableSwFrame()) | |||
407 | { | |||
408 | const basegfx::B2DHomMatrix aTransform( | |||
409 | basegfx::utils::createTranslateB2DHomMatrix( | |||
410 | rOffset.X(), rOffset.Y())); | |||
411 | ||||
412 | // transform using TransformableSwFrame | |||
413 | getTransformableSwFrame()->transform(aTransform); | |||
414 | } | |||
415 | } | |||
416 | ||||
417 | // RotateFlyFrame3 - outer frame | |||
418 | double getLocalFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame) | |||
419 | { | |||
420 | return rNoTextFrame.getLocalFrameRotation(); | |||
421 | } | |||
422 | ||||
423 | double SwFlyFreeFrame::getLocalFrameRotation() const | |||
424 | { | |||
425 | // SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower() | |||
426 | // calls SwLayoutFrame::Lower() when it's a SwLayoutFrame - so use GetLower() | |||
427 | const SwNoTextFrame* pSwNoTextFrame(dynamic_cast< const SwNoTextFrame* >(GetLower())); | |||
428 | ||||
429 | if(nullptr != pSwNoTextFrame) | |||
430 | { | |||
431 | return getLocalFrameRotation_from_SwNoTextFrame(*pSwNoTextFrame); | |||
432 | } | |||
433 | ||||
434 | // no rotation | |||
435 | return 0.0; | |||
436 | } | |||
437 | ||||
438 | /** determines, if direct environment of fly frame has 'auto' size | |||
439 | ||||
440 | #i17297# | |||
441 | start with anchor frame and search via <GetUpper()> for a header, footer, | |||
442 | row or fly frame stopping at page frame. | |||
443 | return <true>, if such a frame is found and it has 'auto' size. | |||
444 | otherwise <false> is returned. | |||
445 | ||||
446 | @return boolean indicating, that direct environment has 'auto' size | |||
447 | */ | |||
448 | bool SwFlyFreeFrame::HasEnvironmentAutoSize() const | |||
449 | { | |||
450 | bool bRetVal = false; | |||
451 | ||||
452 | const SwFrame* pToBeCheckedFrame = GetAnchorFrame(); | |||
453 | while ( pToBeCheckedFrame && | |||
454 | !pToBeCheckedFrame->IsPageFrame() ) | |||
455 | { | |||
456 | if ( pToBeCheckedFrame->IsHeaderFrame() || | |||
457 | pToBeCheckedFrame->IsFooterFrame() || | |||
458 | pToBeCheckedFrame->IsRowFrame() || | |||
459 | pToBeCheckedFrame->IsFlyFrame() ) | |||
460 | { | |||
461 | bRetVal = SwFrameSize::Fixed != | |||
462 | pToBeCheckedFrame->GetAttrSet()->GetFrameSize().GetHeightSizeType(); | |||
463 | break; | |||
464 | } | |||
465 | else | |||
466 | { | |||
467 | pToBeCheckedFrame = pToBeCheckedFrame->GetUpper(); | |||
468 | } | |||
469 | } | |||
470 | ||||
471 | return bRetVal; | |||
472 | } | |||
473 | ||||
474 | void SwFlyFreeFrame::CheckClip( const SwFormatFrameSize &rSz ) | |||
475 | { | |||
476 | // It's probably time now to take appropriate measures, if the Fly | |||
477 | // doesn't fit into its surrounding. | |||
478 | // First, the Fly gives up its position, then it's formatted. | |||
479 | // Only if it still doesn't fit after giving up its position, the | |||
480 | // width or height are given up as well. The frame will be squeezed | |||
481 | // as much as needed. | |||
482 | ||||
483 | const SwVirtFlyDrawObj *pObj = GetVirtDrawObj(); | |||
484 | SwRect aClip, aTmpStretch; | |||
485 | ::CalcClipRect( pObj, aClip ); | |||
486 | ::CalcClipRect( pObj, aTmpStretch, false ); | |||
487 | aClip.Intersection_( aTmpStretch ); | |||
488 | ||||
489 | const long nBot = getFrameArea().Top() + getFrameArea().Height(); | |||
490 | const long nRig = getFrameArea().Left() + getFrameArea().Width(); | |||
491 | const long nClipBot = aClip.Top() + aClip.Height(); | |||
492 | const long nClipRig = aClip.Left() + aClip.Width(); | |||
493 | ||||
494 | const bool bBot = nBot > nClipBot; | |||
495 | const bool bRig = nRig > nClipRig; | |||
496 | if (( bBot || bRig ) && !IsDraggingOffPageAllowed(FindFrameFormat(GetDrawObj()))) | |||
497 | { | |||
498 | bool bAgain = false; | |||
499 | // #i37068# - no move, if it's requested | |||
500 | if ( bBot && !IsNoMoveOnCheckClip() && | |||
501 | !GetDrawObjs() && !GetAnchorFrame()->IsInTab() ) | |||
502 | { | |||
503 | SwFrame* pHeader = FindFooterOrHeader(); | |||
504 | // In a header, correction of the position is no good idea. | |||
505 | // If the fly moves, some paragraphs have to be formatted, this | |||
506 | // could cause a change of the height of the headerframe, | |||
507 | // now the flyframe can change its position and so on ... | |||
508 | if ( !pHeader || !pHeader->IsHeaderFrame() ) | |||
509 | { | |||
510 | const long nOld = getFrameArea().Top(); | |||
511 | ||||
512 | // tdf#112443 disable positioning if content is completely off page | |||
513 | bool bDisableOffPagePositioning = GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING); | |||
514 | if ( !bDisableOffPagePositioning || nOld <= nClipBot) | |||
515 | { | |||
516 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
517 | aFrm.Pos().setY( std::max( aClip.Top(), nClipBot - aFrm.Height() ) ); | |||
518 | } | |||
519 | ||||
520 | if ( getFrameArea().Top() != nOld ) | |||
521 | { | |||
522 | bAgain = true; | |||
523 | } | |||
524 | ||||
525 | m_bHeightClipped = true; | |||
526 | } | |||
527 | } | |||
528 | if ( bRig ) | |||
529 | { | |||
530 | const long nOld = getFrameArea().Left(); | |||
531 | ||||
532 | // tdf#112443 disable positioning if content is completely off page | |||
533 | bool bDisableOffPagePositioning = GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING); | |||
534 | if ( !bDisableOffPagePositioning || nOld <= nClipRig ) | |||
535 | { | |||
536 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
537 | aFrm.Pos().setX( std::max( aClip.Left(), nClipRig - aFrm.Width() ) ); | |||
538 | } | |||
539 | ||||
540 | if ( getFrameArea().Left() != nOld ) | |||
541 | { | |||
542 | const SwFormatHoriOrient &rH = GetFormat()->GetHoriOrient(); | |||
543 | // Left-aligned ones may not be moved to the left when they | |||
544 | // are avoiding another one. | |||
545 | if( rH.GetHoriOrient() == text::HoriOrientation::LEFT ) | |||
546 | { | |||
547 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
548 | aFrm.Pos().setX( nOld ); | |||
549 | } | |||
550 | else | |||
551 | { | |||
552 | bAgain = true; | |||
553 | } | |||
554 | } | |||
555 | m_bWidthClipped = true; | |||
556 | } | |||
557 | if ( bAgain ) | |||
558 | { | |||
559 | setFrameAreaSizeValid(false); | |||
560 | } | |||
561 | else | |||
562 | { | |||
563 | // If we reach this branch, the Frame protrudes into forbidden | |||
564 | // areas, and correcting the position is not allowed or not | |||
565 | // possible or not required. | |||
566 | ||||
567 | // For Flys with OLE objects as lower, we make sure that | |||
568 | // we always resize proportionally | |||
569 | Size aOldSize( getFrameArea().SSize() ); | |||
570 | ||||
571 | // First, setup the FrameRect, then transfer it to the Frame. | |||
572 | SwRect aFrameRect( getFrameArea() ); | |||
573 | ||||
574 | if ( bBot ) | |||
575 | { | |||
576 | long nDiff = nClipBot; | |||
577 | nDiff -= aFrameRect.Top(); // nDiff represents the available distance | |||
578 | nDiff = aFrameRect.Height() - nDiff; | |||
579 | aFrameRect.Height( aFrameRect.Height() - nDiff ); | |||
580 | m_bHeightClipped = true; | |||
581 | } | |||
582 | if ( bRig ) | |||
583 | { | |||
584 | long nDiff = nClipRig; | |||
585 | nDiff -= aFrameRect.Left();// nDiff represents the available distance | |||
586 | nDiff = aFrameRect.Width() - nDiff; | |||
587 | aFrameRect.Width( aFrameRect.Width() - nDiff ); | |||
588 | m_bWidthClipped = true; | |||
589 | } | |||
590 | ||||
591 | // #i17297# - no proportional | |||
592 | // scaling of graphics in environments, which determines its size | |||
593 | // by its content ('auto' size). Otherwise layout loops can occur and | |||
594 | // layout sizes of the environment can be incorrect. | |||
595 | // Such environment are: | |||
596 | // (1) header and footer frames with 'auto' size | |||
597 | // (2) table row frames with 'auto' size | |||
598 | // (3) fly frames with 'auto' size | |||
599 | // Note: section frames seems to be not critical - didn't found | |||
600 | // any critical layout situation so far. | |||
601 | if ( Lower() && Lower()->IsNoTextFrame() && | |||
602 | (static_cast<SwNoTextFrame*>(Lower())->GetNode()->GetOLENode() || | |||
603 | !HasEnvironmentAutoSize() ) ) | |||
604 | { | |||
605 | // If width and height got adjusted, then the bigger | |||
606 | // change is relevant. | |||
607 | if ( aFrameRect.Width() != aOldSize.Width() && | |||
608 | aFrameRect.Height()!= aOldSize.Height() ) | |||
609 | { | |||
610 | if ( (aOldSize.Width() - aFrameRect.Width()) > | |||
611 | (aOldSize.Height()- aFrameRect.Height()) ) | |||
612 | aFrameRect.Height( aOldSize.Height() ); | |||
613 | else | |||
614 | aFrameRect.Width( aOldSize.Width() ); | |||
615 | } | |||
616 | ||||
617 | // Adjusted the width? change height proportionally | |||
618 | if( aFrameRect.Width() != aOldSize.Width() ) | |||
619 | { | |||
620 | aFrameRect.Height( aFrameRect.Width() * aOldSize.Height() / | |||
621 | aOldSize.Width() ); | |||
622 | m_bHeightClipped = true; | |||
623 | } | |||
624 | // Adjusted the height? change width proportionally | |||
625 | else if( aFrameRect.Height() != aOldSize.Height() ) | |||
626 | { | |||
627 | aFrameRect.Width( aFrameRect.Height() * aOldSize.Width() / | |||
628 | aOldSize.Height() ); | |||
629 | m_bWidthClipped = true; | |||
630 | } | |||
631 | ||||
632 | // #i17297# - reactivate change | |||
633 | // of size attribute for fly frames containing an ole object. | |||
634 | ||||
635 | // Added the aFrameRect.HasArea() hack, because | |||
636 | // the environment of the ole object does not have to be valid | |||
637 | // at this moment, or even worse, it does not have to have a | |||
638 | // reasonable size. In this case we do not want to change to | |||
639 | // attributes permanently. Maybe one day somebody dares to remove | |||
640 | // this code. | |||
641 | if ( aFrameRect.HasArea() && | |||
642 | static_cast<SwNoTextFrame*>(Lower())->GetNode()->GetOLENode() && | |||
643 | ( m_bWidthClipped || m_bHeightClipped ) ) | |||
644 | { | |||
645 | SwFlyFrameFormat *pFormat = GetFormat(); | |||
646 | pFormat->LockModify(); | |||
647 | SwFormatFrameSize aFrameSize( rSz ); | |||
648 | aFrameSize.SetWidth( aFrameRect.Width() ); | |||
649 | aFrameSize.SetHeight( aFrameRect.Height() ); | |||
650 | pFormat->SetFormatAttr( aFrameSize ); | |||
651 | pFormat->UnlockModify(); | |||
652 | } | |||
653 | } | |||
654 | ||||
655 | // Now change the Frame; for columns, we put the new values into the attributes, | |||
656 | // otherwise we'll end up with unwanted side-effects/oscillations | |||
657 | const long nPrtHeightDiff = getFrameArea().Height() - getFramePrintArea().Height(); | |||
658 | const long nPrtWidthDiff = getFrameArea().Width() - getFramePrintArea().Width(); | |||
659 | maUnclippedFrame = getFrameArea(); | |||
660 | ||||
661 | { | |||
662 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
663 | aFrm.Height( aFrameRect.Height() ); | |||
664 | aFrm.Width ( std::max( long(MINLAY23), aFrameRect.Width() ) ); | |||
665 | } | |||
666 | ||||
667 | if ( Lower() && Lower()->IsColumnFrame() ) | |||
668 | { | |||
669 | ColLock(); //lock grow/shrink | |||
670 | const Size aTmpOldSize( getFramePrintArea().SSize() ); | |||
671 | ||||
672 | { | |||
673 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | |||
674 | aPrt.Height( getFrameArea().Height() - nPrtHeightDiff ); | |||
675 | aPrt.Width ( getFrameArea().Width() - nPrtWidthDiff ); | |||
676 | } | |||
677 | ||||
678 | ChgLowersProp( aTmpOldSize ); | |||
679 | SwFrame *pLow = Lower(); | |||
680 | do | |||
681 | { | |||
682 | pLow->Calc(getRootFrame()->GetCurrShell()->GetOut()); | |||
683 | // also calculate the (Column)BodyFrame | |||
684 | static_cast<SwLayoutFrame*>(pLow)->Lower()->Calc(getRootFrame()->GetCurrShell()->GetOut()); | |||
685 | pLow = pLow->GetNext(); | |||
686 | } while ( pLow ); | |||
687 | ::CalcContent( this ); | |||
688 | ColUnlock(); | |||
689 | ||||
690 | if ( !isFrameAreaSizeValid() && !m_bWidthClipped ) | |||
691 | { | |||
692 | setFrameAreaSizeValid(true); | |||
693 | m_bFormatHeightOnly = true; | |||
694 | } | |||
695 | } | |||
696 | else | |||
697 | { | |||
698 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | |||
699 | aPrt.Height( getFrameArea().Height() - nPrtHeightDiff ); | |||
700 | aPrt.Width ( getFrameArea().Width() - nPrtWidthDiff ); | |||
701 | } | |||
702 | } | |||
703 | } | |||
704 | ||||
705 | // #i26945# | |||
706 | OSL_ENSURE( getFrameArea().Height() >= 0,do { if (true && (!(getFrameArea().Height() >= 0)) ) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "707" ": "), "%s", "<SwFlyFreeFrame::CheckClip(..)> - fly frame has negative height now." ); } } while (false) | |||
707 | "<SwFlyFreeFrame::CheckClip(..)> - fly frame has negative height now." )do { if (true && (!(getFrameArea().Height() >= 0)) ) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "707" ": "), "%s", "<SwFlyFreeFrame::CheckClip(..)> - fly frame has negative height now." ); } } while (false); | |||
708 | } | |||
709 | ||||
710 | /** method to determine, if a <MakeAll()> on the Writer fly frame is possible | |||
711 | #i43771# | |||
712 | */ | |||
713 | bool SwFlyFreeFrame::IsFormatPossible() const | |||
714 | { | |||
715 | return SwFlyFrame::IsFormatPossible() && | |||
716 | ( GetPageFrame() || | |||
717 | ( GetAnchorFrame() && GetAnchorFrame()->IsInFly() ) ); | |||
718 | } | |||
719 | ||||
720 | SwFlyLayFrame::SwFlyLayFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) : | |||
721 | SwFlyFreeFrame( pFormat, pSib, pAnch ) | |||
722 | { | |||
723 | m_bLayout = true; | |||
724 | } | |||
725 | ||||
726 | // #i28701# | |||
727 | ||||
728 | void SwFlyLayFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew ) | |||
729 | { | |||
730 | const SwFormatAnchor *pAnch = nullptr; | |||
731 | ||||
732 | if (pNew) | |||
733 | { | |||
734 | const sal_uInt16 nWhich = pNew->Which(); | |||
735 | if( RES_ATTRSET_CHG == nWhich && SfxItemState::SET == | |||
736 | static_cast<const SwAttrSetChg*>(pNew)->GetChgSet()->GetItemState( RES_ANCHOR, false, | |||
737 | reinterpret_cast<const SfxPoolItem**>(&pAnch) )) | |||
738 | ; // GetItemState sets the anchor pointer! | |||
739 | ||||
740 | else if( RES_ANCHOR == nWhich ) | |||
741 | { | |||
742 | // Change of anchor. I'm attaching myself to the new place. | |||
743 | // It's not allowed to change the anchor type. This is only | |||
744 | // possible via SwFEShell. | |||
745 | pAnch = static_cast<const SwFormatAnchor*>(pNew); | |||
746 | } | |||
747 | } | |||
748 | ||||
749 | if( pAnch ) | |||
750 | { | |||
751 | OSL_ENSURE( pAnch->GetAnchorId() ==do { if (true && (!(pAnch->GetAnchorId() == GetFormat ()->GetAnchor().GetAnchorId()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "753" ": "), "%s", "8-) Invalid change of anchor type.") ; } } while (false) | |||
752 | GetFormat()->GetAnchor().GetAnchorId(),do { if (true && (!(pAnch->GetAnchorId() == GetFormat ()->GetAnchor().GetAnchorId()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "753" ": "), "%s", "8-) Invalid change of anchor type.") ; } } while (false) | |||
753 | "8-) Invalid change of anchor type." )do { if (true && (!(pAnch->GetAnchorId() == GetFormat ()->GetAnchor().GetAnchorId()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "753" ": "), "%s", "8-) Invalid change of anchor type.") ; } } while (false); | |||
754 | ||||
755 | // Unregister, get hold of the page, attach to the corresponding LayoutFrame. | |||
756 | SwRect aOld( GetObjRectWithSpaces() ); | |||
757 | // #i28701# - use new method <GetPageFrame()> | |||
758 | SwPageFrame *pOldPage = GetPageFrame(); | |||
759 | AnchorFrame()->RemoveFly( this ); | |||
760 | ||||
761 | if ( RndStdIds::FLY_AT_PAGE == pAnch->GetAnchorId() ) | |||
762 | { | |||
763 | sal_uInt16 nPgNum = pAnch->GetPageNum(); | |||
764 | SwRootFrame *pRoot = getRootFrame(); | |||
765 | SwPageFrame *pTmpPage = static_cast<SwPageFrame*>(pRoot->Lower()); | |||
766 | for ( sal_uInt16 i = 1; (i <= nPgNum) && pTmpPage; ++i, | |||
767 | pTmpPage = static_cast<SwPageFrame*>(pTmpPage->GetNext()) ) | |||
768 | { | |||
769 | if ( i == nPgNum ) | |||
770 | { | |||
771 | // #i50432# - adjust synopsis of <PlaceFly(..)> | |||
772 | pTmpPage->PlaceFly( this, nullptr ); | |||
773 | } | |||
774 | } | |||
775 | if( !pTmpPage ) | |||
776 | { | |||
777 | pRoot->SetAssertFlyPages(); | |||
778 | pRoot->AssertFlyPages(); | |||
779 | } | |||
780 | } | |||
781 | else | |||
782 | { | |||
783 | SwNodeIndex aIdx( pAnch->GetContentAnchor()->nNode ); | |||
784 | SwContentFrame *pContent = GetFormat()->GetDoc()->GetNodes().GoNext( &aIdx )-> | |||
785 | GetContentNode()->getLayoutFrame(getRootFrame(), nullptr, nullptr); | |||
786 | if( pContent ) | |||
787 | { | |||
788 | SwFlyFrame *pTmp = pContent->FindFlyFrame(); | |||
789 | if( pTmp ) | |||
790 | pTmp->AppendFly( this ); | |||
791 | } | |||
792 | } | |||
793 | // #i28701# - use new method <GetPageFrame()> | |||
794 | if ( pOldPage && pOldPage != GetPageFrame() ) | |||
795 | NotifyBackground( pOldPage, aOld, PrepareHint::FlyFrameLeave ); | |||
796 | SetCompletePaint(); | |||
797 | InvalidateAll(); | |||
798 | SetNotifyBack(); | |||
799 | } | |||
800 | else | |||
801 | SwFlyFrame::Modify( pOld, pNew ); | |||
802 | } | |||
803 | ||||
804 | void SwPageFrame::AppendFlyToPage( SwFlyFrame *pNew ) | |||
805 | { | |||
806 | if ( !pNew->GetVirtDrawObj()->IsInserted() ) | |||
807 | getRootFrame()->GetDrawPage()->InsertObject( | |||
808 | static_cast<SdrObject*>(pNew->GetVirtDrawObj()), | |||
809 | pNew->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() ); | |||
810 | ||||
811 | InvalidateSpelling(); | |||
812 | InvalidateSmartTags(); | |||
813 | InvalidateAutoCompleteWords(); | |||
814 | InvalidateWordCount(); | |||
815 | ||||
816 | if ( GetUpper() ) | |||
817 | { | |||
818 | static_cast<SwRootFrame*>(GetUpper())->SetIdleFlags(); | |||
819 | static_cast<SwRootFrame*>(GetUpper())->InvalidateBrowseWidth(); | |||
820 | } | |||
821 | ||||
822 | SdrObject* pObj = pNew->GetVirtDrawObj(); | |||
823 | OSL_ENSURE( pNew->GetAnchorFrame(), "Fly without Anchor" )do { if (true && (!(pNew->GetAnchorFrame()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "823" ": "), "%s", "Fly without Anchor"); } } while (false ); | |||
824 | SwFlyFrame* pFly = const_cast<SwFlyFrame*>(pNew->GetAnchorFrame()->FindFlyFrame()); | |||
825 | if ( pFly && pObj->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() ) | |||
826 | { | |||
827 | //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed. | |||
828 | sal_uInt32 nNewNum = pObj->GetOrdNumDirect(); | |||
829 | if ( pObj->getSdrPageFromSdrObject() ) | |||
830 | pObj->getSdrPageFromSdrObject()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum ); | |||
831 | else | |||
832 | pFly->GetVirtDrawObj()->SetOrdNum( nNewNum ); | |||
833 | } | |||
834 | ||||
835 | // Don't look further at Flys that sit inside the Content. | |||
836 | if ( pNew->IsFlyInContentFrame() ) | |||
837 | InvalidateFlyInCnt(); | |||
838 | else | |||
839 | { | |||
840 | InvalidateFlyContent(); | |||
841 | ||||
842 | if ( !m_pSortedObjs ) | |||
843 | { | |||
844 | m_pSortedObjs.reset(new SwSortedObjs()); | |||
845 | } | |||
846 | ||||
847 | const bool bSuccessInserted = m_pSortedObjs->Insert( *pNew ); | |||
848 | OSL_ENSURE( bSuccessInserted, "Fly not inserted in Sorted." )do { if (true && (!(bSuccessInserted))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "848" ": "), "%s", "Fly not inserted in Sorted."); } } while (false); | |||
849 | ||||
850 | // #i87493# | |||
851 | OSL_ENSURE( pNew->GetPageFrame() == nullptr || pNew->GetPageFrame() == this,do { if (true && (!(pNew->GetPageFrame() == nullptr || pNew->GetPageFrame() == this))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "852" ": "), "%s", "<SwPageFrame::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect." ); } } while (false) | |||
852 | "<SwPageFrame::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect." )do { if (true && (!(pNew->GetPageFrame() == nullptr || pNew->GetPageFrame() == this))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "852" ": "), "%s", "<SwPageFrame::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect." ); } } while (false); | |||
853 | // #i28701# - use new method <SetPageFrame(..)> | |||
854 | pNew->SetPageFrame( this ); | |||
855 | pNew->InvalidatePage( this ); | |||
856 | // #i28701# | |||
857 | pNew->UnlockPosition(); | |||
858 | // needed to reposition at-page anchored flys moved from different page | |||
859 | pNew->InvalidateObjPos(); | |||
860 | ||||
861 | // Notify accessible layout. That's required at this place for | |||
862 | // frames only where the anchor is moved. Creation of new frames | |||
863 | // is additionally handled by the SwFrameNotify class. | |||
864 | if( GetUpper() && | |||
865 | static_cast< SwRootFrame * >( GetUpper() )->IsAnyShellAccessible() && | |||
866 | static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell() ) | |||
867 | { | |||
868 | static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell()->Imp() | |||
869 | ->AddAccessibleFrame( pNew ); | |||
870 | } | |||
871 | } | |||
872 | ||||
873 | // #i28701# - correction: consider also drawing objects | |||
874 | if ( !pNew->GetDrawObjs() ) | |||
875 | return; | |||
876 | ||||
877 | SwSortedObjs &rObjs = *pNew->GetDrawObjs(); | |||
878 | for (SwAnchoredObject* pTmpObj : rObjs) | |||
879 | { | |||
880 | if ( dynamic_cast<const SwFlyFrame*>( pTmpObj) != nullptr ) | |||
881 | { | |||
882 | SwFlyFrame* pTmpFly = static_cast<SwFlyFrame*>(pTmpObj); | |||
883 | // #i28701# - use new method <GetPageFrame()> | |||
884 | if ( pTmpFly->IsFlyFreeFrame() && !pTmpFly->GetPageFrame() ) | |||
885 | AppendFlyToPage( pTmpFly ); | |||
886 | } | |||
887 | else if ( dynamic_cast<const SwAnchoredDrawObject*>( pTmpObj) != nullptr ) | |||
888 | { | |||
889 | // #i87493# | |||
890 | if ( pTmpObj->GetPageFrame() != this ) | |||
891 | { | |||
892 | if ( pTmpObj->GetPageFrame() != nullptr ) | |||
893 | { | |||
894 | pTmpObj->GetPageFrame()->RemoveDrawObjFromPage( *pTmpObj ); | |||
895 | } | |||
896 | AppendDrawObjToPage( *pTmpObj ); | |||
897 | } | |||
898 | } | |||
899 | } | |||
900 | } | |||
901 | ||||
902 | void SwPageFrame::RemoveFlyFromPage( SwFlyFrame *pToRemove ) | |||
903 | { | |||
904 | const sal_uInt32 nOrdNum = pToRemove->GetVirtDrawObj()->GetOrdNum(); | |||
905 | getRootFrame()->GetDrawPage()->RemoveObject( nOrdNum ); | |||
906 | pToRemove->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum ); | |||
907 | ||||
908 | if ( GetUpper() ) | |||
909 | { | |||
910 | if ( !pToRemove->IsFlyInContentFrame() ) | |||
911 | static_cast<SwRootFrame*>(GetUpper())->SetSuperfluous(); | |||
912 | static_cast<SwRootFrame*>(GetUpper())->InvalidateBrowseWidth(); | |||
913 | } | |||
914 | ||||
915 | // Don't look further at Flys that sit inside the Content. | |||
916 | if ( pToRemove->IsFlyInContentFrame() ) | |||
917 | return; | |||
918 | ||||
919 | // Don't delete collections just yet. This will happen at the end of the | |||
920 | // action in the RemoveSuperfluous of the page, kicked off by a method of | |||
921 | // the same name in the root. | |||
922 | // The FlyColl might be gone already, because the page's dtor is being | |||
923 | // executed. | |||
924 | // Remove it _before_ disposing accessible frames to avoid accesses to | |||
925 | // the Frame from event handlers. | |||
926 | if (m_pSortedObjs) | |||
927 | { | |||
928 | m_pSortedObjs->Remove(*pToRemove); | |||
929 | if (!m_pSortedObjs->size()) | |||
930 | { | |||
931 | m_pSortedObjs.reset(); | |||
932 | } | |||
933 | } | |||
934 | ||||
935 | // Notify accessible layout. That's required at this place for | |||
936 | // frames only where the anchor is moved. Creation of new frames | |||
937 | // is additionally handled by the SwFrameNotify class. | |||
938 | if( GetUpper() && | |||
939 | static_cast< SwRootFrame * >( GetUpper() )->IsAnyShellAccessible() && | |||
940 | static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell() ) | |||
941 | { | |||
942 | static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell()->Imp() | |||
943 | ->DisposeAccessibleFrame( pToRemove, true ); | |||
944 | } | |||
945 | ||||
946 | // #i28701# - use new method <SetPageFrame(..)> | |||
947 | pToRemove->SetPageFrame( nullptr ); | |||
948 | } | |||
949 | ||||
950 | void SwPageFrame::MoveFly( SwFlyFrame *pToMove, SwPageFrame *pDest ) | |||
951 | { | |||
952 | // Invalidations | |||
953 | if ( GetUpper() ) | |||
954 | { | |||
955 | static_cast<SwRootFrame*>(GetUpper())->SetIdleFlags(); | |||
956 | if ( !pToMove->IsFlyInContentFrame() && pDest->GetPhyPageNum() < GetPhyPageNum() ) | |||
957 | static_cast<SwRootFrame*>(GetUpper())->SetSuperfluous(); | |||
958 | } | |||
959 | ||||
960 | pDest->InvalidateSpelling(); | |||
961 | pDest->InvalidateSmartTags(); | |||
962 | pDest->InvalidateAutoCompleteWords(); | |||
963 | pDest->InvalidateWordCount(); | |||
964 | ||||
965 | if ( pToMove->IsFlyInContentFrame() ) | |||
966 | { | |||
967 | pDest->InvalidateFlyInCnt(); | |||
968 | return; | |||
969 | } | |||
970 | ||||
971 | // Notify accessible layout. That's required at this place for | |||
972 | // frames only where the anchor is moved. Creation of new frames | |||
973 | // is additionally handled by the SwFrameNotify class. | |||
974 | if( GetUpper() && | |||
975 | static_cast< SwRootFrame * >( GetUpper() )->IsAnyShellAccessible() && | |||
976 | static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell() ) | |||
977 | { | |||
978 | static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell()->Imp() | |||
979 | ->DisposeAccessibleFrame( pToMove, true ); | |||
980 | } | |||
981 | ||||
982 | // The FlyColl might be gone already, because the page's dtor is being executed. | |||
983 | if ( m_pSortedObjs ) | |||
984 | { | |||
985 | m_pSortedObjs->Remove( *pToMove ); | |||
986 | if ( !m_pSortedObjs->size() ) | |||
987 | { | |||
988 | m_pSortedObjs.reset(); | |||
989 | } | |||
990 | } | |||
991 | ||||
992 | // Register | |||
993 | if ( !pDest->GetSortedObjs() ) | |||
994 | pDest->m_pSortedObjs.reset(new SwSortedObjs()); | |||
995 | ||||
996 | const bool bSuccessInserted = pDest->GetSortedObjs()->Insert( *pToMove ); | |||
997 | OSL_ENSURE( bSuccessInserted, "Fly not inserted in Sorted." )do { if (true && (!(bSuccessInserted))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "997" ": "), "%s", "Fly not inserted in Sorted."); } } while (false); | |||
998 | ||||
999 | // #i28701# - use new method <SetPageFrame(..)> | |||
1000 | pToMove->SetPageFrame( pDest ); | |||
1001 | pToMove->InvalidatePage( pDest ); | |||
1002 | pToMove->SetNotifyBack(); | |||
1003 | pDest->InvalidateFlyContent(); | |||
1004 | // #i28701# | |||
1005 | pToMove->UnlockPosition(); | |||
1006 | ||||
1007 | // Notify accessible layout. That's required at this place for | |||
1008 | // frames only where the anchor is moved. Creation of new frames | |||
1009 | // is additionally handled by the SwFrameNotify class. | |||
1010 | if( GetUpper() && | |||
1011 | static_cast< SwRootFrame * >( GetUpper() )->IsAnyShellAccessible() && | |||
1012 | static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell() ) | |||
1013 | { | |||
1014 | static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell()->Imp() | |||
1015 | ->AddAccessibleFrame( pToMove ); | |||
1016 | } | |||
1017 | ||||
1018 | // #i28701# - correction: move lowers of Writer fly frame | |||
1019 | if ( !pToMove->GetDrawObjs() ) | |||
1020 | return; | |||
1021 | ||||
1022 | SwSortedObjs &rObjs = *pToMove->GetDrawObjs(); | |||
1023 | for (SwAnchoredObject* pObj : rObjs) | |||
1024 | { | |||
1025 | if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr ) | |||
1026 | { | |||
1027 | SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pObj); | |||
1028 | if ( pFly->IsFlyFreeFrame() ) | |||
1029 | { | |||
1030 | // #i28701# - use new method <GetPageFrame()> | |||
1031 | SwPageFrame* pPageFrame = pFly->GetPageFrame(); | |||
1032 | if ( pPageFrame ) | |||
1033 | pPageFrame->MoveFly( pFly, pDest ); | |||
1034 | else | |||
1035 | pDest->AppendFlyToPage( pFly ); | |||
1036 | } | |||
1037 | } | |||
1038 | else if ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr ) | |||
1039 | { | |||
1040 | RemoveDrawObjFromPage( *pObj ); | |||
1041 | pDest->AppendDrawObjToPage( *pObj ); | |||
1042 | } | |||
1043 | } | |||
1044 | } | |||
1045 | ||||
1046 | void SwPageFrame::AppendDrawObjToPage( SwAnchoredObject& _rNewObj ) | |||
1047 | { | |||
1048 | if ( dynamic_cast<const SwAnchoredDrawObject*>( &_rNewObj) == nullptr ) | |||
1049 | { | |||
1050 | OSL_FAIL( "SwPageFrame::AppendDrawObjToPage(..) - anchored object of unexpected type -> object not appended" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1050" ": "), "%s", "SwPageFrame::AppendDrawObjToPage(..) - anchored object of unexpected type -> object not appended" ); } } while (false); | |||
1051 | return; | |||
1052 | } | |||
1053 | ||||
1054 | if ( GetUpper() ) | |||
1055 | { | |||
1056 | static_cast<SwRootFrame*>(GetUpper())->InvalidateBrowseWidth(); | |||
1057 | } | |||
1058 | ||||
1059 | assert(_rNewObj.GetAnchorFrame())(static_cast <bool> (_rNewObj.GetAnchorFrame()) ? void ( 0) : __assert_fail ("_rNewObj.GetAnchorFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" , 1059, __extension__ __PRETTY_FUNCTION__)); | |||
1060 | SwFlyFrame* pFlyFrame = const_cast<SwFlyFrame*>(_rNewObj.GetAnchorFrame()->FindFlyFrame()); | |||
1061 | if ( pFlyFrame && | |||
1062 | _rNewObj.GetDrawObj()->GetOrdNum() < pFlyFrame->GetVirtDrawObj()->GetOrdNum() ) | |||
1063 | { | |||
1064 | //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed. | |||
1065 | sal_uInt32 nNewNum = _rNewObj.GetDrawObj()->GetOrdNumDirect(); | |||
1066 | if ( _rNewObj.GetDrawObj()->getSdrPageFromSdrObject() ) | |||
1067 | _rNewObj.DrawObj()->getSdrPageFromSdrObject()->SetObjectOrdNum( pFlyFrame->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum ); | |||
1068 | else | |||
1069 | pFlyFrame->GetVirtDrawObj()->SetOrdNum( nNewNum ); | |||
1070 | } | |||
1071 | ||||
1072 | if ( RndStdIds::FLY_AS_CHAR == _rNewObj.GetFrameFormat().GetAnchor().GetAnchorId() ) | |||
1073 | { | |||
1074 | return; | |||
1075 | } | |||
1076 | ||||
1077 | if ( !m_pSortedObjs ) | |||
1078 | { | |||
1079 | m_pSortedObjs.reset(new SwSortedObjs()); | |||
1080 | } | |||
1081 | if ( !m_pSortedObjs->Insert( _rNewObj ) ) | |||
1082 | { | |||
1083 | OSL_ENSURE( m_pSortedObjs->Contains( _rNewObj ),do { if (true && (!(m_pSortedObjs->Contains( _rNewObj )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1084" ": "), "%s", "Drawing object not appended into list <pSortedObjs>." ); } } while (false) | |||
1084 | "Drawing object not appended into list <pSortedObjs>." )do { if (true && (!(m_pSortedObjs->Contains( _rNewObj )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1084" ": "), "%s", "Drawing object not appended into list <pSortedObjs>." ); } } while (false); | |||
1085 | } | |||
1086 | // #i87493# | |||
1087 | OSL_ENSURE( _rNewObj.GetPageFrame() == nullptr || _rNewObj.GetPageFrame() == this,do { if (true && (!(_rNewObj.GetPageFrame() == nullptr || _rNewObj.GetPageFrame() == this))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1088" ": "), "%s", "<SwPageFrame::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect." ); } } while (false) | |||
1088 | "<SwPageFrame::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect." )do { if (true && (!(_rNewObj.GetPageFrame() == nullptr || _rNewObj.GetPageFrame() == this))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1088" ": "), "%s", "<SwPageFrame::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect." ); } } while (false); | |||
1089 | _rNewObj.SetPageFrame( this ); | |||
1090 | ||||
1091 | // invalidate page in order to force a reformat of object layout of the page. | |||
1092 | InvalidateFlyLayout(); | |||
1093 | } | |||
1094 | ||||
1095 | void SwPageFrame::RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj ) | |||
1096 | { | |||
1097 | if ( dynamic_cast<const SwAnchoredDrawObject*>( &_rToRemoveObj) == nullptr ) | |||
1098 | { | |||
1099 | OSL_FAIL( "SwPageFrame::RemoveDrawObjFromPage(..) - anchored object of unexpected type -> object not removed" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1099" ": "), "%s", "SwPageFrame::RemoveDrawObjFromPage(..) - anchored object of unexpected type -> object not removed" ); } } while (false); | |||
1100 | return; | |||
1101 | } | |||
1102 | ||||
1103 | if ( m_pSortedObjs ) | |||
1104 | { | |||
1105 | m_pSortedObjs->Remove( _rToRemoveObj ); | |||
1106 | if ( !m_pSortedObjs->size() ) | |||
1107 | { | |||
1108 | m_pSortedObjs.reset(); | |||
1109 | } | |||
1110 | if ( GetUpper() ) | |||
1111 | { | |||
1112 | if (RndStdIds::FLY_AS_CHAR != | |||
1113 | _rToRemoveObj.GetFrameFormat().GetAnchor().GetAnchorId()) | |||
1114 | { | |||
1115 | static_cast<SwRootFrame*>(GetUpper())->SetSuperfluous(); | |||
1116 | InvalidatePage(); | |||
1117 | } | |||
1118 | static_cast<SwRootFrame*>(GetUpper())->InvalidateBrowseWidth(); | |||
1119 | } | |||
1120 | } | |||
1121 | _rToRemoveObj.SetPageFrame( nullptr ); | |||
1122 | } | |||
1123 | ||||
1124 | // #i50432# - adjust method description and synopsis. | |||
1125 | void SwPageFrame::PlaceFly( SwFlyFrame* pFly, SwFlyFrameFormat* pFormat ) | |||
1126 | { | |||
1127 | // #i50432# - consider the case that page is an empty page: | |||
1128 | // In this case append the fly frame at the next page | |||
1129 | OSL_ENSURE( !IsEmptyPage() || GetNext(),do { if (true && (!(!IsEmptyPage() || GetNext()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1130" ": "), "%s", "<SwPageFrame::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" ); } } while (false) | |||
1130 | "<SwPageFrame::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" )do { if (true && (!(!IsEmptyPage() || GetNext()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1130" ": "), "%s", "<SwPageFrame::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" ); } } while (false); | |||
1131 | if ( IsEmptyPage() && GetNext() ) | |||
1132 | { | |||
1133 | static_cast<SwPageFrame*>(GetNext())->PlaceFly( pFly, pFormat ); | |||
1134 | } | |||
1135 | else | |||
1136 | { | |||
1137 | // If we received a Fly, we use that one. Otherwise, create a new | |||
1138 | // one using the Format. | |||
1139 | if ( pFly ) | |||
1140 | AppendFly( pFly ); | |||
1141 | else | |||
1142 | { | |||
1143 | OSL_ENSURE( pFormat, ":-( No Format given for Fly." )do { if (true && (!(pFormat))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1143" ": "), "%s", ":-( No Format given for Fly."); } } while (false); | |||
1144 | pFly = new SwFlyLayFrame( pFormat, this, this ); | |||
1145 | AppendFly( pFly ); | |||
1146 | ::RegistFlys( this, pFly ); | |||
1147 | } | |||
1148 | } | |||
1149 | } | |||
1150 | ||||
1151 | // #i18732# - adjustments for following text flow or not | |||
1152 | // AND alignment at 'page areas' for to paragraph/to character anchored objects | |||
1153 | // #i22305# - adjustment for following text flow for to frame anchored objects | |||
1154 | // #i29778# - Because calculating the floating screen object's position | |||
1155 | // (Writer fly frame or drawing object) doesn't perform a calculation on its | |||
1156 | // upper frames and its anchor frame, a calculation of the upper frames in this | |||
1157 | // method is no longer sensible. | |||
1158 | // #i28701# - if document compatibility option 'Consider wrapping style influence | |||
1159 | // on object positioning' is ON, the clip area corresponds to the one as the | |||
1160 | // object doesn't follow the text flow. | |||
1161 | bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, bool bMove ) | |||
1162 | { | |||
1163 | bool bRet = true; | |||
1164 | if ( auto pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(pSdrObj) ) | |||
| ||||
1165 | { | |||
1166 | const SwFlyFrame* pFly = pVirtFlyDrawObj->GetFlyFrame(); | |||
1167 | const bool bFollowTextFlow = pFly->GetFormat()->GetFollowTextFlow().GetValue(); | |||
1168 | // #i28701# | |||
1169 | const bool bConsiderWrapOnObjPos = | |||
1170 | pFly->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION); | |||
1171 | const SwFormatVertOrient &rV = pFly->GetFormat()->GetVertOrient(); | |||
1172 | if( pFly->IsFlyLayFrame() ) | |||
1173 | { | |||
1174 | const SwFrame* pClip; | |||
1175 | // #i22305# | |||
1176 | // #i28701# | |||
1177 | if ( !bFollowTextFlow || bConsiderWrapOnObjPos ) | |||
1178 | { | |||
1179 | pClip = pFly->GetAnchorFrame()->FindPageFrame(); | |||
1180 | } | |||
1181 | else | |||
1182 | { | |||
1183 | pClip = pFly->GetAnchorFrame(); | |||
1184 | } | |||
1185 | ||||
1186 | rRect = pClip->getFrameArea(); | |||
1187 | SwRectFnSet aRectFnSet(pClip); | |||
1188 | ||||
1189 | // vertical clipping: Top and Bottom, also to PrtArea if necessary | |||
1190 | if( rV.GetVertOrient() != text::VertOrientation::NONE && | |||
1191 | rV.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) | |||
1192 | { | |||
1193 | aRectFnSet.SetTop( rRect, aRectFnSet.GetPrtTop(*pClip) ); | |||
1194 | aRectFnSet.SetBottom( rRect, aRectFnSet.GetPrtBottom(*pClip) ); | |||
1195 | } | |||
1196 | // horizontal clipping: Top and Bottom, also to PrtArea if necessary | |||
1197 | const SwFormatHoriOrient &rH = pFly->GetFormat()->GetHoriOrient(); | |||
1198 | if( rH.GetHoriOrient() != text::HoriOrientation::NONE && | |||
1199 | rH.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) | |||
1200 | { | |||
1201 | aRectFnSet.SetLeft( rRect, aRectFnSet.GetPrtLeft(*pClip) ); | |||
1202 | aRectFnSet.SetRight(rRect, aRectFnSet.GetPrtRight(*pClip)); | |||
1203 | } | |||
1204 | } | |||
1205 | else if( pFly->IsFlyAtContentFrame() ) | |||
1206 | { | |||
1207 | // #i18732# - consider following text flow or not | |||
1208 | // AND alignment at 'page areas' | |||
1209 | const SwFrame* pVertPosOrientFrame = pFly->GetVertPosOrientFrame(); | |||
1210 | if ( !pVertPosOrientFrame ) | |||
1211 | { | |||
1212 | OSL_FAIL( "::CalcClipRect(..) - frame, vertical position is oriented at, is missing .")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1212" ": "), "%s", "::CalcClipRect(..) - frame, vertical position is oriented at, is missing ." ); } } while (false); | |||
1213 | pVertPosOrientFrame = pFly->GetAnchorFrame(); | |||
1214 | } | |||
1215 | ||||
1216 | if ( !bFollowTextFlow || bConsiderWrapOnObjPos ) | |||
1217 | { | |||
1218 | const SwLayoutFrame* pClipFrame = pVertPosOrientFrame->FindPageFrame(); | |||
1219 | if (!pClipFrame) | |||
1220 | { | |||
1221 | OSL_FAIL("!pClipFrame: "do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1222" ": "), "%s", "!pClipFrame: " "if you can reproduce this please file a bug" ); } } while (false) | |||
1222 | "if you can reproduce this please file a bug")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1222" ": "), "%s", "!pClipFrame: " "if you can reproduce this please file a bug" ); } } while (false); | |||
1223 | return false; | |||
1224 | } | |||
1225 | rRect = bMove ? pClipFrame->GetUpper()->getFrameArea() | |||
1226 | : pClipFrame->getFrameArea(); | |||
1227 | // #i26945# - consider that a table, during | |||
1228 | // its format, can exceed its upper printing area bottom. | |||
1229 | // Thus, enlarge the clip rectangle, if such a case occurred | |||
1230 | if ( pFly->GetAnchorFrame()->IsInTab() ) | |||
1231 | { | |||
1232 | const SwTabFrame* pTabFrame = const_cast<SwFlyFrame*>(pFly) | |||
1233 | ->GetAnchorFrameContainingAnchPos()->FindTabFrame(); | |||
1234 | SwRect aTmp( pTabFrame->getFramePrintArea() ); | |||
1235 | aTmp += pTabFrame->getFrameArea().Pos(); | |||
1236 | rRect.Union( aTmp ); | |||
1237 | // #i43913# - consider also the cell frame | |||
1238 | const SwFrame* pCellFrame = const_cast<SwFlyFrame*>(pFly) | |||
1239 | ->GetAnchorFrameContainingAnchPos()->GetUpper(); | |||
1240 | while ( pCellFrame && !pCellFrame->IsCellFrame() ) | |||
1241 | { | |||
1242 | pCellFrame = pCellFrame->GetUpper(); | |||
1243 | } | |||
1244 | if ( pCellFrame ) | |||
1245 | { | |||
1246 | aTmp = pCellFrame->getFramePrintArea(); | |||
1247 | aTmp += pCellFrame->getFrameArea().Pos(); | |||
1248 | rRect.Union( aTmp ); | |||
1249 | } | |||
1250 | } | |||
1251 | } | |||
1252 | else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME || | |||
1253 | rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) | |||
1254 | { | |||
1255 | // new class <SwEnvironmentOfAnchoredObject> | |||
1256 | objectpositioning::SwEnvironmentOfAnchoredObject | |||
1257 | aEnvOfObj( bFollowTextFlow ); | |||
1258 | const SwLayoutFrame& rVertClipFrame = | |||
1259 | aEnvOfObj.GetVertEnvironmentLayoutFrame( *pVertPosOrientFrame ); | |||
1260 | if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ) | |||
1261 | { | |||
1262 | rRect = rVertClipFrame.getFrameArea(); | |||
1263 | } | |||
1264 | else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) | |||
1265 | { | |||
1266 | if ( rVertClipFrame.IsPageFrame() ) | |||
1267 | { | |||
1268 | rRect = static_cast<const SwPageFrame&>(rVertClipFrame).PrtWithoutHeaderAndFooter(); | |||
1269 | } | |||
1270 | else | |||
1271 | { | |||
1272 | rRect = rVertClipFrame.getFrameArea(); | |||
1273 | } | |||
1274 | } | |||
1275 | const SwLayoutFrame* pHoriClipFrame = | |||
1276 | pFly->GetAnchorFrame()->FindPageFrame()->GetUpper(); | |||
1277 | SwRectFnSet aRectFnSet(pFly->GetAnchorFrame()); | |||
1278 | aRectFnSet.SetLeft( rRect, aRectFnSet.GetLeft(pHoriClipFrame->getFrameArea()) ); | |||
1279 | aRectFnSet.SetRight(rRect, aRectFnSet.GetRight(pHoriClipFrame->getFrameArea())); | |||
1280 | } | |||
1281 | else | |||
1282 | { | |||
1283 | // #i26945# | |||
1284 | const SwFrame *pClip = | |||
1285 | const_cast<SwFlyFrame*>(pFly)->GetAnchorFrameContainingAnchPos(); | |||
1286 | SwRectFnSet aRectFnSet(pClip); | |||
1287 | const SwLayoutFrame *pUp = pClip->GetUpper(); | |||
1288 | const SwFrame *pCell = pUp->IsCellFrame() ? pUp : nullptr; | |||
1289 | const SwFrameType nType = bMove | |||
1290 | ? SwFrameType::Root | SwFrameType::Fly | SwFrameType::Header | | |||
1291 | SwFrameType::Footer | SwFrameType::Ftn | |||
1292 | : SwFrameType::Body | SwFrameType::Fly | SwFrameType::Header | | |||
1293 | SwFrameType::Footer | SwFrameType::Cell| SwFrameType::Ftn; | |||
1294 | ||||
1295 | while ( !(pUp->GetType() & nType) || pUp->IsColBodyFrame() ) | |||
1296 | { | |||
1297 | pUp = pUp->GetUpper(); | |||
1298 | if ( !pCell && pUp->IsCellFrame() ) | |||
1299 | pCell = pUp; | |||
1300 | } | |||
1301 | if ( bMove && pUp->IsRootFrame() ) | |||
1302 | { | |||
1303 | rRect = pUp->getFramePrintArea(); | |||
1304 | rRect += pUp->getFrameArea().Pos(); | |||
1305 | pUp = nullptr; | |||
1306 | } | |||
1307 | if ( pUp ) | |||
1308 | { | |||
1309 | if ( pUp->GetType() & SwFrameType::Body ) | |||
1310 | { | |||
1311 | const SwPageFrame *pPg; | |||
1312 | if ( pUp->GetUpper() != (pPg = pFly->FindPageFrame()) ) | |||
1313 | pUp = pPg->FindBodyCont(); | |||
1314 | if (pUp) | |||
1315 | { | |||
1316 | rRect = pUp->GetUpper()->getFrameArea(); | |||
1317 | aRectFnSet.SetTop( rRect, aRectFnSet.GetPrtTop(*pUp) ); | |||
1318 | aRectFnSet.SetBottom(rRect, aRectFnSet.GetPrtBottom(*pUp)); | |||
1319 | } | |||
1320 | } | |||
1321 | else | |||
1322 | { | |||
1323 | if( ( pUp->GetType() & (SwFrameType::Fly | SwFrameType::Ftn ) ) && | |||
1324 | !pUp->getFrameArea().IsInside( pFly->getFrameArea().Pos() ) ) | |||
1325 | { | |||
1326 | if( pUp->IsFlyFrame() ) | |||
1327 | { | |||
1328 | const SwFlyFrame *pTmpFly = static_cast<const SwFlyFrame*>(pUp); | |||
1329 | while( pTmpFly->GetNextLink() ) | |||
1330 | { | |||
1331 | pTmpFly = pTmpFly->GetNextLink(); | |||
1332 | if( pTmpFly->getFrameArea().IsInside( pFly->getFrameArea().Pos() ) ) | |||
1333 | break; | |||
1334 | } | |||
1335 | pUp = pTmpFly; | |||
1336 | } | |||
1337 | else if( pUp->IsInFootnote() ) | |||
1338 | { | |||
1339 | const SwFootnoteFrame *pTmp = pUp->FindFootnoteFrame(); | |||
1340 | while( pTmp->GetFollow() ) | |||
1341 | { | |||
1342 | pTmp = pTmp->GetFollow(); | |||
1343 | if( pTmp->getFrameArea().IsInside( pFly->getFrameArea().Pos() ) ) | |||
1344 | break; | |||
1345 | } | |||
1346 | pUp = pTmp; | |||
1347 | } | |||
1348 | } | |||
1349 | rRect = pUp->getFramePrintArea(); | |||
1350 | rRect.Pos() += pUp->getFrameArea().Pos(); | |||
1351 | if ( pUp->GetType() & (SwFrameType::Header | SwFrameType::Footer) ) | |||
1352 | { | |||
1353 | rRect.Left ( pUp->GetUpper()->getFrameArea().Left() ); | |||
1354 | rRect.Width( pUp->GetUpper()->getFrameArea().Width()); | |||
1355 | } | |||
1356 | else if ( pUp->IsCellFrame() ) //MA_FLY_HEIGHT | |||
1357 | { | |||
1358 | const SwFrame *pTab = pUp->FindTabFrame(); | |||
1359 | aRectFnSet.SetBottom( rRect, aRectFnSet.GetPrtBottom(*pTab->GetUpper()) ); | |||
1360 | // expand to left and right cell border | |||
1361 | rRect.Left ( pUp->getFrameArea().Left() ); | |||
1362 | rRect.Width( pUp->getFrameArea().Width() ); | |||
1363 | } | |||
1364 | } | |||
1365 | } | |||
1366 | if ( pCell ) | |||
1367 | { | |||
1368 | // CellFrames might also sit in unallowed areas. In this case, | |||
1369 | // the Fly is allowed to do so as well | |||
1370 | SwRect aTmp( pCell->getFramePrintArea() ); | |||
1371 | aTmp += pCell->getFrameArea().Pos(); | |||
1372 | rRect.Union( aTmp ); | |||
1373 | } | |||
1374 | } | |||
1375 | } | |||
1376 | else | |||
1377 | { | |||
1378 | const SwFrame *pUp = pFly->GetAnchorFrame()->GetUpper(); | |||
1379 | SwRectFnSet aRectFnSet(pFly->GetAnchorFrame()); | |||
1380 | while( pUp->IsColumnFrame() || pUp->IsSctFrame() || pUp->IsColBodyFrame()) | |||
1381 | pUp = pUp->GetUpper(); | |||
1382 | rRect = pUp->getFrameArea(); | |||
1383 | if( !pUp->IsBodyFrame() ) | |||
1384 | { | |||
1385 | rRect += pUp->getFramePrintArea().Pos(); | |||
1386 | rRect.SSize( pUp->getFramePrintArea().SSize() ); | |||
1387 | if ( pUp->IsCellFrame() ) | |||
1388 | { | |||
1389 | const SwFrame *pTab = pUp->FindTabFrame(); | |||
1390 | aRectFnSet.SetBottom( rRect, aRectFnSet.GetPrtBottom(*pTab->GetUpper()) ); | |||
1391 | } | |||
1392 | } | |||
1393 | else if ( pUp->GetUpper()->IsPageFrame() ) | |||
1394 | { | |||
1395 | // Objects anchored as character may exceed right margin | |||
1396 | // of body frame: | |||
1397 | aRectFnSet.SetRight( rRect, aRectFnSet.GetRight(pUp->GetUpper()->getFrameArea()) ); | |||
1398 | } | |||
1399 | long nHeight = (9*aRectFnSet.GetHeight(rRect))/10; | |||
1400 | long nTop; | |||
1401 | const SwFormat *pFormat = GetUserCall(pSdrObj)->GetFormat(); | |||
1402 | const SvxULSpaceItem &rUL = pFormat->GetULSpace(); | |||
1403 | if( bMove ) | |||
1404 | { | |||
1405 | nTop = aRectFnSet.IsVert() ? static_cast<const SwFlyInContentFrame*>(pFly)->GetRefPoint().X() : | |||
1406 | static_cast<const SwFlyInContentFrame*>(pFly)->GetRefPoint().Y(); | |||
1407 | nTop = aRectFnSet.YInc( nTop, -nHeight ); | |||
1408 | long nWidth = aRectFnSet.GetWidth(pFly->getFrameArea()); | |||
1409 | aRectFnSet.SetLeftAndWidth( rRect, aRectFnSet.IsVert() ? | |||
1410 | static_cast<const SwFlyInContentFrame*>(pFly)->GetRefPoint().Y() : | |||
1411 | static_cast<const SwFlyInContentFrame*>(pFly)->GetRefPoint().X(), nWidth ); | |||
1412 | nHeight = 2*nHeight - rUL.GetLower() - rUL.GetUpper(); | |||
1413 | } | |||
1414 | else | |||
1415 | { | |||
1416 | nTop = aRectFnSet.YInc( aRectFnSet.GetBottom(pFly->getFrameArea()), | |||
1417 | rUL.GetLower() - nHeight ); | |||
1418 | nHeight = 2*nHeight - aRectFnSet.GetHeight(pFly->getFrameArea()) | |||
1419 | - rUL.GetLower() - rUL.GetUpper(); | |||
1420 | } | |||
1421 | aRectFnSet.SetTopAndHeight( rRect, nTop, nHeight ); | |||
1422 | } | |||
1423 | } | |||
1424 | else | |||
1425 | { | |||
1426 | const SwDrawContact *pC = static_cast<const SwDrawContact*>(GetUserCall(pSdrObj)); | |||
1427 | const SwFrameFormat *pFormat = pC->GetFormat(); | |||
1428 | const SwFormatAnchor &rAnch = pFormat->GetAnchor(); | |||
1429 | if ( RndStdIds::FLY_AS_CHAR == rAnch.GetAnchorId() ) | |||
1430 | { | |||
1431 | const SwFrame* pAnchorFrame = pC->GetAnchorFrame( pSdrObj ); | |||
1432 | if( !pAnchorFrame ) | |||
1433 | { | |||
1434 | OSL_FAIL( "<::CalcClipRect(..)> - missing anchor frame." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/flylay.cxx" ":" "1434" ": "), "%s", "<::CalcClipRect(..)> - missing anchor frame." ); } } while (false); | |||
1435 | const_cast<SwDrawContact*>(pC)->ConnectToLayout(); | |||
1436 | pAnchorFrame = pC->GetAnchorFrame(); | |||
1437 | } | |||
1438 | const SwFrame* pUp = pAnchorFrame->GetUpper(); | |||
1439 | rRect = pUp->getFramePrintArea(); | |||
1440 | rRect += pUp->getFrameArea().Pos(); | |||
1441 | SwRectFnSet aRectFnSet(pAnchorFrame); | |||
1442 | long nHeight = (9*aRectFnSet.GetHeight(rRect))/10; | |||
1443 | long nTop; | |||
1444 | const SvxULSpaceItem &rUL = pFormat->GetULSpace(); | |||
1445 | SwRect aSnapRect( pSdrObj->GetSnapRect() ); | |||
| ||||
1446 | long nTmpH = 0; | |||
1447 | if( bMove ) | |||
1448 | { | |||
1449 | nTop = aRectFnSet.YInc( aRectFnSet.IsVert() ? pSdrObj->GetAnchorPos().X() : | |||
1450 | pSdrObj->GetAnchorPos().Y(), -nHeight ); | |||
1451 | long nWidth = aRectFnSet.GetWidth(aSnapRect); | |||
1452 | aRectFnSet.SetLeftAndWidth( rRect, aRectFnSet.IsVert() ? | |||
1453 | pSdrObj->GetAnchorPos().Y() : | |||
1454 | pSdrObj->GetAnchorPos().X(), nWidth ); | |||
1455 | } | |||
1456 | else | |||
1457 | { | |||
1458 | // #i26791# - value of <nTmpH> is needed to | |||
1459 | // calculate value of <nTop>. | |||
1460 | nTmpH = aRectFnSet.IsVert() ? pSdrObj->GetCurrentBoundRect().GetWidth() : | |||
1461 | pSdrObj->GetCurrentBoundRect().GetHeight(); | |||
1462 | nTop = aRectFnSet.YInc( aRectFnSet.GetTop(aSnapRect), | |||
1463 | rUL.GetLower() + nTmpH - nHeight ); | |||
1464 | } | |||
1465 | nHeight = 2*nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper(); | |||
1466 | aRectFnSet.SetTopAndHeight( rRect, nTop, nHeight ); | |||
1467 | } | |||
1468 | else | |||
1469 | { | |||
1470 | // restrict clip rectangle for drawing | |||
1471 | // objects in header/footer to the page frame. | |||
1472 | // #i26791# | |||
1473 | const SwFrame* pAnchorFrame = pC->GetAnchorFrame( pSdrObj ); | |||
1474 | if ( pAnchorFrame && pAnchorFrame->FindFooterOrHeader() ) | |||
1475 | { | |||
1476 | // clip frame is the page frame the header/footer is on. | |||
1477 | const SwFrame* pClipFrame = pAnchorFrame->FindPageFrame(); | |||
1478 | rRect = pClipFrame->getFrameArea(); | |||
1479 | } | |||
1480 | else | |||
1481 | { | |||
1482 | bRet = false; | |||
1483 | } | |||
1484 | } | |||
1485 | } | |||
1486 | return bRet; | |||
1487 | } | |||
1488 | ||||
1489 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |