xref: /AOO41X/main/sw/source/core/text/frmpaint.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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