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