1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ascharanchoredobjectposition.cxx,v $
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>
36 #include <flyfrms.hxx>
37 #ifndef _SVX_SVDOBJ_HXX
38 #include <svx/svdobj.hxx>
40 #include <dcontact.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
;
57 SwAsCharAnchoredObjectPosition::SwAsCharAnchoredObjectPosition(
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
),
68 mnLineAscent( _nLineAscent
),
69 mnLineDescent( _nLineDescent
),
70 mnLineAscentInclObjs( _nLineAscentInclObjs
),
71 mnLineDescentInclObjs( _nLineDescentInclObjs
),
72 maAnchorPos ( Point() ),
74 maObjBoundRect ( SwRect() ),
82 SwAsCharAnchoredObjectPosition::~SwAsCharAnchoredObjectPosition()
85 /** method to cast <SwAnchoredObjectPosition::GetAnchorFrm()> to needed type
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.
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();
141 if ( rAnchorFrm
.IsRightToLeft() )
143 nLRSpaceLeft
= rLRSpace
.GetRight();
144 nLRSpaceRight
= rLRSpace
.GetLeft();
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.
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
;
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.
217 if( mnFlags
& AS_CHAR_ROTATE
)
219 if( mnFlags
& AS_CHAR_REVERSE
)
220 aRelPos
.X() = -nRelPos
- aObjBoundRect
.Width();
223 aRelPos
.X() = nRelPos
;
224 aRelPos
.Y() = -aObjBoundRect
.Height();
228 aRelPos
.Y() = nRelPos
;
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
);
272 if ( rAnchorFrm
.IsRightToLeft() )
273 aDiff
= aRelPos
+ aAbsAnchorPos
- aSnapRect
.TopLeft();
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() );
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.
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() );
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
;
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.
365 SwTwips
SwAsCharAnchoredObjectPosition::_GetRelPosToBase(
366 const SwTwips _nObjBoundHeight
,
367 const SwFmtVertOrient
& _rVert
)
369 SwTwips nRelPosToBase
= 0;
373 const sal_Int16 eVertOrient
= _rVert
.GetVertOrient();
375 if ( eVertOrient
== text::VertOrientation::NONE
)
376 nRelPosToBase
= _rVert
.GetPos();
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
)
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
;
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
)
400 else if ( eVertOrient
== text::VertOrientation::LINE_TOP
)
402 else if ( eVertOrient
== text::VertOrientation::LINE_BOTTOM
)
405 else if ( eVertOrient
== text::VertOrientation::LINE_CENTER
)
407 nRelPosToBase
-= ( _nObjBoundHeight
+ mnLineAscentInclObjs
- mnLineDescentInclObjs
) / 2;
410 else if ( eVertOrient
== text::VertOrientation::LINE_TOP
)
412 nRelPosToBase
-= mnLineAscentInclObjs
;
415 else if ( eVertOrient
== text::VertOrientation::LINE_BOTTOM
)
417 nRelPosToBase
+= mnLineDescentInclObjs
- _nObjBoundHeight
;
423 return nRelPosToBase
;
426 /** calculated anchored position for object position
430 Point
SwAsCharAnchoredObjectPosition::GetAnchorPos() const
435 /** calculated relative position to base line for object position
439 SwTwips
SwAsCharAnchoredObjectPosition::GetRelPosY() const
444 /** determined object rectangle including spacing for object
448 SwRect
SwAsCharAnchoredObjectPosition::GetObjBoundRectInclSpacing() const
450 return maObjBoundRect
;
453 /** determined line alignment
457 sal_uInt8
SwAsCharAnchoredObjectPosition::GetLineAlignment() const
459 return mnLineAlignment
;