LibreOffice Module sw (master)  1
ascharanchoredobjectposition.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
21 #include <frame.hxx>
22 #include <txtfrm.hxx>
23 #include <flyfrms.hxx>
24 #include <svx/svdobj.hxx>
25 #include <dcontact.hxx>
26 #include <frmfmt.hxx>
27 #include <frmatr.hxx>
28 #include <editeng/lrspitem.hxx>
29 #include <editeng/ulspitem.hxx>
30 #include <fmtornt.hxx>
31 
32 
33 using namespace ::com::sun::star;
34 using namespace objectpositioning;
35 
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 )
56 {}
57 
60 {}
61 
64 {
65  OSL_ENSURE( dynamic_cast<const SwTextFrame*>( &GetAnchorFrame() ) != nullptr,
66  "SwAsCharAnchoredObjectPosition::GetAnchorTextFrame() - wrong anchor frame type" );
67 
68  return static_cast<const SwTextFrame&>(GetAnchorFrame());
69 }
70 
79 {
80  const SwTextFrame& rAnchorFrame = GetAnchorTextFrame();
81  // swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
82  SwFrameSwapper aFrameSwapper( &rAnchorFrame, false );
83 
84  SwRectFnSet aRectFnSet(&rAnchorFrame);
85 
86  Point aAnchorPos( mrProposedAnchorPos );
87 
88  const SwFrameFormat& rFrameFormat = GetFrameFormat();
89 
90  SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
91  SwTwips nObjWidth = aRectFnSet.GetWidth(aObjBoundRect);
92 
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;
97  {
98  if ( rAnchorFrame.IsVertical() )
99  {
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 );
104 
105  // convert the spacing values
106  nLRSpaceLeft = rULSpace.GetUpper();
107  nLRSpaceRight = rULSpace.GetLower();
108  nULSpaceUpper = rLRSpace.GetRight();
109  nULSpaceLower = rLRSpace.GetLeft();
110  }
111  else
112  {
113  if ( rAnchorFrame.IsRightToLeft() )
114  {
115  nLRSpaceLeft = rLRSpace.GetRight();
116  nLRSpaceRight = rLRSpace.GetLeft();
117  }
118  else
119  {
120  nLRSpaceLeft = rLRSpace.GetLeft();
121  nLRSpaceRight = rLRSpace.GetRight();
122  }
123 
124  nULSpaceUpper = rULSpace.GetUpper();
125  nULSpaceLower = rULSpace.GetLower();
126  }
127  }
128 
129  // consider left and upper spacing by adjusting anchor position.
130  // left spacing is only considered, if requested.
132  {
133  aAnchorPos.AdjustX(nLRSpaceLeft );
134  }
135  aAnchorPos.AdjustY(nULSpaceUpper );
136 
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() )
141  {
142  SwRect aSnapRect = GetObject().GetSnapRect();
143  if ( rAnchorFrame.IsVertical() )
144  {
145  rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
146  }
147 
148  if( mnFlags & AsCharFlags::UlSpace )
149  {
150  aAnchorPos.AdjustX(aSnapRect.Left() - aObjBoundRect.Left() );
151  }
152  aAnchorPos.AdjustY(aSnapRect.Top() - aObjBoundRect.Top() );
153  }
154 
155  // enlarge bounding rectangle of object by its spacing.
156  aObjBoundRect.Left( aObjBoundRect.Left() - nLRSpaceLeft );
157  aObjBoundRect.Width( aObjBoundRect.Width() + nLRSpaceRight );
158  aObjBoundRect.Top( aObjBoundRect.Top() - nULSpaceUpper );
159  aObjBoundRect.Height( aObjBoundRect.Height() + nULSpaceLower );
160 
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 );
167 
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 )
174  {
176  aAnchorPos.AdjustX( -(mnLineAscentInclObjs + nRelPos) );
177  else
178  aAnchorPos.AdjustY( -(mnLineAscentInclObjs + nRelPos) );
179  }
180 
181  // consider BIDI-multiportion by adjusting proposed anchor position
182  if( mnFlags & AsCharFlags::Bidi )
183  aAnchorPos.AdjustX( -(aObjBoundRect.Width()) );
184 
185  // calculate relative position considering rotation and inside rotation
186  // reverse direction.
187  Point aRelPos;
188  {
190  {
192  aRelPos.setX( -nRelPos - aObjBoundRect.Width() );
193  else
194  {
195  aRelPos.setX( nRelPos );
196  aRelPos.setY( -aObjBoundRect.Height() );
197  }
198  }
199  else
200  aRelPos.setY( nRelPos );
201  }
202 
203  if( !IsObjFly() )
204  {
205  if( !( mnFlags & AsCharFlags::Quick ) )
206  {
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 )
212  {
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();
218  }
219 
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() )
225  {
226  rAnchorFrame.SwitchLTRtoRTL( aAbsAnchorPos );
227  aAbsAnchorPos.AdjustX( -nObjWidth );
228  }
229  if ( rAnchorFrame.IsVertical() )
230  rAnchorFrame.SwitchHorizontalToVertical( aAbsAnchorPos );
231 
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 );
236 
237  // move drawing object to set its correct relative position.
238  {
239  SwRect aSnapRect = GetObject().GetSnapRect();
240  if ( rAnchorFrame.IsVertical() )
241  rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
242 
243  Point aDiff;
244  if ( rAnchorFrame.IsRightToLeft() )
245  aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
246  else
247  aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
248 
249  if ( rAnchorFrame.IsVertical() )
250  aDiff = Point( -aDiff.Y(), aDiff.X() );
251 
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() ) );
255  }
256  }
257 
258  // switch horizontal, LTR anchor position to absolute values.
259  if ( rAnchorFrame.IsRightToLeft() )
260  {
261  rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
262  aAnchorPos.AdjustX( -nObjWidth );
263  }
264  if ( rAnchorFrame.IsVertical() )
265  rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
266 
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() );
273  }
274  else
275  {
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() )
281  {
282  rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
283  aAnchorPos.AdjustX( -nObjWidth );
284  }
285  if ( rAnchorFrame.IsVertical() )
286  {
287  rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
288  aRelAttr = Point( -nRelPos, 0 );
289  aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
290  }
291  else
292  aRelAttr = Point( 0, nRelPos );
293 
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() ) )
302  {
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()) )
307  {
308  // recalculate object bound rectangle, if object width has changed.
309  aObjBoundRect = GetAnchoredObj().GetObjRect();
310  aObjBoundRect.Left( aObjBoundRect.Left() - rLRSpace.GetLeft() );
311  aObjBoundRect.Width( aObjBoundRect.Width() + rLRSpace.GetRight() );
312  aObjBoundRect.Top( aObjBoundRect.Top() - rULSpace.GetUpper() );
313  aObjBoundRect.Height( aObjBoundRect.Height() + rULSpace.GetLower() );
314  }
315  }
316  OSL_ENSURE( aRectFnSet.GetHeight(rFlyInContentFrame.getFrameArea()),
317  "SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
318  }
319 
320  // keep calculated values
321  maAnchorPos = aAnchorPos;
322  mnRelPos = nRelPos;
323  maObjBoundRect = aObjBoundRect;
324 }
325 
335  const SwTwips _nObjBoundHeight,
336  const SwFormatVertOrient& _rVert )
337 {
338  SwTwips nRelPosToBase = 0;
339 
341 
342  const sal_Int16 eVertOrient = _rVert.GetVertOrient();
343 
344  if ( eVertOrient == text::VertOrientation::NONE )
345  nRelPosToBase = _rVert.GetPos();
346  else
347  {
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
361  {
362  if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
363  {
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 )
369  else if ( eVertOrient == text::VertOrientation::LINE_TOP )
371  else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
373  }
374  else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
375  {
376  nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
378  }
379  else if ( eVertOrient == text::VertOrientation::LINE_TOP )
380  {
381  nRelPosToBase -= mnLineAscentInclObjs;
383  }
384  else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
385  {
386  nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
388  }
389  }
390  }
391 
392  return nRelPosToBase;
393 }
394 
395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long GetLeft() const
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
void SwitchVerticalToHorizontal(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from vertical to horizontal layout...
Definition: txtfrm.cxx:590
class for the positioning of drawing objects
sal_uInt16 GetLower() const
SwAsCharAnchoredObjectPosition(SdrObject &_rDrawObj, const Point &_rProposedAnchorPos, const AsCharFlags _nFlags, const SwTwips _nLineAscent, const SwTwips _nLineDescent, const SwTwips _nLineAscentInclObjs, const SwTwips _nLineDescentInclObjs)
constructor; provided object to be positioned and needed data for calculation of the object position ...
long AdjustX(long nHorzMove)
const SwFormatVertOrient & GetVertOrient(bool=true) const
Definition: fmtornt.hxx:106
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:483
void Height(long nNew)
Definition: swrect.hxx:189
long SwTwips
Definition: swtypes.hxx:49
Dialog to specify the properties of drop-down form field.
Definition: accfrmobj.cxx:40
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
virtual const tools::Rectangle & GetSnapRect() const
void Top(const long nTop)
Definition: swrect.hxx:202
NONE
const SwRect & getFrameArea() const
Definition: frame.hxx:175
void setX(long nX)
virtual void SetAnchorPos(const Point &rPnt)
const Point & GetRefPoint() const
Definition: flyfrms.hxx:218
void setY(long nY)
virtual const SwRect GetObjRect() const =0
virtual const SwRect GetObjRect() const override
Style of a layout element.
Definition: frmfmt.hxx:57
long AdjustY(long nVertMove)
Helper class which can be used instead of the macros if a function has too many returns.
Definition: txtfrm.hxx:919
void SetPos(SwTwips nNew)
Definition: fmtornt.hxx:60
SwTwips GetRelPosToBase(const SwTwips _nObjBoundHeight, const SwFormatVertOrient &_rVert)
determine the relative position to base line for object position
virtual void Move(const Size &rSiz)
void SetLastObjRect(const tools::Rectangle &_rNewObjRect)
long X() const
const Point TopLeft() const
Definition: swrect.cxx:177
void SwitchLTRtoRTL(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from LTR to RTL layout.
Definition: txtfrm.cxx:693
long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1342
void Left(const long nLeft)
Definition: swrect.hxx:193
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:76
const Point & GetCurrRelPos() const
tools::Rectangle SVRect() const
Definition: swrect.hxx:282
FuncFlags const mnFlags
void Width(long nNew)
Definition: swrect.hxx:185
SwTwips GetPos() const
Definition: fmtornt.hxx:59
bool IsRightToLeft() const
Definition: frame.hxx:963
const SwTextFrame & GetAnchorTextFrame() const
method to cast to needed type
sal_Int16 GetVertOrient() const
Definition: fmtornt.hxx:54
long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1343
long GetRight() const
void SetRefPoint(const Point &rPoint, const Point &rRelAttr, const Point &rRelPos)
Definition: flyincnt.cxx:62
bool IsVertical() const
Definition: frame.hxx:949
virtual void CalcPosition() override
calculate position for object position
long Y() const
sal_uInt16 GetUpper() const
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74