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