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;
IsClipChg()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 );
~SwExtraPainter()103 ~SwExtraPainter() { delete pFnt; }
GetFont() const104 inline SwFont* GetFont() const { return pFnt; }
IncLineNr()105 inline void IncLineNr() { ++nLineNr; }
HasNumber()106 inline sal_Bool HasNumber() { return !( nLineNr % rLineInf.GetCountBy() ); }
HasDivider()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
SwExtraPainter(const SwTxtFrm * pFrm,ViewShell * pVwSh,const SwLineNumberInfo & rLnInf,const SwRect & rRct,sal_Int16 eHor,sal_Bool bLnNm)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
PaintExtra(SwTwips nY,long nAsc,long nMax,sal_Bool bRed)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
PaintRedline(SwTwips nY,long nMax)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
PaintExtraData(const SwRect & rRect) const301 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
Paint()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
PaintEmpty(const SwRect & rRect,sal_Bool bCheck) const476 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
Paint(SwRect const & rRect,SwPrintData const * const) const596 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