android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / objectpositioning / ascharanchoredobjectposition.cxx
blobe82659ccd59fde77ff40b37cf28c90d9da5bbc00
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <anchoreddrawobject.hxx>
21 #include <ascharanchoredobjectposition.hxx>
22 #include <frame.hxx>
23 #include <txtfrm.hxx>
24 #include <flyfrms.hxx>
25 #include <svx/svdobj.hxx>
26 #include <frmfmt.hxx>
27 #include <frmatr.hxx>
28 #include <editeng/lrspitem.hxx>
29 #include <editeng/ulspitem.hxx>
30 #include <osl/diagnose.h>
31 #include <fmtornt.hxx>
34 using namespace ::com::sun::star;
36 namespace objectpositioning
39 /** constructor */
40 SwAsCharAnchoredObjectPosition::SwAsCharAnchoredObjectPosition(
41 SdrObject& _rDrawObj,
42 const Point& _rProposedAnchorPos,
43 const AsCharFlags _nFlags,
44 const SwTwips _nLineAscent,
45 const SwTwips _nLineDescent,
46 const SwTwips _nLineAscentInclObjs,
47 const SwTwips _nLineDescentInclObjs )
48 : SwAnchoredObjectPosition( _rDrawObj ),
49 mrProposedAnchorPos( _rProposedAnchorPos ),
50 mnFlags( _nFlags ),
51 mnLineAscent( _nLineAscent ),
52 mnLineDescent( _nLineDescent ),
53 mnLineAscentInclObjs( _nLineAscentInclObjs ),
54 mnLineDescentInclObjs( _nLineDescentInclObjs ),
55 mnRelPos ( 0 ),
56 mnLineAlignment ( sw::LineAlign::NONE )
59 /** destructor */
60 SwAsCharAnchoredObjectPosition::~SwAsCharAnchoredObjectPosition()
63 /** method to cast <SwAnchoredObjectPosition::GetAnchorFrame()> to needed type */
64 const SwTextFrame& SwAsCharAnchoredObjectPosition::GetAnchorTextFrame() const
66 assert( dynamic_cast<const SwTextFrame*>( &GetAnchorFrame() ) &&
67 "SwAsCharAnchoredObjectPosition::GetAnchorTextFrame() - wrong anchor frame type" );
69 return static_cast<const SwTextFrame&>(GetAnchorFrame());
72 /** calculate position for object
74 OD 30.07.2003 #110978#
75 members <maAnchorPos>, <mnRelPos>, <maObjBoundRect> and
76 <mnLineAlignment> are calculated.
77 calculated position is set at the given object.
79 void SwAsCharAnchoredObjectPosition::CalcPosition()
81 const SwTextFrame& rAnchorFrame = GetAnchorTextFrame();
82 // swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
83 SwFrameSwapper aFrameSwapper( &rAnchorFrame, false );
85 SwRectFnSet aRectFnSet(&rAnchorFrame);
87 Point aAnchorPos( mrProposedAnchorPos );
89 const SwFrameFormat& rFrameFormat = GetFrameFormat();
91 SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
92 SwTwips nObjWidth = aRectFnSet.GetWidth(aObjBoundRect);
94 // determine spacing values considering layout-/text-direction
95 const SvxLRSpaceItem& rLRSpace = rFrameFormat.GetLRSpace();
96 const SvxULSpaceItem& rULSpace = rFrameFormat.GetULSpace();
97 SwTwips nLRSpaceLeft, nLRSpaceRight, nULSpaceUpper, nULSpaceLower;
99 if ( rAnchorFrame.IsVertical() )
101 // Seems to be easier to do it all the horizontal way
102 // So, from now on think horizontal.
103 rAnchorFrame.SwitchVerticalToHorizontal( aObjBoundRect );
104 rAnchorFrame.SwitchVerticalToHorizontal( aAnchorPos );
106 // convert the spacing values
107 nLRSpaceLeft = rULSpace.GetUpper();
108 nLRSpaceRight = rULSpace.GetLower();
109 nULSpaceUpper = rLRSpace.GetRight();
110 nULSpaceLower = rLRSpace.GetLeft();
112 else
114 if ( rAnchorFrame.IsRightToLeft() )
116 nLRSpaceLeft = rLRSpace.GetRight();
117 nLRSpaceRight = rLRSpace.GetLeft();
119 else
121 nLRSpaceLeft = rLRSpace.GetLeft();
122 nLRSpaceRight = rLRSpace.GetRight();
125 nULSpaceUpper = rULSpace.GetUpper();
126 nULSpaceLower = rULSpace.GetLower();
130 // consider left and upper spacing by adjusting anchor position.
131 // left spacing is only considered, if requested.
132 if( mnFlags & AsCharFlags::UlSpace )
134 aAnchorPos.AdjustX(nLRSpaceLeft );
136 aAnchorPos.AdjustY(nULSpaceUpper );
138 // for drawing objects: consider difference between its bounding rectangle
139 // and its snapping rectangle by adjusting anchor position.
140 // left difference is only considered, if requested.
141 if( !IsObjFly() )
143 SwRect aSnapRect(GetObject().GetSnapRect());
144 if ( rAnchorFrame.IsVertical() )
146 rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
149 if( mnFlags & AsCharFlags::UlSpace )
151 aAnchorPos.AdjustX(aSnapRect.Left() - aObjBoundRect.Left() );
153 aAnchorPos.AdjustY(aSnapRect.Top() - aObjBoundRect.Top() );
156 // enlarge bounding rectangle of object by its spacing.
157 aObjBoundRect.AddLeft( - nLRSpaceLeft );
158 aObjBoundRect.AddWidth( nLRSpaceRight );
159 aObjBoundRect.AddTop( - nULSpaceUpper );
160 aObjBoundRect.AddHeight( nULSpaceLower );
162 // calculate relative position to given base line.
163 const SwFormatVertOrient& rVert = rFrameFormat.GetVertOrient();
164 const SwTwips nObjBoundHeight = ( mnFlags & AsCharFlags::Rotate )
165 ? aObjBoundRect.Width()
166 : aObjBoundRect.Height();
167 const SwTwips nRelPos = GetRelPosToBase( nObjBoundHeight, rVert );
169 // for initial positioning:
170 // adjust the proposed anchor position by difference between
171 // calculated relative position to base line and current maximal line ascent.
172 // Note: In the following line formatting the base line will be adjusted
173 // by the same difference.
174 if( mnFlags & AsCharFlags::Init && nRelPos < 0 && mnLineAscentInclObjs < -nRelPos )
176 if( mnFlags & AsCharFlags::Rotate )
177 aAnchorPos.AdjustX( -(mnLineAscentInclObjs + nRelPos) );
178 else
179 aAnchorPos.AdjustY( -(mnLineAscentInclObjs + nRelPos) );
182 // consider BIDI-multiportion by adjusting proposed anchor position
183 if( mnFlags & AsCharFlags::Bidi )
184 aAnchorPos.AdjustX( -(aObjBoundRect.Width()) );
186 // calculate relative position considering rotation and inside rotation
187 // reverse direction.
188 Point aRelPos;
190 if( mnFlags & AsCharFlags::Rotate )
192 if( mnFlags & AsCharFlags::Reverse )
193 aRelPos.setX( -nRelPos - aObjBoundRect.Width() );
194 else
196 aRelPos.setX( nRelPos );
197 aRelPos.setY( -aObjBoundRect.Height() );
200 else
201 aRelPos.setY( nRelPos );
204 if( !IsObjFly() )
206 if( !( mnFlags & AsCharFlags::Quick ) )
208 // save calculated Y-position value for 'automatic' vertical positioning,
209 // in order to avoid a switch to 'manual' vertical positioning in
210 // <SwDrawContact::Changed_(..)>.
211 const sal_Int16 eVertOrient = rVert.GetVertOrient();
212 if( rVert.GetPos() != nRelPos && eVertOrient != text::VertOrientation::NONE )
214 SwFormatVertOrient aVert( rVert );
215 aVert.SetPos( nRelPos );
216 const_cast<SwFrameFormat&>(rFrameFormat).LockModify();
217 const_cast<SwFrameFormat&>(rFrameFormat).SetFormatAttr( aVert );
218 const_cast<SwFrameFormat&>(rFrameFormat).UnlockModify();
221 // determine absolute anchor position considering layout directions.
222 // Note: Use copy of <aAnchorPos>, because it's needed for
223 // setting relative position.
224 Point aAbsAnchorPos( aAnchorPos );
225 if ( rAnchorFrame.IsRightToLeft() )
227 rAnchorFrame.SwitchLTRtoRTL( aAbsAnchorPos );
228 aAbsAnchorPos.AdjustX( -nObjWidth );
230 if ( rAnchorFrame.IsVertical() )
231 rAnchorFrame.SwitchHorizontalToVertical( aAbsAnchorPos );
233 // set proposed anchor position at the drawing object.
234 // OD 2004-04-06 #i26791# - distinction between 'master' drawing
235 // object and 'virtual' drawing object no longer needed.
236 GetObject().SetAnchorPos( aAbsAnchorPos );
238 // move drawing object to set its correct relative position.
240 SwRect aSnapRect(GetObject().GetSnapRect());
241 if ( rAnchorFrame.IsVertical() )
242 rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
244 Point aDiff;
245 if ( rAnchorFrame.IsRightToLeft() )
246 aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
247 else
248 aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
250 if ( rAnchorFrame.IsVertical() )
251 aDiff = Point( -aDiff.Y(), aDiff.X() );
253 // OD 2004-04-06 #i26791# - distinction between 'master' drawing
254 // object and 'virtual' drawing object no longer needed.
255 GetObject().Move( Size( aDiff.X(), aDiff.Y() ) );
259 // switch horizontal, LTR anchor position to absolute values.
260 if ( rAnchorFrame.IsRightToLeft() )
262 rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
263 aAnchorPos.AdjustX( -nObjWidth );
265 if ( rAnchorFrame.IsVertical() )
266 rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
268 // #i44347# - keep last object rectangle at anchored object
269 assert( dynamic_cast<const SwAnchoredDrawObject*>( &GetAnchoredObj() ) &&
270 "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong type of anchored object." );
271 SwAnchoredDrawObject& rAnchoredDrawObj =
272 static_cast<SwAnchoredDrawObject&>( GetAnchoredObj() );
273 rAnchoredDrawObj.SetLastObjRect( rAnchoredDrawObj.GetObjRect().SVRect() );
275 else
277 // determine absolute anchor position and calculate corresponding
278 // relative position and its relative position attribute.
279 // Note: The relative position contains the spacing values.
280 Point aRelAttr;
281 if ( rAnchorFrame.IsRightToLeft() )
283 rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
284 aAnchorPos.AdjustX( -nObjWidth );
286 if ( rAnchorFrame.IsVertical() )
288 rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
289 aRelAttr = Point( -nRelPos, 0 );
290 aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
292 else
293 aRelAttr = Point( 0, nRelPos );
295 // OD 2004-03-23 #i26791#
296 assert( dynamic_cast<const SwFlyInContentFrame*>( &GetAnchoredObj()) &&
297 "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong anchored object." );
298 const SwFlyInContentFrame& rFlyInContentFrame =
299 static_cast<const SwFlyInContentFrame&>(GetAnchoredObj());
300 if ( !(mnFlags & AsCharFlags::Quick) &&
301 ( aAnchorPos != rFlyInContentFrame.GetRefPoint() ||
302 aRelAttr != rFlyInContentFrame.GetCurrRelPos() ) )
304 // set new anchor position and relative position
305 SwFlyInContentFrame* pFlyInContentFrame = &const_cast<SwFlyInContentFrame&>(rFlyInContentFrame);
306 pFlyInContentFrame->SetRefPoint( aAnchorPos, aRelAttr, aRelPos );
307 if( nObjWidth != aRectFnSet.GetWidth(pFlyInContentFrame->getFrameArea()) )
309 // recalculate object bound rectangle, if object width has changed.
310 aObjBoundRect = GetAnchoredObj().GetObjRect();
311 aObjBoundRect.AddLeft( - rLRSpace.GetLeft() );
312 aObjBoundRect.AddWidth( rLRSpace.GetRight() );
313 aObjBoundRect.AddTop( - rULSpace.GetUpper() );
314 aObjBoundRect.AddHeight( rULSpace.GetLower() );
317 OSL_ENSURE( aRectFnSet.GetHeight(rFlyInContentFrame.getFrameArea()),
318 "SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
321 // keep calculated values
322 maAnchorPos = aAnchorPos;
323 mnRelPos = nRelPos;
324 maObjBoundRect = aObjBoundRect;
327 /** determine the relative position to base line for object position type AS_CHAR
329 OD 29.07.2003 #110978#
330 Note about values set at member <mnLineAlignment> -
331 value gives feedback for the line formatting.
332 0 - no feedback; 1|2|3 - proposed formatting of characters
333 at top|at center|at bottom of line.
335 SwTwips SwAsCharAnchoredObjectPosition::GetRelPosToBase(
336 const SwTwips _nObjBoundHeight,
337 const SwFormatVertOrient& _rVert )
339 SwTwips nRelPosToBase = 0;
341 mnLineAlignment = sw::LineAlign::NONE;
343 const sal_Int16 eVertOrient = _rVert.GetVertOrient();
345 if ( eVertOrient == text::VertOrientation::NONE )
346 nRelPosToBase = _rVert.GetPos();
347 else
349 if ( eVertOrient == text::VertOrientation::CENTER )
350 nRelPosToBase -= _nObjBoundHeight / 2;
351 else if ( eVertOrient == text::VertOrientation::TOP )
352 nRelPosToBase -= _nObjBoundHeight;
353 else if ( eVertOrient == text::VertOrientation::BOTTOM )
354 nRelPosToBase = 0;
355 else if ( eVertOrient == text::VertOrientation::CHAR_CENTER )
356 nRelPosToBase -= ( _nObjBoundHeight + mnLineAscent - mnLineDescent ) / 2;
357 else if ( eVertOrient == text::VertOrientation::CHAR_TOP )
358 nRelPosToBase -= mnLineAscent;
359 else if ( eVertOrient == text::VertOrientation::CHAR_BOTTOM )
360 nRelPosToBase += mnLineDescent - _nObjBoundHeight;
361 else
363 if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
365 // object is at least as high as the line. Thus, no more is
366 // positioning necessary. Also, the max. ascent isn't changed.
367 nRelPosToBase -= mnLineAscentInclObjs;
368 if ( eVertOrient == text::VertOrientation::LINE_CENTER )
369 mnLineAlignment = sw::LineAlign::CENTER;
370 else if ( eVertOrient == text::VertOrientation::LINE_TOP )
371 mnLineAlignment = sw::LineAlign::TOP;
372 else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
373 mnLineAlignment = sw::LineAlign::BOTTOM;
375 else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
377 nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
378 mnLineAlignment = sw::LineAlign::CENTER;
380 else if ( eVertOrient == text::VertOrientation::LINE_TOP )
382 nRelPosToBase -= mnLineAscentInclObjs;
383 mnLineAlignment = sw::LineAlign::TOP;
385 else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
387 nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
388 mnLineAlignment = sw::LineAlign::BOTTOM;
393 return nRelPosToBase;
398 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */