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
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
34using namespace ::com::sun::star;
35
36namespace objectpositioning
37{
38
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 )
57{}
58
61{}
62
65{
66 assert( dynamic_cast<const SwTextFrame*>( &GetAnchorFrame() ) &&
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
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
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 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() );
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 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() ) )
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}
397
398/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
virtual void SetAnchorPos(const Point &rPnt)
virtual void Move(const Size &rSiz)
tools::Long GetRight() const
tools::Long GetLeft() const
sal_uInt16 GetUpper() const
sal_uInt16 GetLower() const
class for the positioning of drawing objects
void SetLastObjRect(const tools::Rectangle &_rNewObjRect)
virtual SwRect GetObjRect() const override
virtual SwRect GetObjRect() const =0
const Point & GetCurrRelPos() const
Flys that are anchored as a character in the content.
Definition: flyfrms.hxx:210
const Point & GetRefPoint() const
Definition: flyfrms.hxx:229
void SetRefPoint(const Point &rPoint, const Point &rRelAttr, const Point &rRelPos)
Definition: flyincnt.cxx:63
Defines the vertical position of a fly frame.
Definition: fmtornt.hxx:37
SwTwips GetPos() const
Definition: fmtornt.hxx:62
void SetPos(SwTwips nNew)
Definition: fmtornt.hxx:63
sal_Int16 GetVertOrient() const
Definition: fmtornt.hxx:57
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:98
const SwFormatVertOrient & GetVertOrient(bool=true) const
Definition: fmtornt.hxx:113
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:100
const SwRect & getFrameArea() const
Definition: frame.hxx:179
Style of a layout element.
Definition: frmfmt.hxx:72
Helper class which can be used instead of the macros if a function has too many returns.
Definition: txtfrm.hxx:956
bool IsRightToLeft() const
Definition: frame.hxx:993
bool IsVertical() const
Definition: frame.hxx:979
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1387
tools::Long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1386
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
void Height(tools::Long nNew)
Definition: swrect.hxx:193
Point TopLeft() const
Definition: swrect.hxx:254
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
void AddLeft(const tools::Long nAdd)
Definition: swrect.cxx:125
void AddHeight(const tools::Long nAdd)
Definition: swrect.cxx:124
void AddTop(const tools::Long nAdd)
Definition: swrect.cxx:128
void AddWidth(const tools::Long nAdd)
Definition: swrect.cxx:123
tools::Rectangle SVRect() const
Definition: swrect.hxx:292
void Left(const tools::Long nLeft)
Definition: swrect.hxx:197
void Width(tools::Long nNew)
Definition: swrect.hxx:189
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
void SwitchVerticalToHorizontal(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from vertical to horizontal layout.
Definition: txtfrm.cxx:580
void SwitchLTRtoRTL(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from LTR to RTL layout.
Definition: txtfrm.cxx:683
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout.
Definition: txtfrm.cxx:473
const SwTextFrame & GetAnchorTextFrame() const
method to cast <SwAnchoredObjectPosition::GetAnchorFrame()> to needed type
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
SwTwips GetRelPosToBase(const SwTwips _nObjBoundHeight, const SwFormatVertOrient &_rVert)
determine the relative position to base line for object position
virtual void CalcPosition() override
calculate position for object position
FuncFlags mnFlags
NONE
Dialog to specify the properties of date form field.
tools::Long SwTwips
Definition: swtypes.hxx:51