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