summaryrefslogtreecommitdiff
path: root/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx')
-rw-r--r--sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx457
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;
+}