| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| #include <anchoredobjectposition.hxx> |
| #ifndef _ENVIRONMENTOFANCHOREDOBJECT |
| #include <environmentofanchoredobject.hxx> |
| #endif |
| #include <flyfrm.hxx> |
| #include <flyfrms.hxx> |
| #include <txtfrm.hxx> |
| #include <pagefrm.hxx> |
| #include <frmtool.hxx> |
| #ifndef _SVX_SVDOBJ_HXX |
| #include <svx/svdobj.hxx> |
| #endif |
| #include <dflyobj.hxx> |
| #include <dcontact.hxx> |
| #include <frmfmt.hxx> |
| #include <fmtornt.hxx> |
| // --> OD 2006-03-15 #i62875# |
| #include <fmtfollowtextflow.hxx> |
| // <-- |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/ulspitem.hxx> |
| #include <ndtxt.hxx> |
| #include <IDocumentSettingAccess.hxx> |
| |
| using namespace ::com::sun::star; |
| using namespace objectpositioning; |
| |
| // ************************************************************************** |
| // constructor, destructor, initialization |
| // ************************************************************************** |
| SwAnchoredObjectPosition::SwAnchoredObjectPosition( SdrObject& _rDrawObj ) |
| : mrDrawObj( _rDrawObj ), |
| mbIsObjFly( false ), |
| mpAnchoredObj( 0 ), |
| mpAnchorFrm( 0 ), |
| mpContact( 0 ), |
| // --> OD 2006-03-15 #i62875# |
| mbFollowTextFlow( false ), |
| mbDoNotCaptureAnchoredObj( false ) |
| // <-- |
| { |
| #if OSL_DEBUG_LEVEL > 1 |
| // assert, if object isn't of excepted type |
| const bool bObjOfExceptedType = |
| mrDrawObj.ISA(SwVirtFlyDrawObj) || // object representing fly frame |
| mrDrawObj.ISA(SwDrawVirtObj) || // 'virtual' drawing object |
| ( !mrDrawObj.ISA(SdrVirtObj) && // 'master' drawing object |
| !mrDrawObj.ISA(SwFlyDrawObj) ); // - indirectly checked |
| (void) bObjOfExceptedType; |
| ASSERT( bObjOfExceptedType, |
| "SwAnchoredObjectPosition(..) - object of unexcepted type!" ); |
| #endif |
| |
| _GetInfoAboutObj(); |
| } |
| |
| /** determine information about object |
| |
| OD 30.07.2003 #110978# |
| members <mbIsObjFly>, <mpFrmOfObj>, <mpAnchorFrm>, <mpContact>, |
| <mbFollowTextFlow> and <mbDoNotCaptureAnchoredObj> are set |
| |
| @author OD |
| */ |
| void SwAnchoredObjectPosition::_GetInfoAboutObj() |
| { |
| // determine, if object represents a fly frame |
| { |
| mbIsObjFly = mrDrawObj.ISA(SwVirtFlyDrawObj); |
| } |
| |
| // determine contact object |
| { |
| mpContact = static_cast<SwContact*>(GetUserCall( &mrDrawObj )); |
| ASSERT( mpContact, |
| "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing SwContact-object." ); |
| } |
| |
| // determine anchored object, the object belongs to |
| { |
| // OD 2004-03-30 #i26791# |
| mpAnchoredObj = mpContact->GetAnchoredObj( &mrDrawObj ); |
| ASSERT( mpAnchoredObj, |
| "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchored object." ); |
| } |
| |
| // determine frame, the object is anchored at |
| { |
| // OD 2004-03-23 #i26791# |
| mpAnchorFrm = mpAnchoredObj->AnchorFrm(); |
| ASSERT( mpAnchorFrm, |
| "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchor frame." ); |
| } |
| |
| // determine format the object belongs to |
| { |
| // --> OD 2004-07-01 #i28701# |
| mpFrmFmt = &mpAnchoredObj->GetFrmFmt(); |
| ASSERT( mpFrmFmt, |
| "<SwAnchoredObjectPosition::_GetInfoAboutObj() - missing frame format." ); |
| } |
| |
| // --> OD 2006-03-15 #i62875# |
| // determine attribute value of <Follow-Text-Flow> |
| { |
| mbFollowTextFlow = mpFrmFmt->GetFollowTextFlow().GetValue(); |
| } |
| |
| // determine, if anchored object has not to be captured on the page. |
| // the following conditions must be hold to *not* capture it: |
| // - corresponding document compatibility flag is set |
| // - it's a drawing object |
| // - it doesn't follow the text flow |
| { |
| mbDoNotCaptureAnchoredObj = !mbIsObjFly && !mbFollowTextFlow && |
| mpFrmFmt->getIDocumentSettingAccess()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE); |
| } |
| // <-- |
| } |
| |
| SwAnchoredObjectPosition::~SwAnchoredObjectPosition() |
| {} |
| |
| bool SwAnchoredObjectPosition::IsAnchoredToChar() const |
| { |
| return false; |
| } |
| |
| const SwFrm* SwAnchoredObjectPosition::ToCharOrientFrm() const |
| { |
| return NULL; |
| } |
| |
| const SwRect* SwAnchoredObjectPosition::ToCharRect() const |
| { |
| return NULL; |
| } |
| |
| // OD 12.11.2003 #i22341# |
| SwTwips SwAnchoredObjectPosition::ToCharTopOfLine() const |
| { |
| return 0L; |
| } |
| |
| /** helper method to determine top of a frame for the vertical |
| object positioning |
| |
| OD 2004-03-11 #i11860# |
| |
| @author OD |
| */ |
| SwTwips SwAnchoredObjectPosition::_GetTopForObjPos( const SwFrm& _rFrm, |
| const SwRectFn& _fnRect, |
| const bool _bVert ) const |
| { |
| SwTwips nTopOfFrmForObjPos = (_rFrm.Frm().*_fnRect->fnGetTop)(); |
| |
| if ( _rFrm.IsTxtFrm() ) |
| { |
| const SwTxtFrm& rTxtFrm = static_cast<const SwTxtFrm&>(_rFrm); |
| if ( _bVert ) |
| { |
| nTopOfFrmForObjPos -= |
| rTxtFrm.GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid(); |
| } |
| else |
| { |
| nTopOfFrmForObjPos += |
| rTxtFrm.GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid(); |
| } |
| } |
| |
| return nTopOfFrmForObjPos; |
| } |
| |
| void SwAnchoredObjectPosition::_GetVertAlignmentValues( |
| const SwFrm& _rVertOrientFrm, |
| const SwFrm& _rPageAlignLayFrm, |
| const sal_Int16 _eRelOrient, |
| SwTwips& _orAlignAreaHeight, |
| SwTwips& _orAlignAreaOffset ) const |
| { |
| SwTwips nHeight = 0; |
| SwTwips nOffset = 0; |
| SWRECTFN( (&_rVertOrientFrm) ) |
| // OD 2004-03-11 #i11860# - top of <_rVertOrientFrm> for object positioning |
| const SwTwips nVertOrientTop = _GetTopForObjPos( _rVertOrientFrm, fnRect, bVert ); |
| // OD 2004-03-11 #i11860# - upper space amount of <_rVertOrientFrm> considered |
| // for previous frame |
| const SwTwips nVertOrientUpperSpaceForPrevFrmAndPageGrid = |
| _rVertOrientFrm.IsTxtFrm() |
| ? static_cast<const SwTxtFrm&>(_rVertOrientFrm). |
| GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() |
| : 0; |
| switch ( _eRelOrient ) |
| { |
| case text::RelOrientation::FRAME: |
| { |
| // OD 2004-03-11 #i11860# - consider upper space of previous frame |
| nHeight = (_rVertOrientFrm.Frm().*fnRect->fnGetHeight)() - |
| nVertOrientUpperSpaceForPrevFrmAndPageGrid; |
| nOffset = 0; |
| } |
| break; |
| case text::RelOrientation::PRINT_AREA: |
| { |
| nHeight = (_rVertOrientFrm.Prt().*fnRect->fnGetHeight)(); |
| // OD 2004-03-11 #i11860# - consider upper space of previous frame |
| nOffset = (_rVertOrientFrm.*fnRect->fnGetTopMargin)() - |
| nVertOrientUpperSpaceForPrevFrmAndPageGrid; |
| // if aligned to page in horizontal layout, consider header and |
| // footer frame height appropriately. |
| if( _rVertOrientFrm.IsPageFrm() && !bVert ) |
| { |
| const SwFrm* pPrtFrm = |
| static_cast<const SwPageFrm&>(_rVertOrientFrm).Lower(); |
| while( pPrtFrm ) |
| { |
| if( pPrtFrm->IsHeaderFrm() ) |
| { |
| nHeight -= pPrtFrm->Frm().Height(); |
| nOffset += pPrtFrm->Frm().Height(); |
| } |
| else if( pPrtFrm->IsFooterFrm() ) |
| { |
| nHeight -= pPrtFrm->Frm().Height(); |
| } |
| pPrtFrm = pPrtFrm->GetNext(); |
| } |
| } |
| } |
| break; |
| case text::RelOrientation::PAGE_FRAME: |
| { |
| nHeight = (_rPageAlignLayFrm.Frm().*fnRect->fnGetHeight)(); |
| nOffset = (*fnRect->fnYDiff)( |
| (_rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(), |
| nVertOrientTop ); |
| } |
| break; |
| case text::RelOrientation::PAGE_PRINT_AREA: |
| { |
| nHeight = (_rPageAlignLayFrm.Prt().*fnRect->fnGetHeight)(); |
| nOffset = (_rPageAlignLayFrm.*fnRect->fnGetTopMargin)() + |
| (*fnRect->fnYDiff)( |
| (_rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(), |
| nVertOrientTop ); |
| // if aligned to page in horizontal layout, consider header and |
| // footer frame height appropriately. |
| if( _rPageAlignLayFrm.IsPageFrm() && !bVert ) |
| { |
| const SwFrm* pPrtFrm = |
| static_cast<const SwPageFrm&>(_rPageAlignLayFrm).Lower(); |
| while( pPrtFrm ) |
| { |
| if( pPrtFrm->IsHeaderFrm() ) |
| { |
| nHeight -= pPrtFrm->Frm().Height(); |
| nOffset += pPrtFrm->Frm().Height(); |
| } |
| else if( pPrtFrm->IsFooterFrm() ) |
| { |
| nHeight -= pPrtFrm->Frm().Height(); |
| } |
| pPrtFrm = pPrtFrm->GetNext(); |
| } |
| } |
| } |
| break; |
| // OD 12.11.2003 #i22341# - vertical alignment at top of line |
| case text::RelOrientation::TEXT_LINE: |
| { |
| if ( IsAnchoredToChar() ) |
| { |
| nHeight = 0; |
| nOffset = (*fnRect->fnYDiff)( ToCharTopOfLine(), nVertOrientTop ); |
| } |
| else |
| { |
| ASSERT( false, |
| "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" ); |
| } |
| } |
| break; |
| case text::RelOrientation::CHAR: |
| { |
| if ( IsAnchoredToChar() ) |
| { |
| nHeight = (ToCharRect()->*fnRect->fnGetHeight)(); |
| nOffset = (*fnRect->fnYDiff)( (ToCharRect()->*fnRect->fnGetTop)(), |
| nVertOrientTop ); |
| } |
| else |
| { |
| ASSERT( false, |
| "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" ); |
| } |
| } |
| break; |
| // no break here, because text::RelOrientation::CHAR is invalid, if !mbAnchorToChar |
| default: |
| //case text::RelOrientation::PAGE_LEFT: not valid for vertical alignment |
| //case text::RelOrientation::PAGE_RIGHT: not valid for vertical alignment |
| //case text::RelOrientation::FRAME_LEFT: not valid for vertical alignment |
| //case text::RelOrientation::FRAME_RIGHT: not valid for vertical alignment |
| { |
| ASSERT( false, |
| "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" ); |
| } |
| } |
| |
| _orAlignAreaHeight = nHeight; |
| _orAlignAreaOffset = nOffset; |
| } |
| |
| // --> OD 2004-06-17 #i26791# - add output parameter <_roVertOffsetToFrmAnchorPos> |
| SwTwips SwAnchoredObjectPosition::_GetVertRelPos( |
| const SwFrm& _rVertOrientFrm, |
| const SwFrm& _rPageAlignLayFrm, |
| const sal_Int16 _eVertOrient, |
| const sal_Int16 _eRelOrient, |
| const SwTwips _nVertPos, |
| const SvxLRSpaceItem& _rLRSpacing, |
| const SvxULSpaceItem& _rULSpacing, |
| SwTwips& _roVertOffsetToFrmAnchorPos ) const |
| { |
| SwTwips nRelPosY = 0; |
| SWRECTFN( (&_rVertOrientFrm) ); |
| |
| SwTwips nAlignAreaHeight; |
| SwTwips nAlignAreaOffset; |
| _GetVertAlignmentValues( _rVertOrientFrm, _rPageAlignLayFrm, |
| _eRelOrient, nAlignAreaHeight, nAlignAreaOffset ); |
| |
| nRelPosY = nAlignAreaOffset; |
| const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() ); |
| const SwTwips nObjHeight = (aObjBoundRect.*fnRect->fnGetHeight)(); |
| |
| switch ( _eVertOrient ) |
| { |
| case text::VertOrientation::NONE: |
| { |
| // 'manual' vertical position |
| nRelPosY += _nVertPos; |
| } |
| break; |
| case text::VertOrientation::TOP: |
| { |
| //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin |
| nRelPosY += bVert |
| ? ( bVertL2R |
| ? _rLRSpacing.GetLeft() |
| : _rLRSpacing.GetRight() ) |
| : _rULSpacing.GetUpper(); |
| } |
| break; |
| case text::VertOrientation::CENTER: |
| { |
| nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2); |
| } |
| break; |
| case text::VertOrientation::BOTTOM: |
| { |
| //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin |
| nRelPosY += nAlignAreaHeight - |
| ( nObjHeight + ( bVert |
| ? ( bVertL2R |
| ? _rLRSpacing.GetRight() |
| : _rLRSpacing.GetLeft() ) |
| : _rULSpacing.GetLower() ) ); |
| } |
| break; |
| default: |
| { |
| ASSERT( false, |
| "<SwAnchoredObjectPosition::_GetVertRelPos(..) - invalid vertical positioning" ); |
| } |
| } |
| |
| // --> OD 2004-06-17 #i26791# |
| _roVertOffsetToFrmAnchorPos = nAlignAreaOffset; |
| |
| return nRelPosY; |
| } |
| |
| /** adjust calculated vertical in order to keep object inside |
| 'page' alignment layout frame. |
| |
| OD 2004-07-01 #i28701# - parameter <nTopOfAnch> and <bVert> added |
| OD 2004-07-22 #i31805# - add parameter <bCheckBottom> |
| OD 2004-10-08 #i26945# - add parameter <bFollowTextFlow> |
| OD 2006-03-15 #i62875# - method now private and renamed. |
| OD 2009-09-01 #mongolianlayout# - add parameter <bVertL2R> |
| |
| @author OD |
| */ |
| SwTwips SwAnchoredObjectPosition::_ImplAdjustVertRelPos( const SwTwips nTopOfAnch, |
| const bool bVert, |
| const bool bVertL2R, |
| const SwFrm& rPageAlignLayFrm, |
| const SwTwips nProposedRelPosY, |
| const bool bFollowTextFlow, |
| const bool bCheckBottom ) const |
| { |
| SwTwips nAdjustedRelPosY = nProposedRelPosY; |
| |
| const Size aObjSize( GetAnchoredObj().GetObjRect().SSize() ); |
| |
| // determine the area of 'page' alignment frame, to which the vertical |
| // position is restricted. |
| // --> OD 2004-07-06 #i28701# - Extend restricted area for the vertical |
| // position to area of the page frame, if wrapping style influence is |
| // considered on object positioning. Needed to avoid layout loops in the |
| // object positioning algorithm considering the wrapping style influence |
| // caused by objects, which follow the text flow and thus are restricted |
| // to its environment (e.g. page header/footer). |
| SwRect aPgAlignArea; |
| { |
| // --> OD 2004-10-08 #i26945# - no extension of restricted area, if |
| // object's attribute follow text flow is set and its inside a table |
| if ( GetFrmFmt().getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) && |
| ( !bFollowTextFlow || |
| !GetAnchoredObj().GetAnchorFrm()->IsInTab() ) ) |
| { |
| aPgAlignArea = rPageAlignLayFrm.FindPageFrm()->Frm(); |
| } |
| else |
| { |
| aPgAlignArea = rPageAlignLayFrm.Frm(); |
| } |
| } |
| |
| if ( bVert ) |
| { |
| // --> OD 2009-09-01 #mongolianlayout# |
| if ( !bVertL2R ) |
| // <-- |
| { |
| if ( bCheckBottom && |
| nTopOfAnch - nAdjustedRelPosY - aObjSize.Width() < |
| aPgAlignArea.Left() ) |
| { |
| nAdjustedRelPosY = aPgAlignArea.Left() + |
| nTopOfAnch - |
| aObjSize.Width(); |
| } |
| if ( nTopOfAnch - nAdjustedRelPosY > aPgAlignArea.Right() ) |
| { |
| nAdjustedRelPosY = nTopOfAnch - aPgAlignArea.Right(); |
| } |
| } |
| // --> OD 2009-09-01 #mongolianlayout# |
| else |
| { |
| if ( bCheckBottom && |
| nTopOfAnch + nAdjustedRelPosY + aObjSize.Width() > |
| aPgAlignArea.Right() ) |
| { |
| nAdjustedRelPosY = aPgAlignArea.Right() - |
| nTopOfAnch - |
| aObjSize.Width(); |
| } |
| if ( nTopOfAnch + nAdjustedRelPosY < aPgAlignArea.Left() ) |
| { |
| nAdjustedRelPosY = aPgAlignArea.Left() - nTopOfAnch; |
| } |
| } |
| // <-- |
| } |
| else |
| { |
| if ( bCheckBottom && |
| nTopOfAnch + nAdjustedRelPosY + aObjSize.Height() > |
| aPgAlignArea.Top() + aPgAlignArea.Height() ) |
| { |
| nAdjustedRelPosY = aPgAlignArea.Top() + aPgAlignArea.Height() - |
| nTopOfAnch - |
| aObjSize.Height(); |
| } |
| if ( nTopOfAnch + nAdjustedRelPosY < aPgAlignArea.Top() ) |
| { |
| nAdjustedRelPosY = aPgAlignArea.Top() - nTopOfAnch; |
| } |
| } |
| |
| return nAdjustedRelPosY; |
| } |
| |
| /** adjust calculated horizontal in order to keep object inside |
| 'page' alignment layout frame. |
| |
| OD 2006-03-15 #i62875# - method now private and renamed. |
| |
| @author OD |
| */ |
| SwTwips SwAnchoredObjectPosition::_ImplAdjustHoriRelPos( |
| const SwFrm& _rPageAlignLayFrm, |
| const SwTwips _nProposedRelPosX ) const |
| { |
| SwTwips nAdjustedRelPosX = _nProposedRelPosX; |
| |
| const SwFrm& rAnchorFrm = GetAnchorFrm(); |
| const bool bVert = rAnchorFrm.IsVertical(); |
| |
| const Size aObjSize( GetAnchoredObj().GetObjRect().SSize() ); |
| |
| if( bVert ) |
| { |
| if ( rAnchorFrm.Frm().Top() + nAdjustedRelPosX + aObjSize.Height() > |
| _rPageAlignLayFrm.Frm().Bottom() ) |
| { |
| nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Bottom() - |
| rAnchorFrm.Frm().Top() - |
| aObjSize.Height(); |
| } |
| if ( rAnchorFrm.Frm().Top() + nAdjustedRelPosX < |
| _rPageAlignLayFrm.Frm().Top() ) |
| { |
| nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Top() - |
| rAnchorFrm.Frm().Top(); |
| } |
| } |
| else |
| { |
| if ( rAnchorFrm.Frm().Left() + nAdjustedRelPosX + aObjSize.Width() > |
| _rPageAlignLayFrm.Frm().Right() ) |
| { |
| nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Right() - |
| rAnchorFrm.Frm().Left() - |
| aObjSize.Width(); |
| } |
| if ( rAnchorFrm.Frm().Left() + nAdjustedRelPosX < |
| _rPageAlignLayFrm.Frm().Left() ) |
| { |
| nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Left() - |
| rAnchorFrm.Frm().Left(); |
| } |
| } |
| |
| return nAdjustedRelPosX; |
| } |
| |
| /** determine alignment value for horizontal position of object |
| |
| @author OD |
| */ |
| void SwAnchoredObjectPosition::_GetHoriAlignmentValues( const SwFrm& _rHoriOrientFrm, |
| const SwFrm& _rPageAlignLayFrm, |
| const sal_Int16 _eRelOrient, |
| const bool _bObjWrapThrough, |
| SwTwips& _orAlignAreaWidth, |
| SwTwips& _orAlignAreaOffset, |
| bool& _obAlignedRelToPage ) const |
| { |
| SwTwips nWidth = 0; |
| SwTwips nOffset = 0; |
| SWRECTFN( (&_rHoriOrientFrm) ) |
| switch ( _eRelOrient ) |
| { |
| case text::RelOrientation::PRINT_AREA: |
| { |
| nWidth = (_rHoriOrientFrm.Prt().*fnRect->fnGetWidth)(); |
| nOffset = (_rHoriOrientFrm.*fnRect->fnGetLeftMargin)(); |
| if ( _rHoriOrientFrm.IsTxtFrm() ) |
| { |
| // consider movement of text frame left |
| nOffset += static_cast<const SwTxtFrm&>(_rHoriOrientFrm).GetBaseOfstForFly( !_bObjWrapThrough ); |
| } |
| else if ( _rHoriOrientFrm.IsPageFrm() && bVert ) |
| { |
| // for to-page anchored objects, consider header/footer frame |
| // in vertical layout |
| const SwFrm* pPrtFrm = |
| static_cast<const SwPageFrm&>(_rHoriOrientFrm).Lower(); |
| while( pPrtFrm ) |
| { |
| if( pPrtFrm->IsHeaderFrm() ) |
| { |
| nWidth -= pPrtFrm->Frm().Height(); |
| nOffset += pPrtFrm->Frm().Height(); |
| } |
| else if( pPrtFrm->IsFooterFrm() ) |
| { |
| nWidth -= pPrtFrm->Frm().Height(); |
| } |
| pPrtFrm = pPrtFrm->GetNext(); |
| } |
| } |
| break; |
| } |
| case text::RelOrientation::PAGE_LEFT: |
| { |
| // align at left border of page frame/fly frame/cell frame |
| nWidth = (_rPageAlignLayFrm.*fnRect->fnGetLeftMargin)(); |
| nOffset = (*fnRect->fnXDiff)( |
| (_rPageAlignLayFrm.Frm().*fnRect->fnGetLeft)(), |
| (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)() ); |
| _obAlignedRelToPage = true; |
| } |
| break; |
| case text::RelOrientation::PAGE_RIGHT: |
| { |
| // align at right border of page frame/fly frame/cell frame |
| nWidth = (_rPageAlignLayFrm.*fnRect->fnGetRightMargin)(); |
| nOffset = (*fnRect->fnXDiff)( |
| (_rPageAlignLayFrm.*fnRect->fnGetPrtRight)(), |
| (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)() ); |
| _obAlignedRelToPage = true; |
| } |
| break; |
| case text::RelOrientation::FRAME_LEFT: |
| { |
| // align at left border of anchor frame |
| nWidth = (_rHoriOrientFrm.*fnRect->fnGetLeftMargin)(); |
| nOffset = 0; |
| } |
| break; |
| case text::RelOrientation::FRAME_RIGHT: |
| { |
| // align at right border of anchor frame |
| // OD 19.08.2003 #110978# - unify and simplify |
| nWidth = (_rHoriOrientFrm.*fnRect->fnGetRightMargin)(); |
| //nOffset = (_rHoriOrientFrm.Frm().*fnRect->fnGetWidth)() - |
| // nWidth; |
| nOffset = (_rHoriOrientFrm.Prt().*fnRect->fnGetRight)(); |
| } |
| break; |
| case text::RelOrientation::CHAR: |
| { |
| // alignment relative to character - assure, that corresponding |
| // character rectangle is set. |
| if ( IsAnchoredToChar() ) |
| { |
| nWidth = 0; |
| nOffset = (*fnRect->fnXDiff)( |
| (ToCharRect()->*fnRect->fnGetLeft)(), |
| (ToCharOrientFrm()->Frm().*fnRect->fnGetLeft)() ); |
| break; |
| } |
| // no break! |
| } |
| case text::RelOrientation::PAGE_PRINT_AREA: |
| { |
| nWidth = (_rPageAlignLayFrm.Prt().*fnRect->fnGetWidth)(); |
| nOffset = (*fnRect->fnXDiff)( |
| (_rPageAlignLayFrm.*fnRect->fnGetPrtLeft)(), |
| (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)() ); |
| if ( _rHoriOrientFrm.IsPageFrm() && bVert ) |
| { |
| // for to-page anchored objects, consider header/footer frame |
| // in vertical layout |
| const SwFrm* pPrtFrm = |
| static_cast<const SwPageFrm&>(_rHoriOrientFrm).Lower(); |
| while( pPrtFrm ) |
| { |
| if( pPrtFrm->IsHeaderFrm() ) |
| { |
| nWidth -= pPrtFrm->Frm().Height(); |
| nOffset += pPrtFrm->Frm().Height(); |
| } |
| else if( pPrtFrm->IsFooterFrm() ) |
| { |
| nWidth -= pPrtFrm->Frm().Height(); |
| } |
| pPrtFrm = pPrtFrm->GetNext(); |
| } |
| } |
| _obAlignedRelToPage = true; |
| break; |
| } |
| case text::RelOrientation::PAGE_FRAME: |
| { |
| nWidth = (_rPageAlignLayFrm.Frm().*fnRect->fnGetWidth)(); |
| nOffset = (*fnRect->fnXDiff)( |
| (_rPageAlignLayFrm.Frm().*fnRect->fnGetLeft)(), |
| (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)() ); |
| _obAlignedRelToPage = true; |
| break; |
| } |
| default: |
| // case text::RelOrientation::FRAME: |
| { |
| nWidth = (_rHoriOrientFrm.Frm().*fnRect->fnGetWidth)(); |
| nOffset = _rHoriOrientFrm.IsTxtFrm() ? |
| static_cast<const SwTxtFrm&>(_rHoriOrientFrm).GetBaseOfstForFly( !_bObjWrapThrough ) : |
| 0; |
| break; |
| } |
| } |
| |
| _orAlignAreaWidth = nWidth; |
| _orAlignAreaOffset = nOffset; |
| } |
| |
| /** toggle given horizontal orientation and relative alignment |
| |
| @author OD |
| */ |
| void SwAnchoredObjectPosition::_ToggleHoriOrientAndAlign( |
| const bool _bToggleLeftRight, |
| sal_Int16& _ioeHoriOrient, |
| sal_Int16& _iopeRelOrient |
| ) const |
| { |
| if( _bToggleLeftRight ) |
| { |
| // toggle orientation |
| switch ( _ioeHoriOrient ) |
| { |
| case text::HoriOrientation::RIGHT : |
| { |
| _ioeHoriOrient = text::HoriOrientation::LEFT; |
| } |
| break; |
| case text::HoriOrientation::LEFT : |
| { |
| _ioeHoriOrient = text::HoriOrientation::RIGHT; |
| } |
| break; |
| default: |
| break; |
| } |
| |
| // toggle relative alignment |
| switch ( _iopeRelOrient ) |
| { |
| case text::RelOrientation::PAGE_RIGHT : |
| { |
| _iopeRelOrient = text::RelOrientation::PAGE_LEFT; |
| } |
| break; |
| case text::RelOrientation::PAGE_LEFT : |
| { |
| _iopeRelOrient = text::RelOrientation::PAGE_RIGHT; |
| } |
| break; |
| case text::RelOrientation::FRAME_RIGHT : |
| { |
| _iopeRelOrient = text::RelOrientation::FRAME_LEFT; |
| } |
| break; |
| case text::RelOrientation::FRAME_LEFT : |
| { |
| _iopeRelOrient = text::RelOrientation::FRAME_RIGHT; |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| /** calculate relative horizontal position |
| |
| @author OD |
| */ |
| SwTwips SwAnchoredObjectPosition::_CalcRelPosX( |
| const SwFrm& _rHoriOrientFrm, |
| const SwEnvironmentOfAnchoredObject& _rEnvOfObj, |
| const SwFmtHoriOrient& _rHoriOrient, |
| const SvxLRSpaceItem& _rLRSpacing, |
| const SvxULSpaceItem& _rULSpacing, |
| const bool _bObjWrapThrough, |
| const SwTwips _nRelPosY, |
| SwTwips& _roHoriOffsetToFrmAnchorPos |
| ) const |
| { |
| // determine 'page' alignment layout frame |
| const SwFrm& rPageAlignLayFrm = |
| _rEnvOfObj.GetHoriEnvironmentLayoutFrm( _rHoriOrientFrm ); |
| |
| const bool bEvenPage = !rPageAlignLayFrm.OnRightPage(); |
| const bool bToggle = _rHoriOrient.IsPosToggle() && bEvenPage; |
| |
| // determine orientation and relative alignment |
| sal_Int16 eHoriOrient = _rHoriOrient.GetHoriOrient(); |
| sal_Int16 eRelOrient = _rHoriOrient.GetRelationOrient(); |
| // toggle orientation and relative alignment |
| _ToggleHoriOrientAndAlign( bToggle, eHoriOrient, eRelOrient ); |
| |
| // determine alignment parameter |
| // <nWidth>: 'width' of alignment area |
| // <nOffset>: offset of alignment area, relative to 'left' of anchor frame |
| SwTwips nWidth = 0; |
| SwTwips nOffset = 0; |
| bool bAlignedRelToPage = false; |
| _GetHoriAlignmentValues( _rHoriOrientFrm, rPageAlignLayFrm, |
| eRelOrient, _bObjWrapThrough, |
| nWidth, nOffset, bAlignedRelToPage ); |
| |
| const SwFrm& rAnchorFrm = GetAnchorFrm(); |
| SWRECTFN( (&_rHoriOrientFrm) ) |
| SwTwips nObjWidth = (GetAnchoredObj().GetObjRect().*fnRect->fnGetWidth)(); |
| SwTwips nRelPosX = nOffset; |
| if ( _rHoriOrient.GetHoriOrient() == text::HoriOrientation::NONE ) |
| { |
| // 'manual' horizonal position |
| const bool bR2L = rAnchorFrm.IsRightToLeft(); |
| if( IsAnchoredToChar() && text::RelOrientation::CHAR == eRelOrient ) |
| { |
| if( bR2L ) |
| nRelPosX -= _rHoriOrient.GetPos(); |
| else |
| nRelPosX += _rHoriOrient.GetPos(); |
| } |
| else if ( bToggle || ( !_rHoriOrient.IsPosToggle() && bR2L ) ) |
| { |
| // OD 04.08.2003 #110978# - correction: consider <nOffset> also for |
| // toggling from left to right. |
| nRelPosX += nWidth - nObjWidth - _rHoriOrient.GetPos(); |
| } |
| else |
| { |
| nRelPosX += _rHoriOrient.GetPos(); |
| } |
| } |
| else if ( text::HoriOrientation::CENTER == eHoriOrient ) |
| nRelPosX += (nWidth / 2) - (nObjWidth / 2); |
| else if ( text::HoriOrientation::RIGHT == eHoriOrient ) |
| nRelPosX += nWidth - |
| ( nObjWidth + |
| ( bVert ? _rULSpacing.GetLower() : _rLRSpacing.GetRight() ) ); |
| else |
| nRelPosX += bVert ? _rULSpacing.GetUpper() : _rLRSpacing.GetLeft(); |
| |
| // adjust relative position by distance between anchor frame and |
| // the frame, the object is oriented at. |
| if ( &rAnchorFrm != &_rHoriOrientFrm ) |
| { |
| SwTwips nLeftOrient = (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)(); |
| SwTwips nLeftAnchor = (rAnchorFrm.Frm().*fnRect->fnGetLeft)(); |
| nRelPosX += (*fnRect->fnXDiff)( nLeftOrient, nLeftAnchor ); |
| } |
| |
| // OD 2004-05-21 #i28701# - deactivate follow code |
| // // adjust relative horizontal position, if object is manual horizontal |
| // // positioned (not 'page' aligned) and orients not at the anchor frame, |
| // // but it overlaps anchor frame. |
| // if ( _rHoriOrient.GetHoriOrient() == text::HoriOrientation::NONE && !bAlignedRelToPage && |
| // &rAnchorFrm != &_rHoriOrientFrm ) |
| // { |
| // // E.g.: consider a columned page/section with an horizontal |
| // // negative positioned object. |
| // // OD 2004-03-23 #i26791# |
| // const SwRect& rObjRect = GetAnchoredObj().GetObjRect(); |
| // if( bVert ) |
| // { |
| // if( _rHoriOrientFrm.Frm().Top() > rAnchorFrm.Frm().Bottom() && |
| // rObjRect.Right() > rAnchorFrm.Frm().Left() ) |
| // { |
| // const SwTwips nProposedPosX = nRelPosX + rAnchorFrm.Frm().Top(); |
| // if ( nProposedPosX < rAnchorFrm.Frm().Bottom() ) |
| // nRelPosX = rAnchorFrm.Frm().Height() + 1; |
| // } |
| // } |
| // else |
| // { |
| // if( _rHoriOrientFrm.Frm().Left() > rAnchorFrm.Frm().Right() && |
| // rObjRect.Top() < rAnchorFrm.Frm().Bottom() ) |
| // { |
| // // OD 04.08.2003 #110978# - correction: use <nRelPosX> |
| // // instead of <aRelPos.X()> |
| // const SwTwips nProposedPosX = nRelPosX + rAnchorFrm.Frm().Left(); |
| // if ( nProposedPosX < rAnchorFrm.Frm().Right() ) |
| // nRelPosX = rAnchorFrm.Frm().Width() + 1; |
| // } |
| // } |
| // } |
| // adjust calculated relative horizontal position, in order to |
| // keep object inside 'page' alignment layout frame |
| const SwFrm& rEnvironmentLayFrm = |
| _rEnvOfObj.GetHoriEnvironmentLayoutFrm( _rHoriOrientFrm ); |
| nRelPosX = _AdjustHoriRelPos( rEnvironmentLayFrm, nRelPosX ); |
| |
| // if object is a Writer fly frame and it's anchored to a content and |
| // it is horizontal positioned left or right, but not relative to character, |
| // it has to be drawn aside another object, which have the same horizontal |
| // position and lay below it. |
| if ( GetAnchoredObj().ISA(SwFlyFrm) && |
| ( GetContact().ObjAnchoredAtPara() || GetContact().ObjAnchoredAtChar() ) && |
| ( eHoriOrient == text::HoriOrientation::LEFT || eHoriOrient == text::HoriOrientation::RIGHT ) && |
| eRelOrient != text::RelOrientation::CHAR ) |
| { |
| nRelPosX = _AdjustHoriRelPosForDrawAside( _rHoriOrientFrm, |
| nRelPosX, _nRelPosY, |
| eHoriOrient, eRelOrient, |
| _rLRSpacing, _rULSpacing, |
| bEvenPage ); |
| } |
| |
| // --> OD 2004-06-17 #i26791# |
| _roHoriOffsetToFrmAnchorPos = nOffset; |
| |
| return nRelPosX; |
| } |
| |
| // ************************************************************************** |
| // method incl. helper methods for adjusting proposed horizontal position, |
| // if object has to draw aside another object. |
| // ************************************************************************** |
| /** adjust calculated horizontal position in order to draw object |
| aside other objects with same positioning |
| |
| @author OD |
| */ |
| SwTwips SwAnchoredObjectPosition::_AdjustHoriRelPosForDrawAside( |
| const SwFrm& _rHoriOrientFrm, |
| const SwTwips _nProposedRelPosX, |
| const SwTwips _nRelPosY, |
| const sal_Int16 _eHoriOrient, |
| const sal_Int16 _eRelOrient, |
| const SvxLRSpaceItem& _rLRSpacing, |
| const SvxULSpaceItem& _rULSpacing, |
| const bool _bEvenPage |
| ) const |
| { |
| // OD 2004-03-23 #i26791# |
| if ( !GetAnchorFrm().ISA(SwTxtFrm) || |
| !GetAnchoredObj().ISA(SwFlyAtCntFrm) ) |
| { |
| ASSERT( false, |
| "<SwAnchoredObjectPosition::_AdjustHoriRelPosForDrawAside(..) - usage for wrong anchor type" ); |
| return _nProposedRelPosX; |
| } |
| |
| const SwTxtFrm& rAnchorTxtFrm = static_cast<const SwTxtFrm&>(GetAnchorFrm()); |
| // OD 2004-03-23 #i26791# |
| const SwFlyAtCntFrm& rFlyAtCntFrm = |
| static_cast<const SwFlyAtCntFrm&>(GetAnchoredObj()); |
| const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() ); |
| SWRECTFN( (&_rHoriOrientFrm) ) |
| |
| SwTwips nAdjustedRelPosX = _nProposedRelPosX; |
| |
| // determine proposed object bound rectangle |
| Point aTmpPos = (rAnchorTxtFrm.Frm().*fnRect->fnGetPos)(); |
| if( bVert ) |
| { |
| aTmpPos.X() -= _nRelPosY + aObjBoundRect.Width(); |
| aTmpPos.Y() += nAdjustedRelPosX; |
| } |
| else |
| { |
| aTmpPos.X() += nAdjustedRelPosX; |
| aTmpPos.Y() += _nRelPosY; |
| } |
| SwRect aTmpObjRect( aTmpPos, aObjBoundRect.SSize() ); |
| |
| const sal_uInt32 nObjOrdNum = GetObject().GetOrdNum(); |
| const SwPageFrm* pObjPage = rFlyAtCntFrm.FindPageFrm(); |
| const SwFrm* pObjContext = ::FindKontext( &rAnchorTxtFrm, FRM_COLUMN ); |
| sal_uLong nObjIndex = rAnchorTxtFrm.GetTxtNode()->GetIndex(); |
| SwOrderIter aIter( pObjPage, sal_True ); |
| const SwFlyFrm* pFly = ((SwVirtFlyDrawObj*)aIter.Bottom())->GetFlyFrm(); |
| while ( pFly && nObjOrdNum > pFly->GetVirtDrawObj()->GetOrdNumDirect() ) |
| { |
| if ( _DrawAsideFly( pFly, aTmpObjRect, pObjContext, nObjIndex, |
| _bEvenPage, _eHoriOrient, _eRelOrient ) ) |
| { |
| if( bVert ) |
| { |
| const SvxULSpaceItem& rOtherUL = pFly->GetFmt()->GetULSpace(); |
| const SwTwips nOtherTop = pFly->Frm().Top() - rOtherUL.GetUpper(); |
| const SwTwips nOtherBot = pFly->Frm().Bottom() + rOtherUL.GetLower(); |
| if ( nOtherTop <= aTmpObjRect.Bottom() + _rULSpacing.GetLower() && |
| nOtherBot >= aTmpObjRect.Top() - _rULSpacing.GetUpper() ) |
| { |
| if ( _eHoriOrient == text::HoriOrientation::LEFT ) |
| { |
| SwTwips nTmp = nOtherBot + 1 + _rULSpacing.GetUpper() - |
| rAnchorTxtFrm.Frm().Top(); |
| if ( nTmp > nAdjustedRelPosX && |
| rAnchorTxtFrm.Frm().Top() + nTmp + |
| aObjBoundRect.Height() + _rULSpacing.GetLower() |
| <= pObjPage->Frm().Height() + pObjPage->Frm().Top() ) |
| { |
| nAdjustedRelPosX = nTmp; |
| } |
| } |
| else if ( _eHoriOrient == text::HoriOrientation::RIGHT ) |
| { |
| SwTwips nTmp = nOtherTop - 1 - _rULSpacing.GetLower() - |
| aObjBoundRect.Height() - |
| rAnchorTxtFrm.Frm().Top(); |
| if ( nTmp < nAdjustedRelPosX && |
| rAnchorTxtFrm.Frm().Top() + nTmp - _rULSpacing.GetUpper() |
| >= pObjPage->Frm().Top() ) |
| { |
| nAdjustedRelPosX = nTmp; |
| } |
| } |
| aTmpObjRect.Pos().Y() = rAnchorTxtFrm.Frm().Top() + |
| nAdjustedRelPosX; |
| } |
| } |
| else |
| { |
| const SvxLRSpaceItem& rOtherLR = pFly->GetFmt()->GetLRSpace(); |
| const SwTwips nOtherLeft = pFly->Frm().Left() - rOtherLR.GetLeft(); |
| const SwTwips nOtherRight = pFly->Frm().Right() + rOtherLR.GetRight(); |
| if( nOtherLeft <= aTmpObjRect.Right() + _rLRSpacing.GetRight() && |
| nOtherRight >= aTmpObjRect.Left() - _rLRSpacing.GetLeft() ) |
| { |
| if ( _eHoriOrient == text::HoriOrientation::LEFT ) |
| { |
| SwTwips nTmp = nOtherRight + 1 + _rLRSpacing.GetLeft() - |
| rAnchorTxtFrm.Frm().Left(); |
| if ( nTmp > nAdjustedRelPosX && |
| rAnchorTxtFrm.Frm().Left() + nTmp + |
| aObjBoundRect.Width() + _rLRSpacing.GetRight() |
| <= pObjPage->Frm().Width() + pObjPage->Frm().Left() ) |
| { |
| nAdjustedRelPosX = nTmp; |
| } |
| } |
| else if ( _eHoriOrient == text::HoriOrientation::RIGHT ) |
| { |
| SwTwips nTmp = nOtherLeft - 1 - _rLRSpacing.GetRight() - |
| aObjBoundRect.Width() - |
| rAnchorTxtFrm.Frm().Left(); |
| if ( nTmp < nAdjustedRelPosX && |
| rAnchorTxtFrm.Frm().Left() + nTmp - _rLRSpacing.GetLeft() |
| >= pObjPage->Frm().Left() ) |
| { |
| nAdjustedRelPosX = nTmp; |
| } |
| } |
| aTmpObjRect.Pos().X() = rAnchorTxtFrm.Frm().Left() + |
| nAdjustedRelPosX; |
| } |
| } // end of <if (bVert)> |
| } // end of <if _DrawAsideFly(..)> |
| |
| pFly = ((SwVirtFlyDrawObj*)aIter.Next())->GetFlyFrm(); |
| } // end of <loop on fly frames |
| |
| return nAdjustedRelPosX; |
| } |
| |
| /** detemine, if object has to draw aside given fly frame |
| |
| method used by <_AdjustHoriRelPosForDrawAside(..)> |
| |
| @author OD |
| */ |
| bool SwAnchoredObjectPosition::_DrawAsideFly( const SwFlyFrm* _pFly, |
| const SwRect& _rObjRect, |
| const SwFrm* _pObjContext, |
| const sal_uLong _nObjIndex, |
| const bool _bEvenPage, |
| const sal_Int16 _eHoriOrient, |
| const sal_Int16 _eRelOrient |
| ) const |
| { |
| bool bRetVal = false; |
| |
| SWRECTFN( (&GetAnchorFrm()) ) |
| |
| if ( _pFly->IsFlyAtCntFrm() && |
| (_pFly->Frm().*fnRect->fnBottomDist)( (_rObjRect.*fnRect->fnGetTop)() ) < 0 && |
| (_rObjRect.*fnRect->fnBottomDist)( (_pFly->Frm().*fnRect->fnGetTop)() ) < 0 && |
| ::FindKontext( _pFly->GetAnchorFrm(), FRM_COLUMN ) == _pObjContext ) |
| { |
| sal_uLong nOtherIndex = |
| static_cast<const SwTxtFrm*>(_pFly->GetAnchorFrm())->GetTxtNode()->GetIndex(); |
| if( _nObjIndex >= nOtherIndex ) |
| { |
| const SwFmtHoriOrient& rHori = _pFly->GetFmt()->GetHoriOrient(); |
| sal_Int16 eOtherRelOrient = rHori.GetRelationOrient(); |
| if( text::RelOrientation::CHAR != eOtherRelOrient ) |
| { |
| sal_Int16 eOtherHoriOrient = rHori.GetHoriOrient(); |
| _ToggleHoriOrientAndAlign( _bEvenPage && rHori.IsPosToggle(), |
| eOtherHoriOrient, |
| eOtherRelOrient ); |
| if ( eOtherHoriOrient == _eHoriOrient && |
| _Minor( _eRelOrient, eOtherRelOrient, text::HoriOrientation::LEFT == _eHoriOrient ) ) |
| { |
| bRetVal = true; |
| } |
| } |
| } |
| } |
| |
| return bRetVal; |
| } |
| |
| /** determine, if object has to draw aside another object |
| |
| the different alignments of the objects determines, if one has |
| to draw aside another one. Thus, the given alignment are checked |
| against each other, which one has to be drawn aside the other one. |
| depending on parameter _bLeft check is done for left or right |
| positioning. |
| method used by <_DrawAsideFly(..)> |
| |
| @author OD |
| */ |
| bool SwAnchoredObjectPosition::_Minor( sal_Int16 _eRelOrient1, |
| sal_Int16 _eRelOrient2, |
| bool _bLeft ) const |
| { |
| bool bRetVal; |
| |
| // draw aside order for left horizontal position |
| //! one array entry for each value in text::RelOrientation |
| static sal_uInt16 __READONLY_DATA aLeft[ 10 ] = |
| { 5, 6, 0, 1, 8, 4, 7, 2, 3, 9 }; |
| // draw aside order for right horizontal position |
| //! one array entry for each value in text::RelOrientation |
| static sal_uInt16 __READONLY_DATA aRight[ 10 ] = |
| { 5, 6, 0, 8, 1, 7, 4, 2, 3, 9 }; |
| |
| // decide depending on given order, which frame has to draw aside another frame |
| if( _bLeft ) |
| bRetVal = aLeft[ _eRelOrient1 ] >= aLeft[ _eRelOrient2 ]; |
| else |
| bRetVal = aRight[ _eRelOrient1 ] >= aRight[ _eRelOrient2 ]; |
| |
| return bRetVal; |
| } |