1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include <tolayoutanchoredobjectposition.hxx>
27 #include <anchoredobject.hxx>
28 #include <frame.hxx>
29 #include <pagefrm.hxx>
30 #include <svx/svdobj.hxx>
31 #include <frmfmt.hxx>
32 #include <fmtanchr.hxx>
33 #include <fmtornt.hxx>
34 #include <fmtsrnd.hxx>
35 #include <IDocumentSettingAccess.hxx>
36 #include <frmatr.hxx>
37 #include "viewsh.hxx"
38 #include "viewopt.hxx"
39 #include "rootfrm.hxx"
40 #include <editeng/lrspitem.hxx>
41 #include <editeng/ulspitem.hxx>
42 
43 using namespace objectpositioning;
44 using namespace ::com::sun::star;
45 
46 
SwToLayoutAnchoredObjectPosition(SdrObject & _rDrawObj)47 SwToLayoutAnchoredObjectPosition::SwToLayoutAnchoredObjectPosition( SdrObject& _rDrawObj )
48     : SwAnchoredObjectPosition( _rDrawObj ),
49       maRelPos( Point() ),
50       // --> OD 2004-06-17 #i26791#
51       maOffsetToFrmAnchorPos( Point() )
52 {}
53 
~SwToLayoutAnchoredObjectPosition()54 SwToLayoutAnchoredObjectPosition::~SwToLayoutAnchoredObjectPosition()
55 {}
56 
57 /** calculate position for object position type TO_LAYOUT
58 
59     @author OD
60 */
CalcPosition()61 void SwToLayoutAnchoredObjectPosition::CalcPosition()
62 {
63     const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
64 
65     SWRECTFN( (&GetAnchorFrm()) );
66 
67     const SwFrmFmt& rFrmFmt = GetFrmFmt();
68     const SvxLRSpaceItem &rLR = rFrmFmt.GetLRSpace();
69     const SvxULSpaceItem &rUL = rFrmFmt.GetULSpace();
70 
71     const bool bFlyAtFly = FLY_AT_FLY == rFrmFmt.GetAnchor().GetAnchorId();
72 
73     // determine position.
74     // 'vertical' and 'horizontal' position are calculated separately
75     Point aRelPos;
76 
77     // calculate 'vertical' position
78     SwFmtVertOrient aVert( rFrmFmt.GetVertOrient() );
79     {
80         // to-frame anchored objects are *only* vertical positioned centered or
81         // bottom, if its wrap mode is 'throught' and its anchor frame has fixed
82         // size. Otherwise, it's positioned top.
83         sal_Int16 eVertOrient = aVert.GetVertOrient();
84         if ( ( bFlyAtFly &&
85                ( eVertOrient == text::VertOrientation::CENTER ||
86                  eVertOrient == text::VertOrientation::BOTTOM ) &&
87              SURROUND_THROUGHT != rFrmFmt.GetSurround().GetSurround() &&
88              !GetAnchorFrm().HasFixSize() ) )
89         {
90             eVertOrient = text::VertOrientation::TOP;
91         }
92         // --> OD 2004-06-17 #i26791# - get vertical offset to frame anchor position.
93         SwTwips nVertOffsetToFrmAnchorPos( 0L );
94         SwTwips nRelPosY =
95                 _GetVertRelPos( GetAnchorFrm(), GetAnchorFrm(), eVertOrient,
96                                 aVert.GetRelationOrient(), aVert.GetPos(),
97                                 rLR, rUL, nVertOffsetToFrmAnchorPos );
98 
99 
100         // keep the calculated relative vertical position - needed for filters
101         // (including the xml-filter)
102         {
103             SwTwips nAttrRelPosY = nRelPosY - nVertOffsetToFrmAnchorPos;
104             if ( aVert.GetVertOrient() != text::VertOrientation::NONE &&
105                  aVert.GetPos() != nAttrRelPosY )
106             {
107                 aVert.SetPos( nAttrRelPosY );
108                 const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
109                 const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
110                 const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
111             }
112         }
113 
114         // determine absolute 'vertical' position, depending on layout-direction
115         // --> OD 2004-06-17 #i26791# - determine offset to 'vertical' frame
116         // anchor position, depending on layout-direction
117         if( bVert )
118         {
119             ASSERT( !bRev, "<SwToLayoutAnchoredObjectPosition::CalcPosition()> - reverse layout set." );
120             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
121             if ( bVertL2R )
122                	aRelPos.X() = nRelPosY;
123             else
124                	aRelPos.X() = -nRelPosY - aObjBoundRect.Width();
125             maOffsetToFrmAnchorPos.X() = nVertOffsetToFrmAnchorPos;
126         }
127         else
128         {
129             aRelPos.Y() = nRelPosY;
130             maOffsetToFrmAnchorPos.Y() = nVertOffsetToFrmAnchorPos;
131         }
132 
133         // if in online-layout the bottom of to-page anchored object is beyond
134         // the page bottom, the page frame has to grow by growing its body frame.
135         const ViewShell *pSh = GetAnchorFrm().getRootFrm()->GetCurrShell();
136         if ( !bFlyAtFly && GetAnchorFrm().IsPageFrm() &&
137              pSh && pSh->GetViewOptions()->getBrowseMode() )
138         {
139             const long nAnchorBottom = GetAnchorFrm().Frm().Bottom();
140             const long nBottom = GetAnchorFrm().Frm().Top() +
141                                  aRelPos.Y() + aObjBoundRect.Height();
142             if ( nAnchorBottom < nBottom )
143             {
144                 static_cast<SwPageFrm&>(GetAnchorFrm()).
145                         FindBodyCont()->Grow( nBottom - nAnchorBottom );
146             }
147         }
148     } // end of determination of vertical position
149 
150     // calculate 'horizontal' position
151     SwFmtHoriOrient aHori( rFrmFmt.GetHoriOrient() );
152     {
153         // consider toggle of horizontal position for even pages.
154         const bool bToggle = aHori.IsPosToggle() &&
155                              !GetAnchorFrm().FindPageFrm()->OnRightPage();
156         sal_Int16 eHoriOrient = aHori.GetHoriOrient();
157         sal_Int16 eRelOrient = aHori.GetRelationOrient();
158         // toggle orientation
159         _ToggleHoriOrientAndAlign( bToggle, eHoriOrient, eRelOrient );
160 
161         // determine alignment values:
162         // <nWidth>: 'width' of the alignment area
163         // <nOffset>: offset of alignment area, relative to 'left' of
164         //            frame anchor position
165         SwTwips nWidth, nOffset;
166         {
167             bool bDummy; // in this context irrelevant output parameter
168             _GetHoriAlignmentValues( GetAnchorFrm(), GetAnchorFrm(),
169                                      eRelOrient, false,
170                                      nWidth, nOffset, bDummy );
171         }
172 
173         SwTwips nObjWidth = (aObjBoundRect.*fnRect->fnGetWidth)();
174 
175         // determine relative horizontal position
176         SwTwips nRelPosX;
177         if ( text::HoriOrientation::NONE == eHoriOrient )
178         {
179             if( bToggle ||
180                 ( !aHori.IsPosToggle() && GetAnchorFrm().IsRightToLeft() ) )
181             {
182                 nRelPosX = nWidth - nObjWidth - aHori.GetPos();
183             }
184             else
185             {
186                 nRelPosX = aHori.GetPos();
187             }
188         }
189         else if ( text::HoriOrientation::CENTER == eHoriOrient )
190             nRelPosX = (nWidth / 2) - (nObjWidth / 2);
191         else if ( text::HoriOrientation::RIGHT == eHoriOrient )
192             nRelPosX = nWidth - ( nObjWidth +
193                              ( bVert ? rUL.GetLower() : rLR.GetRight() ) );
194         else
195             nRelPosX = bVert ? rUL.GetUpper() : rLR.GetLeft();
196         nRelPosX += nOffset;
197 
198         // no 'negative' relative horizontal position
199         // OD 06.11.2003 #FollowTextFlowAtFrame# - negative positions allow for
200         // to frame anchored objects.
201         if ( !bFlyAtFly && nRelPosX < 0 )
202         {
203             nRelPosX = 0;
204         }
205 
206         // determine absolute 'horizontal' position, depending on layout-direction
207         // --> OD 2004-06-17 #i26791# - determine offset to 'horizontal' frame
208         // anchor position, depending on layout-direction
209         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
210         // --> OD 2009-09-04 #mongolianlayout#
211         if( bVert || bVertL2R )
212         // <--
213         {
214 
215             aRelPos.Y() = nRelPosX;
216             maOffsetToFrmAnchorPos.Y() = nOffset;
217         }
218         else
219         {
220             aRelPos.X() = nRelPosX;
221             maOffsetToFrmAnchorPos.X() = nOffset;
222         }
223 
224         // keep the calculated relative horizontal position - needed for filters
225         // (including the xml-filter)
226         {
227             SwTwips nAttrRelPosX = nRelPosX - nOffset;
228             if ( text::HoriOrientation::NONE != aHori.GetHoriOrient() &&
229                  aHori.GetPos() != nAttrRelPosX )
230             {
231                 aHori.SetPos( nAttrRelPosX );
232                 const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
233                 const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aHori );
234                 const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
235             }
236         }
237     } // end of determination of horizontal position
238 
239     // keep calculate relative position
240     maRelPos = aRelPos;
241 }
242 
243 /** calculated relative position for object position
244 
245     @author OD
246 */
GetRelPos() const247 Point SwToLayoutAnchoredObjectPosition::GetRelPos() const
248 {
249     return maRelPos;
250 }
251 
252