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 
20 #include <anchoreddrawobject.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>
32 
33 
34 using namespace ::com::sun::star;
35 using namespace objectpositioning;
36 
39  SdrObject& _rDrawObj,
40  const Point& _rProposedAnchorPos,
41  const AsCharFlags _nFlags,
42  const SwTwips _nLineAscent,
43  const SwTwips _nLineDescent,
44  const SwTwips _nLineAscentInclObjs,
45  const SwTwips _nLineDescentInclObjs )
46  : SwAnchoredObjectPosition( _rDrawObj ),
47  mrProposedAnchorPos( _rProposedAnchorPos ),
48  mnFlags( _nFlags ),
49  mnLineAscent( _nLineAscent ),
50  mnLineDescent( _nLineDescent ),
51  mnLineAscentInclObjs( _nLineAscentInclObjs ),
52  mnLineDescentInclObjs( _nLineDescentInclObjs ),
53  mnRelPos ( 0 ),
54  mnLineAlignment ( sw::LineAlign::NONE )
55 {}
56 
59 {}
60 
63 {
64  assert( dynamic_cast<const SwTextFrame*>( &GetAnchorFrame() ) &&
65  "SwAsCharAnchoredObjectPosition::GetAnchorTextFrame() - wrong anchor frame type" );
66 
67  return static_cast<const SwTextFrame&>(GetAnchorFrame());
68 }
69 
78 {
79  const SwTextFrame& rAnchorFrame = GetAnchorTextFrame();
80  // swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
81  SwFrameSwapper aFrameSwapper( &rAnchorFrame, false );
82 
83  SwRectFnSet aRectFnSet(&rAnchorFrame);
84 
85  Point aAnchorPos( mrProposedAnchorPos );
86 
87  const SwFrameFormat& rFrameFormat = GetFrameFormat();
88 
89  SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
90  SwTwips nObjWidth = aRectFnSet.GetWidth(aObjBoundRect);
91 
92  // determine spacing values considering layout-/text-direction
93  const SvxLRSpaceItem& rLRSpace = rFrameFormat.GetLRSpace();
94  const SvxULSpaceItem& rULSpace = rFrameFormat.GetULSpace();
95  SwTwips nLRSpaceLeft, nLRSpaceRight, nULSpaceUpper, nULSpaceLower;
96  {
97  if ( rAnchorFrame.IsVertical() )
98  {
99  // Seems to be easier to do it all the horizontal way
100  // So, from now on think horizontal.
101  rAnchorFrame.SwitchVerticalToHorizontal( aObjBoundRect );
102  rAnchorFrame.SwitchVerticalToHorizontal( aAnchorPos );
103 
104  // convert the spacing values
105  nLRSpaceLeft = rULSpace.GetUpper();
106  nLRSpaceRight = rULSpace.GetLower();
107  nULSpaceUpper = rLRSpace.GetRight();
108  nULSpaceLower = rLRSpace.GetLeft();
109  }
110  else
111  {
112  if ( rAnchorFrame.IsRightToLeft() )
113  {
114  nLRSpaceLeft = rLRSpace.GetRight();
115  nLRSpaceRight = rLRSpace.GetLeft();
116  }
117  else
118  {
119  nLRSpaceLeft = rLRSpace.GetLeft();
120  nLRSpaceRight = rLRSpace.GetRight();
121  }
122 
123  nULSpaceUpper = rULSpace.GetUpper();
124  nULSpaceLower = rULSpace.GetLower();
125  }
126  }
127 
128  // consider left and upper spacing by adjusting anchor position.
129  // left spacing is only considered, if requested.
131  {
132  aAnchorPos.AdjustX(nLRSpaceLeft );
133  }
134  aAnchorPos.AdjustY(nULSpaceUpper );
135 
136  // for drawing objects: consider difference between its bounding rectangle
137  // and its snapping rectangle by adjusting anchor position.
138  // left difference is only considered, if requested.
139  if( !IsObjFly() )
140  {
141  SwRect aSnapRect(GetObject().GetSnapRect());
142  if ( rAnchorFrame.IsVertical() )
143  {
144  rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
145  }
146 
147  if( mnFlags & AsCharFlags::UlSpace )
148  {
149  aAnchorPos.AdjustX(aSnapRect.Left() - aObjBoundRect.Left() );
150  }
151  aAnchorPos.AdjustY(aSnapRect.Top() - aObjBoundRect.Top() );
152  }
153 
154  // enlarge bounding rectangle of object by its spacing.
155  aObjBoundRect.AddLeft( - nLRSpaceLeft );
156  aObjBoundRect.AddWidth( nLRSpaceRight );
157  aObjBoundRect.AddTop( - nULSpaceUpper );
158  aObjBoundRect.AddHeight( nULSpaceLower );
159 
160  // calculate relative position to given base line.
161  const SwFormatVertOrient& rVert = rFrameFormat.GetVertOrient();
162  const SwTwips nObjBoundHeight = ( mnFlags & AsCharFlags::Rotate )
163  ? aObjBoundRect.Width()
164  : aObjBoundRect.Height();
165  const SwTwips nRelPos = GetRelPosToBase( nObjBoundHeight, rVert );
166 
167  // for initial positioning:
168  // adjust the proposed anchor position by difference between
169  // calculated relative position to base line and current maximal line ascent.
170  // Note: In the following line formatting the base line will be adjusted
171  // by the same difference.
172  if( mnFlags & AsCharFlags::Init && nRelPos < 0 && mnLineAscentInclObjs < -nRelPos )
173  {
175  aAnchorPos.AdjustX( -(mnLineAscentInclObjs + nRelPos) );
176  else
177  aAnchorPos.AdjustY( -(mnLineAscentInclObjs + nRelPos) );
178  }
179 
180  // consider BIDI-multiportion by adjusting proposed anchor position
181  if( mnFlags & AsCharFlags::Bidi )
182  aAnchorPos.AdjustX( -(aObjBoundRect.Width()) );
183 
184  // calculate relative position considering rotation and inside rotation
185  // reverse direction.
186  Point aRelPos;
187  {
189  {
191  aRelPos.setX( -nRelPos - aObjBoundRect.Width() );
192  else
193  {
194  aRelPos.setX( nRelPos );
195  aRelPos.setY( -aObjBoundRect.Height() );
196  }
197  }
198  else
199  aRelPos.setY( nRelPos );
200  }
201 
202  if( !IsObjFly() )
203  {
204  if( !( mnFlags & AsCharFlags::Quick ) )
205  {
206  // save calculated Y-position value for 'automatic' vertical positioning,
207  // in order to avoid a switch to 'manual' vertical positioning in
208  // <SwDrawContact::Changed_(..)>.
209  const sal_Int16 eVertOrient = rVert.GetVertOrient();
210  if( rVert.GetPos() != nRelPos && eVertOrient != text::VertOrientation::NONE )
211  {
212  SwFormatVertOrient aVert( rVert );
213  aVert.SetPos( nRelPos );
214  const_cast<SwFrameFormat&>(rFrameFormat).LockModify();
215  const_cast<SwFrameFormat&>(rFrameFormat).SetFormatAttr( aVert );
216  const_cast<SwFrameFormat&>(rFrameFormat).UnlockModify();
217  }
218 
219  // determine absolute anchor position considering layout directions.
220  // Note: Use copy of <aAnchorPos>, because it's needed for
221  // setting relative position.
222  Point aAbsAnchorPos( aAnchorPos );
223  if ( rAnchorFrame.IsRightToLeft() )
224  {
225  rAnchorFrame.SwitchLTRtoRTL( aAbsAnchorPos );
226  aAbsAnchorPos.AdjustX( -nObjWidth );
227  }
228  if ( rAnchorFrame.IsVertical() )
229  rAnchorFrame.SwitchHorizontalToVertical( aAbsAnchorPos );
230 
231  // set proposed anchor position at the drawing object.
232  // OD 2004-04-06 #i26791# - distinction between 'master' drawing
233  // object and 'virtual' drawing object no longer needed.
234  GetObject().SetAnchorPos( aAbsAnchorPos );
235 
236  // move drawing object to set its correct relative position.
237  {
238  SwRect aSnapRect(GetObject().GetSnapRect());
239  if ( rAnchorFrame.IsVertical() )
240  rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
241 
242  Point aDiff;
243  if ( rAnchorFrame.IsRightToLeft() )
244  aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
245  else
246  aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
247 
248  if ( rAnchorFrame.IsVertical() )
249  aDiff = Point( -aDiff.Y(), aDiff.X() );
250 
251  // OD 2004-04-06 #i26791# - distinction between 'master' drawing
252  // object and 'virtual' drawing object no longer needed.
253  GetObject().Move( Size( aDiff.X(), aDiff.Y() ) );
254  }
255  }
256 
257  // switch horizontal, LTR anchor position to absolute values.
258  if ( rAnchorFrame.IsRightToLeft() )
259  {
260  rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
261  aAnchorPos.AdjustX( -nObjWidth );
262  }
263  if ( rAnchorFrame.IsVertical() )
264  rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
265 
266  // #i44347# - keep last object rectangle at anchored object
267  assert( dynamic_cast<const SwAnchoredDrawObject*>( &GetAnchoredObj() ) &&
268  "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong type of anchored object." );
269  SwAnchoredDrawObject& rAnchoredDrawObj =
270  static_cast<SwAnchoredDrawObject&>( GetAnchoredObj() );
271  rAnchoredDrawObj.SetLastObjRect( rAnchoredDrawObj.GetObjRect().SVRect() );
272  }
273  else
274  {
275  // determine absolute anchor position and calculate corresponding
276  // relative position and its relative position attribute.
277  // Note: The relative position contains the spacing values.
278  Point aRelAttr;
279  if ( rAnchorFrame.IsRightToLeft() )
280  {
281  rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
282  aAnchorPos.AdjustX( -nObjWidth );
283  }
284  if ( rAnchorFrame.IsVertical() )
285  {
286  rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
287  aRelAttr = Point( -nRelPos, 0 );
288  aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
289  }
290  else
291  aRelAttr = Point( 0, nRelPos );
292 
293  // OD 2004-03-23 #i26791#
294  assert( dynamic_cast<const SwFlyInContentFrame*>( &GetAnchoredObj()) &&
295  "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong anchored object." );
296  const SwFlyInContentFrame& rFlyInContentFrame =
297  static_cast<const SwFlyInContentFrame&>(GetAnchoredObj());
298  if ( !(mnFlags & AsCharFlags::Quick) &&
299  ( aAnchorPos != rFlyInContentFrame.GetRefPoint() ||
300  aRelAttr != rFlyInContentFrame.GetCurrRelPos() ) )
301  {
302  // set new anchor position and relative position
303  SwFlyInContentFrame* pFlyInContentFrame = &const_cast<SwFlyInContentFrame&>(rFlyInContentFrame);
304  pFlyInContentFrame->SetRefPoint( aAnchorPos, aRelAttr, aRelPos );
305  if( nObjWidth != aRectFnSet.GetWidth(pFlyInContentFrame->getFrameArea()) )
306  {
307  // recalculate object bound rectangle, if object width has changed.
308  aObjBoundRect = GetAnchoredObj().GetObjRect();
309  aObjBoundRect.AddLeft( - rLRSpace.GetLeft() );
310  aObjBoundRect.AddWidth( rLRSpace.GetRight() );
311  aObjBoundRect.AddTop( - rULSpace.GetUpper() );
312  aObjBoundRect.AddHeight( rULSpace.GetLower() );
313  }
314  }
315  OSL_ENSURE( aRectFnSet.GetHeight(rFlyInContentFrame.getFrameArea()),
316  "SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
317  }
318 
319  // keep calculated values
320  maAnchorPos = aAnchorPos;
321  mnRelPos = nRelPos;
322  maObjBoundRect = aObjBoundRect;
323 }
324 
334  const SwTwips _nObjBoundHeight,
335  const SwFormatVertOrient& _rVert )
336 {
337  SwTwips nRelPosToBase = 0;
338 
340 
341  const sal_Int16 eVertOrient = _rVert.GetVertOrient();
342 
343  if ( eVertOrient == text::VertOrientation::NONE )
344  nRelPosToBase = _rVert.GetPos();
345  else
346  {
347  if ( eVertOrient == text::VertOrientation::CENTER )
348  nRelPosToBase -= _nObjBoundHeight / 2;
349  else if ( eVertOrient == text::VertOrientation::TOP )
350  nRelPosToBase -= _nObjBoundHeight;
351  else if ( eVertOrient == text::VertOrientation::BOTTOM )
352  nRelPosToBase = 0;
353  else if ( eVertOrient == text::VertOrientation::CHAR_CENTER )
354  nRelPosToBase -= ( _nObjBoundHeight + mnLineAscent - mnLineDescent ) / 2;
355  else if ( eVertOrient == text::VertOrientation::CHAR_TOP )
356  nRelPosToBase -= mnLineAscent;
357  else if ( eVertOrient == text::VertOrientation::CHAR_BOTTOM )
358  nRelPosToBase += mnLineDescent - _nObjBoundHeight;
359  else
360  {
361  if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
362  {
363  // object is at least as high as the line. Thus, no more is
364  // positioning necessary. Also, the max. ascent isn't changed.
365  nRelPosToBase -= mnLineAscentInclObjs;
366  if ( eVertOrient == text::VertOrientation::LINE_CENTER )
368  else if ( eVertOrient == text::VertOrientation::LINE_TOP )
370  else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
372  }
373  else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
374  {
375  nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
377  }
378  else if ( eVertOrient == text::VertOrientation::LINE_TOP )
379  {
380  nRelPosToBase -= mnLineAscentInclObjs;
382  }
383  else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
384  {
385  nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
387  }
388  }
389  }
390 
391  return nRelPosToBase;
392 }
393 
394 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:158
virtual SwRect GetObjRect() const =0
void SwitchVerticalToHorizontal(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from vertical to horizontal layout...
Definition: txtfrm.cxx:582
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 ...
const SwFormatVertOrient & GetVertOrient(bool=true) const
Definition: fmtornt.hxx:106
void Left(const tools::Long nLeft)
Definition: swrect.hxx:194
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:475
tools::Long GetRight() const
Dialog to specify the properties of date form field.
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
tools::Long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1382
void AddTop(const tools::Long nAdd)
Definition: swrect.cxx:165
Point TopLeft() const
Definition: swrect.cxx:174
FuncFlags mnFlags
NONE
const SwRect & getFrameArea() const
Definition: frame.hxx:180
virtual void SetAnchorPos(const Point &rPnt)
void Width(tools::Long nNew)
Definition: swrect.hxx:186
const Point & GetRefPoint() const
Definition: flyfrms.hxx:214
Style of a layout element.
Definition: frmfmt.hxx:59
virtual SwRect GetObjRect() const override
Helper class which can be used instead of the macros if a function has too many returns.
Definition: txtfrm.hxx:921
void SetPos(SwTwips nNew)
Definition: fmtornt.hxx:60
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1383
SwTwips GetRelPosToBase(const SwTwips _nObjBoundHeight, const SwFormatVertOrient &_rVert)
determine the relative position to base line for object position
tools::Long GetLeft() const
void AddHeight(const tools::Long nAdd)
Definition: swrect.cxx:161
void AddWidth(const tools::Long nAdd)
Definition: swrect.cxx:160
virtual void Move(const Size &rSiz)
void SetLastObjRect(const tools::Rectangle &_rNewObjRect)
tools::Long SwTwips
Definition: swtypes.hxx:52
void SwitchLTRtoRTL(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from LTR to RTL layout.
Definition: txtfrm.cxx:685
void AddLeft(const tools::Long nAdd)
Definition: swrect.cxx:162
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:76
const Point & GetCurrRelPos() const
tools::Rectangle SVRect() const
Definition: swrect.hxx:272
SwTwips GetPos() const
Definition: fmtornt.hxx:59
bool IsRightToLeft() const
Definition: frame.hxx:988
void Top(const tools::Long nTop)
Definition: swrect.hxx:203
const SwTextFrame & GetAnchorTextFrame() const
method to cast to needed type
sal_Int16 GetVertOrient() const
Definition: fmtornt.hxx:54
void SetRefPoint(const Point &rPoint, const Point &rRelAttr, const Point &rRelPos)
Definition: flyincnt.cxx:62
bool IsVertical() const
Definition: frame.hxx:974
void Height(tools::Long nNew)
Definition: swrect.hxx:190
virtual void CalcPosition() override
calculate position for object position
sal_uInt16 GetUpper() const
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74