merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / objectpositioning / ascharanchoredobjectposition.cxx
blob40f0c5d727a39eca995ffd4426fdd9df6ba5bb16
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ascharanchoredobjectposition.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <ascharanchoredobjectposition.hxx>
34 #include <frame.hxx>
35 #include <txtfrm.hxx>
36 #include <flyfrms.hxx>
37 #ifndef _SVX_SVDOBJ_HXX
38 #include <svx/svdobj.hxx>
39 #endif
40 #include <dcontact.hxx>
41 #include <frmfmt.hxx>
42 #include <frmatr.hxx>
43 #include <svx/lrspitem.hxx>
44 #include <svx/ulspitem.hxx>
45 #include <fmtornt.hxx>
47 #include <com/sun/star/text/HoriOrientation.hpp>
50 using namespace ::com::sun::star;
51 using namespace objectpositioning;
53 /** constructor
55 @author OD
57 SwAsCharAnchoredObjectPosition::SwAsCharAnchoredObjectPosition(
58 SdrObject& _rDrawObj,
59 const Point& _rProposedAnchorPos,
60 const AsCharFlags _nFlags,
61 const SwTwips _nLineAscent,
62 const SwTwips _nLineDescent,
63 const SwTwips _nLineAscentInclObjs,
64 const SwTwips _nLineDescentInclObjs )
65 : SwAnchoredObjectPosition( _rDrawObj ),
66 mrProposedAnchorPos( _rProposedAnchorPos ),
67 mnFlags( _nFlags ),
68 mnLineAscent( _nLineAscent ),
69 mnLineDescent( _nLineDescent ),
70 mnLineAscentInclObjs( _nLineAscentInclObjs ),
71 mnLineDescentInclObjs( _nLineDescentInclObjs ),
72 maAnchorPos ( Point() ),
73 mnRelPos ( 0 ),
74 maObjBoundRect ( SwRect() ),
75 mnLineAlignment ( 0 )
78 /** destructor
80 @author OD
82 SwAsCharAnchoredObjectPosition::~SwAsCharAnchoredObjectPosition()
85 /** method to cast <SwAnchoredObjectPosition::GetAnchorFrm()> to needed type
87 @author OD
89 const SwTxtFrm& SwAsCharAnchoredObjectPosition::GetAnchorTxtFrm() const
91 ASSERT( GetAnchorFrm().ISA(SwTxtFrm),
92 "SwAsCharAnchoredObjectPosition::GetAnchorTxtFrm() - wrong anchor frame type" );
94 return static_cast<const SwTxtFrm&>(GetAnchorFrm());
97 /** calculate position for object
99 OD 30.07.2003 #110978#
100 members <maAnchorPos>, <mnRelPos>, <maObjBoundRect> and
101 <mnLineAlignment> are calculated.
102 calculated position is set at the given object.
104 @author OD
106 void SwAsCharAnchoredObjectPosition::CalcPosition()
108 const SwTxtFrm& rAnchorFrm = GetAnchorTxtFrm();
109 // swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
110 SwFrmSwapper aFrmSwapper( &rAnchorFrm, false );
112 SWRECTFN( ( &rAnchorFrm ) )
114 Point aAnchorPos( mrProposedAnchorPos );
116 const SwFrmFmt& rFrmFmt = GetFrmFmt();
118 SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
119 SwTwips nObjWidth = (aObjBoundRect.*fnRect->fnGetWidth)();
121 // determine spacing values considering layout-/text-direction
122 const SvxLRSpaceItem& rLRSpace = rFrmFmt.GetLRSpace();
123 const SvxULSpaceItem& rULSpace = rFrmFmt.GetULSpace();
124 SwTwips nLRSpaceLeft, nLRSpaceRight, nULSpaceUpper, nULSpaceLower;
126 if ( rAnchorFrm.IsVertical() )
128 // Seems to be easier to do it all the horizontal way
129 // So, from now on think horizontal.
130 rAnchorFrm.SwitchVerticalToHorizontal( aObjBoundRect );
131 rAnchorFrm.SwitchVerticalToHorizontal( aAnchorPos );
133 // convert the spacing values
134 nLRSpaceLeft = rULSpace.GetUpper();
135 nLRSpaceRight = rULSpace.GetLower();
136 nULSpaceUpper = rLRSpace.GetRight();
137 nULSpaceLower = rLRSpace.GetLeft();
139 else
141 if ( rAnchorFrm.IsRightToLeft() )
143 nLRSpaceLeft = rLRSpace.GetRight();
144 nLRSpaceRight = rLRSpace.GetLeft();
146 else
148 nLRSpaceLeft = rLRSpace.GetLeft();
149 nLRSpaceRight = rLRSpace.GetRight();
152 nULSpaceUpper = rULSpace.GetUpper();
153 nULSpaceLower = rULSpace.GetLower();
157 // consider left and upper spacing by adjusting anchor position.
158 // left spacing is only considered, if requested.
159 if( mnFlags & AS_CHAR_ULSPACE )
161 aAnchorPos.X() += nLRSpaceLeft;
163 aAnchorPos.Y() += nULSpaceUpper;
165 // for drawing objects: consider difference between its bounding rectangle
166 // and its snapping rectangle by adjusting anchor position.
167 // left difference is only considered, if requested.
168 if( !IsObjFly() )
170 SwRect aSnapRect = GetObject().GetSnapRect();
171 if ( rAnchorFrm.IsVertical() )
173 rAnchorFrm.SwitchVerticalToHorizontal( aSnapRect );
176 if( mnFlags & AS_CHAR_ULSPACE )
178 aAnchorPos.X() += aSnapRect.Left() - aObjBoundRect.Left();
180 aAnchorPos.Y() += aSnapRect.Top() - aObjBoundRect.Top();
183 // enlarge bounding rectangle of object by its spacing.
184 aObjBoundRect.Left( aObjBoundRect.Left() - nLRSpaceLeft );
185 aObjBoundRect.Width( aObjBoundRect.Width() + nLRSpaceRight );
186 aObjBoundRect.Top( aObjBoundRect.Top() - nULSpaceUpper );
187 aObjBoundRect.Height( aObjBoundRect.Height() + nULSpaceLower );
189 // calculate relative position to given base line.
190 const SwFmtVertOrient& rVert = rFrmFmt.GetVertOrient();
191 const SwTwips nObjBoundHeight = ( mnFlags & AS_CHAR_ROTATE )
192 ? aObjBoundRect.Width()
193 : aObjBoundRect.Height();
194 const SwTwips nRelPos = _GetRelPosToBase( nObjBoundHeight, rVert );
196 // for initial positioning:
197 // adjust the proposed anchor position by difference between
198 // calculated relative position to base line and current maximal line ascent.
199 // Note: In the following line formatting the base line will be adjusted
200 // by the same difference.
201 if( mnFlags & AS_CHAR_INIT && nRelPos < 0 && mnLineAscentInclObjs < -nRelPos )
203 if( mnFlags & AS_CHAR_ROTATE )
204 aAnchorPos.X() -= mnLineAscentInclObjs + nRelPos;
205 else
206 aAnchorPos.Y() -= mnLineAscentInclObjs + nRelPos;
209 // consider BIDI-multiportion by adjusting proposed anchor position
210 if( mnFlags & AS_CHAR_BIDI )
211 aAnchorPos.X() -= aObjBoundRect.Width();
213 // calculate relative position considering rotation and inside rotation
214 // reverse direction.
215 Point aRelPos;
217 if( mnFlags & AS_CHAR_ROTATE )
219 if( mnFlags & AS_CHAR_REVERSE )
220 aRelPos.X() = -nRelPos - aObjBoundRect.Width();
221 else
223 aRelPos.X() = nRelPos;
224 aRelPos.Y() = -aObjBoundRect.Height();
227 else
228 aRelPos.Y() = nRelPos;
231 if( !IsObjFly() )
233 if( !( mnFlags & AS_CHAR_QUICK ) )
235 // save calculated Y-position value for 'automatic' vertical positioning,
236 // in order to avoid a switch to 'manual' vertical positioning in
237 // <SwDrawContact::_Changed(..)>.
238 const sal_Int16 eVertOrient = rVert.GetVertOrient();
239 if( rVert.GetPos() != nRelPos && eVertOrient != text::VertOrientation::NONE )
241 SwFmtVertOrient aVert( rVert );
242 aVert.SetPos( nRelPos );
243 const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
244 const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
245 const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
248 // determine absolute anchor position considering layout directions.
249 // Note: Use copy of <aAnchorPos>, because it's needed for
250 // setting relative position.
251 Point aAbsAnchorPos( aAnchorPos );
252 if ( rAnchorFrm.IsRightToLeft() )
254 rAnchorFrm.SwitchLTRtoRTL( aAbsAnchorPos );
255 aAbsAnchorPos.X() -= nObjWidth;
257 if ( rAnchorFrm.IsVertical() )
258 rAnchorFrm.SwitchHorizontalToVertical( aAbsAnchorPos );
260 // set proposed anchor position at the drawing object.
261 // OD 2004-04-06 #i26791# - distinction between 'master' drawing
262 // object and 'virtual' drawing object no longer needed.
263 GetObject().SetAnchorPos( aAbsAnchorPos );
265 // move drawing object to set its correct relative position.
267 SwRect aSnapRect = GetObject().GetSnapRect();
268 if ( rAnchorFrm.IsVertical() )
269 rAnchorFrm.SwitchVerticalToHorizontal( aSnapRect );
271 Point aDiff;
272 if ( rAnchorFrm.IsRightToLeft() )
273 aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
274 else
275 aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
277 if ( rAnchorFrm.IsVertical() )
278 aDiff = Point( -aDiff.Y(), aDiff.X() );
280 // OD 2004-04-06 #i26791# - distinction between 'master' drawing
281 // object and 'virtual' drawing object no longer needed.
282 GetObject().Move( Size( aDiff.X(), aDiff.Y() ) );
286 // switch horizontal, LTR anchor position to absolute values.
287 if ( rAnchorFrm.IsRightToLeft() )
289 rAnchorFrm.SwitchLTRtoRTL( aAnchorPos );
290 aAnchorPos.X() -= nObjWidth;
292 if ( rAnchorFrm.IsVertical() )
293 rAnchorFrm.SwitchHorizontalToVertical( aAnchorPos );
295 // --> OD 2005-03-09 #i44347# - keep last object rectangle at anchored object
296 ASSERT ( GetAnchoredObj().ISA(SwAnchoredDrawObject),
297 "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong type of anchored object." );
298 SwAnchoredDrawObject& rAnchoredDrawObj =
299 static_cast<SwAnchoredDrawObject&>( GetAnchoredObj() );
300 rAnchoredDrawObj.SetLastObjRect( rAnchoredDrawObj.GetObjRect().SVRect() );
301 // <--
303 else
305 // determine absolute anchor position and calculate corresponding
306 // relative position and its relative position attribute.
307 // Note: The relative position contains the spacing values.
308 Point aRelAttr;
309 if ( rAnchorFrm.IsRightToLeft() )
311 rAnchorFrm.SwitchLTRtoRTL( aAnchorPos );
312 aAnchorPos.X() -= nObjWidth;
314 if ( rAnchorFrm.IsVertical() )
316 rAnchorFrm.SwitchHorizontalToVertical( aAnchorPos );
317 aRelAttr = Point( -nRelPos, 0 );
318 aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
320 else
321 aRelAttr = Point( 0, nRelPos );
323 // OD 2004-03-23 #i26791#
324 ASSERT( GetAnchoredObj().ISA(SwFlyInCntFrm),
325 "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong anchored object." );
326 const SwFlyInCntFrm& rFlyInCntFrm =
327 static_cast<const SwFlyInCntFrm&>(GetAnchoredObj());
328 if ( !(mnFlags & AS_CHAR_QUICK) &&
329 ( aAnchorPos != rFlyInCntFrm.GetRefPoint() ||
330 aRelAttr != rFlyInCntFrm.GetCurrRelPos() ) )
332 // set new anchor position and relative position
333 SwFlyInCntFrm* pFlyInCntFrm = &(const_cast<SwFlyInCntFrm&>(rFlyInCntFrm));
334 pFlyInCntFrm->SetRefPoint( aAnchorPos, aRelAttr, aRelPos );
335 if( nObjWidth != (pFlyInCntFrm->Frm().*fnRect->fnGetWidth)() )
337 // recalculate object bound rectangle, if object width has changed.
338 aObjBoundRect = GetAnchoredObj().GetObjRect();
339 aObjBoundRect.Left( aObjBoundRect.Left() - rLRSpace.GetLeft() );
340 aObjBoundRect.Width( aObjBoundRect.Width() + rLRSpace.GetRight() );
341 aObjBoundRect.Top( aObjBoundRect.Top() - rULSpace.GetUpper() );
342 aObjBoundRect.Height( aObjBoundRect.Height() + rULSpace.GetLower() );
345 ASSERT( (rFlyInCntFrm.Frm().*fnRect->fnGetHeight)(),
346 "SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
349 // keep calculated values
350 maAnchorPos = aAnchorPos;
351 mnRelPos = nRelPos;
352 maObjBoundRect = aObjBoundRect;
355 /** determine the relative position to base line for object position type AS_CHAR
357 OD 29.07.2003 #110978#
358 Note about values set at member <mnLineAlignment> -
359 value gives feedback for the line formatting.
360 0 - no feedback; 1|2|3 - proposed formatting of characters
361 at top|at center|at bottom of line.
363 @author OD
365 SwTwips SwAsCharAnchoredObjectPosition::_GetRelPosToBase(
366 const SwTwips _nObjBoundHeight,
367 const SwFmtVertOrient& _rVert )
369 SwTwips nRelPosToBase = 0;
371 mnLineAlignment = 0;
373 const sal_Int16 eVertOrient = _rVert.GetVertOrient();
375 if ( eVertOrient == text::VertOrientation::NONE )
376 nRelPosToBase = _rVert.GetPos();
377 else
379 if ( eVertOrient == text::VertOrientation::CENTER )
380 nRelPosToBase -= _nObjBoundHeight / 2;
381 else if ( eVertOrient == text::VertOrientation::TOP )
382 nRelPosToBase -= _nObjBoundHeight;
383 else if ( eVertOrient == text::VertOrientation::BOTTOM )
384 nRelPosToBase = 0;
385 else if ( eVertOrient == text::VertOrientation::CHAR_CENTER )
386 nRelPosToBase -= ( _nObjBoundHeight + mnLineAscent - mnLineDescent ) / 2;
387 else if ( eVertOrient == text::VertOrientation::CHAR_TOP )
388 nRelPosToBase -= mnLineAscent;
389 else if ( eVertOrient == text::VertOrientation::CHAR_BOTTOM )
390 nRelPosToBase += mnLineDescent - _nObjBoundHeight;
391 else
393 if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
395 // object is at least as high as the line. Thus, no more is
396 // positioning necessary. Also, the max. ascent isn't changed.
397 nRelPosToBase -= mnLineAscentInclObjs;
398 if ( eVertOrient == text::VertOrientation::LINE_CENTER )
399 mnLineAlignment = 2;
400 else if ( eVertOrient == text::VertOrientation::LINE_TOP )
401 mnLineAlignment = 1;
402 else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
403 mnLineAlignment = 3;
405 else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
407 nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
408 mnLineAlignment = 2;
410 else if ( eVertOrient == text::VertOrientation::LINE_TOP )
412 nRelPosToBase -= mnLineAscentInclObjs;
413 mnLineAlignment = 1;
415 else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
417 nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
418 mnLineAlignment = 3;
423 return nRelPosToBase;
426 /** calculated anchored position for object position
428 @author OD
430 Point SwAsCharAnchoredObjectPosition::GetAnchorPos() const
432 return maAnchorPos;
435 /** calculated relative position to base line for object position
437 @author OD
439 SwTwips SwAsCharAnchoredObjectPosition::GetRelPosY() const
441 return mnRelPos;
444 /** determined object rectangle including spacing for object
446 @author OD
448 SwRect SwAsCharAnchoredObjectPosition::GetObjBoundRectInclSpacing() const
450 return maObjBoundRect;
453 /** determined line alignment
455 @author OD
457 sal_uInt8 SwAsCharAnchoredObjectPosition::GetLineAlignment() const
459 return mnLineAlignment;