nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / objectpositioning / ascharanchoredobjectposition.cxx
blobffe9a3682a6d958a4db50ace6ef83995061ac434
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 <fmtornt.hxx>
33 using namespace ::com::sun::star;
34 using namespace objectpositioning;
36 /** constructor */
37 SwAsCharAnchoredObjectPosition::SwAsCharAnchoredObjectPosition(
38 SdrObject& _rDrawObj,
39 const Point& _rProposedAnchorPos,
40 const AsCharFlags _nFlags,
41 const SwTwips _nLineAscent,
42 const SwTwips _nLineDescent,
43 const SwTwips _nLineAscentInclObjs,
44 const SwTwips _nLineDescentInclObjs )
45 : SwAnchoredObjectPosition( _rDrawObj ),
46 mrProposedAnchorPos( _rProposedAnchorPos ),
47 mnFlags( _nFlags ),
48 mnLineAscent( _nLineAscent ),
49 mnLineDescent( _nLineDescent ),
50 mnLineAscentInclObjs( _nLineAscentInclObjs ),
51 mnLineDescentInclObjs( _nLineDescentInclObjs ),
52 maAnchorPos ( Point() ),
53 mnRelPos ( 0 ),
54 maObjBoundRect ( SwRect() ),
55 mnLineAlignment ( sw::LineAlign::NONE )
58 /** destructor */
59 SwAsCharAnchoredObjectPosition::~SwAsCharAnchoredObjectPosition()
62 /** method to cast <SwAnchoredObjectPosition::GetAnchorFrame()> to needed type */
63 const SwTextFrame& SwAsCharAnchoredObjectPosition::GetAnchorTextFrame() const
65 OSL_ENSURE( dynamic_cast<const SwTextFrame*>( &GetAnchorFrame() ) != nullptr,
66 "SwAsCharAnchoredObjectPosition::GetAnchorTextFrame() - wrong anchor frame type" );
68 return static_cast<const SwTextFrame&>(GetAnchorFrame());
71 /** calculate position for object
73 OD 30.07.2003 #110978#
74 members <maAnchorPos>, <mnRelPos>, <maObjBoundRect> and
75 <mnLineAlignment> are calculated.
76 calculated position is set at the given object.
78 void SwAsCharAnchoredObjectPosition::CalcPosition()
80 const SwTextFrame& rAnchorFrame = GetAnchorTextFrame();
81 // swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
82 SwFrameSwapper aFrameSwapper( &rAnchorFrame, false );
84 SwRectFnSet aRectFnSet(&rAnchorFrame);
86 Point aAnchorPos( mrProposedAnchorPos );
88 const SwFrameFormat& rFrameFormat = GetFrameFormat();
90 SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
91 SwTwips nObjWidth = aRectFnSet.GetWidth(aObjBoundRect);
93 // determine spacing values considering layout-/text-direction
94 const SvxLRSpaceItem& rLRSpace = rFrameFormat.GetLRSpace();
95 const SvxULSpaceItem& rULSpace = rFrameFormat.GetULSpace();
96 SwTwips nLRSpaceLeft, nLRSpaceRight, nULSpaceUpper, nULSpaceLower;
98 if ( rAnchorFrame.IsVertical() )
100 // Seems to be easier to do it all the horizontal way
101 // So, from now on think horizontal.
102 rAnchorFrame.SwitchVerticalToHorizontal( aObjBoundRect );
103 rAnchorFrame.SwitchVerticalToHorizontal( aAnchorPos );
105 // convert the spacing values
106 nLRSpaceLeft = rULSpace.GetUpper();
107 nLRSpaceRight = rULSpace.GetLower();
108 nULSpaceUpper = rLRSpace.GetRight();
109 nULSpaceLower = rLRSpace.GetLeft();
111 else
113 if ( rAnchorFrame.IsRightToLeft() )
115 nLRSpaceLeft = rLRSpace.GetRight();
116 nLRSpaceRight = rLRSpace.GetLeft();
118 else
120 nLRSpaceLeft = rLRSpace.GetLeft();
121 nLRSpaceRight = rLRSpace.GetRight();
124 nULSpaceUpper = rULSpace.GetUpper();
125 nULSpaceLower = rULSpace.GetLower();
129 // consider left and upper spacing by adjusting anchor position.
130 // left spacing is only considered, if requested.
131 if( mnFlags & AsCharFlags::UlSpace )
133 aAnchorPos.AdjustX(nLRSpaceLeft );
135 aAnchorPos.AdjustY(nULSpaceUpper );
137 // for drawing objects: consider difference between its bounding rectangle
138 // and its snapping rectangle by adjusting anchor position.
139 // left difference is only considered, if requested.
140 if( !IsObjFly() )
142 SwRect aSnapRect = GetObject().GetSnapRect();
143 if ( rAnchorFrame.IsVertical() )
145 rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
148 if( mnFlags & AsCharFlags::UlSpace )
150 aAnchorPos.AdjustX(aSnapRect.Left() - aObjBoundRect.Left() );
152 aAnchorPos.AdjustY(aSnapRect.Top() - aObjBoundRect.Top() );
155 // enlarge bounding rectangle of object by its spacing.
156 aObjBoundRect.AddLeft( - nLRSpaceLeft );
157 aObjBoundRect.AddWidth( nLRSpaceRight );
158 aObjBoundRect.AddTop( - nULSpaceUpper );
159 aObjBoundRect.AddHeight( nULSpaceLower );
161 // calculate relative position to given base line.
162 const SwFormatVertOrient& rVert = rFrameFormat.GetVertOrient();
163 const SwTwips nObjBoundHeight = ( mnFlags & AsCharFlags::Rotate )
164 ? aObjBoundRect.Width()
165 : aObjBoundRect.Height();
166 const SwTwips nRelPos = GetRelPosToBase( nObjBoundHeight, rVert );
168 // for initial positioning:
169 // adjust the proposed anchor position by difference between
170 // calculated relative position to base line and current maximal line ascent.
171 // Note: In the following line formatting the base line will be adjusted
172 // by the same difference.
173 if( mnFlags & AsCharFlags::Init && nRelPos < 0 && mnLineAscentInclObjs < -nRelPos )
175 if( mnFlags & AsCharFlags::Rotate )
176 aAnchorPos.AdjustX( -(mnLineAscentInclObjs + nRelPos) );
177 else
178 aAnchorPos.AdjustY( -(mnLineAscentInclObjs + nRelPos) );
181 // consider BIDI-multiportion by adjusting proposed anchor position
182 if( mnFlags & AsCharFlags::Bidi )
183 aAnchorPos.AdjustX( -(aObjBoundRect.Width()) );
185 // calculate relative position considering rotation and inside rotation
186 // reverse direction.
187 Point aRelPos;
189 if( mnFlags & AsCharFlags::Rotate )
191 if( mnFlags & AsCharFlags::Reverse )
192 aRelPos.setX( -nRelPos - aObjBoundRect.Width() );
193 else
195 aRelPos.setX( nRelPos );
196 aRelPos.setY( -aObjBoundRect.Height() );
199 else
200 aRelPos.setY( nRelPos );
203 if( !IsObjFly() )
205 if( !( mnFlags & AsCharFlags::Quick ) )
207 // save calculated Y-position value for 'automatic' vertical positioning,
208 // in order to avoid a switch to 'manual' vertical positioning in
209 // <SwDrawContact::Changed_(..)>.
210 const sal_Int16 eVertOrient = rVert.GetVertOrient();
211 if( rVert.GetPos() != nRelPos && eVertOrient != text::VertOrientation::NONE )
213 SwFormatVertOrient aVert( rVert );
214 aVert.SetPos( nRelPos );
215 const_cast<SwFrameFormat&>(rFrameFormat).LockModify();
216 const_cast<SwFrameFormat&>(rFrameFormat).SetFormatAttr( aVert );
217 const_cast<SwFrameFormat&>(rFrameFormat).UnlockModify();
220 // determine absolute anchor position considering layout directions.
221 // Note: Use copy of <aAnchorPos>, because it's needed for
222 // setting relative position.
223 Point aAbsAnchorPos( aAnchorPos );
224 if ( rAnchorFrame.IsRightToLeft() )
226 rAnchorFrame.SwitchLTRtoRTL( aAbsAnchorPos );
227 aAbsAnchorPos.AdjustX( -nObjWidth );
229 if ( rAnchorFrame.IsVertical() )
230 rAnchorFrame.SwitchHorizontalToVertical( aAbsAnchorPos );
232 // set proposed anchor position at the drawing object.
233 // OD 2004-04-06 #i26791# - distinction between 'master' drawing
234 // object and 'virtual' drawing object no longer needed.
235 GetObject().SetAnchorPos( aAbsAnchorPos );
237 // move drawing object to set its correct relative position.
239 SwRect aSnapRect = GetObject().GetSnapRect();
240 if ( rAnchorFrame.IsVertical() )
241 rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
243 Point aDiff;
244 if ( rAnchorFrame.IsRightToLeft() )
245 aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
246 else
247 aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
249 if ( rAnchorFrame.IsVertical() )
250 aDiff = Point( -aDiff.Y(), aDiff.X() );
252 // OD 2004-04-06 #i26791# - distinction between 'master' drawing
253 // object and 'virtual' drawing object no longer needed.
254 GetObject().Move( Size( aDiff.X(), aDiff.Y() ) );
258 // switch horizontal, LTR anchor position to absolute values.
259 if ( rAnchorFrame.IsRightToLeft() )
261 rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
262 aAnchorPos.AdjustX( -nObjWidth );
264 if ( rAnchorFrame.IsVertical() )
265 rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
267 // #i44347# - keep last object rectangle at anchored object
268 OSL_ENSURE( dynamic_cast<const SwAnchoredDrawObject*>( &GetAnchoredObj() ) != nullptr,
269 "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong type of anchored object." );
270 SwAnchoredDrawObject& rAnchoredDrawObj =
271 static_cast<SwAnchoredDrawObject&>( GetAnchoredObj() );
272 rAnchoredDrawObj.SetLastObjRect( rAnchoredDrawObj.GetObjRect().SVRect() );
274 else
276 // determine absolute anchor position and calculate corresponding
277 // relative position and its relative position attribute.
278 // Note: The relative position contains the spacing values.
279 Point aRelAttr;
280 if ( rAnchorFrame.IsRightToLeft() )
282 rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
283 aAnchorPos.AdjustX( -nObjWidth );
285 if ( rAnchorFrame.IsVertical() )
287 rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
288 aRelAttr = Point( -nRelPos, 0 );
289 aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
291 else
292 aRelAttr = Point( 0, nRelPos );
294 // OD 2004-03-23 #i26791#
295 OSL_ENSURE( dynamic_cast<const SwFlyInContentFrame*>( &GetAnchoredObj()) != nullptr,
296 "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong anchored object." );
297 const SwFlyInContentFrame& rFlyInContentFrame =
298 static_cast<const SwFlyInContentFrame&>(GetAnchoredObj());
299 if ( !(mnFlags & AsCharFlags::Quick) &&
300 ( aAnchorPos != rFlyInContentFrame.GetRefPoint() ||
301 aRelAttr != rFlyInContentFrame.GetCurrRelPos() ) )
303 // set new anchor position and relative position
304 SwFlyInContentFrame* pFlyInContentFrame = &const_cast<SwFlyInContentFrame&>(rFlyInContentFrame);
305 pFlyInContentFrame->SetRefPoint( aAnchorPos, aRelAttr, aRelPos );
306 if( nObjWidth != aRectFnSet.GetWidth(pFlyInContentFrame->getFrameArea()) )
308 // recalculate object bound rectangle, if object width has changed.
309 aObjBoundRect = GetAnchoredObj().GetObjRect();
310 aObjBoundRect.AddLeft( - rLRSpace.GetLeft() );
311 aObjBoundRect.AddWidth( rLRSpace.GetRight() );
312 aObjBoundRect.AddTop( - rULSpace.GetUpper() );
313 aObjBoundRect.AddHeight( rULSpace.GetLower() );
316 OSL_ENSURE( aRectFnSet.GetHeight(rFlyInContentFrame.getFrameArea()),
317 "SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
320 // keep calculated values
321 maAnchorPos = aAnchorPos;
322 mnRelPos = nRelPos;
323 maObjBoundRect = aObjBoundRect;
326 /** determine the relative position to base line for object position type AS_CHAR
328 OD 29.07.2003 #110978#
329 Note about values set at member <mnLineAlignment> -
330 value gives feedback for the line formatting.
331 0 - no feedback; 1|2|3 - proposed formatting of characters
332 at top|at center|at bottom of line.
334 SwTwips SwAsCharAnchoredObjectPosition::GetRelPosToBase(
335 const SwTwips _nObjBoundHeight,
336 const SwFormatVertOrient& _rVert )
338 SwTwips nRelPosToBase = 0;
340 mnLineAlignment = sw::LineAlign::NONE;
342 const sal_Int16 eVertOrient = _rVert.GetVertOrient();
344 if ( eVertOrient == text::VertOrientation::NONE )
345 nRelPosToBase = _rVert.GetPos();
346 else
348 if ( eVertOrient == text::VertOrientation::CENTER )
349 nRelPosToBase -= _nObjBoundHeight / 2;
350 else if ( eVertOrient == text::VertOrientation::TOP )
351 nRelPosToBase -= _nObjBoundHeight;
352 else if ( eVertOrient == text::VertOrientation::BOTTOM )
353 nRelPosToBase = 0;
354 else if ( eVertOrient == text::VertOrientation::CHAR_CENTER )
355 nRelPosToBase -= ( _nObjBoundHeight + mnLineAscent - mnLineDescent ) / 2;
356 else if ( eVertOrient == text::VertOrientation::CHAR_TOP )
357 nRelPosToBase -= mnLineAscent;
358 else if ( eVertOrient == text::VertOrientation::CHAR_BOTTOM )
359 nRelPosToBase += mnLineDescent - _nObjBoundHeight;
360 else
362 if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
364 // object is at least as high as the line. Thus, no more is
365 // positioning necessary. Also, the max. ascent isn't changed.
366 nRelPosToBase -= mnLineAscentInclObjs;
367 if ( eVertOrient == text::VertOrientation::LINE_CENTER )
368 mnLineAlignment = sw::LineAlign::CENTER;
369 else if ( eVertOrient == text::VertOrientation::LINE_TOP )
370 mnLineAlignment = sw::LineAlign::TOP;
371 else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
372 mnLineAlignment = sw::LineAlign::BOTTOM;
374 else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
376 nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
377 mnLineAlignment = sw::LineAlign::CENTER;
379 else if ( eVertOrient == text::VertOrientation::LINE_TOP )
381 nRelPosToBase -= mnLineAscentInclObjs;
382 mnLineAlignment = sw::LineAlign::TOP;
384 else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
386 nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
387 mnLineAlignment = sw::LineAlign::BOTTOM;
392 return nRelPosToBase;
395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */