1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 #include <com/sun/star/text/HoriOrientation.hpp> 32 #include <hintids.hxx> 33 #include <vcl/sound.hxx> 34 #include <tools/shl.hxx> // SW_MOD 35 #include <editeng/pgrditem.hxx> 36 #include <editeng/lrspitem.hxx> 37 #include <pagedesc.hxx> // SwPageDesc 38 #include <tgrditem.hxx> 39 #include <paratr.hxx> 40 41 #include <fmtline.hxx> 42 #include <lineinfo.hxx> 43 #include <charfmt.hxx> 44 #include "rootfrm.hxx" 45 #include <pagefrm.hxx> 46 #include <viewsh.hxx> // ViewShell 47 #include <viewimp.hxx> // SwViewImp 48 #include <viewopt.hxx> // SwViewOption 49 #include <frmtool.hxx> // DrawGraphic 50 #include <txtcfg.hxx> 51 #include <txtfrm.hxx> // SwTxtFrm 52 #include <itrpaint.hxx> // SwTxtPainter 53 #include <txtpaint.hxx> // SwSaveClip 54 #include <txtcache.hxx> // SwTxtLineAccess 55 #include <flyfrm.hxx> // SwFlyFrm 56 #include <redlnitr.hxx> // SwRedlineItr 57 #include <swmodule.hxx> // SW_MOD 58 #include <tabfrm.hxx> // SwTabFrm (Redlining) 59 #include <SwGrammarMarkUp.hxx> 60 61 // --> FME 2004-06-08 #i12836# enhanced pdf export 62 #include <EnhancedPDFExportHelper.hxx> 63 // <-- 64 65 #include <IDocumentStylePoolAccess.hxx> 66 #include <IDocumentLineNumberAccess.hxx> 67 68 // --> OD 2006-06-27 #b6440955# 69 // variable moved to class <numfunc:GetDefBulletConfig> 70 //extern const sal_Char __FAR_DATA sBulletFntName[]; 71 namespace numfunc 72 { 73 extern const String& GetDefBulletFontname(); 74 extern bool IsDefBulletFontUserDefined(); 75 } 76 // <-- 77 78 79 #define REDLINE_DISTANCE 567/4 80 #define REDLINE_MINDIST 567/10 81 82 using namespace ::com::sun::star; 83 84 //////////////////////////////////////////////////////////// 85 86 sal_Bool bInitFont = sal_True; 87 88 class SwExtraPainter 89 { 90 SwSaveClip aClip; 91 SwRect aRect; 92 const SwTxtFrm* pTxtFrm; 93 ViewShell *pSh; 94 SwFont* pFnt; 95 const SwLineNumberInfo &rLineInf; 96 SwTwips nX; 97 SwTwips nRedX; 98 sal_uLong nLineNr; 99 MSHORT nDivider; 100 sal_Bool bGoLeft; 101 sal_Bool bLineNum; 102 inline sal_Bool IsClipChg() { return aClip.IsChg(); } 103 public: 104 SwExtraPainter( const SwTxtFrm *pFrm, ViewShell *pVwSh, 105 const SwLineNumberInfo &rLnInf, const SwRect &rRct, 106 sal_Int16 eHor, sal_Bool bLnNm ); 107 ~SwExtraPainter() { delete pFnt; } 108 inline SwFont* GetFont() const { return pFnt; } 109 inline void IncLineNr() { ++nLineNr; } 110 inline sal_Bool HasNumber() { return !( nLineNr % rLineInf.GetCountBy() ); } 111 inline sal_Bool HasDivider() { if( !nDivider ) return sal_False; 112 return !(nLineNr % rLineInf.GetDividerCountBy()); } 113 114 void PaintExtra( SwTwips nY, long nAsc, long nMax, sal_Bool bRed ); 115 void PaintRedline( SwTwips nY, long nMax ); 116 }; 117 118 119 SwExtraPainter::SwExtraPainter( const SwTxtFrm *pFrm, ViewShell *pVwSh, 120 const SwLineNumberInfo &rLnInf, const SwRect &rRct, 121 sal_Int16 eHor, sal_Bool bLnNm ) 122 : aClip( pVwSh->GetWin() || pFrm->IsUndersized() ? pVwSh->GetOut() : 0 ), 123 aRect( rRct ), pTxtFrm( pFrm ), pSh( pVwSh ), pFnt( 0 ), rLineInf( rLnInf ), 124 nLineNr( 1L ), bLineNum( bLnNm ) 125 { 126 if( pFrm->IsUndersized() ) 127 { 128 SwTwips nBottom = pFrm->Frm().Bottom(); 129 if( aRect.Bottom() > nBottom ) 130 aRect.Bottom( nBottom ); 131 } 132 MSHORT nVirtPageNum = 0; 133 if( bLineNum ) 134 { /* initialisiert die Member, die bei Zeilennumerierung notwendig sind: 135 136 nDivider, wie oft ist ein Teilerstring gewuenscht, 0 == nie; 137 nX, X-Position der Zeilennummern; 138 pFnt, der Font der Zeilennummern; 139 nLineNr, die erste Zeilennummer; 140 bLineNum wird ggf.wieder auf sal_False gesetzt, wenn die Numerierung sich 141 komplett ausserhalb des Paint-Rechtecks aufhaelt. */ 142 nDivider = rLineInf.GetDivider().Len() ? rLineInf.GetDividerCountBy() : 0; 143 nX = pFrm->Frm().Left(); 144 SwCharFmt* pFmt = rLineInf.GetCharFmt( const_cast<IDocumentStylePoolAccess&>(*pFrm->GetNode()->getIDocumentStylePoolAccess()) ); 145 ASSERT( pFmt, "PaintExtraData without CharFmt" ); 146 pFnt = new SwFont( &pFmt->GetAttrSet(), pFrm->GetTxtNode()->getIDocumentSettingAccess() ); 147 pFnt->Invalidate(); 148 pFnt->ChgPhysFnt( pSh, *pSh->GetOut() ); 149 pFnt->SetVertical( 0, pFrm->IsVertical() ); 150 nLineNr += pFrm->GetAllLines() - pFrm->GetThisLines(); 151 LineNumberPosition ePos = rLineInf.GetPos(); 152 if( ePos != LINENUMBER_POS_LEFT && ePos != LINENUMBER_POS_RIGHT ) 153 { 154 if( pFrm->FindPageFrm()->OnRightPage() ) 155 { 156 nVirtPageNum = 1; 157 ePos = ePos == LINENUMBER_POS_INSIDE ? 158 LINENUMBER_POS_LEFT : LINENUMBER_POS_RIGHT; 159 } 160 else 161 { 162 nVirtPageNum = 2; 163 ePos = ePos == LINENUMBER_POS_OUTSIDE ? 164 LINENUMBER_POS_LEFT : LINENUMBER_POS_RIGHT; 165 } 166 } 167 if( LINENUMBER_POS_LEFT == ePos ) 168 { 169 bGoLeft = sal_True; 170 nX -= rLineInf.GetPosFromLeft(); 171 if( nX < aRect.Left() ) 172 bLineNum = sal_False; 173 } 174 else 175 { 176 bGoLeft = sal_False; 177 nX += pFrm->Frm().Width() + rLineInf.GetPosFromLeft(); 178 if( nX > aRect.Right() ) 179 bLineNum = sal_False; 180 } 181 } 182 if( eHor != text::HoriOrientation::NONE ) 183 { 184 if( text::HoriOrientation::INSIDE == eHor || text::HoriOrientation::OUTSIDE == eHor ) 185 { 186 if( !nVirtPageNum ) 187 nVirtPageNum = pFrm->FindPageFrm()->OnRightPage() ? 1 : 2; 188 if( nVirtPageNum % 2 ) 189 eHor = eHor == text::HoriOrientation::INSIDE ? text::HoriOrientation::LEFT : text::HoriOrientation::RIGHT; 190 else 191 eHor = eHor == text::HoriOrientation::OUTSIDE ? text::HoriOrientation::LEFT : text::HoriOrientation::RIGHT; 192 } 193 const SwFrm* pTmpFrm = pFrm->FindTabFrm(); 194 if( !pTmpFrm ) 195 pTmpFrm = pFrm; 196 nRedX = text::HoriOrientation::LEFT == eHor ? pTmpFrm->Frm().Left() - REDLINE_DISTANCE : 197 pTmpFrm->Frm().Right() + REDLINE_DISTANCE; 198 } 199 } 200 201 /************************************************************************* 202 * SwExtraPainter::PaintExtra() 203 **************************************************************************/ 204 205 void SwExtraPainter::PaintExtra( SwTwips nY, long nAsc, long nMax, sal_Bool bRed ) 206 { 207 //Zeilennummer ist staerker als der Teiler 208 const XubString aTmp( HasNumber() ? rLineInf.GetNumType().GetNumStr( nLineNr ) 209 : rLineInf.GetDivider() ); 210 211 // get script type of line numbering: 212 pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmp, 0 ) ); 213 214 SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), 0, aTmp, 0, aTmp.Len() ); 215 aDrawInf.SetSpace( 0 ); 216 aDrawInf.SetWrong( NULL ); 217 aDrawInf.SetGrammarCheck( NULL ); 218 aDrawInf.SetSmartTags( NULL ); // SMARTTAGS 219 aDrawInf.SetLeft( 0 ); 220 aDrawInf.SetRight( LONG_MAX ); 221 aDrawInf.SetFrm( pTxtFrm ); 222 aDrawInf.SetFont( pFnt ); 223 aDrawInf.SetSnapToGrid( sal_False ); 224 aDrawInf.SetIgnoreFrmRTL( sal_True ); 225 226 sal_Bool bTooBig = pFnt->GetSize( pFnt->GetActual() ).Height() > nMax && 227 pFnt->GetHeight( pSh, *pSh->GetOut() ) > nMax; 228 SwFont* pTmpFnt; 229 if( bTooBig ) 230 { 231 pTmpFnt = new SwFont( *GetFont() ); 232 if( nMax >= 20 ) 233 { 234 nMax *= 17; 235 nMax /= 20; 236 } 237 pTmpFnt->SetSize( Size( 0, nMax ), pTmpFnt->GetActual() ); 238 } 239 else 240 pTmpFnt = GetFont(); 241 Point aTmpPos( nX, nY ); 242 aTmpPos.Y() += nAsc; 243 sal_Bool bPaint = sal_True; 244 if( !IsClipChg() ) 245 { 246 Size aSize = pTmpFnt->_GetTxtSize( aDrawInf ); 247 if( bGoLeft ) 248 aTmpPos.X() -= aSize.Width(); 249 // calculate rectangle containing the line number 250 SwRect aRct( Point( aTmpPos.X(), 251 aTmpPos.Y() - pTmpFnt->GetAscent( pSh, *pSh->GetOut() ) 252 ), aSize ); 253 if( !aRect.IsInside( aRct ) ) 254 { 255 if( aRct.Intersection( aRect ).IsEmpty() ) 256 bPaint = sal_False; 257 else 258 aClip.ChgClip( aRect, pTxtFrm ); 259 } 260 } 261 else if( bGoLeft ) 262 aTmpPos.X() -= pTmpFnt->_GetTxtSize( aDrawInf ).Width(); 263 aDrawInf.SetPos( aTmpPos ); 264 if( bPaint ) 265 pTmpFnt->_DrawText( aDrawInf ); 266 267 if( bTooBig ) 268 delete pTmpFnt; 269 if( bRed ) 270 { 271 long nDiff = bGoLeft ? nRedX - nX : nX - nRedX; 272 if( nDiff > REDLINE_MINDIST ) 273 PaintRedline( nY, nMax ); 274 } 275 } 276 277 void SwExtraPainter::PaintRedline( SwTwips nY, long nMax ) 278 { 279 Point aStart( nRedX, nY ); 280 Point aEnd( nRedX, nY + nMax ); 281 282 if( !IsClipChg() ) 283 { 284 SwRect aRct( aStart, aEnd ); 285 if( !aRect.IsInside( aRct ) ) 286 { 287 if( aRct.Intersection( aRect ).IsEmpty() ) 288 return; 289 aClip.ChgClip( aRect, pTxtFrm ); 290 } 291 } 292 const Color aOldCol( pSh->GetOut()->GetLineColor() ); 293 pSh->GetOut()->SetLineColor( SW_MOD()->GetRedlineMarkColor() ); 294 295 if ( pTxtFrm->IsVertical() ) 296 { 297 pTxtFrm->SwitchHorizontalToVertical( aStart ); 298 pTxtFrm->SwitchHorizontalToVertical( aEnd ); 299 } 300 301 pSh->GetOut()->DrawLine( aStart, aEnd ); 302 pSh->GetOut()->SetLineColor( aOldCol ); 303 } 304 305 void SwTxtFrm::PaintExtraData( const SwRect &rRect ) const 306 { 307 if( Frm().Top() > rRect.Bottom() || Frm().Bottom() < rRect.Top() ) 308 return; 309 310 const SwTxtNode& rTxtNode = *GetTxtNode(); 311 const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess(); 312 const SwLineNumberInfo &rLineInf = rTxtNode.getIDocumentLineNumberAccess()->GetLineNumberInfo(); 313 const SwFmtLineNumber &rLineNum = GetAttrSet()->GetLineNumber(); 314 sal_Bool bLineNum = !IsInTab() && rLineInf.IsPaintLineNumbers() && 315 ( !IsInFly() || rLineInf.IsCountInFlys() ) && rLineNum.IsCount(); 316 sal_Int16 eHor = (sal_Int16)SW_MOD()->GetRedlineMarkPos(); 317 if( eHor != text::HoriOrientation::NONE && !IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) ) 318 eHor = text::HoriOrientation::NONE; 319 sal_Bool bRedLine = eHor != text::HoriOrientation::NONE; 320 if ( bLineNum || bRedLine ) 321 { 322 if( IsLocked() || IsHiddenNow() || !Prt().Height() ) 323 return; 324 ViewShell *pSh = getRootFrm()->GetCurrShell(); 325 326 SWAP_IF_NOT_SWAPPED( this ) 327 SwRect rOldRect( rRect ); 328 329 if ( IsVertical() ) 330 SwitchVerticalToHorizontal( (SwRect&)rRect ); 331 332 SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() ); 333 aLayoutModeModifier.Modify( sal_False ); 334 335 // --> FME 2004-06-24 #i16816# tagged pdf support 336 SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() ); 337 // <-- 338 339 SwExtraPainter aExtra( this, pSh, rLineInf, rRect, eHor, bLineNum ); 340 341 if( HasPara() ) 342 { 343 SwTxtFrmLocker aLock((SwTxtFrm*)this); 344 345 SwTxtLineAccess aAccess( (SwTxtFrm*)this ); 346 aAccess.GetPara(); 347 348 SwTxtPaintInfo aInf( (SwTxtFrm*)this, rRect ); 349 350 aLayoutModeModifier.Modify( sal_False ); 351 352 SwTxtPainter aLine( (SwTxtFrm*)this, &aInf ); 353 sal_Bool bNoDummy = !aLine.GetNext(); // Nur eine Leerzeile! 354 355 while( aLine.Y() + aLine.GetLineHeight() <= rRect.Top() ) 356 { 357 if( !aLine.GetCurr()->IsDummy() && 358 ( rLineInf.IsCountBlankLines() || 359 aLine.GetCurr()->HasCntnt() ) ) 360 aExtra.IncLineNr(); 361 if( !aLine.Next() ) 362 { 363 (SwRect&)rRect = rOldRect; 364 UNDO_SWAP( this ) 365 return; 366 } 367 } 368 369 long nBottom = rRect.Bottom(); 370 371 sal_Bool bNoPrtLine = 0 == GetMinPrtLine(); 372 if( !bNoPrtLine ) 373 { 374 while ( aLine.Y() < GetMinPrtLine() ) 375 { 376 if( ( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasCntnt() ) 377 && !aLine.GetCurr()->IsDummy() ) 378 aExtra.IncLineNr(); 379 if( !aLine.Next() ) 380 break; 381 } 382 bNoPrtLine = aLine.Y() >= GetMinPrtLine(); 383 } 384 if( bNoPrtLine ) 385 { 386 do 387 { 388 if( bNoDummy || !aLine.GetCurr()->IsDummy() ) 389 { 390 sal_Bool bRed = bRedLine && aLine.GetCurr()->HasRedline(); 391 if( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasCntnt() ) 392 { 393 if( bLineNum && 394 ( aExtra.HasNumber() || aExtra.HasDivider() ) ) 395 { 396 KSHORT nTmpHeight, nTmpAscent; 397 aLine.CalcAscentAndHeight( nTmpAscent, nTmpHeight ); 398 aExtra.PaintExtra( aLine.Y(), nTmpAscent, 399 nTmpHeight, bRed ); 400 bRed = sal_False; 401 } 402 aExtra.IncLineNr(); 403 } 404 if( bRed ) 405 aExtra.PaintRedline( aLine.Y(), aLine.GetLineHeight() ); 406 } 407 } while( aLine.Next() && aLine.Y() <= nBottom ); 408 } 409 } 410 else 411 { 412 bRedLine &= ( MSHRT_MAX!= pIDRA->GetRedlinePos(rTxtNode, USHRT_MAX) ); 413 414 if( bLineNum && rLineInf.IsCountBlankLines() && 415 ( aExtra.HasNumber() || aExtra.HasDivider() ) ) 416 { 417 aExtra.PaintExtra( Frm().Top()+Prt().Top(), aExtra.GetFont() 418 ->GetAscent( pSh, *pSh->GetOut() ), Prt().Height(), bRedLine ); 419 } 420 else if( bRedLine ) 421 aExtra.PaintRedline( Frm().Top()+Prt().Top(), Prt().Height() ); 422 } 423 424 (SwRect&)rRect = rOldRect; 425 UNDO_SWAP( this ) 426 } 427 } 428 429 /************************************************************************* 430 * SwTxtFrm::Paint() 431 *************************************************************************/ 432 433 SwRect SwTxtFrm::Paint() 434 { 435 #if OSL_DEBUG_LEVEL > 1 436 const SwTwips nDbgY = Frm().Top(); 437 (void)nDbgY; 438 #endif 439 440 // finger layout 441 ASSERT( GetValidPosFlag(), "+SwTxtFrm::Paint: no Calc()" ); 442 443 SwRect aRet( Prt() ); 444 if ( IsEmpty() || !HasPara() ) 445 aRet += Frm().Pos(); 446 else 447 { 448 // AMA: Wir liefern jetzt mal das richtige Repaintrechteck zurueck, 449 // d.h. als linken Rand den berechneten PaintOfst! 450 SwRepaint *pRepaint = GetPara()->GetRepaint(); 451 long l; 452 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 453 if ( IsVertLR() ) // mba: the following line was added, but we don't need it for the existing directions; kept for IsVertLR(), but should be checked 454 pRepaint->Chg( ( GetUpper()->Frm() ).Pos() + ( GetUpper()->Prt() ).Pos(), ( GetUpper()->Prt() ).SSize() ); 455 456 if( pRepaint->GetOfst() ) 457 pRepaint->Left( pRepaint->GetOfst() ); 458 459 l = pRepaint->GetRightOfst(); 460 if( l && ( pRepaint->GetOfst() || l > pRepaint->Right() ) ) 461 pRepaint->Right( l ); 462 pRepaint->SetOfst( 0 ); 463 aRet = *pRepaint; 464 465 if ( IsRightToLeft() ) 466 SwitchLTRtoRTL( aRet ); 467 468 if ( IsVertical() ) 469 SwitchHorizontalToVertical( aRet ); 470 } 471 ResetRepaint(); 472 473 return aRet; 474 } 475 476 /************************************************************************* 477 * SwTxtFrm::Paint() 478 *************************************************************************/ 479 480 sal_Bool SwTxtFrm::PaintEmpty( const SwRect &rRect, sal_Bool bCheck ) const 481 { 482 ViewShell *pSh = getRootFrm()->GetCurrShell(); 483 if( pSh && ( pSh->GetViewOptions()->IsParagraph() || bInitFont ) ) 484 { 485 bInitFont = sal_False; 486 SwTxtFly aTxtFly( this ); 487 aTxtFly.SetTopRule(); 488 SwRect aRect; 489 if( bCheck && aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) ) 490 return sal_False; 491 else if( pSh->GetWin() ) 492 { 493 SwFont *pFnt; 494 const SwTxtNode& rTxtNode = *GetTxtNode(); 495 if ( rTxtNode.HasSwAttrSet() ) 496 { 497 const SwAttrSet *pAttrSet = &( rTxtNode.GetSwAttrSet() ); 498 pFnt = new SwFont( pAttrSet, rTxtNode.getIDocumentSettingAccess() ); 499 } 500 else 501 { 502 SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pSh ); 503 pFnt = new SwFont( *aFontAccess.Get()->GetFont() ); 504 } 505 506 const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess(); 507 if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) ) 508 { 509 MSHORT nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX ); 510 if( MSHRT_MAX != nRedlPos ) 511 { 512 SwAttrHandler aAttrHandler; 513 aAttrHandler.Init( rTxtNode.GetSwAttrSet(), 514 *rTxtNode.getIDocumentSettingAccess(), NULL ); 515 SwRedlineItr aRedln( rTxtNode, *pFnt, aAttrHandler, nRedlPos, sal_True ); 516 } 517 } 518 519 if( pSh->GetViewOptions()->IsParagraph() && Prt().Height() ) 520 { 521 if( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet( SW_LATIN ) && 522 pFnt->GetName( SW_LATIN ) != numfunc::GetDefBulletFontname() ) 523 { 524 pFnt->SetFamily( FAMILY_DONTKNOW, SW_LATIN ); 525 pFnt->SetName( numfunc::GetDefBulletFontname(), SW_LATIN ); 526 pFnt->SetStyleName( aEmptyStr, SW_LATIN ); 527 pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, SW_LATIN ); 528 } 529 pFnt->SetVertical( 0, IsVertical() ); 530 SwFrmSwapper aSwapper( this, sal_True ); 531 SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() ); 532 aLayoutModeModifier.Modify( IsRightToLeft() ); 533 534 pFnt->Invalidate(); 535 pFnt->ChgPhysFnt( pSh, *pSh->GetOut() ); 536 Point aPos = Frm().Pos() + Prt().Pos(); 537 538 const SvxLRSpaceItem &rSpace = 539 GetTxtNode()->GetSwAttrSet().GetLRSpace(); 540 541 if ( rSpace.GetTxtFirstLineOfst() > 0 ) 542 aPos.X() += rSpace.GetTxtFirstLineOfst(); 543 544 SwSaveClip *pClip; 545 if( IsUndersized() ) 546 { 547 pClip = new SwSaveClip( pSh->GetOut() ); 548 pClip->ChgClip( rRect ); 549 } 550 else 551 pClip = NULL; 552 553 aPos.Y() += pFnt->GetAscent( pSh, *pSh->GetOut() ); 554 555 if ( GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() && 556 IsInDocBody() ) 557 { 558 GETGRID( FindPageFrm() ) 559 if ( pGrid ) 560 { 561 // center character in grid line 562 aPos.Y() += ( pGrid->GetBaseHeight() - 563 pFnt->GetHeight( pSh, *pSh->GetOut() ) ) / 2; 564 565 if ( ! pGrid->GetRubyTextBelow() ) 566 aPos.Y() += pGrid->GetRubyHeight(); 567 } 568 } 569 570 const XubString aTmp( CH_PAR ); 571 SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), 0, aTmp, 0, 1 ); 572 aDrawInf.SetLeft( rRect.Left() ); 573 aDrawInf.SetRight( rRect.Right() ); 574 aDrawInf.SetPos( aPos ); 575 aDrawInf.SetSpace( 0 ); 576 aDrawInf.SetKanaComp( 0 ); 577 aDrawInf.SetWrong( NULL ); 578 aDrawInf.SetGrammarCheck( NULL ); 579 aDrawInf.SetSmartTags( NULL ); // SMARTTAGS 580 aDrawInf.SetFrm( this ); 581 aDrawInf.SetFont( pFnt ); 582 aDrawInf.SetSnapToGrid( sal_False ); 583 584 pFnt->_DrawText( aDrawInf ); 585 delete pClip; 586 } 587 delete pFnt; 588 return sal_True; 589 } 590 } 591 else 592 return sal_True; 593 return sal_False; 594 } 595 596 /************************************************************************* 597 * SwTxtFrm::Paint() 598 *************************************************************************/ 599 600 void SwTxtFrm::Paint(SwRect const& rRect, SwPrintData const*const) const 601 { 602 ResetRepaint(); 603 604 // --> FME 2004-06-24 #i16816# tagged pdf support 605 ViewShell *pSh = getRootFrm()->GetCurrShell(); 606 607 Num_Info aNumInfo( *this ); 608 SwTaggedPDFHelper aTaggedPDFHelperNumbering( &aNumInfo, 0, 0, *pSh->GetOut() ); 609 610 Frm_Info aFrmInfo( *this ); 611 SwTaggedPDFHelper aTaggedPDFHelperParagraph( 0, &aFrmInfo, 0, *pSh->GetOut() ); 612 // <-- 613 614 DBG_LOOP_RESET; 615 if( !IsEmpty() || !PaintEmpty( rRect, sal_True ) ) 616 { 617 #if OSL_DEBUG_LEVEL > 1 618 const SwTwips nDbgY = Frm().Top(); 619 (void)nDbgY; 620 #endif 621 622 #ifdef DBGTXT 623 if( IsDbg( this ) ) 624 DBTXTFRM << "Paint()" << endl; 625 #endif 626 if( IsLocked() || IsHiddenNow() || ! Prt().HasArea() ) 627 return; 628 629 //Kann gut sein, dass mir der IdleCollector mir die gecachten 630 //Informationen entzogen hat. 631 if( !HasPara() ) 632 { 633 ASSERT( GetValidPosFlag(), "+SwTxtFrm::Paint: no Calc()" ); 634 635 // --> FME 2004-10-29 #i29062# pass info that we are currently 636 // painting. 637 ((SwTxtFrm*)this)->GetFormatted( true ); 638 // <-- 639 if( IsEmpty() ) 640 { 641 PaintEmpty( rRect, sal_False ); 642 return; 643 } 644 if( !HasPara() ) 645 { 646 ASSERT( !this, "+SwTxtFrm::Paint: missing format information" ); 647 return; 648 } 649 } 650 651 // Waehrend wir painten, wollen wir nicht gestoert werden. 652 // Aber erst hinter dem Format() ! 653 SwTxtFrmLocker aLock((SwTxtFrm*)this); 654 655 //Hier wird ggf. nur der Teil des TxtFrm ausgegeben, der sich veraendert 656 //hat und der in dem Bereich liegt, dessen Ausgabe angefordert wurde. 657 //Man kann jetzt auf die Idee kommen, dass der Bereich rRect ausgegeben 658 //werden _muss_ obwohl rRepaint gesetzt ist; in der Tat kann dieses 659 //Problem nicht formal vermieden werden. Gluecklicherweise koennen 660 //wir davon ausgehen, dass rRepaint immer dann leer ist, wenn der Frm 661 //komplett gepainted werden muss. 662 SwTxtLineAccess aAccess( (SwTxtFrm*)this ); 663 SwParaPortion *pPara = aAccess.GetPara(); 664 665 SwRepaint &rRepaint = *(pPara->GetRepaint()); 666 667 // Das Recycling muss abgeschaltet werden, wenn wir uns im 668 // FlyCntFrm befinden, weil ein DrawRect fuer die Retusche der 669 // Zeile aufgerufen wird. 670 if( rRepaint.GetOfst() ) 671 { 672 const SwFlyFrm *pFly = FindFlyFrm(); 673 if( pFly && pFly->IsFlyInCntFrm() ) 674 rRepaint.SetOfst( 0 ); 675 } 676 677 // Hier holen wir uns den String fuer die Ausgabe, besonders 678 // die Laenge ist immer wieder interessant. 679 680 // Rectangle 681 ASSERT( ! IsSwapped(), "A frame is swapped before Paint" ); 682 SwRect aOldRect( rRect ); 683 684 SWAP_IF_NOT_SWAPPED( this ) 685 686 if ( IsVertical() ) 687 SwitchVerticalToHorizontal( (SwRect&)rRect ); 688 689 if ( IsRightToLeft() ) 690 SwitchRTLtoLTR( (SwRect&)rRect ); 691 692 SwTxtPaintInfo aInf( (SwTxtFrm*)this, rRect ); 693 aInf.SetWrongList( ( (SwTxtNode*)GetTxtNode() )->GetWrong() ); 694 aInf.SetGrammarCheckList( ( (SwTxtNode*)GetTxtNode() )->GetGrammarCheck() ); 695 aInf.SetSmartTags( ( (SwTxtNode*)GetTxtNode() )->GetSmartTags() ); // SMARTTAGS 696 aInf.GetTxtFly()->SetTopRule(); 697 698 SwTxtPainter aLine( (SwTxtFrm*)this, &aInf ); 699 // Eine Optimierung, die sich lohnt: wenn kein freifliegender Frame 700 // in unsere Zeile ragt, schaltet sich der SwTxtFly einfach ab: 701 aInf.GetTxtFly()->Relax(); 702 703 OutputDevice* pOut = aInf.GetOut(); 704 const sal_Bool bOnWin = pSh->GetWin() != 0; 705 706 SwSaveClip aClip( bOnWin || IsUndersized() ? pOut : 0 ); 707 708 // Ausgabeschleife: Fuer jede Zeile ... (die noch zu sehen ist) ... 709 // rRect muss angepasst werden (Top+1, Bottom-1), weil der Iterator 710 // die Zeilen nahtlos aneinanderfuegt. 711 aLine.TwipsToLine( rRect.Top() + 1 ); 712 long nBottom = rRect.Bottom(); 713 714 sal_Bool bNoPrtLine = 0 == GetMinPrtLine(); 715 if( !bNoPrtLine ) 716 { 717 while ( aLine.Y() < GetMinPrtLine() && aLine.Next() ) 718 ; 719 bNoPrtLine = aLine.Y() >= GetMinPrtLine(); 720 } 721 if( bNoPrtLine ) 722 { 723 do 724 { 725 //DBG_LOOP; shadows declaration above. 726 //resolved into: 727 #if OSL_DEBUG_LEVEL > 1 728 #ifdef DBG_UTIL 729 DbgLoop aDbgLoop2( (const void*) this ); 730 #endif 731 #endif 732 aLine.DrawTextLine( rRect, aClip, IsUndersized() ); 733 734 } while( aLine.Next() && aLine.Y() <= nBottom ); 735 } 736 737 // Einmal reicht: 738 if( aLine.IsPaintDrop() ) 739 aLine.PaintDropPortion(); 740 741 if( rRepaint.HasArea() ) 742 rRepaint.Clear(); 743 744 UNDO_SWAP( this ) 745 (SwRect&)rRect = aOldRect; 746 747 ASSERT( ! IsSwapped(), "A frame is swapped after Paint" ); 748 } 749 } 750 751