1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: anchoredobjectposition.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <anchoredobjectposition.hxx>
34 #ifndef _ENVIRONMENTOFANCHOREDOBJECT
35 #include <environmentofanchoredobject.hxx>
38 #include <flyfrms.hxx>
40 #include <pagefrm.hxx>
41 #include <frmtool.hxx>
42 #ifndef _SVX_SVDOBJ_HXX
43 #include <svx/svdobj.hxx>
45 #include <dflyobj.hxx>
46 #include <dcontact.hxx>
48 #include <fmtornt.hxx>
49 // --> OD 2006-03-15 #i62875#
50 #include <fmtfollowtextflow.hxx>
52 #include <svx/lrspitem.hxx>
53 #include <svx/ulspitem.hxx>
55 #include <IDocumentSettingAccess.hxx>
57 using namespace ::com::sun::star
;
58 using namespace objectpositioning
;
60 // **************************************************************************
61 // constructor, destructor, initialization
62 // **************************************************************************
63 SwAnchoredObjectPosition::SwAnchoredObjectPosition( SdrObject
& _rDrawObj
)
64 : mrDrawObj( _rDrawObj
),
69 // --> OD 2006-03-15 #i62875#
70 mbFollowTextFlow( false ),
71 mbDoNotCaptureAnchoredObj( false )
74 #if OSL_DEBUG_LEVEL > 1
75 // assert, if object isn't of excepted type
76 const bool bObjOfExceptedType
=
77 mrDrawObj
.ISA(SwVirtFlyDrawObj
) || // object representing fly frame
78 mrDrawObj
.ISA(SwDrawVirtObj
) || // 'virtual' drawing object
79 ( !mrDrawObj
.ISA(SdrVirtObj
) && // 'master' drawing object
80 !mrDrawObj
.ISA(SwFlyDrawObj
) ); // - indirectly checked
81 (void) bObjOfExceptedType
;
82 ASSERT( bObjOfExceptedType
,
83 "SwAnchoredObjectPosition(..) - object of unexcepted type!" );
89 /** determine information about object
91 OD 30.07.2003 #110978#
92 members <mbIsObjFly>, <mpFrmOfObj>, <mpAnchorFrm>, <mpContact>,
93 <mbFollowTextFlow> and <mbDoNotCaptureAnchoredObj> are set
97 void SwAnchoredObjectPosition::_GetInfoAboutObj()
99 // determine, if object represents a fly frame
101 mbIsObjFly
= mrDrawObj
.ISA(SwVirtFlyDrawObj
);
104 // determine contact object
106 mpContact
= static_cast<SwContact
*>(GetUserCall( &mrDrawObj
));
108 "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing SwContact-object." );
111 // determine anchored object, the object belongs to
113 // OD 2004-03-30 #i26791#
114 mpAnchoredObj
= mpContact
->GetAnchoredObj( &mrDrawObj
);
115 ASSERT( mpAnchoredObj
,
116 "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchored object." );
119 // determine frame, the object is anchored at
121 // OD 2004-03-23 #i26791#
122 mpAnchorFrm
= mpAnchoredObj
->AnchorFrm();
124 "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchor frame." );
127 // determine format the object belongs to
129 // --> OD 2004-07-01 #i28701#
130 mpFrmFmt
= &mpAnchoredObj
->GetFrmFmt();
132 "<SwAnchoredObjectPosition::_GetInfoAboutObj() - missing frame format." );
135 // --> OD 2006-03-15 #i62875#
136 // determine attribute value of <Follow-Text-Flow>
138 mbFollowTextFlow
= mpFrmFmt
->GetFollowTextFlow().GetValue();
141 // determine, if anchored object has not to be captured on the page.
142 // the following conditions must be hold to *not* capture it:
143 // - corresponding document compatibility flag is set
144 // - it's a drawing object
145 // - it doesn't follow the text flow
147 mbDoNotCaptureAnchoredObj
= !mbIsObjFly
&& !mbFollowTextFlow
&&
148 mpFrmFmt
->getIDocumentSettingAccess()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE
);
153 SwAnchoredObjectPosition::~SwAnchoredObjectPosition()
156 bool SwAnchoredObjectPosition::IsAnchoredToChar() const
161 const SwFrm
* SwAnchoredObjectPosition::ToCharOrientFrm() const
166 const SwRect
* SwAnchoredObjectPosition::ToCharRect() const
171 // OD 12.11.2003 #i22341#
172 SwTwips
SwAnchoredObjectPosition::ToCharTopOfLine() const
177 /** helper method to determine top of a frame for the vertical
180 OD 2004-03-11 #i11860#
184 SwTwips
SwAnchoredObjectPosition::_GetTopForObjPos( const SwFrm
& _rFrm
,
185 const SwRectFn
& _fnRect
,
186 const bool _bVert
) const
188 SwTwips nTopOfFrmForObjPos
= (_rFrm
.Frm().*_fnRect
->fnGetTop
)();
190 if ( _rFrm
.IsTxtFrm() )
192 const SwTxtFrm
& rTxtFrm
= static_cast<const SwTxtFrm
&>(_rFrm
);
195 nTopOfFrmForObjPos
-=
196 rTxtFrm
.GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
200 nTopOfFrmForObjPos
+=
201 rTxtFrm
.GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
205 return nTopOfFrmForObjPos
;
208 void SwAnchoredObjectPosition::_GetVertAlignmentValues(
209 const SwFrm
& _rVertOrientFrm
,
210 const SwFrm
& _rPageAlignLayFrm
,
211 const sal_Int16 _eRelOrient
,
212 SwTwips
& _orAlignAreaHeight
,
213 SwTwips
& _orAlignAreaOffset
) const
217 SWRECTFN( (&_rVertOrientFrm
) )
218 // OD 2004-03-11 #i11860# - top of <_rVertOrientFrm> for object positioning
219 const SwTwips nVertOrientTop
= _GetTopForObjPos( _rVertOrientFrm
, fnRect
, bVert
);
220 // OD 2004-03-11 #i11860# - upper space amount of <_rVertOrientFrm> considered
221 // for previous frame
222 const SwTwips nVertOrientUpperSpaceForPrevFrmAndPageGrid
=
223 _rVertOrientFrm
.IsTxtFrm()
224 ? static_cast<const SwTxtFrm
&>(_rVertOrientFrm
).
225 GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid()
227 switch ( _eRelOrient
)
229 case text::RelOrientation::FRAME
:
231 // OD 2004-03-11 #i11860# - consider upper space of previous frame
232 nHeight
= (_rVertOrientFrm
.Frm().*fnRect
->fnGetHeight
)() -
233 nVertOrientUpperSpaceForPrevFrmAndPageGrid
;
237 case text::RelOrientation::PRINT_AREA
:
239 nHeight
= (_rVertOrientFrm
.Prt().*fnRect
->fnGetHeight
)();
240 // OD 2004-03-11 #i11860# - consider upper space of previous frame
241 nOffset
= (_rVertOrientFrm
.*fnRect
->fnGetTopMargin
)() -
242 nVertOrientUpperSpaceForPrevFrmAndPageGrid
;
243 // if aligned to page in horizontal layout, consider header and
244 // footer frame height appropriately.
245 if( _rVertOrientFrm
.IsPageFrm() && !bVert
)
247 const SwFrm
* pPrtFrm
=
248 static_cast<const SwPageFrm
&>(_rVertOrientFrm
).Lower();
251 if( pPrtFrm
->IsHeaderFrm() )
253 nHeight
-= pPrtFrm
->Frm().Height();
254 nOffset
+= pPrtFrm
->Frm().Height();
256 else if( pPrtFrm
->IsFooterFrm() )
258 nHeight
-= pPrtFrm
->Frm().Height();
260 pPrtFrm
= pPrtFrm
->GetNext();
265 case text::RelOrientation::PAGE_FRAME
:
267 nHeight
= (_rPageAlignLayFrm
.Frm().*fnRect
->fnGetHeight
)();
268 nOffset
= (*fnRect
->fnYDiff
)(
269 (_rPageAlignLayFrm
.Frm().*fnRect
->fnGetTop
)(),
273 case text::RelOrientation::PAGE_PRINT_AREA
:
275 nHeight
= (_rPageAlignLayFrm
.Prt().*fnRect
->fnGetHeight
)();
276 nOffset
= (_rPageAlignLayFrm
.*fnRect
->fnGetTopMargin
)() +
278 (_rPageAlignLayFrm
.Frm().*fnRect
->fnGetTop
)(),
280 // if aligned to page in horizontal layout, consider header and
281 // footer frame height appropriately.
282 if( _rPageAlignLayFrm
.IsPageFrm() && !bVert
)
284 const SwFrm
* pPrtFrm
=
285 static_cast<const SwPageFrm
&>(_rPageAlignLayFrm
).Lower();
288 if( pPrtFrm
->IsHeaderFrm() )
290 nHeight
-= pPrtFrm
->Frm().Height();
291 nOffset
+= pPrtFrm
->Frm().Height();
293 else if( pPrtFrm
->IsFooterFrm() )
295 nHeight
-= pPrtFrm
->Frm().Height();
297 pPrtFrm
= pPrtFrm
->GetNext();
302 // OD 12.11.2003 #i22341# - vertical alignment at top of line
303 case text::RelOrientation::TEXT_LINE
:
305 if ( IsAnchoredToChar() )
308 nOffset
= (*fnRect
->fnYDiff
)( ToCharTopOfLine(), nVertOrientTop
);
313 "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" );
317 case text::RelOrientation::CHAR
:
319 if ( IsAnchoredToChar() )
321 nHeight
= (ToCharRect()->*fnRect
->fnGetHeight
)();
322 nOffset
= (*fnRect
->fnYDiff
)( (ToCharRect()->*fnRect
->fnGetTop
)(),
328 "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" );
332 // no break here, because text::RelOrientation::CHAR is invalid, if !mbAnchorToChar
334 //case text::RelOrientation::PAGE_LEFT: not valid for vertical alignment
335 //case text::RelOrientation::PAGE_RIGHT: not valid for vertical alignment
336 //case text::RelOrientation::FRAME_LEFT: not valid for vertical alignment
337 //case text::RelOrientation::FRAME_RIGHT: not valid for vertical alignment
340 "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" );
344 _orAlignAreaHeight
= nHeight
;
345 _orAlignAreaOffset
= nOffset
;
348 // --> OD 2004-06-17 #i26791# - add output parameter <_roVertOffsetToFrmAnchorPos>
349 SwTwips
SwAnchoredObjectPosition::_GetVertRelPos(
350 const SwFrm
& _rVertOrientFrm
,
351 const SwFrm
& _rPageAlignLayFrm
,
352 const sal_Int16 _eVertOrient
,
353 const sal_Int16 _eRelOrient
,
354 const SwTwips _nVertPos
,
355 const SvxLRSpaceItem
& _rLRSpacing
,
356 const SvxULSpaceItem
& _rULSpacing
,
357 SwTwips
& _roVertOffsetToFrmAnchorPos
) const
359 SwTwips nRelPosY
= 0;
360 SWRECTFN( (&_rVertOrientFrm
) );
362 SwTwips nAlignAreaHeight
;
363 SwTwips nAlignAreaOffset
;
364 _GetVertAlignmentValues( _rVertOrientFrm
, _rPageAlignLayFrm
,
365 _eRelOrient
, nAlignAreaHeight
, nAlignAreaOffset
);
367 nRelPosY
= nAlignAreaOffset
;
368 const SwRect
aObjBoundRect( GetAnchoredObj().GetObjRect() );
369 const SwTwips nObjHeight
= (aObjBoundRect
.*fnRect
->fnGetHeight
)();
371 switch ( _eVertOrient
)
373 case text::VertOrientation::NONE
:
375 // 'manual' vertical position
376 nRelPosY
+= _nVertPos
;
379 case text::VertOrientation::TOP
:
381 nRelPosY
+= bVert
? _rLRSpacing
.GetRight() : _rULSpacing
.GetUpper();
384 case text::VertOrientation::CENTER
:
386 nRelPosY
+= (nAlignAreaHeight
/ 2) - (nObjHeight
/ 2);
389 case text::VertOrientation::BOTTOM
:
391 nRelPosY
+= nAlignAreaHeight
-
392 ( nObjHeight
+ ( bVert
? _rLRSpacing
.GetLeft() : _rULSpacing
.GetLower() ) );
398 "<SwAnchoredObjectPosition::_GetVertRelPos(..) - invalid vertical positioning" );
402 // --> OD 2004-06-17 #i26791#
403 _roVertOffsetToFrmAnchorPos
= nAlignAreaOffset
;
408 /** adjust calculated vertical in order to keep object inside
409 'page' alignment layout frame.
411 OD 2004-07-01 #i28701# - parameter <_nTopOfAnch> and <_bVert> added
412 OD 2004-07-22 #i31805# - add parameter <_bCheckBottom>
413 OD 2004-10-08 #i26945# - add parameter <_bFollowTextFlow>
414 OD 2006-03-15 #i62875# - method now private and renamed.
418 SwTwips
SwAnchoredObjectPosition::_ImplAdjustVertRelPos( const SwTwips _nTopOfAnch
,
420 const SwFrm
& _rPageAlignLayFrm
,
421 const SwTwips _nProposedRelPosY
,
422 const bool _bFollowTextFlow
,
423 const bool _bCheckBottom
) const
425 SwTwips nAdjustedRelPosY
= _nProposedRelPosY
;
427 const Size
aObjSize( GetAnchoredObj().GetObjRect().SSize() );
429 // determine the area of 'page' alignment frame, to which the vertical
430 // position is restricted.
431 // --> OD 2004-07-06 #i28701# - Extend restricted area for the vertical
432 // position to area of the page frame, if wrapping style influence is
433 // considered on object positioning. Needed to avoid layout loops in the
434 // object positioning algorithm considering the wrapping style influence
435 // caused by objects, which follow the text flow and thus are restricted
436 // to its environment (e.g. page header/footer).
439 // --> OD 2004-10-08 #i26945# - no extension of restricted area, if
440 // object's attribute follow text flow is set and its inside a table
441 if ( GetFrmFmt().getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION
) &&
442 ( !_bFollowTextFlow
||
443 !GetAnchoredObj().GetAnchorFrm()->IsInTab() ) )
445 aPgAlignArea
= _rPageAlignLayFrm
.FindPageFrm()->Frm();
449 aPgAlignArea
= _rPageAlignLayFrm
.Frm();
455 // OD 2004-07-22 #i31805# - consider value of <_bCheckBottom>
456 if ( _bCheckBottom
&&
457 _nTopOfAnch
- nAdjustedRelPosY
- aObjSize
.Width() <
458 aPgAlignArea
.Left() )
460 nAdjustedRelPosY
= aPgAlignArea
.Left() +
464 // --> OD 2004-08-13 #i32964# - correction
465 if ( _nTopOfAnch
- nAdjustedRelPosY
> aPgAlignArea
.Right() )
467 nAdjustedRelPosY
= _nTopOfAnch
- aPgAlignArea
.Right();
473 // OD 2004-07-22 #i31805# - consider value of <_bCheckBottom>
474 if ( _bCheckBottom
&&
475 _nTopOfAnch
+ nAdjustedRelPosY
+ aObjSize
.Height() >
476 // --> OD 2006-01-13 #129959#
477 // Do not mix usage of <top + height> and <bottom>
478 // aPgAlignArea.Bottom() )
479 aPgAlignArea
.Top() + aPgAlignArea
.Height() )
482 // --> OD 2006-01-13 #129959#
483 // Do not mix usage of <top + height> and <bottom>
484 // nAdjustedRelPosY = aPgAlignArea.Bottom() -
485 nAdjustedRelPosY
= aPgAlignArea
.Top() + aPgAlignArea
.Height() -
490 if ( _nTopOfAnch
+ nAdjustedRelPosY
< aPgAlignArea
.Top() )
492 nAdjustedRelPosY
= aPgAlignArea
.Top() - _nTopOfAnch
;
496 return nAdjustedRelPosY
;
499 /** adjust calculated horizontal in order to keep object inside
500 'page' alignment layout frame.
502 OD 2006-03-15 #i62875# - method now private and renamed.
506 SwTwips
SwAnchoredObjectPosition::_ImplAdjustHoriRelPos(
507 const SwFrm
& _rPageAlignLayFrm
,
508 const SwTwips _nProposedRelPosX
) const
510 SwTwips nAdjustedRelPosX
= _nProposedRelPosX
;
512 const SwFrm
& rAnchorFrm
= GetAnchorFrm();
513 const bool bVert
= rAnchorFrm
.IsVertical();
515 const Size
aObjSize( GetAnchoredObj().GetObjRect().SSize() );
519 if ( rAnchorFrm
.Frm().Top() + nAdjustedRelPosX
+ aObjSize
.Height() >
520 _rPageAlignLayFrm
.Frm().Bottom() )
522 nAdjustedRelPosX
= _rPageAlignLayFrm
.Frm().Bottom() -
523 rAnchorFrm
.Frm().Top() -
526 if ( rAnchorFrm
.Frm().Top() + nAdjustedRelPosX
<
527 _rPageAlignLayFrm
.Frm().Top() )
529 nAdjustedRelPosX
= _rPageAlignLayFrm
.Frm().Top() -
530 rAnchorFrm
.Frm().Top();
535 if ( rAnchorFrm
.Frm().Left() + nAdjustedRelPosX
+ aObjSize
.Width() >
536 _rPageAlignLayFrm
.Frm().Right() )
538 nAdjustedRelPosX
= _rPageAlignLayFrm
.Frm().Right() -
539 rAnchorFrm
.Frm().Left() -
542 if ( rAnchorFrm
.Frm().Left() + nAdjustedRelPosX
<
543 _rPageAlignLayFrm
.Frm().Left() )
545 nAdjustedRelPosX
= _rPageAlignLayFrm
.Frm().Left() -
546 rAnchorFrm
.Frm().Left();
550 return nAdjustedRelPosX
;
553 /** determine alignment value for horizontal position of object
557 void SwAnchoredObjectPosition::_GetHoriAlignmentValues( const SwFrm
& _rHoriOrientFrm
,
558 const SwFrm
& _rPageAlignLayFrm
,
559 const sal_Int16 _eRelOrient
,
560 const bool _bObjWrapThrough
,
561 SwTwips
& _orAlignAreaWidth
,
562 SwTwips
& _orAlignAreaOffset
,
563 bool& _obAlignedRelToPage
) const
567 SWRECTFN( (&_rHoriOrientFrm
) )
568 switch ( _eRelOrient
)
570 case text::RelOrientation::PRINT_AREA
:
572 nWidth
= (_rHoriOrientFrm
.Prt().*fnRect
->fnGetWidth
)();
573 nOffset
= (_rHoriOrientFrm
.*fnRect
->fnGetLeftMargin
)();
574 if ( _rHoriOrientFrm
.IsTxtFrm() )
576 // consider movement of text frame left
577 nOffset
+= static_cast<const SwTxtFrm
&>(_rHoriOrientFrm
).GetBaseOfstForFly( !_bObjWrapThrough
);
579 else if ( _rHoriOrientFrm
.IsPageFrm() && bVert
)
581 // for to-page anchored objects, consider header/footer frame
582 // in vertical layout
583 const SwFrm
* pPrtFrm
=
584 static_cast<const SwPageFrm
&>(_rHoriOrientFrm
).Lower();
587 if( pPrtFrm
->IsHeaderFrm() )
589 nWidth
-= pPrtFrm
->Frm().Height();
590 nOffset
+= pPrtFrm
->Frm().Height();
592 else if( pPrtFrm
->IsFooterFrm() )
594 nWidth
-= pPrtFrm
->Frm().Height();
596 pPrtFrm
= pPrtFrm
->GetNext();
601 case text::RelOrientation::PAGE_LEFT
:
603 // align at left border of page frame/fly frame/cell frame
604 nWidth
= (_rPageAlignLayFrm
.*fnRect
->fnGetLeftMargin
)();
605 nOffset
= (*fnRect
->fnXDiff
)(
606 (_rPageAlignLayFrm
.Frm().*fnRect
->fnGetLeft
)(),
607 (_rHoriOrientFrm
.Frm().*fnRect
->fnGetLeft
)() );
608 _obAlignedRelToPage
= true;
611 case text::RelOrientation::PAGE_RIGHT
:
613 // align at right border of page frame/fly frame/cell frame
614 nWidth
= (_rPageAlignLayFrm
.*fnRect
->fnGetRightMargin
)();
615 nOffset
= (*fnRect
->fnXDiff
)(
616 (_rPageAlignLayFrm
.*fnRect
->fnGetPrtRight
)(),
617 (_rHoriOrientFrm
.Frm().*fnRect
->fnGetLeft
)() );
618 _obAlignedRelToPage
= true;
621 case text::RelOrientation::FRAME_LEFT
:
623 // align at left border of anchor frame
624 nWidth
= (_rHoriOrientFrm
.*fnRect
->fnGetLeftMargin
)();
628 case text::RelOrientation::FRAME_RIGHT
:
630 // align at right border of anchor frame
631 // OD 19.08.2003 #110978# - unify and simplify
632 nWidth
= (_rHoriOrientFrm
.*fnRect
->fnGetRightMargin
)();
633 //nOffset = (_rHoriOrientFrm.Frm().*fnRect->fnGetWidth)() -
635 nOffset
= (_rHoriOrientFrm
.Prt().*fnRect
->fnGetRight
)();
638 case text::RelOrientation::CHAR
:
640 // alignment relative to character - assure, that corresponding
641 // character rectangle is set.
642 if ( IsAnchoredToChar() )
645 nOffset
= (*fnRect
->fnXDiff
)(
646 (ToCharRect()->*fnRect
->fnGetLeft
)(),
647 (ToCharOrientFrm()->Frm().*fnRect
->fnGetLeft
)() );
652 case text::RelOrientation::PAGE_PRINT_AREA
:
654 nWidth
= (_rPageAlignLayFrm
.Prt().*fnRect
->fnGetWidth
)();
655 nOffset
= (*fnRect
->fnXDiff
)(
656 (_rPageAlignLayFrm
.*fnRect
->fnGetPrtLeft
)(),
657 (_rHoriOrientFrm
.Frm().*fnRect
->fnGetLeft
)() );
658 if ( _rHoriOrientFrm
.IsPageFrm() && bVert
)
660 // for to-page anchored objects, consider header/footer frame
661 // in vertical layout
662 const SwFrm
* pPrtFrm
=
663 static_cast<const SwPageFrm
&>(_rHoriOrientFrm
).Lower();
666 if( pPrtFrm
->IsHeaderFrm() )
668 nWidth
-= pPrtFrm
->Frm().Height();
669 nOffset
+= pPrtFrm
->Frm().Height();
671 else if( pPrtFrm
->IsFooterFrm() )
673 nWidth
-= pPrtFrm
->Frm().Height();
675 pPrtFrm
= pPrtFrm
->GetNext();
678 _obAlignedRelToPage
= true;
681 case text::RelOrientation::PAGE_FRAME
:
683 nWidth
= (_rPageAlignLayFrm
.Frm().*fnRect
->fnGetWidth
)();
684 nOffset
= (*fnRect
->fnXDiff
)(
685 (_rPageAlignLayFrm
.Frm().*fnRect
->fnGetLeft
)(),
686 (_rHoriOrientFrm
.Frm().*fnRect
->fnGetLeft
)() );
687 _obAlignedRelToPage
= true;
691 // case text::RelOrientation::FRAME:
693 nWidth
= (_rHoriOrientFrm
.Frm().*fnRect
->fnGetWidth
)();
694 nOffset
= _rHoriOrientFrm
.IsTxtFrm() ?
695 static_cast<const SwTxtFrm
&>(_rHoriOrientFrm
).GetBaseOfstForFly( !_bObjWrapThrough
) :
701 _orAlignAreaWidth
= nWidth
;
702 _orAlignAreaOffset
= nOffset
;
705 /** toggle given horizontal orientation and relative alignment
709 void SwAnchoredObjectPosition::_ToggleHoriOrientAndAlign(
710 const bool _bToggleLeftRight
,
711 sal_Int16
& _ioeHoriOrient
,
712 sal_Int16
& _iopeRelOrient
715 if( _bToggleLeftRight
)
717 // toggle orientation
718 switch ( _ioeHoriOrient
)
720 case text::HoriOrientation::RIGHT
:
722 _ioeHoriOrient
= text::HoriOrientation::LEFT
;
725 case text::HoriOrientation::LEFT
:
727 _ioeHoriOrient
= text::HoriOrientation::RIGHT
;
734 // toggle relative alignment
735 switch ( _iopeRelOrient
)
737 case text::RelOrientation::PAGE_RIGHT
:
739 _iopeRelOrient
= text::RelOrientation::PAGE_LEFT
;
742 case text::RelOrientation::PAGE_LEFT
:
744 _iopeRelOrient
= text::RelOrientation::PAGE_RIGHT
;
747 case text::RelOrientation::FRAME_RIGHT
:
749 _iopeRelOrient
= text::RelOrientation::FRAME_LEFT
;
752 case text::RelOrientation::FRAME_LEFT
:
754 _iopeRelOrient
= text::RelOrientation::FRAME_RIGHT
;
763 /** calculate relative horizontal position
767 SwTwips
SwAnchoredObjectPosition::_CalcRelPosX(
768 const SwFrm
& _rHoriOrientFrm
,
769 const SwEnvironmentOfAnchoredObject
& _rEnvOfObj
,
770 const SwFmtHoriOrient
& _rHoriOrient
,
771 const SvxLRSpaceItem
& _rLRSpacing
,
772 const SvxULSpaceItem
& _rULSpacing
,
773 const bool _bObjWrapThrough
,
774 const SwTwips _nRelPosY
,
775 SwTwips
& _roHoriOffsetToFrmAnchorPos
778 // determine 'page' alignment layout frame
779 const SwFrm
& rPageAlignLayFrm
=
780 _rEnvOfObj
.GetHoriEnvironmentLayoutFrm( _rHoriOrientFrm
);
782 const bool bEvenPage
= !rPageAlignLayFrm
.OnRightPage();
783 const bool bToggle
= _rHoriOrient
.IsPosToggle() && bEvenPage
;
785 // determine orientation and relative alignment
786 sal_Int16 eHoriOrient
= _rHoriOrient
.GetHoriOrient();
787 sal_Int16 eRelOrient
= _rHoriOrient
.GetRelationOrient();
788 // toggle orientation and relative alignment
789 _ToggleHoriOrientAndAlign( bToggle
, eHoriOrient
, eRelOrient
);
791 // determine alignment parameter
792 // <nWidth>: 'width' of alignment area
793 // <nOffset>: offset of alignment area, relative to 'left' of anchor frame
796 bool bAlignedRelToPage
= false;
797 _GetHoriAlignmentValues( _rHoriOrientFrm
, rPageAlignLayFrm
,
798 eRelOrient
, _bObjWrapThrough
,
799 nWidth
, nOffset
, bAlignedRelToPage
);
801 const SwFrm
& rAnchorFrm
= GetAnchorFrm();
802 SWRECTFN( (&_rHoriOrientFrm
) )
803 SwTwips nObjWidth
= (GetAnchoredObj().GetObjRect().*fnRect
->fnGetWidth
)();
804 SwTwips nRelPosX
= nOffset
;
805 if ( _rHoriOrient
.GetHoriOrient() == text::HoriOrientation::NONE
)
807 // 'manual' horizonal position
808 const bool bR2L
= rAnchorFrm
.IsRightToLeft();
809 if( IsAnchoredToChar() && text::RelOrientation::CHAR
== eRelOrient
)
812 nRelPosX
-= _rHoriOrient
.GetPos();
814 nRelPosX
+= _rHoriOrient
.GetPos();
816 else if ( bToggle
|| ( !_rHoriOrient
.IsPosToggle() && bR2L
) )
818 // OD 04.08.2003 #110978# - correction: consider <nOffset> also for
819 // toggling from left to right.
820 nRelPosX
+= nWidth
- nObjWidth
- _rHoriOrient
.GetPos();
824 nRelPosX
+= _rHoriOrient
.GetPos();
827 else if ( text::HoriOrientation::CENTER
== eHoriOrient
)
828 nRelPosX
+= (nWidth
/ 2) - (nObjWidth
/ 2);
829 else if ( text::HoriOrientation::RIGHT
== eHoriOrient
)
832 ( bVert
? _rULSpacing
.GetLower() : _rLRSpacing
.GetRight() ) );
834 nRelPosX
+= bVert
? _rULSpacing
.GetUpper() : _rLRSpacing
.GetLeft();
836 // adjust relative position by distance between anchor frame and
837 // the frame, the object is oriented at.
838 if ( &rAnchorFrm
!= &_rHoriOrientFrm
)
840 SwTwips nLeftOrient
= (_rHoriOrientFrm
.Frm().*fnRect
->fnGetLeft
)();
841 SwTwips nLeftAnchor
= (rAnchorFrm
.Frm().*fnRect
->fnGetLeft
)();
842 nRelPosX
+= (*fnRect
->fnXDiff
)( nLeftOrient
, nLeftAnchor
);
845 // OD 2004-05-21 #i28701# - deactivate follow code
846 // // adjust relative horizontal position, if object is manual horizontal
847 // // positioned (not 'page' aligned) and orients not at the anchor frame,
848 // // but it overlaps anchor frame.
849 // if ( _rHoriOrient.GetHoriOrient() == text::HoriOrientation::NONE && !bAlignedRelToPage &&
850 // &rAnchorFrm != &_rHoriOrientFrm )
852 // // E.g.: consider a columned page/section with an horizontal
853 // // negative positioned object.
854 // // OD 2004-03-23 #i26791#
855 // const SwRect& rObjRect = GetAnchoredObj().GetObjRect();
858 // if( _rHoriOrientFrm.Frm().Top() > rAnchorFrm.Frm().Bottom() &&
859 // rObjRect.Right() > rAnchorFrm.Frm().Left() )
861 // const SwTwips nProposedPosX = nRelPosX + rAnchorFrm.Frm().Top();
862 // if ( nProposedPosX < rAnchorFrm.Frm().Bottom() )
863 // nRelPosX = rAnchorFrm.Frm().Height() + 1;
868 // if( _rHoriOrientFrm.Frm().Left() > rAnchorFrm.Frm().Right() &&
869 // rObjRect.Top() < rAnchorFrm.Frm().Bottom() )
871 // // OD 04.08.2003 #110978# - correction: use <nRelPosX>
872 // // instead of <aRelPos.X()>
873 // const SwTwips nProposedPosX = nRelPosX + rAnchorFrm.Frm().Left();
874 // if ( nProposedPosX < rAnchorFrm.Frm().Right() )
875 // nRelPosX = rAnchorFrm.Frm().Width() + 1;
879 // adjust calculated relative horizontal position, in order to
880 // keep object inside 'page' alignment layout frame
881 const SwFrm
& rEnvironmentLayFrm
=
882 _rEnvOfObj
.GetHoriEnvironmentLayoutFrm( _rHoriOrientFrm
);
883 nRelPosX
= _AdjustHoriRelPos( rEnvironmentLayFrm
, nRelPosX
);
885 // if object is a Writer fly frame and it's anchored to a content and
886 // it is horizontal positioned left or right, but not relative to character,
887 // it has to be drawn aside another object, which have the same horizontal
888 // position and lay below it.
889 if ( GetAnchoredObj().ISA(SwFlyFrm
) &&
890 ( GetContact().ObjAnchoredAtPara() || GetContact().ObjAnchoredAtChar() ) &&
891 ( eHoriOrient
== text::HoriOrientation::LEFT
|| eHoriOrient
== text::HoriOrientation::RIGHT
) &&
892 eRelOrient
!= text::RelOrientation::CHAR
)
894 nRelPosX
= _AdjustHoriRelPosForDrawAside( _rHoriOrientFrm
,
896 eHoriOrient
, eRelOrient
,
897 _rLRSpacing
, _rULSpacing
,
901 // --> OD 2004-06-17 #i26791#
902 _roHoriOffsetToFrmAnchorPos
= nOffset
;
907 // **************************************************************************
908 // method incl. helper methods for adjusting proposed horizontal position,
909 // if object has to draw aside another object.
910 // **************************************************************************
911 /** adjust calculated horizontal position in order to draw object
912 aside other objects with same positioning
916 SwTwips
SwAnchoredObjectPosition::_AdjustHoriRelPosForDrawAside(
917 const SwFrm
& _rHoriOrientFrm
,
918 const SwTwips _nProposedRelPosX
,
919 const SwTwips _nRelPosY
,
920 const sal_Int16 _eHoriOrient
,
921 const sal_Int16 _eRelOrient
,
922 const SvxLRSpaceItem
& _rLRSpacing
,
923 const SvxULSpaceItem
& _rULSpacing
,
924 const bool _bEvenPage
927 // OD 2004-03-23 #i26791#
928 if ( !GetAnchorFrm().ISA(SwTxtFrm
) ||
929 !GetAnchoredObj().ISA(SwFlyAtCntFrm
) )
932 "<SwAnchoredObjectPosition::_AdjustHoriRelPosForDrawAside(..) - usage for wrong anchor type" );
933 return _nProposedRelPosX
;
936 const SwTxtFrm
& rAnchorTxtFrm
= static_cast<const SwTxtFrm
&>(GetAnchorFrm());
937 // OD 2004-03-23 #i26791#
938 const SwFlyAtCntFrm
& rFlyAtCntFrm
=
939 static_cast<const SwFlyAtCntFrm
&>(GetAnchoredObj());
940 const SwRect
aObjBoundRect( GetAnchoredObj().GetObjRect() );
941 SWRECTFN( (&_rHoriOrientFrm
) )
943 SwTwips nAdjustedRelPosX
= _nProposedRelPosX
;
945 // determine proposed object bound rectangle
946 Point aTmpPos
= (rAnchorTxtFrm
.Frm().*fnRect
->fnGetPos
)();
949 aTmpPos
.X() -= _nRelPosY
+ aObjBoundRect
.Width();
950 aTmpPos
.Y() += nAdjustedRelPosX
;
954 aTmpPos
.X() += nAdjustedRelPosX
;
955 aTmpPos
.Y() += _nRelPosY
;
957 SwRect
aTmpObjRect( aTmpPos
, aObjBoundRect
.SSize() );
959 const UINT32 nObjOrdNum
= GetObject().GetOrdNum();
960 const SwPageFrm
* pObjPage
= rFlyAtCntFrm
.FindPageFrm();
961 const SwFrm
* pObjContext
= ::FindKontext( &rAnchorTxtFrm
, FRM_COLUMN
);
962 ULONG nObjIndex
= rAnchorTxtFrm
.GetTxtNode()->GetIndex();
963 SwOrderIter
aIter( pObjPage
, TRUE
);
964 const SwFlyFrm
* pFly
= ((SwVirtFlyDrawObj
*)aIter
.Bottom())->GetFlyFrm();
965 while ( pFly
&& nObjOrdNum
> pFly
->GetVirtDrawObj()->GetOrdNumDirect() )
967 if ( _DrawAsideFly( pFly
, aTmpObjRect
, pObjContext
, nObjIndex
,
968 _bEvenPage
, _eHoriOrient
, _eRelOrient
) )
972 const SvxULSpaceItem
& rOtherUL
= pFly
->GetFmt()->GetULSpace();
973 const SwTwips nOtherTop
= pFly
->Frm().Top() - rOtherUL
.GetUpper();
974 const SwTwips nOtherBot
= pFly
->Frm().Bottom() + rOtherUL
.GetLower();
975 if ( nOtherTop
<= aTmpObjRect
.Bottom() + _rULSpacing
.GetLower() &&
976 nOtherBot
>= aTmpObjRect
.Top() - _rULSpacing
.GetUpper() )
978 if ( _eHoriOrient
== text::HoriOrientation::LEFT
)
980 SwTwips nTmp
= nOtherBot
+ 1 + _rULSpacing
.GetUpper() -
981 rAnchorTxtFrm
.Frm().Top();
982 if ( nTmp
> nAdjustedRelPosX
&&
983 rAnchorTxtFrm
.Frm().Top() + nTmp
+
984 aObjBoundRect
.Height() + _rULSpacing
.GetLower()
985 <= pObjPage
->Frm().Height() + pObjPage
->Frm().Top() )
987 nAdjustedRelPosX
= nTmp
;
990 else if ( _eHoriOrient
== text::HoriOrientation::RIGHT
)
992 SwTwips nTmp
= nOtherTop
- 1 - _rULSpacing
.GetLower() -
993 aObjBoundRect
.Height() -
994 rAnchorTxtFrm
.Frm().Top();
995 if ( nTmp
< nAdjustedRelPosX
&&
996 rAnchorTxtFrm
.Frm().Top() + nTmp
- _rULSpacing
.GetUpper()
997 >= pObjPage
->Frm().Top() )
999 nAdjustedRelPosX
= nTmp
;
1002 aTmpObjRect
.Pos().Y() = rAnchorTxtFrm
.Frm().Top() +
1008 const SvxLRSpaceItem
& rOtherLR
= pFly
->GetFmt()->GetLRSpace();
1009 const SwTwips nOtherLeft
= pFly
->Frm().Left() - rOtherLR
.GetLeft();
1010 const SwTwips nOtherRight
= pFly
->Frm().Right() + rOtherLR
.GetRight();
1011 if( nOtherLeft
<= aTmpObjRect
.Right() + _rLRSpacing
.GetRight() &&
1012 nOtherRight
>= aTmpObjRect
.Left() - _rLRSpacing
.GetLeft() )
1014 if ( _eHoriOrient
== text::HoriOrientation::LEFT
)
1016 SwTwips nTmp
= nOtherRight
+ 1 + _rLRSpacing
.GetLeft() -
1017 rAnchorTxtFrm
.Frm().Left();
1018 if ( nTmp
> nAdjustedRelPosX
&&
1019 rAnchorTxtFrm
.Frm().Left() + nTmp
+
1020 aObjBoundRect
.Width() + _rLRSpacing
.GetRight()
1021 <= pObjPage
->Frm().Width() + pObjPage
->Frm().Left() )
1023 nAdjustedRelPosX
= nTmp
;
1026 else if ( _eHoriOrient
== text::HoriOrientation::RIGHT
)
1028 SwTwips nTmp
= nOtherLeft
- 1 - _rLRSpacing
.GetRight() -
1029 aObjBoundRect
.Width() -
1030 rAnchorTxtFrm
.Frm().Left();
1031 if ( nTmp
< nAdjustedRelPosX
&&
1032 rAnchorTxtFrm
.Frm().Left() + nTmp
- _rLRSpacing
.GetLeft()
1033 >= pObjPage
->Frm().Left() )
1035 nAdjustedRelPosX
= nTmp
;
1038 aTmpObjRect
.Pos().X() = rAnchorTxtFrm
.Frm().Left() +
1041 } // end of <if (bVert)>
1042 } // end of <if _DrawAsideFly(..)>
1044 pFly
= ((SwVirtFlyDrawObj
*)aIter
.Next())->GetFlyFrm();
1045 } // end of <loop on fly frames
1047 return nAdjustedRelPosX
;
1050 /** detemine, if object has to draw aside given fly frame
1052 method used by <_AdjustHoriRelPosForDrawAside(..)>
1056 bool SwAnchoredObjectPosition::_DrawAsideFly( const SwFlyFrm
* _pFly
,
1057 const SwRect
& _rObjRect
,
1058 const SwFrm
* _pObjContext
,
1059 const ULONG _nObjIndex
,
1060 const bool _bEvenPage
,
1061 const sal_Int16 _eHoriOrient
,
1062 const sal_Int16 _eRelOrient
1065 bool bRetVal
= false;
1067 SWRECTFN( (&GetAnchorFrm()) )
1069 if ( _pFly
->IsFlyAtCntFrm() &&
1070 (_pFly
->Frm().*fnRect
->fnBottomDist
)( (_rObjRect
.*fnRect
->fnGetTop
)() ) < 0 &&
1071 (_rObjRect
.*fnRect
->fnBottomDist
)( (_pFly
->Frm().*fnRect
->fnGetTop
)() ) < 0 &&
1072 ::FindKontext( _pFly
->GetAnchorFrm(), FRM_COLUMN
) == _pObjContext
)
1075 static_cast<const SwTxtFrm
*>(_pFly
->GetAnchorFrm())->GetTxtNode()->GetIndex();
1076 if( _nObjIndex
>= nOtherIndex
)
1078 const SwFmtHoriOrient
& rHori
= _pFly
->GetFmt()->GetHoriOrient();
1079 sal_Int16 eOtherRelOrient
= rHori
.GetRelationOrient();
1080 if( text::RelOrientation::CHAR
!= eOtherRelOrient
)
1082 sal_Int16 eOtherHoriOrient
= rHori
.GetHoriOrient();
1083 _ToggleHoriOrientAndAlign( _bEvenPage
&& rHori
.IsPosToggle(),
1086 if ( eOtherHoriOrient
== _eHoriOrient
&&
1087 _Minor( _eRelOrient
, eOtherRelOrient
, text::HoriOrientation::LEFT
== _eHoriOrient
) )
1098 /** determine, if object has to draw aside another object
1100 the different alignments of the objects determines, if one has
1101 to draw aside another one. Thus, the given alignment are checked
1102 against each other, which one has to be drawn aside the other one.
1103 depending on parameter _bLeft check is done for left or right
1105 method used by <_DrawAsideFly(..)>
1109 bool SwAnchoredObjectPosition::_Minor( sal_Int16 _eRelOrient1
,
1110 sal_Int16 _eRelOrient2
,
1115 // draw aside order for left horizontal position
1116 //! one array entry for each value in text::RelOrientation
1117 static USHORT __READONLY_DATA aLeft
[ 10 ] =
1118 { 5, 6, 0, 1, 8, 4, 7, 2, 3, 9 };
1119 // draw aside order for right horizontal position
1120 //! one array entry for each value in text::RelOrientation
1121 static USHORT __READONLY_DATA aRight
[ 10 ] =
1122 { 5, 6, 0, 8, 1, 7, 4, 2, 3, 9 };
1124 // decide depending on given order, which frame has to draw aside another frame
1126 bRetVal
= aLeft
[ _eRelOrient1
] >= aLeft
[ _eRelOrient2
];
1128 bRetVal
= aRight
[ _eRelOrient1
] >= aRight
[ _eRelOrient2
];