summaryrefslogtreecommitdiff
path: root/sw/source/core/objectpositioning
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/objectpositioning')
-rw-r--r--sw/source/core/objectpositioning/anchoredobjectposition.cxx1129
-rw-r--r--sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx458
-rw-r--r--sw/source/core/objectpositioning/environmentofanchoredobject.cxx124
-rw-r--r--sw/source/core/objectpositioning/makefile.mk59
-rw-r--r--sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx1075
-rw-r--r--sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx245
6 files changed, 3090 insertions, 0 deletions
diff --git a/sw/source/core/objectpositioning/anchoredobjectposition.cxx b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
new file mode 100644
index 000000000000..78b9ba86e362
--- /dev/null
+++ b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
@@ -0,0 +1,1129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 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>
+#include <svx/svdobj.hxx>
+#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;
+ OSL_ENSURE( 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 ));
+ OSL_ENSURE( mpContact,
+ "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing SwContact-object." );
+ }
+
+ // determine anchored object, the object belongs to
+ {
+ // OD 2004-03-30 #i26791#
+ mpAnchoredObj = mpContact->GetAnchoredObj( &mrDrawObj );
+ OSL_ENSURE( mpAnchoredObj,
+ "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchored object." );
+ }
+
+ // determine frame, the object is anchored at
+ {
+ // OD 2004-03-23 #i26791#
+ mpAnchorFrm = mpAnchoredObj->AnchorFrm();
+ OSL_ENSURE( mpAnchorFrm,
+ "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchor frame." );
+ }
+
+ // determine format the object belongs to
+ {
+ // --> OD 2004-07-01 #i28701#
+ mpFrmFmt = &mpAnchoredObj->GetFrmFmt();
+ OSL_ENSURE( 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
+ {
+ OSL_ENSURE( 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
+ {
+ OSL_ENSURE( 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
+ {
+ OSL_ENSURE( 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:
+ {
+ nRelPosY += bVert ? _rLRSpacing.GetRight() : _rULSpacing.GetUpper();
+ }
+ break;
+ case text::VertOrientation::CENTER:
+ {
+ nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
+ }
+ break;
+ case text::VertOrientation::BOTTOM:
+ {
+ nRelPosY += nAlignAreaHeight -
+ ( nObjHeight + ( bVert ? _rLRSpacing.GetLeft() : _rULSpacing.GetLower() ) );
+ }
+ break;
+ default:
+ {
+ OSL_ENSURE( 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.
+
+ @author OD
+*/
+SwTwips SwAnchoredObjectPosition::_ImplAdjustVertRelPos( const SwTwips _nTopOfAnch,
+ const bool _bVert,
+ 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 2004-07-22 #i31805# - consider value of <_bCheckBottom>
+ if ( _bCheckBottom &&
+ _nTopOfAnch - nAdjustedRelPosY - aObjSize.Width() <
+ aPgAlignArea.Left() )
+ {
+ nAdjustedRelPosY = aPgAlignArea.Left() +
+ _nTopOfAnch -
+ aObjSize.Width();
+ }
+ // --> OD 2004-08-13 #i32964# - correction
+ if ( _nTopOfAnch - nAdjustedRelPosY > aPgAlignArea.Right() )
+ {
+ nAdjustedRelPosY = _nTopOfAnch - aPgAlignArea.Right();
+ }
+ // <--
+ }
+ else
+ {
+ // OD 2004-07-22 #i31805# - consider value of <_bCheckBottom>
+ if ( _bCheckBottom &&
+ _nTopOfAnch + nAdjustedRelPosY + aObjSize.Height() >
+ // --> OD 2006-01-13 #129959#
+ // Do not mix usage of <top + height> and <bottom>
+// aPgAlignArea.Bottom() )
+ aPgAlignArea.Top() + aPgAlignArea.Height() )
+ // <--
+ {
+ // --> OD 2006-01-13 #129959#
+ // Do not mix usage of <top + height> and <bottom>
+// nAdjustedRelPosY = aPgAlignArea.Bottom() -
+ 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) )
+ {
+ OSL_ENSURE( 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 UINT32 nObjOrdNum = GetObject().GetOrdNum();
+ const SwPageFrm* pObjPage = rFlyAtCntFrm.FindPageFrm();
+ const SwFrm* pObjContext = ::FindKontext( &rAnchorTxtFrm, FRM_COLUMN );
+ ULONG nObjIndex = rAnchorTxtFrm.GetTxtNode()->GetIndex();
+ SwOrderIter aIter( pObjPage, 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 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 )
+ {
+ 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 USHORT __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 USHORT __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;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx b/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx
new file mode 100644
index 000000000000..be6723d5bafa
--- /dev/null
+++ b/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx
@@ -0,0 +1,458 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <ascharanchoredobjectposition.hxx>
+#include <frame.hxx>
+#include <txtfrm.hxx>
+#include <flyfrms.hxx>
+#include <svx/svdobj.hxx>
+#include <dcontact.hxx>
+#include <frmfmt.hxx>
+#include <frmatr.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <fmtornt.hxx>
+
+#include <com/sun/star/text/HoriOrientation.hpp>
+
+
+using namespace ::com::sun::star;
+using namespace objectpositioning;
+
+/** constructor
+
+ @author OD
+*/
+SwAsCharAnchoredObjectPosition::SwAsCharAnchoredObjectPosition(
+ SdrObject& _rDrawObj,
+ const Point& _rProposedAnchorPos,
+ const AsCharFlags _nFlags,
+ const SwTwips _nLineAscent,
+ const SwTwips _nLineDescent,
+ const SwTwips _nLineAscentInclObjs,
+ const SwTwips _nLineDescentInclObjs )
+ : SwAnchoredObjectPosition( _rDrawObj ),
+ mrProposedAnchorPos( _rProposedAnchorPos ),
+ mnFlags( _nFlags ),
+ mnLineAscent( _nLineAscent ),
+ mnLineDescent( _nLineDescent ),
+ mnLineAscentInclObjs( _nLineAscentInclObjs ),
+ mnLineDescentInclObjs( _nLineDescentInclObjs ),
+ maAnchorPos ( Point() ),
+ mnRelPos ( 0 ),
+ maObjBoundRect ( SwRect() ),
+ mnLineAlignment ( 0 )
+{}
+
+/** destructor
+
+ @author OD
+*/
+SwAsCharAnchoredObjectPosition::~SwAsCharAnchoredObjectPosition()
+{}
+
+/** method to cast <SwAnchoredObjectPosition::GetAnchorFrm()> to needed type
+
+ @author OD
+*/
+const SwTxtFrm& SwAsCharAnchoredObjectPosition::GetAnchorTxtFrm() const
+{
+ OSL_ENSURE( GetAnchorFrm().ISA(SwTxtFrm),
+ "SwAsCharAnchoredObjectPosition::GetAnchorTxtFrm() - wrong anchor frame type" );
+
+ return static_cast<const SwTxtFrm&>(GetAnchorFrm());
+}
+
+/** calculate position for object
+
+ OD 30.07.2003 #110978#
+ members <maAnchorPos>, <mnRelPos>, <maObjBoundRect> and
+ <mnLineAlignment> are calculated.
+ calculated position is set at the given object.
+
+ @author OD
+*/
+void SwAsCharAnchoredObjectPosition::CalcPosition()
+{
+ const SwTxtFrm& rAnchorFrm = GetAnchorTxtFrm();
+ // swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
+ SwFrmSwapper aFrmSwapper( &rAnchorFrm, false );
+
+ SWRECTFN( ( &rAnchorFrm ) )
+
+ Point aAnchorPos( mrProposedAnchorPos );
+
+ const SwFrmFmt& rFrmFmt = GetFrmFmt();
+
+ SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
+ SwTwips nObjWidth = (aObjBoundRect.*fnRect->fnGetWidth)();
+
+ // determine spacing values considering layout-/text-direction
+ const SvxLRSpaceItem& rLRSpace = rFrmFmt.GetLRSpace();
+ const SvxULSpaceItem& rULSpace = rFrmFmt.GetULSpace();
+ SwTwips nLRSpaceLeft, nLRSpaceRight, nULSpaceUpper, nULSpaceLower;
+ {
+ if ( rAnchorFrm.IsVertical() )
+ {
+ // Seems to be easier to do it all the horizontal way
+ // So, from now on think horizontal.
+ rAnchorFrm.SwitchVerticalToHorizontal( aObjBoundRect );
+ rAnchorFrm.SwitchVerticalToHorizontal( aAnchorPos );
+
+ // convert the spacing values
+ nLRSpaceLeft = rULSpace.GetUpper();
+ nLRSpaceRight = rULSpace.GetLower();
+ nULSpaceUpper = rLRSpace.GetRight();
+ nULSpaceLower = rLRSpace.GetLeft();
+ }
+ else
+ {
+ if ( rAnchorFrm.IsRightToLeft() )
+ {
+ nLRSpaceLeft = rLRSpace.GetRight();
+ nLRSpaceRight = rLRSpace.GetLeft();
+ }
+ else
+ {
+ nLRSpaceLeft = rLRSpace.GetLeft();
+ nLRSpaceRight = rLRSpace.GetRight();
+ }
+
+ nULSpaceUpper = rULSpace.GetUpper();
+ nULSpaceLower = rULSpace.GetLower();
+ }
+ }
+
+ // consider left and upper spacing by adjusting anchor position.
+ // left spacing is only considered, if requested.
+ if( mnFlags & AS_CHAR_ULSPACE )
+ {
+ aAnchorPos.X() += nLRSpaceLeft;
+ }
+ aAnchorPos.Y() += nULSpaceUpper;
+
+ // for drawing objects: consider difference between its bounding rectangle
+ // and its snapping rectangle by adjusting anchor position.
+ // left difference is only considered, if requested.
+ if( !IsObjFly() )
+ {
+ SwRect aSnapRect = GetObject().GetSnapRect();
+ if ( rAnchorFrm.IsVertical() )
+ {
+ rAnchorFrm.SwitchVerticalToHorizontal( aSnapRect );
+ }
+
+ if( mnFlags & AS_CHAR_ULSPACE )
+ {
+ aAnchorPos.X() += aSnapRect.Left() - aObjBoundRect.Left();
+ }
+ aAnchorPos.Y() += aSnapRect.Top() - aObjBoundRect.Top();
+ }
+
+ // enlarge bounding rectangle of object by its spacing.
+ aObjBoundRect.Left( aObjBoundRect.Left() - nLRSpaceLeft );
+ aObjBoundRect.Width( aObjBoundRect.Width() + nLRSpaceRight );
+ aObjBoundRect.Top( aObjBoundRect.Top() - nULSpaceUpper );
+ aObjBoundRect.Height( aObjBoundRect.Height() + nULSpaceLower );
+
+ // calculate relative position to given base line.
+ const SwFmtVertOrient& rVert = rFrmFmt.GetVertOrient();
+ const SwTwips nObjBoundHeight = ( mnFlags & AS_CHAR_ROTATE )
+ ? aObjBoundRect.Width()
+ : aObjBoundRect.Height();
+ const SwTwips nRelPos = _GetRelPosToBase( nObjBoundHeight, rVert );
+
+ // for initial positioning:
+ // adjust the proposed anchor position by difference between
+ // calculated relative position to base line and current maximal line ascent.
+ // Note: In the following line formatting the base line will be adjusted
+ // by the same difference.
+ if( mnFlags & AS_CHAR_INIT && nRelPos < 0 && mnLineAscentInclObjs < -nRelPos )
+ {
+ if( mnFlags & AS_CHAR_ROTATE )
+ aAnchorPos.X() -= mnLineAscentInclObjs + nRelPos;
+ else
+ aAnchorPos.Y() -= mnLineAscentInclObjs + nRelPos;
+ }
+
+ // consider BIDI-multiportion by adjusting proposed anchor position
+ if( mnFlags & AS_CHAR_BIDI )
+ aAnchorPos.X() -= aObjBoundRect.Width();
+
+ // calculate relative position considering rotation and inside rotation
+ // reverse direction.
+ Point aRelPos;
+ {
+ if( mnFlags & AS_CHAR_ROTATE )
+ {
+ if( mnFlags & AS_CHAR_REVERSE )
+ aRelPos.X() = -nRelPos - aObjBoundRect.Width();
+ else
+ {
+ aRelPos.X() = nRelPos;
+ aRelPos.Y() = -aObjBoundRect.Height();
+ }
+ }
+ else
+ aRelPos.Y() = nRelPos;
+ }
+
+ if( !IsObjFly() )
+ {
+ if( !( mnFlags & AS_CHAR_QUICK ) )
+ {
+ // save calculated Y-position value for 'automatic' vertical positioning,
+ // in order to avoid a switch to 'manual' vertical positioning in
+ // <SwDrawContact::_Changed(..)>.
+ const sal_Int16 eVertOrient = rVert.GetVertOrient();
+ if( rVert.GetPos() != nRelPos && eVertOrient != text::VertOrientation::NONE )
+ {
+ SwFmtVertOrient aVert( rVert );
+ aVert.SetPos( nRelPos );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+
+ // determine absolute anchor position considering layout directions.
+ // Note: Use copy of <aAnchorPos>, because it's needed for
+ // setting relative position.
+ Point aAbsAnchorPos( aAnchorPos );
+ if ( rAnchorFrm.IsRightToLeft() )
+ {
+ rAnchorFrm.SwitchLTRtoRTL( aAbsAnchorPos );
+ aAbsAnchorPos.X() -= nObjWidth;
+ }
+ if ( rAnchorFrm.IsVertical() )
+ rAnchorFrm.SwitchHorizontalToVertical( aAbsAnchorPos );
+
+ // set proposed anchor position at the drawing object.
+ // OD 2004-04-06 #i26791# - distinction between 'master' drawing
+ // object and 'virtual' drawing object no longer needed.
+ GetObject().SetAnchorPos( aAbsAnchorPos );
+
+ // move drawing object to set its correct relative position.
+ {
+ SwRect aSnapRect = GetObject().GetSnapRect();
+ if ( rAnchorFrm.IsVertical() )
+ rAnchorFrm.SwitchVerticalToHorizontal( aSnapRect );
+
+ Point aDiff;
+ if ( rAnchorFrm.IsRightToLeft() )
+ aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
+ else
+ aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
+
+ if ( rAnchorFrm.IsVertical() )
+ aDiff = Point( -aDiff.Y(), aDiff.X() );
+
+ // OD 2004-04-06 #i26791# - distinction between 'master' drawing
+ // object and 'virtual' drawing object no longer needed.
+ GetObject().Move( Size( aDiff.X(), aDiff.Y() ) );
+ }
+ }
+
+ // switch horizontal, LTR anchor position to absolute values.
+ if ( rAnchorFrm.IsRightToLeft() )
+ {
+ rAnchorFrm.SwitchLTRtoRTL( aAnchorPos );
+ aAnchorPos.X() -= nObjWidth;
+ }
+ if ( rAnchorFrm.IsVertical() )
+ rAnchorFrm.SwitchHorizontalToVertical( aAnchorPos );
+
+ // --> OD 2005-03-09 #i44347# - keep last object rectangle at anchored object
+ OSL_ENSURE( GetAnchoredObj().ISA(SwAnchoredDrawObject),
+ "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong type of anchored object." );
+ SwAnchoredDrawObject& rAnchoredDrawObj =
+ static_cast<SwAnchoredDrawObject&>( GetAnchoredObj() );
+ rAnchoredDrawObj.SetLastObjRect( rAnchoredDrawObj.GetObjRect().SVRect() );
+ // <--
+ }
+ else
+ {
+ // determine absolute anchor position and calculate corresponding
+ // relative position and its relative position attribute.
+ // Note: The relative position contains the spacing values.
+ Point aRelAttr;
+ if ( rAnchorFrm.IsRightToLeft() )
+ {
+ rAnchorFrm.SwitchLTRtoRTL( aAnchorPos );
+ aAnchorPos.X() -= nObjWidth;
+ }
+ if ( rAnchorFrm.IsVertical() )
+ {
+ rAnchorFrm.SwitchHorizontalToVertical( aAnchorPos );
+ aRelAttr = Point( -nRelPos, 0 );
+ aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
+ }
+ else
+ aRelAttr = Point( 0, nRelPos );
+
+ // OD 2004-03-23 #i26791#
+ OSL_ENSURE( GetAnchoredObj().ISA(SwFlyInCntFrm),
+ "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong anchored object." );
+ const SwFlyInCntFrm& rFlyInCntFrm =
+ static_cast<const SwFlyInCntFrm&>(GetAnchoredObj());
+ if ( !(mnFlags & AS_CHAR_QUICK) &&
+ ( aAnchorPos != rFlyInCntFrm.GetRefPoint() ||
+ aRelAttr != rFlyInCntFrm.GetCurrRelPos() ) )
+ {
+ // set new anchor position and relative position
+ SwFlyInCntFrm* pFlyInCntFrm = &(const_cast<SwFlyInCntFrm&>(rFlyInCntFrm));
+ pFlyInCntFrm->SetRefPoint( aAnchorPos, aRelAttr, aRelPos );
+ if( nObjWidth != (pFlyInCntFrm->Frm().*fnRect->fnGetWidth)() )
+ {
+ // recalculate object bound rectangle, if object width has changed.
+ aObjBoundRect = GetAnchoredObj().GetObjRect();
+ aObjBoundRect.Left( aObjBoundRect.Left() - rLRSpace.GetLeft() );
+ aObjBoundRect.Width( aObjBoundRect.Width() + rLRSpace.GetRight() );
+ aObjBoundRect.Top( aObjBoundRect.Top() - rULSpace.GetUpper() );
+ aObjBoundRect.Height( aObjBoundRect.Height() + rULSpace.GetLower() );
+ }
+ }
+ OSL_ENSURE( (rFlyInCntFrm.Frm().*fnRect->fnGetHeight)(),
+ "SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
+ }
+
+ // keep calculated values
+ maAnchorPos = aAnchorPos;
+ mnRelPos = nRelPos;
+ maObjBoundRect = aObjBoundRect;
+}
+
+/** determine the relative position to base line for object position type AS_CHAR
+
+ OD 29.07.2003 #110978#
+ Note about values set at member <mnLineAlignment> -
+ value gives feedback for the line formatting.
+ 0 - no feedback; 1|2|3 - proposed formatting of characters
+ at top|at center|at bottom of line.
+
+ @author OD
+*/
+SwTwips SwAsCharAnchoredObjectPosition::_GetRelPosToBase(
+ const SwTwips _nObjBoundHeight,
+ const SwFmtVertOrient& _rVert )
+{
+ SwTwips nRelPosToBase = 0;
+
+ mnLineAlignment = 0;
+
+ const sal_Int16 eVertOrient = _rVert.GetVertOrient();
+
+ if ( eVertOrient == text::VertOrientation::NONE )
+ nRelPosToBase = _rVert.GetPos();
+ else
+ {
+ if ( eVertOrient == text::VertOrientation::CENTER )
+ nRelPosToBase -= _nObjBoundHeight / 2;
+ else if ( eVertOrient == text::VertOrientation::TOP )
+ nRelPosToBase -= _nObjBoundHeight;
+ else if ( eVertOrient == text::VertOrientation::BOTTOM )
+ nRelPosToBase = 0;
+ else if ( eVertOrient == text::VertOrientation::CHAR_CENTER )
+ nRelPosToBase -= ( _nObjBoundHeight + mnLineAscent - mnLineDescent ) / 2;
+ else if ( eVertOrient == text::VertOrientation::CHAR_TOP )
+ nRelPosToBase -= mnLineAscent;
+ else if ( eVertOrient == text::VertOrientation::CHAR_BOTTOM )
+ nRelPosToBase += mnLineDescent - _nObjBoundHeight;
+ else
+ {
+ if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
+ {
+ // object is at least as high as the line. Thus, no more is
+ // positioning necessary. Also, the max. ascent isn't changed.
+ nRelPosToBase -= mnLineAscentInclObjs;
+ if ( eVertOrient == text::VertOrientation::LINE_CENTER )
+ mnLineAlignment = 2;
+ else if ( eVertOrient == text::VertOrientation::LINE_TOP )
+ mnLineAlignment = 1;
+ else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
+ mnLineAlignment = 3;
+ }
+ else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
+ {
+ nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
+ mnLineAlignment = 2;
+ }
+ else if ( eVertOrient == text::VertOrientation::LINE_TOP )
+ {
+ nRelPosToBase -= mnLineAscentInclObjs;
+ mnLineAlignment = 1;
+ }
+ else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
+ {
+ nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
+ mnLineAlignment = 3;
+ }
+ }
+ }
+
+ return nRelPosToBase;
+}
+
+/** calculated anchored position for object position
+
+ @author OD
+*/
+Point SwAsCharAnchoredObjectPosition::GetAnchorPos() const
+{
+ return maAnchorPos;
+}
+
+/** calculated relative position to base line for object position
+
+ @author OD
+*/
+SwTwips SwAsCharAnchoredObjectPosition::GetRelPosY() const
+{
+ return mnRelPos;
+}
+
+/** determined object rectangle including spacing for object
+
+ @author OD
+*/
+SwRect SwAsCharAnchoredObjectPosition::GetObjBoundRectInclSpacing() const
+{
+ return maObjBoundRect;
+}
+
+/** determined line alignment
+
+ @author OD
+*/
+sal_uInt8 SwAsCharAnchoredObjectPosition::GetLineAlignment() const
+{
+ return mnLineAlignment;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/environmentofanchoredobject.cxx b/sw/source/core/objectpositioning/environmentofanchoredobject.cxx
new file mode 100644
index 000000000000..e9ad9ce59415
--- /dev/null
+++ b/sw/source/core/objectpositioning/environmentofanchoredobject.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#ifndef _ENVIRONMENTOFANCHOREDOBJECT
+#include <environmentofanchoredobject.hxx>
+#endif
+#include <frame.hxx>
+#include <pagefrm.hxx>
+#include <flyfrm.hxx>
+
+using namespace objectpositioning;
+
+SwEnvironmentOfAnchoredObject::SwEnvironmentOfAnchoredObject(
+ const bool _bFollowTextFlow )
+ : mbFollowTextFlow( _bFollowTextFlow )
+{}
+
+SwEnvironmentOfAnchoredObject::~SwEnvironmentOfAnchoredObject()
+{}
+
+/** determine environment layout frame for possible horizontal object positions
+
+ OD 05.11.2003
+
+ @author OD
+*/
+const SwLayoutFrm& SwEnvironmentOfAnchoredObject::GetHoriEnvironmentLayoutFrm(
+ const SwFrm& _rHoriOrientFrm ) const
+{
+ const SwFrm* pHoriEnvironmentLayFrm = &_rHoriOrientFrm;
+
+ if ( !mbFollowTextFlow )
+ {
+ // --> OD 2005-01-20 #118546# - no exception any more for page alignment.
+ // the page frame determines the horizontal layout environment.
+ pHoriEnvironmentLayFrm = _rHoriOrientFrm.FindPageFrm();
+ // <--
+ }
+ else
+ {
+ while ( !pHoriEnvironmentLayFrm->IsCellFrm() &&
+ !pHoriEnvironmentLayFrm->IsFlyFrm() &&
+ !pHoriEnvironmentLayFrm->IsPageFrm() )
+ {
+ pHoriEnvironmentLayFrm = pHoriEnvironmentLayFrm->GetUpper();
+ OSL_ENSURE( pHoriEnvironmentLayFrm,
+ "SwEnvironmentOfAnchoredObject::GetHoriEnvironmentLayoutFrm(..) - no page|fly|cell frame found" );
+ }
+ }
+
+ OSL_ENSURE( pHoriEnvironmentLayFrm->ISA(SwLayoutFrm),
+ "SwEnvironmentOfAnchoredObject::GetHoriEnvironmentLayoutFrm(..) - found frame isn't a layout frame" );
+
+ return static_cast<const SwLayoutFrm&>(*pHoriEnvironmentLayFrm);
+}
+
+/** determine environment layout frame for possible vertical object positions
+
+ OD 05.11.2003
+
+ @author OD
+*/
+const SwLayoutFrm& SwEnvironmentOfAnchoredObject::GetVertEnvironmentLayoutFrm(
+ const SwFrm& _rVertOrientFrm ) const
+{
+ const SwFrm* pVertEnvironmentLayFrm = &_rVertOrientFrm;
+
+ if ( !mbFollowTextFlow )
+ {
+ // --> OD 2005-01-20 #118546# - no exception any more for page alignment.
+ // the page frame determines the vertical layout environment.
+ pVertEnvironmentLayFrm = _rVertOrientFrm.FindPageFrm();
+ // <--
+ }
+ else
+ {
+ while ( !pVertEnvironmentLayFrm->IsCellFrm() &&
+ !pVertEnvironmentLayFrm->IsFlyFrm() &&
+ !pVertEnvironmentLayFrm->IsHeaderFrm() &&
+ !pVertEnvironmentLayFrm->IsFooterFrm() &&
+ !pVertEnvironmentLayFrm->IsFtnFrm() &&
+ !pVertEnvironmentLayFrm->IsPageBodyFrm() &&
+ !pVertEnvironmentLayFrm->IsPageFrm() )
+ {
+ pVertEnvironmentLayFrm = pVertEnvironmentLayFrm->GetUpper();
+ OSL_ENSURE( pVertEnvironmentLayFrm,
+ "SwEnvironmentOfAnchoredObject::GetVertEnvironmentLayoutFrm(..) - proposed frame not found" );
+ }
+ }
+
+ OSL_ENSURE( pVertEnvironmentLayFrm->ISA(SwLayoutFrm),
+ "SwEnvironmentOfAnchoredObject::GetVertEnvironmentLayoutFrm(..) - found frame isn't a layout frame" );
+
+ return static_cast<const SwLayoutFrm&>(*pVertEnvironmentLayFrm);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/makefile.mk b/sw/source/core/objectpositioning/makefile.mk
new file mode 100644
index 000000000000..4192414d9b73
--- /dev/null
+++ b/sw/source/core/objectpositioning/makefile.mk
@@ -0,0 +1,59 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=sw
+TARGET=objectpositioning
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : $(PRJ)$/inc$/swpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/inc$/sw.mk
+
+.IF "$(mydebug)" != ""
+CDEFS+=-Dmydebug
+.ENDIF
+
+.IF "$(madebug)" != ""
+CDEFS+=-DDEBUG
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/anchoredobjectposition.obj \
+ $(SLO)$/ascharanchoredobjectposition.obj \
+ $(SLO)$/tolayoutanchoredobjectposition.obj \
+ $(SLO)$/tocntntanchoredobjectposition.obj \
+ $(SLO)$/environmentofanchoredobject.obj
+
+# --- Targets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
new file mode 100644
index 000000000000..b1a96bf97078
--- /dev/null
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -0,0 +1,1075 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <tocntntanchoredobjectposition.hxx>
+#include <anchoredobject.hxx>
+#include <frame.hxx>
+#include <txtfrm.hxx>
+#include <pagefrm.hxx>
+#include <sectfrm.hxx>
+// --> OD 2004-10-15 #i26945#
+#include <tabfrm.hxx>
+// <--
+#include <frmfmt.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfsize.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <svx/svdobj.hxx>
+#include <pam.hxx>
+#include <environmentofanchoredobject.hxx>
+#include <frmtool.hxx>
+#include <ndtxt.hxx>
+#include <dflyobj.hxx>
+
+using namespace objectpositioning;
+using namespace ::com::sun::star;
+
+
+SwToCntntAnchoredObjectPosition::SwToCntntAnchoredObjectPosition( SdrObject& _rDrawObj )
+ : SwAnchoredObjectPosition ( _rDrawObj ),
+ mpVertPosOrientFrm( 0 ),
+ // --> OD 2004-06-17 #i26791#
+ maOffsetToFrmAnchorPos( Point() ),
+ mbAnchorToChar ( false ),
+ mpToCharOrientFrm( 0 ),
+ mpToCharRect( 0 ),
+ // OD 12.11.2003 #i22341#
+ mnToCharTopOfLine( 0 )
+{}
+
+SwToCntntAnchoredObjectPosition::~SwToCntntAnchoredObjectPosition()
+{}
+
+bool SwToCntntAnchoredObjectPosition::IsAnchoredToChar() const
+{
+ return mbAnchorToChar;
+}
+
+const SwFrm* SwToCntntAnchoredObjectPosition::ToCharOrientFrm() const
+{
+ return mpToCharOrientFrm;
+}
+
+const SwRect* SwToCntntAnchoredObjectPosition::ToCharRect() const
+{
+ return mpToCharRect;
+}
+
+// OD 12.11.2003 #i22341#
+SwTwips SwToCntntAnchoredObjectPosition::ToCharTopOfLine() const
+{
+ return mnToCharTopOfLine;
+}
+
+SwTxtFrm& SwToCntntAnchoredObjectPosition::GetAnchorTxtFrm() const
+{
+ OSL_ENSURE( GetAnchorFrm().ISA(SwTxtFrm),
+ "SwToCntntAnchoredObjectPosition::GetAnchorTxtFrm() - wrong anchor frame type" );
+
+ return static_cast<SwTxtFrm&>(GetAnchorFrm());
+}
+
+// --> OD 2004-07-20 #i23512#
+bool lcl_DoesVertPosFits( const SwTwips _nRelPosY,
+ const SwTwips _nAvail,
+ const SwLayoutFrm* _pUpperOfOrientFrm,
+ const bool _bBrowse,
+ const bool _bGrowInTable,
+ SwLayoutFrm*& _orpLayoutFrmToGrow )
+{
+ bool bVertPosFits = false;
+
+ if ( _nRelPosY <= _nAvail )
+ {
+ bVertPosFits = true;
+ }
+ else if ( _bBrowse )
+ {
+ if ( _pUpperOfOrientFrm->IsInSct() )
+ {
+ SwSectionFrm* pSctFrm =
+ const_cast<SwSectionFrm*>(_pUpperOfOrientFrm->FindSctFrm());
+ bVertPosFits = pSctFrm->GetUpper()->Grow( _nRelPosY - _nAvail, TRUE ) > 0;
+ // Note: do not provide a layout frame for a grow.
+ }
+ else
+ {
+ bVertPosFits = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm)->
+ Grow( _nRelPosY - _nAvail, TRUE ) > 0;
+ if ( bVertPosFits )
+ _orpLayoutFrmToGrow = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm);
+ }
+ }
+ else if ( _pUpperOfOrientFrm->IsInTab() && _bGrowInTable )
+ {
+ // --> OD 2005-06-08 #i45085# - check, if upper frame would grow the
+ // excepted amount of twips.
+ const SwTwips nTwipsGrown = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm)->
+ Grow( _nRelPosY - _nAvail, TRUE ) > 0;
+ bVertPosFits = ( nTwipsGrown == ( _nRelPosY - _nAvail ) );
+ // <--
+ if ( bVertPosFits )
+ _orpLayoutFrmToGrow = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm);
+ }
+
+ return bVertPosFits;
+}
+// <--
+
+void SwToCntntAnchoredObjectPosition::CalcPosition()
+{
+ // get format of object
+ const SwFrmFmt& rFrmFmt = GetFrmFmt();
+
+ // declare and set <pFooter> to footer frame, if object is anchored
+ // at a frame belonging to the footer.
+ const SwFrm* pFooter = GetAnchorFrm().FindFooterOrHeader();
+ if ( pFooter && !pFooter->IsFooterFrm() )
+ pFooter = NULL;
+
+ // declare and set <bBrowse> to true, if document is in browser mode and
+ // object is anchored at the body, but not at frame belonging to a table.
+ const bool bBrowse = GetAnchorFrm().IsInDocBody() &&
+ !GetAnchorFrm().IsInTab()
+ ? rFrmFmt.getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE)
+ : false;
+
+ // determine left/right and its upper/lower spacing.
+ const SvxLRSpaceItem &rLR = rFrmFmt.GetLRSpace();
+ const SvxULSpaceItem &rUL = rFrmFmt.GetULSpace();
+
+ // determine, if object has no surrounding.
+ const SwFmtSurround& rSurround = rFrmFmt.GetSurround();
+ const bool bNoSurround = rSurround.GetSurround() == SURROUND_NONE;
+ const bool bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT;
+
+ // OD 29.10.2003 #110978# - new class <SwEnvironmentOfAnchoredObject>
+ SwEnvironmentOfAnchoredObject aEnvOfObj( DoesObjFollowsTextFlow() );
+
+ // OD 30.09.2003 #i18732# - grow only, if object has to follow the text flow
+ const bool bGrow = DoesObjFollowsTextFlow() &&
+ ( !GetAnchorFrm().IsInTab() ||
+ !rFrmFmt.GetFrmSize().GetHeightPercent() );
+
+ // get text frame the object is anchored at
+ const SwTxtFrm& rAnchorTxtFrm = GetAnchorTxtFrm();
+ SWRECTFN( (&rAnchorTxtFrm) )
+
+ const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
+
+ // local variable keeping the calculated relative position; initialized with
+ // current relative position.
+ // OD 2004-03-24 #i26791# - use new object instance of <SwAnchoredObject>
+ Point aRelPos( GetAnchoredObj().GetCurrRelPos() );
+
+ SwTwips nRelDiff = 0;
+
+ bool bMoveable = rAnchorTxtFrm.IsMoveable();
+
+ // determine frame the object position has to be oriented at.
+ const SwTxtFrm* pOrientFrm = &rAnchorTxtFrm;
+ const SwTxtFrm* pAnchorFrmForVertPos = &rAnchorTxtFrm;
+ {
+ // if object is at-character anchored, determine character-rectangle
+ // and frame, position has to be oriented at.
+ mbAnchorToChar = (FLY_AT_CHAR == rFrmFmt.GetAnchor().GetAnchorId());
+ if ( mbAnchorToChar )
+ {
+ const SwFmtAnchor& rAnch = rFrmFmt.GetAnchor();
+ // OD 2004-03-24 #i26791# - use new object instance of <SwAnchoredObject>
+ // OD 2005-01-12 - Due to table break algorithm the character
+ // rectangle can have no height. Thus, check also the width
+ if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
+ !GetAnchoredObj().GetLastCharRect().Width() ) ||
+ !GetAnchoredObj().GetLastTopOfLine() )
+ {
+ // --> OD 2010-07-02 #i111886#
+ // Check existence of paragraph portion information in order
+ // to avoid formatting which could cause deletion of follow frames.
+ GetAnchoredObj().CheckCharRectAndTopOfLine();
+ // <--
+ // OD 2005-01-12 - Due to table break algorithm the character
+ // rectangle can have no height. Thus, check also the width
+ if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
+ !GetAnchoredObj().GetLastCharRect().Width() ) ||
+ !GetAnchoredObj().GetLastTopOfLine() )
+ {
+ // --> OD 2005-01-12 - get default for <mpVertPosOrientFrm>,
+ // if it's not set.
+ if ( !mpVertPosOrientFrm )
+ {
+ mpVertPosOrientFrm = rAnchorTxtFrm.GetUpper();
+ }
+ // <--
+ return;
+ }
+ }
+ mpToCharRect = &(GetAnchoredObj().GetLastCharRect());
+ // OD 12.11.2003 #i22341# - get top of line, in which the anchor
+ // character is.
+ mnToCharTopOfLine = GetAnchoredObj().GetLastTopOfLine();
+ pOrientFrm = &(const_cast<SwTxtFrm&>(rAnchorTxtFrm).GetFrmAtOfst(
+ rAnch.GetCntntAnchor()->nContent.GetIndex() ) );
+ mpToCharOrientFrm = pOrientFrm;
+ }
+ }
+ SWREFRESHFN( pOrientFrm )
+
+ // determine vertical position
+ {
+
+ // determine vertical positioning and alignment attributes
+ SwFmtVertOrient aVert( rFrmFmt.GetVertOrient() );
+
+ // OD 22.09.2003 #i18732# - determine layout frame for vertical
+ // positions aligned to 'page areas'.
+ const SwLayoutFrm& rPageAlignLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pOrientFrm );
+
+ if ( aVert.GetVertOrient() != text::VertOrientation::NONE )
+ {
+ // OD 22.09.2003 #i18732# - adjustments for follow text flow or not
+ // AND vertical alignment at 'page areas'.
+ SwTwips nAlignAreaHeight;
+ SwTwips nAlignAreaOffset;
+ _GetVertAlignmentValues( *pOrientFrm, rPageAlignLayFrm,
+ aVert.GetRelationOrient(),
+ nAlignAreaHeight, nAlignAreaOffset );
+
+ // determine relative vertical position
+ SwTwips nRelPosY = nAlignAreaOffset;
+ SwTwips nObjHeight = (aObjBoundRect.*fnRect->fnGetHeight)();
+ SwTwips nUpperSpace = bVert ? rLR.GetRight() : rUL.GetUpper();
+ SwTwips nLowerSpace = bVert ? rLR.GetLeft() : rUL.GetLower();
+ switch ( aVert.GetVertOrient() )
+ {
+ case text::VertOrientation::CHAR_BOTTOM:
+ {
+ if ( mbAnchorToChar )
+ {
+ // bottom (to character anchored)
+ nRelPosY += nAlignAreaHeight + nUpperSpace;
+ if ( bVert )
+ nRelPosY += nObjHeight;
+ break;
+ }
+ }
+ // no break here
+ case text::VertOrientation::TOP:
+ {
+ // OD 12.11.2003 #i22341# - special case for vertical
+ // alignment at top of line
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY -= (nObjHeight + nLowerSpace);
+ }
+ else
+ {
+ nRelPosY += nUpperSpace;
+ }
+ }
+ break;
+ // OD 14.11.2003 #i22341#
+ case text::VertOrientation::LINE_TOP:
+ {
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY -= (nObjHeight + nLowerSpace);
+ }
+ else
+ {
+ OSL_ENSURE( false,
+ "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
+ }
+ }
+ break;
+ case text::VertOrientation::CENTER:
+ {
+ nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
+ }
+ break;
+ // OD 14.11.2003 #i22341#
+ case text::VertOrientation::LINE_CENTER:
+ {
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
+ }
+ else
+ {
+ OSL_ENSURE( false,
+ "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
+ }
+ }
+ break;
+ case text::VertOrientation::BOTTOM:
+ {
+ if ( ( aVert.GetRelationOrient() == text::RelOrientation::FRAME ||
+ aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
+ bNoSurround )
+ {
+ // bottom (aligned to 'paragraph areas')
+ nRelPosY += nAlignAreaHeight + nUpperSpace;
+ }
+ else
+ {
+ // OD 12.11.2003 #i22341# - special case for vertical
+ // alignment at top of line
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY += nUpperSpace;
+ }
+ else
+ {
+ nRelPosY += nAlignAreaHeight -
+ ( nObjHeight + nLowerSpace );
+ }
+ }
+ }
+ break;
+ // OD 14.11.2003 #i22341#
+ case text::VertOrientation::LINE_BOTTOM:
+ {
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY += nUpperSpace;
+ }
+ else
+ {
+ OSL_ENSURE( false,
+ "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ // adjust relative position by distance between anchor frame and
+ // the frame, the object is oriented at.
+ // OD 2004-05-21 #i28701# - correction: adjust relative position,
+ // only if the floating screen object has to follow the text flow.
+ if ( DoesObjFollowsTextFlow() && pOrientFrm != &rAnchorTxtFrm )
+ {
+ // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos>
+ // to get top of frame for object positioning.
+ const SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrm, fnRect, bVert );
+ nRelPosY += (*fnRect->fnYDiff)( nTopOfOrient,
+ _GetTopForObjPos( rAnchorTxtFrm, fnRect, bVert ) );
+ }
+
+ // --> OD 2005-02-07 #i42124# - capture object inside vertical
+ // layout environment.
+ {
+ const SwTwips nTopOfAnch =
+ _GetTopForObjPos( *pOrientFrm, fnRect, bVert );
+ const SwLayoutFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm(
+ *(pOrientFrm->GetUpper()) );
+ const bool bCheckBottom = !DoesObjFollowsTextFlow();
+ nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert,
+ rVertEnvironLayFrm, nRelPosY,
+ DoesObjFollowsTextFlow(),
+ bCheckBottom );
+ }
+ // <--
+ // keep calculated relative vertical position - needed for filters
+ // (including the xml-filter)
+ {
+ // determine position
+ SwTwips nAttrRelPosY = nRelPosY - nAlignAreaOffset;
+ // set
+ if ( nAttrRelPosY != aVert.GetPos() )
+ {
+ aVert.SetPos( nAttrRelPosY );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+ }
+
+ // determine absolute 'vertical' position, depending on layout-direction
+ // --> OD 2004-06-17 #i26791# - determine offset to 'vertical' frame
+ // anchor position, depending on layout-direction
+ if ( bVert )
+ {
+ aRelPos.X() = nRelPosY;
+ maOffsetToFrmAnchorPos.X() = nAlignAreaOffset;
+ }
+ else
+ {
+ aRelPos.Y() = nRelPosY;
+ maOffsetToFrmAnchorPos.Y() = nAlignAreaOffset;
+ }
+ }
+
+ // OD 29.10.2003 #110978# - determine upper of frame vertical position
+ // is oriented at.
+ // OD 2004-05-21 #i28701# - determine 'virtual' anchor frame.
+ // This frame is used in the following instead of the 'real' anchor
+ // frame <rAnchorTxtFrm> for the 'vertical' position in all cases.
+ const SwLayoutFrm* pUpperOfOrientFrm = 0L;
+ {
+ // OD 2004-05-21 #i28701# - As long as the anchor frame is on the
+ // same page as <pOrientFrm> and the vertical position isn't aligned
+ // automatic at the anchor character or the top of the line of the
+ // anchor character, the anchor frame determines the vertical position.
+ if ( &rAnchorTxtFrm == pOrientFrm ||
+ ( rAnchorTxtFrm.FindPageFrm() == pOrientFrm->FindPageFrm() &&
+ aVert.GetVertOrient() == text::VertOrientation::NONE &&
+ aVert.GetRelationOrient() != text::RelOrientation::CHAR &&
+ aVert.GetRelationOrient() != text::RelOrientation::TEXT_LINE ) )
+ {
+ pUpperOfOrientFrm = rAnchorTxtFrm.GetUpper();
+ pAnchorFrmForVertPos = &rAnchorTxtFrm;
+ }
+ else
+ {
+ pUpperOfOrientFrm = pOrientFrm->GetUpper();
+ pAnchorFrmForVertPos = pOrientFrm;
+ }
+ }
+
+ // ignore one-column sections.
+ // --> OD 2004-07-20 #i23512# - correction: also ignore one-columned
+ // sections with footnotes/endnotes
+ if ( pUpperOfOrientFrm->IsInSct() )
+ {
+ const SwSectionFrm* pSctFrm = pUpperOfOrientFrm->FindSctFrm();
+ const bool bIgnoreSection = pUpperOfOrientFrm->IsSctFrm() ||
+ ( pSctFrm->Lower()->IsColumnFrm() &&
+ !pSctFrm->Lower()->GetNext() );
+ if ( bIgnoreSection )
+ pUpperOfOrientFrm = pSctFrm->GetUpper();
+ }
+
+ if ( aVert.GetVertOrient() == text::VertOrientation::NONE )
+ {
+ // local variable <nRelPosY> for calculation of relative vertical
+ // distance to anchor.
+ SwTwips nRelPosY = 0;
+ // --> OD 2004-06-17 #i26791# - local variable <nVertOffsetToFrmAnchorPos>
+ // for determination of the 'vertical' offset to the frame anchor
+ // position
+ SwTwips nVertOffsetToFrmAnchorPos( 0L );
+ // OD 12.11.2003 #i22341# - add special case for vertical alignment
+ // at top of line.
+ if ( mbAnchorToChar &&
+ ( aVert.GetRelationOrient() == text::RelOrientation::CHAR ||
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) )
+ {
+ // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos>
+ // to get top of frame for object positioning.
+ SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrm, fnRect, bVert );
+ if ( aVert.GetRelationOrient() == text::RelOrientation::CHAR )
+ {
+ nVertOffsetToFrmAnchorPos = (*fnRect->fnYDiff)(
+ (ToCharRect()->*fnRect->fnGetBottom)(),
+ nTopOfOrient );
+ }
+ else
+ {
+ nVertOffsetToFrmAnchorPos = (*fnRect->fnYDiff)( ToCharTopOfLine(),
+ nTopOfOrient );
+ }
+ nRelPosY = nVertOffsetToFrmAnchorPos - aVert.GetPos();
+ }
+ else
+ {
+ // OD 2004-05-21 #i28701# - correction: use <pAnchorFrmForVertPos>
+ // instead of <pOrientFrm> and do not adjust relative position
+ // to get correct vertical position.
+ nVertOffsetToFrmAnchorPos = 0L;
+ // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos>
+ // to get top of frame for object positioning.
+ const SwTwips nTopOfOrient =
+ _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ // OD 02.10.2002 #102646# - increase <nRelPosY> by margin height,
+ // if position is vertical aligned to "paragraph text area"
+ if ( aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
+ {
+ // OD 2004-03-11 #i11860# - consider upper space amount
+ // of previous frame
+ SwTwips nTopMargin = (pAnchorFrmForVertPos->*fnRect->fnGetTopMargin)();
+ if ( pAnchorFrmForVertPos->IsTxtFrm() )
+ {
+ nTopMargin -= static_cast<const SwTxtFrm*>(pAnchorFrmForVertPos)->
+ GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
+ }
+ nVertOffsetToFrmAnchorPos += nTopMargin;
+ }
+ // OD 22.09.2003 #i18732# - adjust <nRelPosY> by difference
+ // between 'page area' and 'anchor' frame, if position is
+ // vertical aligned to 'page areas'
+ else if ( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME )
+ {
+ nVertOffsetToFrmAnchorPos += (*fnRect->fnYDiff)(
+ (rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(),
+ nTopOfOrient );
+ }
+ else if ( aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ SwRect aPgPrtRect( rPageAlignLayFrm.Frm() );
+ if ( rPageAlignLayFrm.IsPageFrm() )
+ {
+ aPgPrtRect =
+ static_cast<const SwPageFrm&>(rPageAlignLayFrm).PrtWithoutHeaderAndFooter();
+ }
+ nVertOffsetToFrmAnchorPos += (*fnRect->fnYDiff)(
+ (aPgPrtRect.*fnRect->fnGetTop)(),
+ nTopOfOrient );
+ }
+ nRelPosY = nVertOffsetToFrmAnchorPos + aVert.GetPos();
+ }
+
+ // <pUpperOfOrientFrm>: layout frame, at which the position has to
+ // is oriented at
+ // <nRelPosY>: rest of the relative distance in the current
+ // layout frame
+ // <nAvail>: space, which is available in the current
+ // layout frame
+
+ // --> OD 2004-06-17 #i26791# - determine offset to 'vertical'
+ // frame anchor position, depending on layout-direction
+ if ( bVert )
+ maOffsetToFrmAnchorPos.X() = nVertOffsetToFrmAnchorPos;
+ else
+ maOffsetToFrmAnchorPos.Y() = nVertOffsetToFrmAnchorPos;
+ // <--
+ // OD 2004-03-11 #i11860# - use new method <_GetTopForObjPos>
+ // to get top of frame for object positioning.
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ if( nRelPosY <= 0 )
+ {
+ // OD 08.09.2003 #110354# - allow negative position, but keep it
+ // inside environment layout frame.
+ const SwLayoutFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
+ // --> OD 2004-07-22 #i31805# - do not check, if bottom of
+ // anchored object would fit into environment layout frame, if
+ // anchored object has to follow the text flow.
+ const bool bCheckBottom = !DoesObjFollowsTextFlow();
+ nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert,
+ rVertEnvironLayFrm, nRelPosY,
+ DoesObjFollowsTextFlow(),
+ bCheckBottom );
+ // <--
+ if ( bVert )
+ aRelPos.X() = nRelPosY;
+ else
+ aRelPos.Y() = nRelPosY;
+ }
+ else
+ {
+ SWREFRESHFN( pAnchorFrmForVertPos )
+ SwTwips nAvail =
+ (*fnRect->fnYDiff)( (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(),
+ nTopOfAnch );
+ const bool bInFtn = pAnchorFrmForVertPos->IsInFtn();
+ while ( nRelPosY )
+ {
+ // --> OD 2004-07-20 #i23512# - correction:
+ // consider section frame for grow in online layout.
+ // use new local method <lcl_DoesVertPosFits(..)>
+ SwLayoutFrm* pLayoutFrmToGrow = 0L;
+ const bool bDoesVertPosFits = lcl_DoesVertPosFits(
+ nRelPosY, nAvail, pUpperOfOrientFrm, bBrowse,
+ bGrow, pLayoutFrmToGrow );
+
+ if ( bDoesVertPosFits )
+ {
+ SwTwips nTmpRelPosY =
+ (*fnRect->fnYDiff)( (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(),
+ nTopOfAnch ) -
+ nAvail + nRelPosY;
+ // --> OD 2004-07-06 #i28701# - adjust calculated
+ // relative vertical position to object's environment.
+ const SwFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
+ // --> OD 2004-08-20 - do not check, if bottom of
+ // anchored object would fit into environment layout
+ // frame, if anchored object has to follow the text flow.
+ const bool bCheckBottom = !DoesObjFollowsTextFlow();
+ nTmpRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert,
+ rVertEnvironLayFrm,
+ nTmpRelPosY,
+ DoesObjFollowsTextFlow(),
+ bCheckBottom );
+ // <--
+ if ( bVert )
+ aRelPos.X() = nTmpRelPosY;
+ else
+ aRelPos.Y() = nTmpRelPosY;
+
+ // --> OD 2004-07-20 #i23512# - use local variable
+ // <pLayoutFrmToGrow> provided by new method
+ // <lcl_DoesVertPosFits(..)>.
+ if ( pLayoutFrmToGrow )
+ {
+ pLayoutFrmToGrow->Grow( nRelPosY - nAvail );
+ }
+ // <--
+ nRelPosY = 0;
+ }
+ else
+ {
+ // --> OD 2004-10-04 #i26495# - floating screen objects,
+ // which are anchored inside a table, doesn't follow
+ // the text flow.
+ if ( DoesObjFollowsTextFlow() &&
+ !( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
+ aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) &&
+ !GetAnchorFrm().IsInTab() )
+ // <--
+ {
+ if ( bMoveable )
+ {
+ // follow the text flow
+ nRelPosY -= nAvail;
+ MakePageType eMakePage = bInFtn ? MAKEPAGE_NONE
+ : MAKEPAGE_APPEND;
+ const bool bInSct = pUpperOfOrientFrm->IsInSct();
+ if( bInSct )
+ eMakePage = MAKEPAGE_NOSECTION;
+
+ const SwLayoutFrm* pTmp =
+ pUpperOfOrientFrm->GetLeaf( eMakePage, TRUE, &rAnchorTxtFrm );
+ if ( pTmp &&
+ ( !bInSct ||
+ pUpperOfOrientFrm->FindSctFrm()->IsAnFollow( pTmp->FindSctFrm() ) ) )
+ {
+ pUpperOfOrientFrm = pTmp;
+ bMoveable = rAnchorTxtFrm.IsMoveable( (SwLayoutFrm*)pUpperOfOrientFrm );
+ SWREFRESHFN( pUpperOfOrientFrm )
+ nAvail = (pUpperOfOrientFrm->Prt().*fnRect->fnGetHeight)();
+ }
+ else
+ {
+ // if there isn't enough space in the (colmuned)
+ // section, leave it and set available space <nAvail>
+ // to the space below the section.
+ // if the new available space isn't also enough,
+ // new pages can be created.
+ if( bInSct )
+ {
+ const SwFrm* pSct = pUpperOfOrientFrm->FindSctFrm();
+ pUpperOfOrientFrm = pSct->GetUpper();
+ nAvail = (*fnRect->fnYDiff)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(),
+ (pSct->*fnRect->fnGetPrtBottom)() );
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( false, "<SwToCntntAnchoredObjectPosition::CalcPosition()> - code under investigation by OD, please inform OD about this assertion!" );
+#endif
+ nRelDiff = nRelPosY;
+ nRelPosY = 0;
+ }
+ }
+ }
+ else
+ {
+ nRelPosY = 0;
+ }
+ }
+ else
+ {
+ // OD 06.10.2003 #i18732# - do not follow text flow respectively
+ // align at 'page areas', but stay inside given environment
+ const SwFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
+ nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert,
+ rVertEnvironLayFrm,
+ nRelPosY,
+ DoesObjFollowsTextFlow() );
+ if( bVert )
+ aRelPos.X() = nRelPosY;
+ else
+ aRelPos.Y() = nRelPosY;
+ nRelPosY = 0;
+ }
+ }
+ } // end of <while ( nRelPosY )>
+ } // end of else <nRelPosY <= 0>
+ } // end of <aVert.GetVertOrient() == text::VertOrientation::NONE>
+
+ //Damit das Teil ggf. auf die richtige Seite gestellt und in die
+ //PrtArea des LayLeaf gezogen werden kann, muss hier seine
+ //absolute Position berechnet werden.
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ if( bVert )
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ ( aRelPos.X() - nRelDiff ) -
+ aObjBoundRect.Width() );
+ }
+ else
+ {
+ GetAnchoredObj().SetObjTop( nTopOfAnch +
+ ( aRelPos.Y() - nRelDiff ) );
+ }
+
+ // grow environment under certain conditions
+ // ignore one-column sections.
+ // --> OD 2004-07-20 #i23512# - correction: also ignore one-columned
+ // sections with footnotes/endnotes
+ if ( pUpperOfOrientFrm->IsInSct() )
+ {
+ const SwSectionFrm* pSctFrm = pUpperOfOrientFrm->FindSctFrm();
+ const bool bIgnoreSection = pUpperOfOrientFrm->IsSctFrm() ||
+ ( pSctFrm->Lower()->IsColumnFrm() &&
+ !pSctFrm->Lower()->GetNext() );
+ if ( bIgnoreSection )
+ pUpperOfOrientFrm = pSctFrm->GetUpper();
+ }
+ SwTwips nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
+ if( nDist < 0 )
+ {
+ // --> OD 2004-07-20 #i23512# - correction:
+ // consider section frame for grow in online layout and
+ // consider page alignment for grow in table.
+ SwLayoutFrm* pLayoutFrmToGrow = 0L;
+ if ( bBrowse && rAnchorTxtFrm.IsMoveable() )
+ {
+ if ( pUpperOfOrientFrm->IsInSct() )
+ {
+ pLayoutFrmToGrow = const_cast<SwLayoutFrm*>(
+ pUpperOfOrientFrm->FindSctFrm()->GetUpper());
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pLayoutFrmToGrow->*fnRect->fnGetPrtBottom)() );
+ if ( nDist >= 0 )
+ {
+ pLayoutFrmToGrow = 0L;
+ }
+ }
+ else
+ {
+ pLayoutFrmToGrow =
+ const_cast<SwLayoutFrm*>(pUpperOfOrientFrm);
+ }
+ }
+ else if ( rAnchorTxtFrm.IsInTab() && bGrow )
+ {
+ pLayoutFrmToGrow = const_cast<SwLayoutFrm*>(pUpperOfOrientFrm);
+ }
+ if ( pLayoutFrmToGrow )
+ {
+ pLayoutFrmToGrow->Grow( -nDist );
+ }
+ // <--
+ }
+
+ if ( DoesObjFollowsTextFlow() &&
+ !( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
+ aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) )
+ {
+
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
+ // --> OD 2004-10-04 #i26945# - floating screen objects, which are
+ // anchored inside a table, doesn't follow the text flow. But, they
+ // have to stay inside its layout environment.
+ if ( nDist < 0 && pOrientFrm->IsInTab() )
+ {
+ // If the anchor frame is the first content of the table cell
+ // and has no follow, the table frame is notified,
+ // that the object doesn't fit into the table cell.
+ // Adjustment of position isn't needed in this case.
+ if ( pOrientFrm == &rAnchorTxtFrm &&
+ !pOrientFrm->GetFollow() &&
+ !pOrientFrm->GetIndPrev() )
+ {
+ const_cast<SwTabFrm*>(pOrientFrm->FindTabFrm())
+ ->SetDoesObjsFit( FALSE );
+ }
+ else
+ {
+ SwTwips nTmpRelPosY( 0L );
+ if ( bVert )
+ nTmpRelPosY = aRelPos.X() - nDist;
+ else
+ nTmpRelPosY = aRelPos.Y() + nDist;
+ const SwLayoutFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
+ nTmpRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert,
+ rVertEnvironLayFrm,
+ nTmpRelPosY,
+ DoesObjFollowsTextFlow(),
+ false );
+ if ( bVert )
+ {
+ aRelPos.X() = nTmpRelPosY;
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ aRelPos.X() -
+ aObjBoundRect.Width() );
+ }
+ else
+ {
+ aRelPos.Y() = nTmpRelPosY;
+ GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
+ }
+ // If the anchor frame is the first content of the table cell
+ // and the object still doesn't fit, the table frame is notified,
+ // that the object doesn't fit into the table cell.
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
+ if ( nDist < 0 &&
+ pOrientFrm == &rAnchorTxtFrm && !pOrientFrm->GetIndPrev() )
+ {
+ const_cast<SwTabFrm*>(pOrientFrm->FindTabFrm())
+ ->SetDoesObjsFit( FALSE );
+ }
+ }
+ }
+ else
+ {
+ // <--
+ // follow text flow
+ const bool bInFtn = rAnchorTxtFrm.IsInFtn();
+ while( bMoveable && nDist < 0 )
+ {
+ bool bInSct = pUpperOfOrientFrm->IsInSct();
+ if ( bInSct )
+ {
+ const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper();
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pTmp->*fnRect->fnGetPrtBottom)() );
+ // --> OD 2004-11-01 #i23129# - Try to flow into next
+ // section|section column. Thus, do *not* leave section
+ // area, if anchored object doesn't fit into upper of section.
+ // But the anchored object is allowed to overlap bottom
+ // section|section column.
+ if ( nDist >= 0 )
+ {
+ break;
+ }
+ // <--
+ }
+ if ( !bInSct &&
+ (GetAnchoredObj().GetObjRect().*fnRect->fnGetTop)() ==
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtTop)() )
+ //Das teil passt nimmer, da hilft auch kein moven.
+ break;
+
+ const SwLayoutFrm* pNextLay = pUpperOfOrientFrm->GetLeaf(
+ ( bInSct
+ ? MAKEPAGE_NOSECTION
+ : ( bInFtn ? MAKEPAGE_NONE : MAKEPAGE_APPEND ) ),
+ TRUE, &rAnchorTxtFrm );
+ // OD 06.10.2003 #110978# - correction:
+ // If anchor is in footnote and proposed next layout environment
+ // isn't a footnote frame, object can't follow the text flow
+ if ( bInFtn && pNextLay && !pNextLay->IsFtnFrm() )
+ {
+ pNextLay = 0L;
+ }
+ if ( pNextLay )
+ {
+ SWRECTFNX( pNextLay )
+ if ( !bInSct ||
+ ( pUpperOfOrientFrm->FindSctFrm()->IsAnFollow( pNextLay->FindSctFrm() ) &&
+ (pNextLay->Prt().*fnRectX->fnGetHeight)() ) )
+ {
+ SwTwips nTmpRelPosY =
+ (*fnRect->fnYDiff)( (pNextLay->*fnRect->fnGetPrtTop)(),
+ nTopOfAnch );
+ if ( bVert )
+ aRelPos.X() = nTmpRelPosY;
+ else
+ aRelPos.Y() = nTmpRelPosY;
+ pUpperOfOrientFrm = pNextLay;
+ SWREFRESHFN( pUpperOfOrientFrm )
+ bMoveable = rAnchorTxtFrm.IsMoveable( (SwLayoutFrm*)pUpperOfOrientFrm );
+ if( bVertX )
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ aRelPos.X() -
+ aObjBoundRect.Width() );
+ else
+ GetAnchoredObj().SetObjTop( nTopOfAnch +
+ aRelPos.Y() );
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
+ }
+ // --> OD 2004-11-01 #i23129# - leave section area
+ else if ( bInSct )
+ {
+ const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper();
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pTmp->*fnRect->fnGetPrtBottom)() );
+ if( nDist < 0 )
+ pUpperOfOrientFrm = pTmp;
+ else
+ break;
+ }
+ // <--
+ }
+ else if ( bInSct )
+ {
+ // Wenn wir innerhalb des Bereich nicht genug Platz haben, gucken
+ // wir uns mal die Seite an.
+ const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper();
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pTmp->*fnRect->fnGetPrtBottom)() );
+ if( nDist < 0 )
+ pUpperOfOrientFrm = pTmp;
+ else
+ break;
+ }
+ else
+ bMoveable = false;
+ }
+ }
+ }
+
+ // keep layout frame vertical position is oriented at.
+ mpVertPosOrientFrm = pUpperOfOrientFrm;
+
+ }
+
+ // determine 'horizontal' position
+ {
+ // determine horizontal positioning and alignment attributes
+ SwFmtHoriOrient aHori( rFrmFmt.GetHoriOrient() );
+
+ // set calculated vertical position in order to determine correct
+ // frame, the horizontal position is oriented at.
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ if( bVert )
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ aRelPos.X() - aObjBoundRect.Width() );
+ else
+ GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
+
+ // determine frame, horizontal position is oriented at.
+ // OD 2004-05-21 #i28701# - If floating screen object doesn't follow
+ // the text flow, its horizontal position is oriented at <pOrientFrm>.
+ const SwFrm* pHoriOrientFrm = DoesObjFollowsTextFlow()
+ ? &_GetHoriVirtualAnchor( *mpVertPosOrientFrm )
+ : pOrientFrm;
+
+ // --> OD 2004-06-17 #i26791# - get 'horizontal' offset to frame anchor position.
+ SwTwips nHoriOffsetToFrmAnchorPos( 0L );
+ SwTwips nRelPosX = _CalcRelPosX( *pHoriOrientFrm, aEnvOfObj,
+ aHori, rLR, rUL, bWrapThrough,
+ ( bVert ? aRelPos.X() : aRelPos.Y() ),
+ nHoriOffsetToFrmAnchorPos );
+
+ // --> OD 2004-06-17 #i26791# - determine offset to 'horizontal' frame
+ // anchor position, depending on layout-direction
+ if ( bVert )
+ {
+ aRelPos.Y() = nRelPosX;
+ maOffsetToFrmAnchorPos.Y() = nHoriOffsetToFrmAnchorPos;
+ }
+ else
+ {
+ aRelPos.X() = nRelPosX;
+ maOffsetToFrmAnchorPos.X() = nHoriOffsetToFrmAnchorPos;
+ }
+
+ // save calculated horizontal position - needed for filters
+ // (including the xml-filter)
+ {
+ SwTwips nAttrRelPosX = nRelPosX - nHoriOffsetToFrmAnchorPos;
+ if ( aHori.GetHoriOrient() != text::HoriOrientation::NONE &&
+ aHori.GetPos() != nAttrRelPosX )
+ {
+ aHori.SetPos( nAttrRelPosX );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aHori );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+ }
+ }
+
+ // set absolute position at object
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ if( bVert )
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ aRelPos.X() - aObjBoundRect.Width() );
+ GetAnchoredObj().SetObjTop( rAnchorTxtFrm.Frm().Top() +
+ aRelPos.Y() );
+ }
+ else
+ {
+ GetAnchoredObj().SetObjLeft( rAnchorTxtFrm.Frm().Left() +
+ aRelPos.X() );
+ GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
+ }
+
+ // set relative position at object
+ GetAnchoredObj().SetCurrRelPos( aRelPos );
+}
+
+/** determine frame for horizontal position
+
+ @author OD
+*/
+const SwFrm& SwToCntntAnchoredObjectPosition::_GetHoriVirtualAnchor(
+ const SwLayoutFrm& _rProposedFrm ) const
+{
+ const SwFrm* pHoriVirtAnchFrm = &_rProposedFrm;
+
+ // Search for first lower content frame, which is the anchor or a follow
+ // of the anchor (Note: <Anchor.IsAnFollow( Anchor )> is true)
+ // If none found, <_rProposedFrm> is returned.
+ const SwFrm* pFrm = _rProposedFrm.Lower();
+ while ( pFrm )
+ {
+ if ( pFrm->IsCntntFrm() &&
+ GetAnchorTxtFrm().IsAnFollow( static_cast<const SwCntntFrm*>(pFrm) ) )
+ {
+ pHoriVirtAnchFrm = pFrm;
+ break;
+ }
+ pFrm = pFrm->GetNext();
+ }
+
+ return *pHoriVirtAnchFrm;
+}
+
+const SwLayoutFrm& SwToCntntAnchoredObjectPosition::GetVertPosOrientFrm() const
+{
+ return *mpVertPosOrientFrm;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
new file mode 100644
index 000000000000..c98e773b2f21
--- /dev/null
+++ b/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
@@ -0,0 +1,245 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <tolayoutanchoredobjectposition.hxx>
+#include <anchoredobject.hxx>
+#include <frame.hxx>
+#include <pagefrm.hxx>
+#include <svx/svdobj.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <frmatr.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+
+using namespace objectpositioning;
+using namespace ::com::sun::star;
+
+
+SwToLayoutAnchoredObjectPosition::SwToLayoutAnchoredObjectPosition( SdrObject& _rDrawObj )
+ : SwAnchoredObjectPosition( _rDrawObj ),
+ maRelPos( Point() ),
+ // --> OD 2004-06-17 #i26791#
+ maOffsetToFrmAnchorPos( Point() )
+{}
+
+SwToLayoutAnchoredObjectPosition::~SwToLayoutAnchoredObjectPosition()
+{}
+
+/** calculate position for object position type TO_LAYOUT
+
+ @author OD
+*/
+void SwToLayoutAnchoredObjectPosition::CalcPosition()
+{
+ const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
+
+ SWRECTFN( (&GetAnchorFrm()) );
+
+ const SwFrmFmt& rFrmFmt = GetFrmFmt();
+ const SvxLRSpaceItem &rLR = rFrmFmt.GetLRSpace();
+ const SvxULSpaceItem &rUL = rFrmFmt.GetULSpace();
+
+ const bool bFlyAtFly = FLY_AT_FLY == rFrmFmt.GetAnchor().GetAnchorId();
+
+ // determine position.
+ // 'vertical' and 'horizontal' position are calculated separately
+ Point aRelPos;
+
+ // calculate 'vertical' position
+ SwFmtVertOrient aVert( rFrmFmt.GetVertOrient() );
+ {
+ // to-frame anchored objects are *only* vertical positioned centered or
+ // bottom, if its wrap mode is 'throught' and its anchor frame has fixed
+ // size. Otherwise, it's positioned top.
+ sal_Int16 eVertOrient = aVert.GetVertOrient();
+ if ( ( bFlyAtFly &&
+ ( eVertOrient == text::VertOrientation::CENTER ||
+ eVertOrient == text::VertOrientation::BOTTOM ) &&
+ SURROUND_THROUGHT != rFrmFmt.GetSurround().GetSurround() &&
+ !GetAnchorFrm().HasFixSize() ) )
+ {
+ eVertOrient = text::VertOrientation::TOP;
+ }
+ // --> OD 2004-06-17 #i26791# - get vertical offset to frame anchor position.
+ SwTwips nVertOffsetToFrmAnchorPos( 0L );
+ SwTwips nRelPosY =
+ _GetVertRelPos( GetAnchorFrm(), GetAnchorFrm(), eVertOrient,
+ aVert.GetRelationOrient(), aVert.GetPos(),
+ rLR, rUL, nVertOffsetToFrmAnchorPos );
+
+
+ // keep the calculated relative vertical position - needed for filters
+ // (including the xml-filter)
+ {
+ SwTwips nAttrRelPosY = nRelPosY - nVertOffsetToFrmAnchorPos;
+ if ( aVert.GetVertOrient() != text::VertOrientation::NONE &&
+ aVert.GetPos() != nAttrRelPosY )
+ {
+ aVert.SetPos( nAttrRelPosY );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+ }
+
+ // determine absolute 'vertical' position, depending on layout-direction
+ // --> OD 2004-06-17 #i26791# - determine offset to 'vertical' frame
+ // anchor position, depending on layout-direction
+ if( bVert )
+ {
+ OSL_ENSURE( !bRev, "<SwToLayoutAnchoredObjectPosition::CalcPosition()> - reverse layout set." );
+ aRelPos.X() = -nRelPosY - aObjBoundRect.Width();
+ maOffsetToFrmAnchorPos.X() = nVertOffsetToFrmAnchorPos;
+ }
+ else
+ {
+ aRelPos.Y() = nRelPosY;
+ maOffsetToFrmAnchorPos.Y() = nVertOffsetToFrmAnchorPos;
+ }
+
+ // if in online-layout the bottom of to-page anchored object is beyond
+ // the page bottom, the page frame has to grow by growing its body frame.
+ if ( !bFlyAtFly && GetAnchorFrm().IsPageFrm() &&
+ rFrmFmt.getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
+ {
+ const long nAnchorBottom = GetAnchorFrm().Frm().Bottom();
+ const long nBottom = GetAnchorFrm().Frm().Top() +
+ aRelPos.Y() + aObjBoundRect.Height();
+ if ( nAnchorBottom < nBottom )
+ {
+ static_cast<SwPageFrm&>(GetAnchorFrm()).
+ FindBodyCont()->Grow( nBottom - nAnchorBottom );
+ }
+ }
+ } // end of determination of vertical position
+
+ // calculate 'horizontal' position
+ SwFmtHoriOrient aHori( rFrmFmt.GetHoriOrient() );
+ {
+ // consider toggle of horizontal position for even pages.
+ const bool bToggle = aHori.IsPosToggle() &&
+ !GetAnchorFrm().FindPageFrm()->OnRightPage();
+ sal_Int16 eHoriOrient = aHori.GetHoriOrient();
+ sal_Int16 eRelOrient = aHori.GetRelationOrient();
+ // toggle orientation
+ _ToggleHoriOrientAndAlign( bToggle, eHoriOrient, eRelOrient );
+
+ // determine alignment values:
+ // <nWidth>: 'width' of the alignment area
+ // <nOffset>: offset of alignment area, relative to 'left' of
+ // frame anchor position
+ SwTwips nWidth, nOffset;
+ {
+ bool bDummy; // in this context irrelevant output parameter
+ _GetHoriAlignmentValues( GetAnchorFrm(), GetAnchorFrm(),
+ eRelOrient, false,
+ nWidth, nOffset, bDummy );
+ }
+
+ SwTwips nObjWidth = (aObjBoundRect.*fnRect->fnGetWidth)();
+
+ // determine relative horizontal position
+ SwTwips nRelPosX;
+ if ( text::HoriOrientation::NONE == eHoriOrient )
+ {
+ if( bToggle ||
+ ( !aHori.IsPosToggle() && GetAnchorFrm().IsRightToLeft() ) )
+ {
+ nRelPosX = nWidth - nObjWidth - aHori.GetPos();
+ }
+ else
+ {
+ nRelPosX = aHori.GetPos();
+ }
+ }
+ else if ( text::HoriOrientation::CENTER == eHoriOrient )
+ nRelPosX = (nWidth / 2) - (nObjWidth / 2);
+ else if ( text::HoriOrientation::RIGHT == eHoriOrient )
+ nRelPosX = nWidth - ( nObjWidth +
+ ( bVert ? rUL.GetLower() : rLR.GetRight() ) );
+ else
+ nRelPosX = bVert ? rUL.GetUpper() : rLR.GetLeft();
+ nRelPosX += nOffset;
+
+ // no 'negative' relative horizontal position
+ // OD 06.11.2003 #FollowTextFlowAtFrame# - negative positions allow for
+ // to frame anchored objects.
+ if ( !bFlyAtFly && nRelPosX < 0 )
+ {
+ nRelPosX = 0;
+ }
+
+ // determine absolute 'horizontal' position, depending on layout-direction
+ // --> OD 2004-06-17 #i26791# - determine offset to 'horizontal' frame
+ // anchor position, depending on layout-direction
+ if ( bVert )
+ {
+ aRelPos.Y() = nRelPosX;
+ maOffsetToFrmAnchorPos.Y() = nOffset;
+ }
+ else
+ {
+ aRelPos.X() = nRelPosX;
+ maOffsetToFrmAnchorPos.X() = nOffset;
+ }
+
+ // keep the calculated relative horizontal position - needed for filters
+ // (including the xml-filter)
+ {
+ SwTwips nAttrRelPosX = nRelPosX - nOffset;
+ if ( text::HoriOrientation::NONE != aHori.GetHoriOrient() &&
+ aHori.GetPos() != nAttrRelPosX )
+ {
+ aHori.SetPos( nAttrRelPosX );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aHori );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+ }
+ } // end of determination of horizontal position
+
+ // keep calculate relative position
+ maRelPos = aRelPos;
+}
+
+/** calculated relative position for object position
+
+ @author OD
+*/
+Point SwToLayoutAnchoredObjectPosition::GetRelPos() const
+{
+ return maRelPos;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */