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  maAnchorPos ( Point() ),
54  mnRelPos ( 0 ),
55  maObjBoundRect ( SwRect() ),
56  mnLineAlignment ( sw::LineAlign::NONE )
57 {}
58 
61 {}
62 
65 {
66  OSL_ENSURE( dynamic_cast<const SwTextFrame*>( &GetAnchorFrame() ) != nullptr,
67  "SwAsCharAnchoredObjectPosition::GetAnchorTextFrame() - wrong anchor frame type" );
68 
69  return static_cast<const SwTextFrame&>(GetAnchorFrame());
70 }
71 
80 {
81  const SwTextFrame& rAnchorFrame = GetAnchorTextFrame();
82  // swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
83  SwFrameSwapper aFrameSwapper( &rAnchorFrame, false );
84 
85  SwRectFnSet aRectFnSet(&rAnchorFrame);
86 
87  Point aAnchorPos( mrProposedAnchorPos );
88 
89  const SwFrameFormat& rFrameFormat = GetFrameFormat();
90 
91  SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
92  SwTwips nObjWidth = aRectFnSet.GetWidth(aObjBoundRect);
93 
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;
98  {
99  if ( rAnchorFrame.IsVertical() )
100  {
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 );
105 
106  // convert the spacing values
107  nLRSpaceLeft = rULSpace.GetUpper();
108  nLRSpaceRight = rULSpace.GetLower();
109  nULSpaceUpper = rLRSpace.GetRight();
110  nULSpaceLower = rLRSpace.GetLeft();
111  }
112  else
113  {
114  if ( rAnchorFrame.IsRightToLeft() )
115  {
116  nLRSpaceLeft = rLRSpace.GetRight();
117  nLRSpaceRight = rLRSpace.GetLeft();
118  }
119  else
120  {
121  nLRSpaceLeft = rLRSpace.GetLeft();
122  nLRSpaceRight = rLRSpace.GetRight();
123  }
124 
125  nULSpaceUpper = rULSpace.GetUpper();
126  nULSpaceLower = rULSpace.GetLower();
127  }
128  }
129 
130  // consider left and upper spacing by adjusting anchor position.
131  // left spacing is only considered, if requested.
133  {
134  aAnchorPos.AdjustX(nLRSpaceLeft );
135  }
136  aAnchorPos.AdjustY(nULSpaceUpper );
137 
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() )
142  {
143  SwRect aSnapRect = GetObject().GetSnapRect();
144  if ( rAnchorFrame.IsVertical() )
145  {
146  rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
147  }
148 
149  if( mnFlags & AsCharFlags::UlSpace )
150  {
151  aAnchorPos.AdjustX(aSnapRect.Left() - aObjBoundRect.Left() );
152  }
153  aAnchorPos.AdjustY(aSnapRect.Top() - aObjBoundRect.Top() );
154  }
155 
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 );
161 
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 );
168 
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 )
175  {
177  aAnchorPos.AdjustX( -(mnLineAscentInclObjs + nRelPos) );
178  else
179  aAnchorPos.AdjustY( -(mnLineAscentInclObjs + nRelPos) );
180  }
181 
182  // consider BIDI-multiportion by adjusting proposed anchor position
183  if( mnFlags & AsCharFlags::Bidi )
184  aAnchorPos.AdjustX( -(aObjBoundRect.Width()) );
185 
186  // calculate relative position considering rotation and inside rotation
187  // reverse direction.
188  Point aRelPos;
189  {
191  {
193  aRelPos.setX( -nRelPos - aObjBoundRect.Width() );
194  else
195  {
196  aRelPos.setX( nRelPos );
197  aRelPos.setY( -aObjBoundRect.Height() );
198  }
199  }
200  else
201  aRelPos.setY( nRelPos );
202  }
203 
204  if( !IsObjFly() )
205  {
206  if( !( mnFlags & AsCharFlags::Quick ) )
207  {
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 )
213  {
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();
219  }
220 
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() )
226  {
227  rAnchorFrame.SwitchLTRtoRTL( aAbsAnchorPos );
228  aAbsAnchorPos.AdjustX( -nObjWidth );
229  }
230  if ( rAnchorFrame.IsVertical() )
231  rAnchorFrame.SwitchHorizontalToVertical( aAbsAnchorPos );
232 
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 );
237 
238  // move drawing object to set its correct relative position.
239  {
240  SwRect aSnapRect = GetObject().GetSnapRect();
241  if ( rAnchorFrame.IsVertical() )
242  rAnchorFrame.SwitchVerticalToHorizontal( aSnapRect );
243 
244  Point aDiff;
245  if ( rAnchorFrame.IsRightToLeft() )
246  aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
247  else
248  aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
249 
250  if ( rAnchorFrame.IsVertical() )
251  aDiff = Point( -aDiff.Y(), aDiff.X() );
252 
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() ) );
256  }
257  }
258 
259  // switch horizontal, LTR anchor position to absolute values.
260  if ( rAnchorFrame.IsRightToLeft() )
261  {
262  rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
263  aAnchorPos.AdjustX( -nObjWidth );
264  }
265  if ( rAnchorFrame.IsVertical() )
266  rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
267 
268  // #i44347# - keep last object rectangle at anchored object
269  OSL_ENSURE( dynamic_cast<const SwAnchoredDrawObject*>( &GetAnchoredObj() ) != nullptr,
270  "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong type of anchored object." );
271  SwAnchoredDrawObject& rAnchoredDrawObj =
272  static_cast<SwAnchoredDrawObject&>( GetAnchoredObj() );
273  rAnchoredDrawObj.SetLastObjRect( rAnchoredDrawObj.GetObjRect().SVRect() );
274  }
275  else
276  {
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() )
282  {
283  rAnchorFrame.SwitchLTRtoRTL( aAnchorPos );
284  aAnchorPos.AdjustX( -nObjWidth );
285  }
286  if ( rAnchorFrame.IsVertical() )
287  {
288  rAnchorFrame.SwitchHorizontalToVertical( aAnchorPos );
289  aRelAttr = Point( -nRelPos, 0 );
290  aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
291  }
292  else
293  aRelAttr = Point( 0, nRelPos );
294 
295  // OD 2004-03-23 #i26791#
296  OSL_ENSURE( dynamic_cast<const SwFlyInContentFrame*>( &GetAnchoredObj()) != nullptr,
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() ) )
303  {
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()) )
308  {
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() );
315  }
316  }
317  OSL_ENSURE( aRectFnSet.GetHeight(rFlyInContentFrame.getFrameArea()),
318  "SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
319  }
320 
321  // keep calculated values
322  maAnchorPos = aAnchorPos;
323  mnRelPos = nRelPos;
324  maObjBoundRect = aObjBoundRect;
325 }
326 
336  const SwTwips _nObjBoundHeight,
337  const SwFormatVertOrient& _rVert )
338 {
339  SwTwips nRelPosToBase = 0;
340 
342 
343  const sal_Int16 eVertOrient = _rVert.GetVertOrient();
344 
345  if ( eVertOrient == text::VertOrientation::NONE )
346  nRelPosToBase = _rVert.GetPos();
347  else
348  {
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
362  {
363  if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
364  {
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 )
370  else if ( eVertOrient == text::VertOrientation::LINE_TOP )
372  else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
374  }
375  else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
376  {
377  nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
379  }
380  else if ( eVertOrient == text::VertOrientation::LINE_TOP )
381  {
382  nRelPosToBase -= mnLineAscentInclObjs;
384  }
385  else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
386  {
387  nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
389  }
390  }
391  }
392 
393  return nRelPosToBase;
394 }
395 
396 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:157
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:578
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:195
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:471
tools::Long GetRight() const
Dialog to specify the properties of date form field.
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
tools::Long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1377
void AddTop(const tools::Long nAdd)
Definition: swrect.cxx:165
virtual const tools::Rectangle & GetSnapRect() const
Point TopLeft() const
Definition: swrect.cxx:174
FuncFlags mnFlags
NONE
const SwRect & getFrameArea() const
Definition: frame.hxx:178
virtual void SetAnchorPos(const Point &rPnt)
void Width(tools::Long nNew)
Definition: swrect.hxx:187
const Point & GetRefPoint() const
Definition: flyfrms.hxx:214
Style of a layout element.
Definition: frmfmt.hxx:58
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:918
void SetPos(SwTwips nNew)
Definition: fmtornt.hxx:60
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1378
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:49
void SwitchLTRtoRTL(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from LTR to RTL layout.
Definition: txtfrm.cxx:681
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:280
SwTwips GetPos() const
Definition: fmtornt.hxx:59
bool IsRightToLeft() const
Definition: frame.hxx:983
void Top(const tools::Long nTop)
Definition: swrect.hxx:204
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:969
void Height(tools::Long nNew)
Definition: swrect.hxx:191
virtual void CalcPosition() override
calculate position for object position
sal_uInt16 GetUpper() const
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74