xref: /trunk/main/sw/source/core/text/frmpaint.cxx (revision 989b13ef2270bbb43d1b5fb03162470a47d7f4cc)
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;
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 );
99     ~SwExtraPainter() { delete pFnt; }
100     inline SwFont* GetFont() const { return pFnt; }
101     inline void IncLineNr() { ++nLineNr; }
102     inline sal_Bool HasNumber() { return !( nLineNr % rLineInf.GetCountBy() ); }
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 
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 
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 
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 
296 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 
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 
471 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 
591 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