Update ooo320-m1
[ooovba.git] / sw / source / core / objectpositioning / anchoredobjectposition.cxx
blob4b1b751fa7a00a8aef1c5f3873f8285d94abb2e0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: anchoredobjectposition.cxx,v $
10 * $Revision: 1.17 $
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>
36 #endif
37 #include <flyfrm.hxx>
38 #include <flyfrms.hxx>
39 #include <txtfrm.hxx>
40 #include <pagefrm.hxx>
41 #include <frmtool.hxx>
42 #ifndef _SVX_SVDOBJ_HXX
43 #include <svx/svdobj.hxx>
44 #endif
45 #include <dflyobj.hxx>
46 #include <dcontact.hxx>
47 #include <frmfmt.hxx>
48 #include <fmtornt.hxx>
49 // --> OD 2006-03-15 #i62875#
50 #include <fmtfollowtextflow.hxx>
51 // <--
52 #include <svx/lrspitem.hxx>
53 #include <svx/ulspitem.hxx>
54 #include <ndtxt.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 ),
65 mbIsObjFly( false ),
66 mpAnchoredObj( 0 ),
67 mpAnchorFrm( 0 ),
68 mpContact( 0 ),
69 // --> OD 2006-03-15 #i62875#
70 mbFollowTextFlow( false ),
71 mbDoNotCaptureAnchoredObj( false )
72 // <--
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!" );
84 #endif
86 _GetInfoAboutObj();
89 /** determine information about object
91 OD 30.07.2003 #110978#
92 members <mbIsObjFly>, <mpFrmOfObj>, <mpAnchorFrm>, <mpContact>,
93 <mbFollowTextFlow> and <mbDoNotCaptureAnchoredObj> are set
95 @author OD
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 ));
107 ASSERT( mpContact,
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();
123 ASSERT( mpAnchorFrm,
124 "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchor frame." );
127 // determine format the object belongs to
129 // --> OD 2004-07-01 #i28701#
130 mpFrmFmt = &mpAnchoredObj->GetFrmFmt();
131 ASSERT( mpFrmFmt,
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);
150 // <--
153 SwAnchoredObjectPosition::~SwAnchoredObjectPosition()
156 bool SwAnchoredObjectPosition::IsAnchoredToChar() const
158 return false;
161 const SwFrm* SwAnchoredObjectPosition::ToCharOrientFrm() const
163 return NULL;
166 const SwRect* SwAnchoredObjectPosition::ToCharRect() const
168 return NULL;
171 // OD 12.11.2003 #i22341#
172 SwTwips SwAnchoredObjectPosition::ToCharTopOfLine() const
174 return 0L;
177 /** helper method to determine top of a frame for the vertical
178 object positioning
180 OD 2004-03-11 #i11860#
182 @author OD
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);
193 if ( _bVert )
195 nTopOfFrmForObjPos -=
196 rTxtFrm.GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
198 else
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
215 SwTwips nHeight = 0;
216 SwTwips nOffset = 0;
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()
226 : 0;
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;
234 nOffset = 0;
236 break;
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();
249 while( pPrtFrm )
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();
264 break;
265 case text::RelOrientation::PAGE_FRAME:
267 nHeight = (_rPageAlignLayFrm.Frm().*fnRect->fnGetHeight)();
268 nOffset = (*fnRect->fnYDiff)(
269 (_rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(),
270 nVertOrientTop );
272 break;
273 case text::RelOrientation::PAGE_PRINT_AREA:
275 nHeight = (_rPageAlignLayFrm.Prt().*fnRect->fnGetHeight)();
276 nOffset = (_rPageAlignLayFrm.*fnRect->fnGetTopMargin)() +
277 (*fnRect->fnYDiff)(
278 (_rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(),
279 nVertOrientTop );
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();
286 while( pPrtFrm )
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();
301 break;
302 // OD 12.11.2003 #i22341# - vertical alignment at top of line
303 case text::RelOrientation::TEXT_LINE:
305 if ( IsAnchoredToChar() )
307 nHeight = 0;
308 nOffset = (*fnRect->fnYDiff)( ToCharTopOfLine(), nVertOrientTop );
310 else
312 ASSERT( false,
313 "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" );
316 break;
317 case text::RelOrientation::CHAR:
319 if ( IsAnchoredToChar() )
321 nHeight = (ToCharRect()->*fnRect->fnGetHeight)();
322 nOffset = (*fnRect->fnYDiff)( (ToCharRect()->*fnRect->fnGetTop)(),
323 nVertOrientTop );
325 else
327 ASSERT( false,
328 "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" );
331 break;
332 // no break here, because text::RelOrientation::CHAR is invalid, if !mbAnchorToChar
333 default:
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
339 ASSERT( false,
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;
378 break;
379 case text::VertOrientation::TOP:
381 nRelPosY += bVert ? _rLRSpacing.GetRight() : _rULSpacing.GetUpper();
383 break;
384 case text::VertOrientation::CENTER:
386 nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
388 break;
389 case text::VertOrientation::BOTTOM:
391 nRelPosY += nAlignAreaHeight -
392 ( nObjHeight + ( bVert ? _rLRSpacing.GetLeft() : _rULSpacing.GetLower() ) );
394 break;
395 default:
397 ASSERT( false,
398 "<SwAnchoredObjectPosition::_GetVertRelPos(..) - invalid vertical positioning" );
402 // --> OD 2004-06-17 #i26791#
403 _roVertOffsetToFrmAnchorPos = nAlignAreaOffset;
405 return nRelPosY;
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.
416 @author OD
418 SwTwips SwAnchoredObjectPosition::_ImplAdjustVertRelPos( const SwTwips _nTopOfAnch,
419 const bool _bVert,
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).
437 SwRect aPgAlignArea;
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();
447 else
449 aPgAlignArea = _rPageAlignLayFrm.Frm();
453 if ( _bVert )
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() +
461 _nTopOfAnch -
462 aObjSize.Width();
464 // --> OD 2004-08-13 #i32964# - correction
465 if ( _nTopOfAnch - nAdjustedRelPosY > aPgAlignArea.Right() )
467 nAdjustedRelPosY = _nTopOfAnch - aPgAlignArea.Right();
469 // <--
471 else
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() )
480 // <--
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() -
486 // <--
487 _nTopOfAnch -
488 aObjSize.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.
504 @author OD
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() );
517 if( bVert )
519 if ( rAnchorFrm.Frm().Top() + nAdjustedRelPosX + aObjSize.Height() >
520 _rPageAlignLayFrm.Frm().Bottom() )
522 nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Bottom() -
523 rAnchorFrm.Frm().Top() -
524 aObjSize.Height();
526 if ( rAnchorFrm.Frm().Top() + nAdjustedRelPosX <
527 _rPageAlignLayFrm.Frm().Top() )
529 nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Top() -
530 rAnchorFrm.Frm().Top();
533 else
535 if ( rAnchorFrm.Frm().Left() + nAdjustedRelPosX + aObjSize.Width() >
536 _rPageAlignLayFrm.Frm().Right() )
538 nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Right() -
539 rAnchorFrm.Frm().Left() -
540 aObjSize.Width();
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
555 @author OD
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
565 SwTwips nWidth = 0;
566 SwTwips nOffset = 0;
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();
585 while( pPrtFrm )
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();
599 break;
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;
610 break;
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;
620 break;
621 case text::RelOrientation::FRAME_LEFT:
623 // align at left border of anchor frame
624 nWidth = (_rHoriOrientFrm.*fnRect->fnGetLeftMargin)();
625 nOffset = 0;
627 break;
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)() -
634 // nWidth;
635 nOffset = (_rHoriOrientFrm.Prt().*fnRect->fnGetRight)();
637 break;
638 case text::RelOrientation::CHAR:
640 // alignment relative to character - assure, that corresponding
641 // character rectangle is set.
642 if ( IsAnchoredToChar() )
644 nWidth = 0;
645 nOffset = (*fnRect->fnXDiff)(
646 (ToCharRect()->*fnRect->fnGetLeft)(),
647 (ToCharOrientFrm()->Frm().*fnRect->fnGetLeft)() );
648 break;
650 // no break!
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();
664 while( pPrtFrm )
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;
679 break;
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;
688 break;
690 default:
691 // case text::RelOrientation::FRAME:
693 nWidth = (_rHoriOrientFrm.Frm().*fnRect->fnGetWidth)();
694 nOffset = _rHoriOrientFrm.IsTxtFrm() ?
695 static_cast<const SwTxtFrm&>(_rHoriOrientFrm).GetBaseOfstForFly( !_bObjWrapThrough ) :
697 break;
701 _orAlignAreaWidth = nWidth;
702 _orAlignAreaOffset = nOffset;
705 /** toggle given horizontal orientation and relative alignment
707 @author OD
709 void SwAnchoredObjectPosition::_ToggleHoriOrientAndAlign(
710 const bool _bToggleLeftRight,
711 sal_Int16& _ioeHoriOrient,
712 sal_Int16& _iopeRelOrient
713 ) const
715 if( _bToggleLeftRight )
717 // toggle orientation
718 switch ( _ioeHoriOrient )
720 case text::HoriOrientation::RIGHT :
722 _ioeHoriOrient = text::HoriOrientation::LEFT;
724 break;
725 case text::HoriOrientation::LEFT :
727 _ioeHoriOrient = text::HoriOrientation::RIGHT;
729 break;
730 default:
731 break;
734 // toggle relative alignment
735 switch ( _iopeRelOrient )
737 case text::RelOrientation::PAGE_RIGHT :
739 _iopeRelOrient = text::RelOrientation::PAGE_LEFT;
741 break;
742 case text::RelOrientation::PAGE_LEFT :
744 _iopeRelOrient = text::RelOrientation::PAGE_RIGHT;
746 break;
747 case text::RelOrientation::FRAME_RIGHT :
749 _iopeRelOrient = text::RelOrientation::FRAME_LEFT;
751 break;
752 case text::RelOrientation::FRAME_LEFT :
754 _iopeRelOrient = text::RelOrientation::FRAME_RIGHT;
756 break;
757 default:
758 break;
763 /** calculate relative horizontal position
765 @author OD
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
776 ) const
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
794 SwTwips nWidth = 0;
795 SwTwips nOffset = 0;
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 )
811 if( bR2L )
812 nRelPosX -= _rHoriOrient.GetPos();
813 else
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();
822 else
824 nRelPosX += _rHoriOrient.GetPos();
827 else if ( text::HoriOrientation::CENTER == eHoriOrient )
828 nRelPosX += (nWidth / 2) - (nObjWidth / 2);
829 else if ( text::HoriOrientation::RIGHT == eHoriOrient )
830 nRelPosX += nWidth -
831 ( nObjWidth +
832 ( bVert ? _rULSpacing.GetLower() : _rLRSpacing.GetRight() ) );
833 else
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 )
851 // {
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();
856 // if( bVert )
857 // {
858 // if( _rHoriOrientFrm.Frm().Top() > rAnchorFrm.Frm().Bottom() &&
859 // rObjRect.Right() > rAnchorFrm.Frm().Left() )
860 // {
861 // const SwTwips nProposedPosX = nRelPosX + rAnchorFrm.Frm().Top();
862 // if ( nProposedPosX < rAnchorFrm.Frm().Bottom() )
863 // nRelPosX = rAnchorFrm.Frm().Height() + 1;
864 // }
865 // }
866 // else
867 // {
868 // if( _rHoriOrientFrm.Frm().Left() > rAnchorFrm.Frm().Right() &&
869 // rObjRect.Top() < rAnchorFrm.Frm().Bottom() )
870 // {
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;
876 // }
877 // }
878 // }
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,
895 nRelPosX, _nRelPosY,
896 eHoriOrient, eRelOrient,
897 _rLRSpacing, _rULSpacing,
898 bEvenPage );
901 // --> OD 2004-06-17 #i26791#
902 _roHoriOffsetToFrmAnchorPos = nOffset;
904 return nRelPosX;
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
914 @author OD
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
925 ) const
927 // OD 2004-03-23 #i26791#
928 if ( !GetAnchorFrm().ISA(SwTxtFrm) ||
929 !GetAnchoredObj().ISA(SwFlyAtCntFrm) )
931 ASSERT( false,
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)();
947 if( bVert )
949 aTmpPos.X() -= _nRelPosY + aObjBoundRect.Width();
950 aTmpPos.Y() += nAdjustedRelPosX;
952 else
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 ) )
970 if( bVert )
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() +
1003 nAdjustedRelPosX;
1006 else
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() +
1039 nAdjustedRelPosX;
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(..)>
1054 @author OD
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
1063 ) const
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 )
1074 ULONG nOtherIndex =
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(),
1084 eOtherHoriOrient,
1085 eOtherRelOrient );
1086 if ( eOtherHoriOrient == _eHoriOrient &&
1087 _Minor( _eRelOrient, eOtherRelOrient, text::HoriOrientation::LEFT == _eHoriOrient ) )
1089 bRetVal = true;
1095 return bRetVal;
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
1104 positioning.
1105 method used by <_DrawAsideFly(..)>
1107 @author OD
1109 bool SwAnchoredObjectPosition::_Minor( sal_Int16 _eRelOrient1,
1110 sal_Int16 _eRelOrient2,
1111 bool _bLeft ) const
1113 bool bRetVal;
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
1125 if( _bLeft )
1126 bRetVal = aLeft[ _eRelOrient1 ] >= aLeft[ _eRelOrient2 ];
1127 else
1128 bRetVal = aRight[ _eRelOrient1 ] >= aRight[ _eRelOrient2 ];
1130 return bRetVal;