1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include <anchoreddrawobject.hxx>
27 #include <svx/svdobj.hxx>
28 #include <dcontact.hxx>
29 #include <rootfrm.hxx>
30 #include <pagefrm.hxx>
31 #include <cntfrm.hxx>
32 #include <doc.hxx>
33 #include <tocntntanchoredobjectposition.hxx>
34 #include <tolayoutanchoredobjectposition.hxx>
35 #include <frmtool.hxx>
36 #include <fmtornt.hxx>
37 // --> OD 2004-08-12 #i32795#
38 #include <txtfrm.hxx>
39 // <--
40 // --> OD 2004-08-12 #i32795#
41 // template class <std::vector>
42 #include <vector>
43 // <--
44 
45 // --> OD 2004-08-10 #i28749#
46 #include <com/sun/star/text/PositionLayoutDir.hpp>
47 // <--
48 // --> OD 2005-03-09 #i44559#
49 #include <ndtxt.hxx>
50 // <--
51 
52 using namespace ::com::sun::star;
53 
54 // ============================================================================
55 // helper class for correct notification due to the positioning of
56 // the anchored drawing object
57 // ============================================================================
58 class SwPosNotify
59 {
60     private:
61         SwAnchoredDrawObject* mpAnchoredDrawObj;
62         SwRect maOldObjRect;
63         SwPageFrm* mpOldPageFrm;
64 
65     public:
66         SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj );
67         ~SwPosNotify();
68         // --> OD 2004-08-12 #i32795#
69         Point LastObjPos() const;
70         // <--
71 };
72 
SwPosNotify(SwAnchoredDrawObject * _pAnchoredDrawObj)73 SwPosNotify::SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj ) :
74     mpAnchoredDrawObj( _pAnchoredDrawObj )
75 {
76     maOldObjRect = mpAnchoredDrawObj->GetObjRect();
77     // --> OD 2004-10-20 #i35640# - determine correct page frame
78     mpOldPageFrm = mpAnchoredDrawObj->GetPageFrm();
79     // <--
80 }
81 
~SwPosNotify()82 SwPosNotify::~SwPosNotify()
83 {
84     if ( maOldObjRect != mpAnchoredDrawObj->GetObjRect() )
85     {
86         if( maOldObjRect.HasArea() && mpOldPageFrm )
87         {
88             mpAnchoredDrawObj->NotifyBackground( mpOldPageFrm, maOldObjRect,
89                                                  PREP_FLY_LEAVE );
90         }
91         SwRect aNewObjRect( mpAnchoredDrawObj->GetObjRect() );
92         if( aNewObjRect.HasArea() )
93         {
94             // --> OD 2004-10-20 #i35640# - determine correct page frame
95             SwPageFrm* pNewPageFrm = mpAnchoredDrawObj->GetPageFrm();
96             // <--
97             if( pNewPageFrm )
98                 mpAnchoredDrawObj->NotifyBackground( pNewPageFrm, aNewObjRect,
99                                                      PREP_FLY_ARRIVE );
100         }
101 
102         ::ClrContourCache( mpAnchoredDrawObj->GetDrawObj() );
103 
104         // --> OD 2004-10-20 #i35640# - additional notify anchor text frame
105         // Needed for negative positioned drawing objects
106         // --> OD 2005-03-01 #i43255# - refine condition to avoid unneeded
107         // invalidations: anchored object had to be on the page of its anchor
108         // text frame.
109         if ( mpAnchoredDrawObj->GetAnchorFrm()->IsTxtFrm() &&
110              mpOldPageFrm == mpAnchoredDrawObj->GetAnchorFrm()->FindPageFrm() )
111         {
112             mpAnchoredDrawObj->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
113         }
114         // <--
115 
116         // indicate a restart of the layout process
117         mpAnchoredDrawObj->SetRestartLayoutProcess( true );
118     }
119     else
120     {
121         // lock position
122         mpAnchoredDrawObj->LockPosition();
123 
124         if ( !mpAnchoredDrawObj->ConsiderForTextWrap() )
125         {
126             // indicate that object has to be considered for text wrap
127             mpAnchoredDrawObj->SetConsiderForTextWrap( true );
128             // invalidate 'background' in order to allow its 'background'
129             // to wrap around it.
130             mpAnchoredDrawObj->NotifyBackground( mpAnchoredDrawObj->GetPageFrm(),
131                                     mpAnchoredDrawObj->GetObjRectWithSpaces(),
132                                     PREP_FLY_ARRIVE );
133             // invalidate position of anchor frame in order to force
134             // a re-format of the anchor frame, which also causes a
135             // re-format of the invalid previous frames of the anchor frame.
136             mpAnchoredDrawObj->AnchorFrm()->InvalidatePos();
137         }
138     }
139 }
140 
141 // --> OD 2004-08-12 #i32795#
LastObjPos() const142 Point SwPosNotify::LastObjPos() const
143 {
144     return maOldObjRect.Pos();
145 }
146 //<--
147 
148 // ============================================================================
149 // OD 2004-08-12 #i32795#
150 // helper class for oscillation control on object positioning
151 // ============================================================================
152 class SwObjPosOscillationControl
153 {
154     private:
155         sal_uInt8 mnPosStackSize;
156 
157         const SwAnchoredDrawObject* mpAnchoredDrawObj;
158 
159         std::vector<Point*> maObjPositions;
160 
161     public:
162         SwObjPosOscillationControl( const SwAnchoredDrawObject& _rAnchoredDrawObj );
163         ~SwObjPosOscillationControl();
164 
165         bool OscillationDetected();
166 };
167 
SwObjPosOscillationControl(const SwAnchoredDrawObject & _rAnchoredDrawObj)168 SwObjPosOscillationControl::SwObjPosOscillationControl(
169                                 const SwAnchoredDrawObject& _rAnchoredDrawObj )
170     : mnPosStackSize( 20 ),
171       mpAnchoredDrawObj( &_rAnchoredDrawObj )
172 {
173 }
174 
~SwObjPosOscillationControl()175 SwObjPosOscillationControl::~SwObjPosOscillationControl()
176 {
177     while ( !maObjPositions.empty() )
178     {
179         Point* pPos = maObjPositions.back();
180         delete pPos;
181 
182         maObjPositions.pop_back();
183     }
184 }
185 
OscillationDetected()186 bool SwObjPosOscillationControl::OscillationDetected()
187 {
188     bool bOscillationDetected = false;
189 
190     if ( maObjPositions.size() == mnPosStackSize )
191     {
192         // position stack is full -> oscillation
193         bOscillationDetected = true;
194     }
195     else
196     {
197         Point* pNewObjPos = new Point( mpAnchoredDrawObj->GetObjRect().Pos() );
198         for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin();
199               aObjPosIter != maObjPositions.end();
200               ++aObjPosIter )
201         {
202             if ( *(pNewObjPos) == *(*aObjPosIter) )
203             {
204                 // position already occurred -> oscillation
205                 bOscillationDetected = true;
206                 delete pNewObjPos;
207                 break;
208             }
209         }
210         if ( !bOscillationDetected )
211         {
212             maObjPositions.push_back( pNewObjPos );
213         }
214     }
215 
216     return bOscillationDetected;
217 }
218 
219 // ============================================================================
220 // implementation of class <SwAnchoredDrawObject>
221 // ============================================================================
222 TYPEINIT1(SwAnchoredDrawObject,SwAnchoredObject);
223 
SwAnchoredDrawObject()224 SwAnchoredDrawObject::SwAnchoredDrawObject() :
225     SwAnchoredObject(),
226     mbValidPos( false ),
227     // --> OD 2004-09-29 #i34748#
228     mpLastObjRect( 0L ),
229     // <--
230     mbNotYetAttachedToAnchorFrame( true ),
231     // --> OD 2004-08-09 #i28749#
232     mbNotYetPositioned( true ),
233     // <--
234     // --> OD 2006-03-17 #i62875#
235     mbCaptureAfterLayoutDirChange( false )
236     // <--
237 {
238 }
239 
~SwAnchoredDrawObject()240 SwAnchoredDrawObject::~SwAnchoredDrawObject()
241 {
242     // --> OD 2004-11-03 - follow-up of #i34748#
243     delete mpLastObjRect;
244     // <--
245 }
246 
247 // --> OD 2006-03-17 #i62875#
UpdateLayoutDir()248 void SwAnchoredDrawObject::UpdateLayoutDir()
249 {
250     SwFrmFmt::tLayoutDir nOldLayoutDir( GetFrmFmt().GetLayoutDir() );
251 
252     SwAnchoredObject::UpdateLayoutDir();
253 
254     if ( !NotYetPositioned() &&
255          GetFrmFmt().GetLayoutDir() != nOldLayoutDir &&
256          GetFrmFmt().GetDoc()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) &&
257          !IsOutsidePage() )
258     {
259         mbCaptureAfterLayoutDirChange = true;
260     }
261 }
262 // <--
263 
264 // --> OD 2006-03-17 #i62875#
IsOutsidePage() const265 bool SwAnchoredDrawObject::IsOutsidePage() const
266 {
267     bool bOutsidePage( false );
268 
269     if ( !NotYetPositioned() && GetPageFrm() )
270     {
271         SwRect aTmpRect( GetObjRect() );
272         bOutsidePage =
273             ( aTmpRect.Intersection( GetPageFrm()->Frm() ) != GetObjRect() );
274     }
275 
276     return bOutsidePage;
277 }
278 // <--
279 
280 // =============================================================================
281 // OD 2004-03-25 #i26791# - implementation of pure virtual method declared in
282 // base class <SwAnchoredObject>
283 // =============================================================================
MakeObjPos()284 void SwAnchoredDrawObject::MakeObjPos()
285 {
286     if ( IsPositioningInProgress() )
287     {
288         // nothind to do - positioning already in progress
289         return;
290     }
291 
292     if ( mbValidPos )
293     {
294         // nothing to do - position is valid
295         return;
296     }
297 
298     // --> OD 2004-08-09 #i28749# - anchored drawing object has to be attached
299     // to anchor frame
300     if ( mbNotYetAttachedToAnchorFrame )
301     {
302         ASSERT( false,
303                 "<SwAnchoredDrawObject::MakeObjPos() - drawing object not yet attached to anchor frame -> no positioning" );
304         return;
305     }
306 
307     SwDrawContact* pDrawContact =
308                         static_cast<SwDrawContact*>(::GetUserCall( GetDrawObj() ));
309 
310     // --> OD 2004-08-09 #i28749# - if anchored drawing object hasn't been yet
311     // positioned, convert its positioning attributes, if its positioning
312     // attributes are given in horizontal left-to-right layout.
313     // --> OD 2004-10-25 #i36010# - Note: horizontal left-to-right layout is made
314     // the default layout direction for <SwDrawFrmFmt> instances. Thus, it has
315     // to be adjusted manually, if no adjustment of the positioning attributes
316     // have to be performed here.
317     // --> OD 2004-11-17 #i35635# - additionally move drawing object to the
318     // visible layer.
319     if ( mbNotYetPositioned )
320     {
321         // --> OD 2004-11-17 #i35635#
322         pDrawContact->MoveObjToVisibleLayer( DrawObj() );
323         // <--
324         // --> OD 2004-09-29 #117975# - perform conversion of positioning
325         // attributes only for 'master' drawing objects
326         // --> OD 2005-03-11 #i44334#, #i44681# - check, if positioning
327         // attributes already have been set.
328         if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
329              !static_cast<SwDrawFrmFmt&>(GetFrmFmt()).IsPosAttrSet() )
330         {
331             _SetPositioningAttr();
332         }
333         // <--
334         // --> OD 2006-05-24 #b6418964#
335         // - reset internal flag after all needed actions are performed to
336         //   avoid callbacks from drawing layer
337         mbNotYetPositioned = false;
338         // <--
339     }
340     // <--
341 
342     // indicate that positioning is in progress
343     {
344         SwObjPositioningInProgress aObjPosInProgress( *this );
345 
346         // determine relative position of drawing object and set it
347         switch ( pDrawContact->GetAnchorId() )
348         {
349             case FLY_AS_CHAR:
350             {
351                 // indicate that position will be valid after positioning is performed
352                 mbValidPos = true;
353                 // nothing to do, because as-character anchored objects are positioned
354                 // during the format of its anchor frame - see <SwFlyCntPortion::SetBase(..)>
355             }
356             break;
357             case FLY_AT_PARA:
358             case FLY_AT_CHAR:
359             {
360                 // --> OD 2004-08-12 #i32795# - move intrinsic positioning to
361                 // helper method <_MakeObjPosAnchoredAtPara()>
362                 _MakeObjPosAnchoredAtPara();
363             }
364             break;
365             case FLY_AT_PAGE:
366             case FLY_AT_FLY:
367             {
368                 // --> OD 2004-08-12 #i32795# - move intrinsic positioning to
369                 // helper method <_MakeObjPosAnchoredAtLayout()>
370                 _MakeObjPosAnchoredAtLayout();
371             }
372             break;
373             default:
374             {
375                 ASSERT( false, "<SwAnchoredDrawObject::MakeObjPos()> - unknown anchor type - please inform OD." );
376             }
377         }
378 
379         // keep, current object rectangle
380         // --> OD 2004-09-29 #i34748# - use new method <SetLastObjRect(..)>
381         SetLastObjRect( GetObjRect().SVRect() );
382         // <--
383 
384         // Assure for 'master' drawing object, that it's registered at the correct page.
385         // Perform check not for as-character anchored drawing objects and only if
386         // the anchor frame is valid.
387         if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
388              !pDrawContact->ObjAnchoredAsChar() &&
389              GetAnchorFrm()->IsValid() )
390         {
391             pDrawContact->ChkPage();
392         }
393     }
394 
395     // --> OD 2006-03-17 #i62875#
396     if ( mbCaptureAfterLayoutDirChange &&
397          GetPageFrm() )
398     {
399         SwRect aPageRect( GetPageFrm()->Frm() );
400         SwRect aObjRect( GetObjRect() );
401         if ( aObjRect.Right() >= aPageRect.Right() + 10 )
402         {
403             Size aSize( aPageRect.Right() - aObjRect.Right(), 0 );
404             DrawObj()->Move( aSize );
405             aObjRect = GetObjRect();
406         }
407 
408         if ( aObjRect.Left() + 10 <= aPageRect.Left() )
409         {
410             Size aSize( aPageRect.Left() - aObjRect.Left(), 0 );
411             DrawObj()->Move( aSize );
412         }
413 
414         mbCaptureAfterLayoutDirChange = false;
415     }
416     // <--
417 }
418 
419 /** method for the intrinsic positioning of a at-paragraph|at-character
420     anchored drawing object
421 
422     OD 2004-08-12 #i32795# - helper method for method <MakeObjPos>
423 
424     @author OD
425 */
_MakeObjPosAnchoredAtPara()426 void SwAnchoredDrawObject::_MakeObjPosAnchoredAtPara()
427 {
428     // --> OD 2004-08-12 #i32795# - adopt positioning algorithm from Writer
429     // fly frames, which are anchored at paragraph|at character
430 
431     // Determine, if anchor frame can/has to be formatted.
432     // If yes, after each object positioning the anchor frame is formatted.
433     // If after the anchor frame format the object position isn't valid, the
434     // object is positioned again.
435     // --> OD 2005-02-22 #i43255# - refine condition: anchor frame format not
436     // allowed, if another anchored object, has to be consider its wrap influence
437     // --> OD 2005-06-07 #i50356# - format anchor frame containing the anchor
438     // position. E.g., for at-character anchored object this can be the follow
439     // frame of the anchor frame, which contains the anchor character.
440     const bool bFormatAnchor =
441             !static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() &&
442             !ConsiderObjWrapInfluenceOnObjPos() &&
443             !ConsiderObjWrapInfluenceOfOtherObjs();
444     // <--
445 
446     if ( bFormatAnchor )
447     {
448         // --> OD 2005-06-07 #i50356#
449         GetAnchorFrmContainingAnchPos()->Calc();
450         // <--
451     }
452 
453     bool bOscillationDetected = false;
454     SwObjPosOscillationControl aObjPosOscCtrl( *this );
455     // --> OD 2004-08-25 #i3317# - boolean, to apply temporarly the
456     // 'straightforward positioning process' for the frame due to its
457     // overlapping with a previous column.
458     bool bConsiderWrapInfluenceDueToOverlapPrevCol( false );
459     // <--
460     do {
461         // indicate that position will be valid after positioning is performed
462         mbValidPos = true;
463 
464         // --> OD 2004-10-20 #i35640# - correct scope for <SwPosNotify> instance
465         {
466             // create instance of <SwPosNotify> for correct notification
467             SwPosNotify aPosNotify( this );
468 
469             // determine and set position
470             objectpositioning::SwToCntntAnchoredObjectPosition
471                     aObjPositioning( *DrawObj() );
472             aObjPositioning.CalcPosition();
473 
474             // get further needed results of the positioning algorithm
475             SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() );
476             _SetDrawObjAnchor();
477 
478             // check for object position oscillation, if position has changed.
479             if ( GetObjRect().Pos() != aPosNotify.LastObjPos() )
480             {
481                 bOscillationDetected = aObjPosOscCtrl.OscillationDetected();
482             }
483         }
484         // <--
485         // format anchor frame, if requested.
486         // Note: the format of the anchor frame can cause the object position
487         // to be invalid.
488         if ( bFormatAnchor )
489         {
490             // --> OD 2005-06-07 #i50356#
491             GetAnchorFrmContainingAnchPos()->Calc();
492             // <--
493         }
494 
495         // --> OD 2004-08-25 #i3317#
496         if ( !ConsiderObjWrapInfluenceOnObjPos() &&
497              OverlapsPrevColumn() )
498         {
499             bConsiderWrapInfluenceDueToOverlapPrevCol = true;
500         }
501         // <--
502     } while ( !mbValidPos && !bOscillationDetected &&
503               !bConsiderWrapInfluenceDueToOverlapPrevCol );
504 
505     // --> OD 2004-08-25 #i3317# - consider a detected oscillation and overlapping
506     // with previous column.
507     // temporarly consider the anchored objects wrapping style influence
508     if ( bOscillationDetected || bConsiderWrapInfluenceDueToOverlapPrevCol )
509     {
510         SetTmpConsiderWrapInfluence( true );
511         SetRestartLayoutProcess( true );
512     }
513     // <--
514 }
515 
516 /** method for the intrinsic positioning of a at-page|at-frame anchored
517     drawing object
518 
519     OD 2004-08-12 #i32795# - helper method for method <MakeObjPos>
520 
521     @author OD
522 */
_MakeObjPosAnchoredAtLayout()523 void SwAnchoredDrawObject::_MakeObjPosAnchoredAtLayout()
524 {
525     // indicate that position will be valid after positioning is performed
526     mbValidPos = true;
527 
528     // create instance of <SwPosNotify> for correct notification
529     SwPosNotify aPosNotify( this );
530 
531     // determine position
532     objectpositioning::SwToLayoutAnchoredObjectPosition
533             aObjPositioning( *DrawObj() );
534     aObjPositioning.CalcPosition();
535 
536     // set position
537 
538     // --> OD 2004-07-29 #i31698#
539     // --> OD 2004-10-18 #i34995# - setting anchor position needed for filters,
540     // especially for the xml-filter to the OpenOffice.org file format
541     {
542         const Point aNewAnchorPos =
543                     GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
544         DrawObj()->SetAnchorPos( aNewAnchorPos );
545         // --> OD 2006-10-05 #i70122# - missing invalidation
546         InvalidateObjRectWithSpaces();
547         // <--
548     }
549     // <--
550     SetCurrRelPos( aObjPositioning.GetRelPos() );
551     const SwFrm* pAnchorFrm = GetAnchorFrm();
552     SWRECTFN( pAnchorFrm );
553     const Point aAnchPos( (pAnchorFrm->Frm().*fnRect->fnGetPos)() );
554     SetObjLeft( aAnchPos.X() + GetCurrRelPos().X() );
555     SetObjTop( aAnchPos.Y() + GetCurrRelPos().Y() );
556     // <--
557 }
558 
_SetDrawObjAnchor()559 void SwAnchoredDrawObject::_SetDrawObjAnchor()
560 {
561     // new anchor position
562     // --> OD 2004-07-29 #i31698# -
563     Point aNewAnchorPos =
564                 GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
565     Point aCurrAnchorPos = GetDrawObj()->GetAnchorPos();
566     if ( aNewAnchorPos != aCurrAnchorPos )
567     {
568         // determine movement to be applied after setting the new anchor position
569         Size aMove( aCurrAnchorPos.X() - aNewAnchorPos.X(),
570                     aCurrAnchorPos.Y() - aNewAnchorPos.Y() );
571         // set new anchor position
572         DrawObj()->SetAnchorPos( aNewAnchorPos );
573         // correct object position, caused by setting new anchor position
574         DrawObj()->Move( aMove );
575         // --> OD 2006-10-05 #i70122# - missing invalidation
576         InvalidateObjRectWithSpaces();
577         // <--
578     }
579 }
580 
581 /** method to invalidate the given page frame
582 
583     OD 2004-07-02 #i28701#
584 
585     @author OD
586 */
_InvalidatePage(SwPageFrm * _pPageFrm)587 void SwAnchoredDrawObject::_InvalidatePage( SwPageFrm* _pPageFrm )
588 {
589     if ( _pPageFrm && !_pPageFrm->GetFmt()->GetDoc()->IsInDtor() )
590     {
591         if ( _pPageFrm->GetUpper() )
592         {
593             // --> OD 2004-11-11 #i35007# - correct invalidation for as-character
594             // anchored objects.
595             if ( GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR )
596             {
597                 _pPageFrm->InvalidateFlyInCnt();
598             }
599             else
600             {
601                 _pPageFrm->InvalidateFlyLayout();
602             }
603             // <--
604 
605             SwRootFrm* pRootFrm = static_cast<SwRootFrm*>(_pPageFrm->GetUpper());
606             pRootFrm->DisallowTurbo();
607             if ( pRootFrm->GetTurbo() )
608             {
609                 const SwCntntFrm* pTmpFrm = pRootFrm->GetTurbo();
610                 pRootFrm->ResetTurbo();
611                 pTmpFrm->InvalidatePage();
612             }
613             pRootFrm->SetIdleFlags();
614         }
615     }
616 }
617 
InvalidateObjPos()618 void SwAnchoredDrawObject::InvalidateObjPos()
619 {
620     // --> OD 2004-07-01 #i28701# - check, if invalidation is allowed
621     if ( mbValidPos &&
622          InvalidationOfPosAllowed() )
623     {
624         mbValidPos = false;
625         // --> OD 2006-08-10 #i68520#
626         InvalidateObjRectWithSpaces();
627         // <--
628 
629         // --> OD 2005-03-08 #i44339# - check, if anchor frame exists.
630         if ( GetAnchorFrm() )
631         {
632             // --> OD 2004-11-22 #118547# - notify anchor frame of as-character
633             // anchored object, because its positioned by the format of its anchor frame.
634             // --> OD 2005-03-09 #i44559# - assure, that text hint is already
635             // existing in the text frame
636             if ( GetAnchorFrm()->ISA(SwTxtFrm) &&
637                  (GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
638             {
639                 SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) );
640                 if ( pAnchorTxtFrm->GetTxtNode()->GetpSwpHints() &&
641                      pAnchorTxtFrm->CalcFlyPos( &GetFrmFmt() ) != STRING_LEN )
642                 {
643                     AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, &GetFrmFmt() );
644                 }
645             }
646             // <--
647 
648             SwPageFrm* pPageFrm = AnchorFrm()->FindPageFrm();
649             _InvalidatePage( pPageFrm );
650 
651             // --> OD 2004-08-12 #i32270# - also invalidate page frame, at which the
652             // drawing object is registered at.
653             SwPageFrm* pPageFrmRegisteredAt = GetPageFrm();
654             if ( pPageFrmRegisteredAt &&
655                  pPageFrmRegisteredAt != pPageFrm )
656             {
657                 _InvalidatePage( pPageFrmRegisteredAt );
658             }
659             // <--
660             // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
661             // is replaced by method <FindPageFrmOfAnchor()>. It's return value
662             // have to be checked.
663             SwPageFrm* pPageFrmOfAnchor = FindPageFrmOfAnchor();
664             if ( pPageFrmOfAnchor &&
665                  pPageFrmOfAnchor != pPageFrm &&
666                  pPageFrmOfAnchor != pPageFrmRegisteredAt )
667             // <--
668             {
669                 _InvalidatePage( pPageFrmOfAnchor );
670             }
671         }
672         // <--
673     }
674 }
675 
GetFrmFmt()676 SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt()
677 {
678     ASSERT( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
679             "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
680     return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
681 }
GetFrmFmt() const682 const SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt() const
683 {
684     ASSERT( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
685             "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
686     return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
687 }
688 
GetObjRect() const689 const SwRect SwAnchoredDrawObject::GetObjRect() const
690 {
691     // use geometry of drawing object
692     //return GetDrawObj()->GetCurrentBoundRect();
693     return GetDrawObj()->GetSnapRect();
694 }
695 
696 // --> OD 2006-10-05 #i70122#
GetObjBoundRect() const697 const SwRect SwAnchoredDrawObject::GetObjBoundRect() const
698 {
699     return GetDrawObj()->GetCurrentBoundRect();
700 }
701 // <--
702 
703 // --> OD 2006-08-10 #i68520#
_SetObjTop(const SwTwips _nTop)704 bool SwAnchoredDrawObject::_SetObjTop( const SwTwips _nTop )
705 {
706     SwTwips nDiff = _nTop - GetObjRect().Top();
707     DrawObj()->Move( Size( 0, nDiff ) );
708 
709     return nDiff != 0;
710 }
_SetObjLeft(const SwTwips _nLeft)711 bool SwAnchoredDrawObject::_SetObjLeft( const SwTwips _nLeft )
712 {
713     SwTwips nDiff = _nLeft - GetObjRect().Left();
714     DrawObj()->Move( Size( nDiff, 0 ) );
715 
716     return nDiff != 0;
717 }
718 // <--
719 
720 /** adjust positioning and alignment attributes for new anchor frame
721 
722     OD 2004-08-24 #i33313# - add second optional parameter <_pNewObjRect>
723 
724     @author OD
725 */
AdjustPositioningAttr(const SwFrm * _pNewAnchorFrm,const SwRect * _pNewObjRect)726 void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrm* _pNewAnchorFrm,
727                                                   const SwRect* _pNewObjRect )
728 {
729     SwTwips nHoriRelPos = 0;
730     SwTwips nVertRelPos = 0;
731     const Point aAnchorPos = _pNewAnchorFrm->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
732     // --> OD 2004-08-24 #i33313#
733     const SwRect aObjRect( _pNewObjRect ? *_pNewObjRect : GetObjRect() );
734     // <--
735     const bool bVert = _pNewAnchorFrm->IsVertical();
736     const bool bR2L = _pNewAnchorFrm->IsRightToLeft();
737     if ( bVert )
738     {
739         nHoriRelPos = aObjRect.Top() - aAnchorPos.Y();
740         nVertRelPos = aAnchorPos.X() - aObjRect.Right();
741     }
742     else if ( bR2L )
743     {
744         nHoriRelPos = aAnchorPos.X() - aObjRect.Right();
745         nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
746     }
747     else
748     {
749         nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
750         nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
751     }
752 
753     GetFrmFmt().SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
754     GetFrmFmt().SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
755 }
756 
757 // --> OD 2004-09-29 #i34748# - change return type
GetLastObjRect() const758 const Rectangle* SwAnchoredDrawObject::GetLastObjRect() const
759 {
760     return mpLastObjRect;
761 }
762 // <--
763 
764 // --> OD 2004-09-29 #i34748# - change return type.
765 // If member <mpLastObjRect> is NULL, create one.
SetLastObjRect(const Rectangle & _rNewLastRect)766 void SwAnchoredDrawObject::SetLastObjRect( const Rectangle& _rNewLastRect )
767 {
768     if ( !mpLastObjRect )
769     {
770         mpLastObjRect = new Rectangle;
771     }
772     *(mpLastObjRect) = _rNewLastRect;
773 }
774 // <--
775 
ObjectAttachedToAnchorFrame()776 void SwAnchoredDrawObject::ObjectAttachedToAnchorFrame()
777 {
778     // --> OD 2004-07-27 #i31698#
779     SwAnchoredObject::ObjectAttachedToAnchorFrame();
780     // <--
781 
782     if ( mbNotYetAttachedToAnchorFrame )
783     {
784         mbNotYetAttachedToAnchorFrame = false;
785     }
786 }
787 
788 /** method to set positioning attributes
789 
790     OD 2004-10-20 #i35798#
791     During load the positioning attributes aren't set.
792     Thus, the positioning attributes are set by the current object geometry.
793     This method is also used for the conversion for drawing objects
794     (not anchored as-character) imported from OpenOffice.org file format
795     once and directly before the first positioning.
796 
797     @author OD
798 */
_SetPositioningAttr()799 void SwAnchoredDrawObject::_SetPositioningAttr()
800 {
801     SwDrawContact* pDrawContact =
802                         static_cast<SwDrawContact*>(GetUserCall( GetDrawObj() ));
803 
804     if ( !pDrawContact->ObjAnchoredAsChar() )
805     {
806         SwRect aObjRect( GetObjRect() );
807 
808         SwTwips nHoriPos = aObjRect.Left();
809         SwTwips nVertPos = aObjRect.Top();
810         // --> OD 2005-03-10 #i44334#, #i44681#
811         // perform conversion only if position is in horizontal-left-to-right-layout.
812         if ( GetFrmFmt().GetPositionLayoutDir() ==
813                 text::PositionLayoutDir::PositionInHoriL2R )
814         {
815             SwFrmFmt::tLayoutDir eLayoutDir = GetFrmFmt().GetLayoutDir();
816             switch ( eLayoutDir )
817             {
818                 case SwFrmFmt::HORI_L2R:
819                 {
820                     // nothing to do
821                 }
822                 break;
823                 case SwFrmFmt::HORI_R2L:
824                 {
825                     nHoriPos = -aObjRect.Left() - aObjRect.Width();
826                 }
827                 break;
828                 case SwFrmFmt::VERT_R2L:
829                 {
830                     nHoriPos = aObjRect.Top();
831                     nVertPos = -aObjRect.Left() - aObjRect.Width();
832                 }
833                 break;
834                 default:
835                 {
836                     ASSERT( false,
837                             "<SwAnchoredDrawObject::_SetPositioningAttr()> - unsupported layout direction" );
838                 }
839             }
840         }
841         // <--
842 
843         // --> OD 2006-11-10 #i71182#
844         // only change position - do not lose other attributes
845         SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() );
846         aHori.SetPos( nHoriPos );
847         GetFrmFmt().SetFmtAttr( aHori );
848 
849         SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() );
850         // --> OD 2007-01-03 #i73079# - vertical position already correct
851 //        if ( aVert.GetRelationOrient() == text::RelOrientation::CHAR ||
852 //             aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
853 //        {
854 //            nVertPos = -nVertPos;
855 //        }
856         // <--
857         aVert.SetPos( nVertPos );
858         GetFrmFmt().SetFmtAttr( aVert );
859         // <--
860 
861         // --> OD 2004-10-25 #i36010# - set layout direction of the position
862         GetFrmFmt().SetPositionLayoutDir(
863             text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
864         // <--
865     }
866     // --> OD 2007-11-29 #i65798# - also for as-character anchored objects
867     // --> OD 2005-05-10 #i45952# - indicate that position
868     // attributes are set now.
869     static_cast<SwDrawFrmFmt&>(GetFrmFmt()).PosAttrSet();
870     // <--
871 }
872 
NotifyBackground(SwPageFrm * _pPageFrm,const SwRect & _rRect,PrepareHint _eHint)873 void SwAnchoredDrawObject::NotifyBackground( SwPageFrm* _pPageFrm,
874                                              const SwRect& _rRect,
875                                              PrepareHint _eHint )
876 {
877     ::Notify_Background( GetDrawObj(), _pPageFrm, _rRect, _eHint, sal_True );
878 }
879 
880 /** method to assure that anchored object is registered at the correct
881     page frame
882 
883     OD 2004-07-02 #i28701#
884 
885     @author OD
886 */
RegisterAtCorrectPage()887 void SwAnchoredDrawObject::RegisterAtCorrectPage()
888 {
889     SwPageFrm* pPageFrm( 0L );
890     if ( GetVertPosOrientFrm() )
891     {
892         pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm());
893     }
894     if ( pPageFrm && GetPageFrm() != pPageFrm )
895     {
896         if ( GetPageFrm() )
897             GetPageFrm()->RemoveDrawObjFromPage( *this );
898         pPageFrm->AppendDrawObjToPage( *this );
899     }
900 }
901 
902 // =============================================================================
903