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 27 28 #include "dcontact.hxx" // SwDrawContact 29 #include "dflyobj.hxx" // SwVirtFlyDrawObj 30 #include "pam.hxx" // SwPosition 31 #include "flyfrm.hxx" // SwFlyInCntFrm 32 #include "rootfrm.hxx" 33 #include "frmfmt.hxx" // SwFrmFmt 34 #include "viewsh.hxx" 35 36 #include <vcl/outdev.hxx> 37 #include <editeng/lrspitem.hxx> 38 #include <editeng/ulspitem.hxx> 39 #include <fmtanchr.hxx> 40 #include <fmtflcnt.hxx> 41 #include <fmtornt.hxx> 42 #include <frmatr.hxx> 43 #include "flyfrms.hxx" 44 #include "txatbase.hxx" // SwTxtAttr 45 #include "porfly.hxx" 46 #include "porlay.hxx" // SetFly 47 #include "inftxt.hxx" // SwTxtPaintInfo 48 49 // OD 2004-05-24 #i28701# 50 #include <sortedobjs.hxx> 51 52 53 /************************************************************************* 54 * class SwFlyPortion 55 * 56 * Wir erwarten ein framelokales SwRect ! 57 *************************************************************************/ 58 59 void SwFlyPortion::Paint( const SwTxtPaintInfo& ) const 60 { 61 } 62 63 /************************************************************************* 64 * virtual SwFlyPortion::Format() 65 *************************************************************************/ 66 sal_Bool SwFlyPortion::Format( SwTxtFormatInfo &rInf ) 67 { 68 ASSERT( Fix() >= rInf.X(), "SwFlyPortion::Format: rush hour" ); 69 // 8537: Tabs muessen expandiert werden. 70 if( rInf.GetLastTab() ) 71 ((SwLinePortion*)rInf.GetLastTab())->FormatEOL( rInf ); 72 73 // Der Glue wird aufgespannt. 74 rInf.GetLast()->FormatEOL( rInf ); 75 PrtWidth( static_cast<sal_uInt16>(Fix() - rInf.X() + PrtWidth()) ); 76 if( !Width() ) 77 { 78 ASSERT( Width(), "+SwFlyPortion::Format: a fly is a fly is a fly" ); 79 Width(1); 80 } 81 82 // Restaurierung 83 rInf.SetFly( 0 ); 84 rInf.Width( rInf.RealWidth() ); 85 rInf.GetParaPortion()->SetFly( sal_True ); 86 87 // trailing blank: 88 if( rInf.GetIdx() < rInf.GetTxt().Len() && 1 < rInf.GetIdx() 89 && !rInf.GetRest() 90 && ' ' == rInf.GetChar( rInf.GetIdx() ) 91 && ' ' != rInf.GetChar( rInf.GetIdx() - 1 ) 92 && ( !rInf.GetLast() || !rInf.GetLast()->IsBreakPortion() ) ) 93 { 94 SetBlankWidth( rInf.GetTxtSize( ' ' ).Width() ); 95 SetLen( 1 ); 96 } 97 98 const sal_uInt16 nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth()); 99 if( rInf.Width() <= nNewWidth ) 100 { 101 Truncate(); 102 if( nNewWidth > rInf.Width() ) 103 { 104 PrtWidth( nNewWidth - rInf.Width() ); 105 SetFixWidth( PrtWidth() ); 106 } 107 return sal_True; 108 } 109 return sal_False; 110 } 111 112 /************************************************************************* 113 * virtual SwFlyCntPortion::Format() 114 *************************************************************************/ 115 sal_Bool SwFlyCntPortion::Format( SwTxtFormatInfo &rInf ) 116 { 117 sal_Bool bFull = rInf.Width() < rInf.X() + PrtWidth(); 118 119 if( bFull ) 120 { 121 // 3924: wenn die Zeile voll ist und der zeichengebundene Frame am 122 // Anfang der Zeile steht. 123 // 5157: nicht wenn einem Fly ausgewichen werden kann! 124 // "Begin of line" criteria ( ! rInf.X() ) has to be extended. 125 // KerningPortions at beginning of line, e.g., for grid layout 126 // must be considered. 127 const SwLinePortion* pLastPor = rInf.GetLast(); 128 const sal_uInt16 nLeft = ( pLastPor && 129 ( pLastPor->IsKernPortion() || 130 pLastPor->IsErgoSumPortion() ) ) ? 131 pLastPor->Width() : 132 0; 133 134 if( nLeft == rInf.X() && ! rInf.GetFly() ) 135 { 136 Width( rInf.Width() ); 137 bFull = sal_False; // Damit Notizen noch in dieser Zeile landen 138 } 139 else 140 { 141 if( !rInf.GetFly() ) 142 rInf.SetNewLine( sal_True ); 143 Width(0); 144 SetAscent(0); 145 SetLen(0); 146 if( rInf.GetLast() ) 147 rInf.GetLast()->FormatEOL( rInf ); 148 149 return bFull; 150 } 151 } 152 153 rInf.GetParaPortion()->SetFly( sal_True ); 154 return bFull; 155 } 156 157 /************************************************************************* 158 * SwTxtFrm::MoveFlyInCnt() haengt jetzt die zeichengebundenen Objekte 159 * innerhalb des angegebenen Bereichs um, damit koennen diese vom Master 160 * zum Follow oder umgekehrt wandern. 161 *************************************************************************/ 162 void SwTxtFrm::MoveFlyInCnt( SwTxtFrm *pNew, xub_StrLen nStart, xub_StrLen nEnd ) 163 { 164 SwSortedObjs *pObjs = 0L; 165 if ( 0 != (pObjs = GetDrawObjs()) ) 166 { 167 for ( sal_uInt32 i = 0; GetDrawObjs() && i < pObjs->Count(); ++i ) 168 { 169 // OD 2004-03-29 #i26791# 170 // --> OD 2004-07-06 #i28701# - consider changed type of 171 // <SwSortedList> entries 172 SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; 173 const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor(); 174 if (rAnch.GetAnchorId() == FLY_AS_CHAR) 175 { 176 const SwPosition* pPos = rAnch.GetCntntAnchor(); 177 xub_StrLen nIdx = pPos->nContent.GetIndex(); 178 if ( nIdx >= nStart && nEnd > nIdx ) 179 { 180 if ( pAnchoredObj->ISA(SwFlyFrm) ) 181 { 182 RemoveFly( static_cast<SwFlyFrm*>(pAnchoredObj) ); 183 pNew->AppendFly( static_cast<SwFlyFrm*>(pAnchoredObj) ); 184 } 185 else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) ) 186 { 187 RemoveDrawObj( *pAnchoredObj ); 188 pNew->AppendDrawObj( *pAnchoredObj ); 189 } 190 --i; 191 } 192 } 193 // <-- 194 } 195 } 196 } 197 198 /************************************************************************* 199 * SwTxtFrm::CalcFlyPos() 200 *************************************************************************/ 201 xub_StrLen SwTxtFrm::CalcFlyPos( SwFrmFmt* pSearch ) 202 { 203 SwpHints* pHints = GetTxtNode()->GetpSwpHints(); 204 ASSERT( pHints, "CalcFlyPos: Why me?" ); 205 if( !pHints ) 206 return STRING_LEN; 207 SwTxtAttr* pFound = NULL; 208 for ( sal_uInt16 i = 0; i < pHints->Count(); i++) 209 { 210 SwTxtAttr *pHt = pHints->GetTextHint( i ); 211 if( RES_TXTATR_FLYCNT == pHt->Which() ) 212 { 213 SwFrmFmt* pFrmFmt = pHt->GetFlyCnt().GetFrmFmt(); 214 if( pFrmFmt == pSearch ) 215 pFound = pHt; 216 } 217 } 218 ASSERT( pHints, "CalcFlyPos: Not Found!" ); 219 if( !pFound ) 220 return STRING_LEN; 221 return *pFound->GetStart(); 222 } 223 224 /************************************************************************* 225 * virtual SwFlyCntPortion::Paint() 226 *************************************************************************/ 227 void SwFlyCntPortion::Paint( const SwTxtPaintInfo &rInf ) const 228 { 229 if( bDraw ) 230 { 231 if( !((SwDrawContact*)pContact)->GetAnchorFrm() ) 232 { 233 // OD 2004-04-01 #i26791# - no direct positioning of the drawing 234 // object is needed. 235 SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(pContact); 236 pDrawContact->ConnectToLayout(); 237 } 238 } 239 else 240 { 241 // Baseline-Ausgabe ! 242 // 7922: Bei CompletePaint alles painten 243 SwRect aRepaintRect( rInf.GetPaintRect() ); 244 245 if ( rInf.GetTxtFrm()->IsRightToLeft() ) 246 rInf.GetTxtFrm()->SwitchLTRtoRTL( aRepaintRect ); 247 248 if ( rInf.GetTxtFrm()->IsVertical() ) 249 rInf.GetTxtFrm()->SwitchHorizontalToVertical( aRepaintRect ); 250 251 if( (GetFlyFrm()->IsCompletePaint() || 252 GetFlyFrm()->Frm().IsOver( aRepaintRect )) && 253 SwFlyFrm::IsPaint( (SdrObject*)GetFlyFrm()->GetVirtDrawObj(), 254 GetFlyFrm()->getRootFrm()->GetCurrShell() )) 255 { 256 SwRect aRect( GetFlyFrm()->Frm() ); 257 if( !GetFlyFrm()->IsCompletePaint() ) 258 aRect._Intersection( aRepaintRect ); 259 260 261 // GetFlyFrm() may change the layout mode at the output device. 262 { 263 SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() ); 264 GetFlyFrm()->Paint( aRect ); 265 } 266 ((SwTxtPaintInfo&)rInf).GetRefDev()->SetLayoutMode( 267 rInf.GetOut()->GetLayoutMode() ); 268 269 // Es hilft alles nichts, im zeichengebundenen Frame kann wer weiss 270 // was am OutputDevice eingestellt sein, wir muessen unseren Font 271 // wieder hineinselektieren. Dass wir im const stehen, soll uns 272 // daran nicht hindern: 273 ((SwTxtPaintInfo&)rInf).SelectFont(); 274 275 // I want to know if this can really happen. So here comes a new 276 ASSERT( ! rInf.GetVsh() || rInf.GetVsh()->GetOut() == rInf.GetOut(), 277 "SwFlyCntPortion::Paint: Outdev has changed" ) 278 if( rInf.GetVsh() ) 279 ((SwTxtPaintInfo&)rInf).SetOut( rInf.GetVsh()->GetOut() ); 280 } 281 } 282 } 283 284 /************************************************************************* 285 * SwFlyCntPortion::SwFlyCntPortion() 286 * 287 * Es werden die Masze vom pFly->OutRect() eingestellt. 288 * Es erfolgt ein SetBase() ! 289 *************************************************************************/ 290 // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags> 291 SwFlyCntPortion::SwFlyCntPortion( const SwTxtFrm& rFrm, 292 SwFlyInCntFrm *pFly, const Point &rBase, 293 long nLnAscent, long nLnDescent, 294 long nFlyAsc, long nFlyDesc, 295 objectpositioning::AsCharFlags nFlags ) : 296 pContact( pFly ), 297 bDraw( sal_False ), 298 bMax( sal_False ), 299 nAlign( 0 ) 300 { 301 ASSERT( pFly, "SwFlyCntPortion::SwFlyCntPortion: no SwFlyInCntFrm!" ); 302 nLineLength = 1; 303 nFlags |= AS_CHAR_ULSPACE | AS_CHAR_INIT; 304 SetBase( rFrm, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags ); 305 SetWhichPor( POR_FLYCNT ); 306 } 307 308 // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags> 309 SwFlyCntPortion::SwFlyCntPortion( const SwTxtFrm& rFrm, 310 SwDrawContact *pDrawContact, const Point &rBase, 311 long nLnAscent, long nLnDescent, 312 long nFlyAsc, long nFlyDesc, 313 objectpositioning::AsCharFlags nFlags ) : 314 pContact( pDrawContact ), 315 bDraw( sal_True ), 316 bMax( sal_False ), 317 nAlign( 0 ) 318 { 319 ASSERT( pDrawContact, "SwFlyCntPortion::SwFlyCntPortion: no SwDrawContact!" ); 320 if( !pDrawContact->GetAnchorFrm() ) 321 { 322 // OD 2004-04-01 #i26791# - no direct positioning needed any more 323 pDrawContact->ConnectToLayout(); 324 // --> OD 2005-01-14 #i40333# - follow-up of #i35635# 325 // move object to visible layer 326 pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() ); 327 // <-- 328 } 329 nLineLength = 1; 330 nFlags |= AS_CHAR_ULSPACE | AS_CHAR_INIT; 331 332 SetBase( rFrm, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags ); 333 334 SetWhichPor( POR_FLYCNT ); 335 } 336 337 338 /************************************************************************* 339 * SwFlyCntPortion::SetBase() 340 * 341 * Nach dem Setzen des RefPoints muss der Ascent neu berechnet werden, 342 * da er von der RelPos abhaengt. 343 * pFly->GetRelPos().Y() bezeichnet die relative Position zur Baseline. 344 * Bei 0 liegt der obere Rand des FlyCnt auf der Baseline der Zeile. 345 *************************************************************************/ 346 // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags> 347 void SwFlyCntPortion::SetBase( const SwTxtFrm& rFrm, const Point &rBase, 348 long nLnAscent, long nLnDescent, 349 long nFlyAsc, long nFlyDesc, 350 objectpositioning::AsCharFlags nFlags ) 351 { 352 // Note: rBase have to be an absolute value 353 354 // OD 28.10.2003 #113049# - use new class to position object 355 // determine drawing object 356 SdrObject* pSdrObj = 0L; 357 if( bDraw ) 358 { 359 // OD 20.06.2003 #108784# - determine drawing object ('master' or 'virtual') 360 // by frame. 361 pSdrObj = GetDrawContact()->GetDrawObjectByAnchorFrm( rFrm ); 362 if ( !pSdrObj ) 363 { 364 ASSERT( false, "SwFlyCntPortion::SetBase(..) - No drawing object found by <GetDrawContact()->GetDrawObjectByAnchorFrm( rFrm )>" ); 365 pSdrObj = GetDrawContact()->GetMaster(); 366 } 367 // --> OD 2007-11-29 #i65798# 368 // call <SwAnchoredDrawObject::MakeObjPos()> to assure that flag at 369 // the <DrawFrmFmt> and at the <SwAnchoredDrawObject> instance are 370 // correctly set. 371 if ( pSdrObj ) 372 { 373 GetDrawContact()->GetAnchoredObj( pSdrObj )->MakeObjPos(); 374 } 375 // <-- 376 } 377 else 378 { 379 pSdrObj = GetFlyFrm()->GetVirtDrawObj(); 380 } 381 382 // position object 383 objectpositioning::SwAsCharAnchoredObjectPosition aObjPositioning( 384 *pSdrObj, 385 rBase, nFlags, 386 nLnAscent, nLnDescent, nFlyAsc, nFlyDesc ); 387 388 // OD 2004-04-13 #i26791# - scope of local variable <aObjPosInProgress> 389 { 390 // OD 2004-04-13 #i26791# 391 SwObjPositioningInProgress aObjPosInProgress( *pSdrObj ); 392 aObjPositioning.CalcPosition(); 393 } 394 395 SetAlign( aObjPositioning.GetLineAlignment() ); 396 397 aRef = aObjPositioning.GetAnchorPos(); 398 if( nFlags & AS_CHAR_ROTATE ) 399 SvXSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() ); 400 else 401 SvLSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() ); 402 if( Height() ) 403 { 404 SwTwips nRelPos = aObjPositioning.GetRelPosY(); 405 if ( nRelPos < 0 ) 406 { 407 nAscent = static_cast<sal_uInt16>(-nRelPos); 408 if( nAscent > Height() ) 409 Height( nAscent ); 410 } 411 else 412 { 413 nAscent = 0; 414 Height( Height() + static_cast<sal_uInt16>(nRelPos) ); 415 } 416 } 417 else 418 { 419 Height( 1 ); 420 nAscent = 0; 421 } 422 } 423 424 /************************************************************************* 425 * virtual SwFlyCntPortion::GetFlyCrsrOfst() 426 *************************************************************************/ 427 428 xub_StrLen SwFlyCntPortion::GetFlyCrsrOfst( const KSHORT nOfst, 429 const Point &rPoint, SwPosition *pPos, SwCrsrMoveState* pCMS ) const 430 { 431 // Da die FlyCnt nicht an der Seite haengen, wird ihr 432 // GetCrsrOfst() nicht gerufen. Um die Layoutseite 433 // von unnoetiger Verwaltung zu entlasten, ruft der Absatz 434 // das GetCrsrOfst des FlyFrm, wenn es erforderlich ist. 435 Point aPoint( rPoint ); 436 if( !pPos || bDraw || !( GetFlyFrm()->GetCrsrOfst( pPos, aPoint, pCMS ) ) ) 437 return SwLinePortion::GetCrsrOfst( nOfst ); 438 else 439 return 0; 440 } 441 442 /************************************************************************* 443 * virtual SwFlyCntPortion::GetCrsrOfst() 444 *************************************************************************/ 445 446 xub_StrLen SwFlyCntPortion::GetCrsrOfst( const KSHORT nOfst ) const 447 { 448 // ASSERT( !this, "SwFlyCntPortion::GetCrsrOfst: use GetFlyCrsrOfst()" ); 449 return SwLinePortion::GetCrsrOfst( nOfst ); 450 } 451 452