diff options
Diffstat (limited to 'sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx')
-rw-r--r-- | sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx b/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx new file mode 100644 index 000000000000..c5a51970f066 --- /dev/null +++ b/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx @@ -0,0 +1,457 @@ +/************************************************************************* + * + * 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> +#ifndef _SVX_SVDOBJ_HXX +#include <svx/svdobj.hxx> +#endif +#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 +{ + ASSERT( 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 + ASSERT ( 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# + ASSERT( 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() ); + } + } + ASSERT( (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; +} |