Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/text/HoriOrientation.hpp>
21 : #include <hintids.hxx>
22 : #include <editeng/pgrditem.hxx>
23 : #include <editeng/lrspitem.hxx>
24 : #include <pagedesc.hxx>
25 : #include <tgrditem.hxx>
26 : #include <paratr.hxx>
27 :
28 : #include <fmtline.hxx>
29 : #include <lineinfo.hxx>
30 : #include <charfmt.hxx>
31 : #include "rootfrm.hxx"
32 : #include <pagefrm.hxx>
33 : #include <viewsh.hxx>
34 : #include <viewimp.hxx>
35 : #include <viewopt.hxx>
36 : #include <frmtool.hxx>
37 : #include <txtfrm.hxx>
38 : #include <itrpaint.hxx>
39 : #include <txtpaint.hxx>
40 : #include <txtcache.hxx>
41 : #include <flyfrm.hxx>
42 : #include <redlnitr.hxx>
43 : #include <swmodule.hxx>
44 : #include <tabfrm.hxx>
45 : #include <numrule.hxx>
46 : #include <SwGrammarMarkUp.hxx>
47 :
48 : #include <EnhancedPDFExportHelper.hxx>
49 :
50 : #include <IDocumentStylePoolAccess.hxx>
51 :
52 : #define REDLINE_DISTANCE 567/4
53 : #define REDLINE_MINDIST 567/10
54 :
55 : using namespace ::com::sun::star;
56 :
57 : static bool bInitFont = true;
58 :
59 : class SwExtraPainter
60 : {
61 : SwSaveClip aClip;
62 : SwRect aRect;
63 : const SwTxtFrm* pTxtFrm;
64 : SwViewShell *pSh;
65 : SwFont* pFnt;
66 : const SwLineNumberInfo &rLineInf;
67 : SwTwips nX;
68 : SwTwips nRedX;
69 : sal_uLong nLineNr;
70 : sal_uInt16 nDivider;
71 : bool bGoLeft;
72 : bool bLineNum;
73 1797 : inline bool IsClipChg() { return aClip.IsChg(); }
74 : public:
75 : SwExtraPainter( const SwTxtFrm *pFrm, SwViewShell *pVwSh,
76 : const SwLineNumberInfo &rLnInf, const SwRect &rRct,
77 : sal_Int16 eHor, bool bLnNm );
78 2222 : ~SwExtraPainter() { delete pFnt; }
79 168 : inline SwFont* GetFont() const { return pFnt; }
80 2849 : inline void IncLineNr() { ++nLineNr; }
81 526 : inline bool HasNumber() { return !( nLineNr % rLineInf.GetCountBy() ); }
82 230 : inline bool HasDivider() { if( !nDivider ) return false;
83 0 : return !(nLineNr % rLineInf.GetDividerCountBy()); }
84 :
85 : void PaintExtra( SwTwips nY, long nAsc, long nMax, bool bRed );
86 : void PaintRedline( SwTwips nY, long nMax );
87 : };
88 :
89 2222 : SwExtraPainter::SwExtraPainter( const SwTxtFrm *pFrm, SwViewShell *pVwSh,
90 : const SwLineNumberInfo &rLnInf, const SwRect &rRct,
91 : sal_Int16 eHor, bool bLnNm )
92 2222 : : aClip( pVwSh->GetWin() || pFrm->IsUndersized() ? pVwSh->GetOut() : 0 )
93 : , aRect( rRct )
94 : , pTxtFrm( pFrm )
95 : , pSh( pVwSh )
96 : , pFnt( 0 )
97 : , rLineInf( rLnInf )
98 : , nX(0)
99 : , nRedX(0)
100 : , nLineNr( 1L )
101 : , nDivider(0)
102 : , bGoLeft(false)
103 4444 : , bLineNum( bLnNm )
104 : {
105 2222 : if( pFrm->IsUndersized() )
106 : {
107 0 : SwTwips nBottom = pFrm->Frm().Bottom();
108 0 : if( aRect.Bottom() > nBottom )
109 0 : aRect.Bottom( nBottom );
110 : }
111 2222 : int nVirtPageNum = 0;
112 2222 : if( bLineNum )
113 : {
114 : /* Initializes the Members necessary for line numbering:
115 :
116 : nDivider, how often do we want a substring; 0 == never
117 : nX, line number's x position
118 : pFnt, line number's font
119 : nLineNr, the first line number
120 : bLineNum is set back to false if the numbering is completely
121 : outside of the paint rect
122 : */
123 324 : nDivider = !rLineInf.GetDivider().isEmpty() ? rLineInf.GetDividerCountBy() : 0;
124 324 : nX = pFrm->Frm().Left();
125 324 : SwCharFmt* pFmt = rLineInf.GetCharFmt( const_cast<IDocumentStylePoolAccess&>(*pFrm->GetNode()->getIDocumentStylePoolAccess()) );
126 : OSL_ENSURE( pFmt, "PaintExtraData without CharFmt" );
127 324 : pFnt = new SwFont( &pFmt->GetAttrSet(), pFrm->GetTxtNode()->getIDocumentSettingAccess() );
128 324 : pFnt->Invalidate();
129 324 : pFnt->ChgPhysFnt( pSh, *pSh->GetOut() );
130 324 : pFnt->SetVertical( 0, pFrm->IsVertical() );
131 324 : nLineNr += pFrm->GetAllLines() - pFrm->GetThisLines();
132 324 : LineNumberPosition ePos = rLineInf.GetPos();
133 324 : if( ePos != LINENUMBER_POS_LEFT && ePos != LINENUMBER_POS_RIGHT )
134 : {
135 0 : if( pFrm->FindPageFrm()->OnRightPage() )
136 : {
137 0 : nVirtPageNum = 1;
138 : ePos = ePos == LINENUMBER_POS_INSIDE ?
139 0 : LINENUMBER_POS_LEFT : LINENUMBER_POS_RIGHT;
140 : }
141 : else
142 : {
143 0 : nVirtPageNum = 2;
144 : ePos = ePos == LINENUMBER_POS_OUTSIDE ?
145 0 : LINENUMBER_POS_LEFT : LINENUMBER_POS_RIGHT;
146 : }
147 : }
148 324 : if( LINENUMBER_POS_LEFT == ePos )
149 : {
150 324 : bGoLeft = true;
151 324 : nX -= rLineInf.GetPosFromLeft();
152 324 : if( nX < aRect.Left() )
153 0 : bLineNum = false;
154 : }
155 : else
156 : {
157 0 : bGoLeft = false;
158 0 : nX += pFrm->Frm().Width() + rLineInf.GetPosFromLeft();
159 0 : if( nX > aRect.Right() )
160 0 : bLineNum = false;
161 : }
162 : }
163 2222 : if( eHor != text::HoriOrientation::NONE )
164 : {
165 2222 : if( text::HoriOrientation::INSIDE == eHor || text::HoriOrientation::OUTSIDE == eHor )
166 : {
167 0 : if( !nVirtPageNum )
168 0 : nVirtPageNum = pFrm->FindPageFrm()->OnRightPage() ? 1 : 2;
169 0 : if( nVirtPageNum % 2 )
170 0 : eHor = eHor == text::HoriOrientation::INSIDE ? text::HoriOrientation::LEFT : text::HoriOrientation::RIGHT;
171 : else
172 0 : eHor = eHor == text::HoriOrientation::OUTSIDE ? text::HoriOrientation::LEFT : text::HoriOrientation::RIGHT;
173 : }
174 2222 : const SwFrm* pTmpFrm = pFrm->FindTabFrm();
175 2222 : if( !pTmpFrm )
176 1494 : pTmpFrm = pFrm;
177 2222 : nRedX = text::HoriOrientation::LEFT == eHor ? pTmpFrm->Frm().Left() - REDLINE_DISTANCE :
178 4444 : pTmpFrm->Frm().Right() + REDLINE_DISTANCE;
179 : }
180 2222 : }
181 :
182 148 : void SwExtraPainter::PaintExtra( SwTwips nY, long nAsc, long nMax, bool bRed )
183 : {
184 : // Line number is stronger than the divider
185 296 : const OUString aTmp( HasNumber() ? rLineInf.GetNumType().GetNumStr( nLineNr )
186 296 : : rLineInf.GetDivider() );
187 :
188 : // Get script type of line numbering:
189 148 : pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmp, 0 ) );
190 :
191 296 : SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), 0, aTmp, 0, aTmp.getLength() );
192 148 : aDrawInf.SetSpace( 0 );
193 148 : aDrawInf.SetWrong( NULL );
194 148 : aDrawInf.SetGrammarCheck( NULL );
195 148 : aDrawInf.SetSmartTags( NULL );
196 148 : aDrawInf.SetLeft( 0 );
197 148 : aDrawInf.SetRight( LONG_MAX );
198 148 : aDrawInf.SetFrm( pTxtFrm );
199 148 : aDrawInf.SetFont( pFnt );
200 148 : aDrawInf.SetSnapToGrid( false );
201 148 : aDrawInf.SetIgnoreFrmRTL( true );
202 :
203 148 : bool bTooBig = pFnt->GetSize( pFnt->GetActual() ).Height() > nMax &&
204 148 : pFnt->GetHeight( pSh, *pSh->GetOut() ) > nMax;
205 : SwFont* pTmpFnt;
206 148 : if( bTooBig )
207 : {
208 0 : pTmpFnt = new SwFont( *GetFont() );
209 0 : if( nMax >= 20 )
210 : {
211 0 : nMax *= 17;
212 0 : nMax /= 20;
213 : }
214 0 : pTmpFnt->SetSize( Size( 0, nMax ), pTmpFnt->GetActual() );
215 : }
216 : else
217 148 : pTmpFnt = GetFont();
218 148 : Point aTmpPos( nX, nY );
219 148 : aTmpPos.Y() += nAsc;
220 148 : bool bPaint = true;
221 148 : if( !IsClipChg() )
222 : {
223 148 : Size aSize = pTmpFnt->_GetTxtSize( aDrawInf );
224 148 : if( bGoLeft )
225 148 : aTmpPos.X() -= aSize.Width();
226 : // calculate rectangle containing the line number
227 148 : SwRect aRct( Point( aTmpPos.X(),
228 296 : aTmpPos.Y() - pTmpFnt->GetAscent( pSh, *pSh->GetOut() )
229 444 : ), aSize );
230 148 : if( !aRect.IsInside( aRct ) )
231 : {
232 0 : if( aRct.Intersection( aRect ).IsEmpty() )
233 0 : bPaint = false;
234 : else
235 0 : aClip.ChgClip( aRect, pTxtFrm );
236 : }
237 : }
238 0 : else if( bGoLeft )
239 0 : aTmpPos.X() -= pTmpFnt->_GetTxtSize( aDrawInf ).Width();
240 148 : aDrawInf.SetPos( aTmpPos );
241 148 : if( bPaint )
242 148 : pTmpFnt->_DrawText( aDrawInf );
243 :
244 148 : if( bTooBig )
245 0 : delete pTmpFnt;
246 148 : if( bRed )
247 : {
248 0 : long nDiff = bGoLeft ? nRedX - nX : nX - nRedX;
249 0 : if( nDiff > REDLINE_MINDIST )
250 0 : PaintRedline( nY, nMax );
251 148 : }
252 148 : }
253 :
254 1649 : void SwExtraPainter::PaintRedline( SwTwips nY, long nMax )
255 : {
256 1649 : Point aStart( nRedX, nY );
257 1649 : Point aEnd( nRedX, nY + nMax );
258 :
259 1649 : if( !IsClipChg() )
260 : {
261 1649 : SwRect aRct( aStart, aEnd );
262 1649 : if( !aRect.IsInside( aRct ) )
263 : {
264 20 : if( aRct.Intersection( aRect ).IsEmpty() )
265 1655 : return;
266 14 : aClip.ChgClip( aRect, pTxtFrm );
267 : }
268 : }
269 1643 : const Color aOldCol( pSh->GetOut()->GetLineColor() );
270 1643 : pSh->GetOut()->SetLineColor( SW_MOD()->GetRedlineMarkColor() );
271 :
272 1643 : if ( pTxtFrm->IsVertical() )
273 : {
274 0 : pTxtFrm->SwitchHorizontalToVertical( aStart );
275 0 : pTxtFrm->SwitchHorizontalToVertical( aEnd );
276 : }
277 :
278 1643 : pSh->GetOut()->DrawLine( aStart, aEnd );
279 1643 : pSh->GetOut()->SetLineColor( aOldCol );
280 : }
281 :
282 2222 : void SwTxtFrm::PaintExtraData( const SwRect &rRect ) const
283 : {
284 2222 : if( Frm().Top() > rRect.Bottom() || Frm().Bottom() < rRect.Top() )
285 0 : return;
286 :
287 2222 : const SwTxtNode& rTxtNode = *GetTxtNode();
288 2222 : const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
289 2222 : const SwLineNumberInfo &rLineInf = rTxtNode.GetDoc()->GetLineNumberInfo();
290 2222 : const SwFmtLineNumber &rLineNum = GetAttrSet()->GetLineNumber();
291 4040 : bool bLineNum = !IsInTab() && rLineInf.IsPaintLineNumbers() &&
292 2546 : ( !IsInFly() || rLineInf.IsCountInFlys() ) && rLineNum.IsCount();
293 2222 : sal_Int16 eHor = (sal_Int16)SW_MOD()->GetRedlineMarkPos();
294 2222 : if( eHor != text::HoriOrientation::NONE && !IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
295 0 : eHor = text::HoriOrientation::NONE;
296 2222 : bool bRedLine = eHor != text::HoriOrientation::NONE;
297 2222 : if ( bLineNum || bRedLine )
298 : {
299 2222 : if( IsLocked() || IsHiddenNow() || !Prt().Height() )
300 0 : return;
301 2222 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
302 :
303 2222 : SWAP_IF_NOT_SWAPPED( this )
304 2222 : SwRect rOldRect( rRect );
305 :
306 2222 : if ( IsVertical() )
307 0 : SwitchVerticalToHorizontal( (SwRect&)rRect );
308 :
309 2222 : SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
310 2222 : aLayoutModeModifier.Modify( false );
311 :
312 : // #i16816# tagged pdf support
313 4444 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
314 :
315 4444 : SwExtraPainter aExtra( this, pSh, rLineInf, rRect, eHor, bLineNum );
316 :
317 2222 : if( HasPara() )
318 : {
319 1878 : SwTxtFrmLocker aLock((SwTxtFrm*)this);
320 :
321 3756 : SwTxtLineAccess aAccess( (SwTxtFrm*)this );
322 1878 : aAccess.GetPara();
323 :
324 3756 : SwTxtPaintInfo aInf( (SwTxtFrm*)this, rRect );
325 :
326 1878 : aLayoutModeModifier.Modify( false );
327 :
328 3756 : SwTxtPainter aLine( (SwTxtFrm*)this, &aInf );
329 1878 : bool bNoDummy = !aLine.GetNext(); // Only one empty line!
330 :
331 3756 : while( aLine.Y() + aLine.GetLineHeight() <= rRect.Top() )
332 : {
333 0 : if( !aLine.GetCurr()->IsDummy() &&
334 0 : ( rLineInf.IsCountBlankLines() ||
335 0 : aLine.GetCurr()->HasCntnt() ) )
336 0 : aExtra.IncLineNr();
337 0 : if( !aLine.Next() )
338 : {
339 0 : (SwRect&)rRect = rOldRect;
340 0 : UNDO_SWAP( this )
341 0 : return;
342 : }
343 : }
344 :
345 1878 : long nBottom = rRect.Bottom();
346 :
347 1878 : bool bNoPrtLine = 0 == GetMinPrtLine();
348 1878 : if( !bNoPrtLine )
349 : {
350 0 : while ( aLine.Y() < GetMinPrtLine() )
351 : {
352 0 : if( ( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasCntnt() )
353 0 : && !aLine.GetCurr()->IsDummy() )
354 0 : aExtra.IncLineNr();
355 0 : if( !aLine.Next() )
356 0 : break;
357 : }
358 0 : bNoPrtLine = aLine.Y() >= GetMinPrtLine();
359 : }
360 1878 : if( bNoPrtLine )
361 : {
362 2849 : do
363 : {
364 2849 : if( bNoDummy || !aLine.GetCurr()->IsDummy() )
365 : {
366 2849 : bool bRed = bRedLine && aLine.GetCurr()->HasRedline();
367 2849 : if( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasCntnt() )
368 : {
369 3313 : if( bLineNum &&
370 544 : ( aExtra.HasNumber() || aExtra.HasDivider() ) )
371 : {
372 : sal_uInt16 nTmpHeight, nTmpAscent;
373 128 : aLine.CalcAscentAndHeight( nTmpAscent, nTmpHeight );
374 : aExtra.PaintExtra( aLine.Y(), nTmpAscent,
375 128 : nTmpHeight, bRed );
376 128 : bRed = false;
377 : }
378 2849 : aExtra.IncLineNr();
379 : }
380 2849 : if( bRed )
381 1623 : aExtra.PaintRedline( aLine.Y(), aLine.GetLineHeight() );
382 : }
383 2849 : } while( aLine.Next() && aLine.Y() <= nBottom );
384 1878 : }
385 : }
386 : else
387 : {
388 344 : if ( USHRT_MAX == pIDRA->GetRedlinePos(rTxtNode, USHRT_MAX) )
389 318 : bRedLine = false;
390 :
391 406 : if( bLineNum && rLineInf.IsCountBlankLines() &&
392 64 : ( aExtra.HasNumber() || aExtra.HasDivider() ) )
393 : {
394 20 : aExtra.PaintExtra( Frm().Top()+Prt().Top(), aExtra.GetFont()
395 40 : ->GetAscent( pSh, *pSh->GetOut() ), Prt().Height(), bRedLine );
396 : }
397 324 : else if( bRedLine )
398 26 : aExtra.PaintRedline( Frm().Top()+Prt().Top(), Prt().Height() );
399 : }
400 :
401 2222 : (SwRect&)rRect = rOldRect;
402 4444 : UNDO_SWAP( this )
403 : }
404 : }
405 :
406 14488 : SwRect SwTxtFrm::Paint()
407 : {
408 : #if OSL_DEBUG_LEVEL > 1
409 : const SwTwips nDbgY = Frm().Top();
410 : (void)nDbgY;
411 : #endif
412 :
413 : // finger layout
414 : OSL_ENSURE( GetValidPosFlag(), "+SwTxtFrm::Paint: no Calc()" );
415 :
416 14488 : SwRect aRet( Prt() );
417 14488 : if ( IsEmpty() || !HasPara() )
418 2537 : aRet += Frm().Pos();
419 : else
420 : {
421 : // We return the right paint rect. Use the calculated PaintOfst as the
422 : // left margin
423 11951 : SwRepaint& rRepaint = GetPara()->GetRepaint();
424 : long l;
425 :
426 11951 : 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
427 0 : rRepaint.Chg( ( GetUpper()->Frm() ).Pos() + ( GetUpper()->Prt() ).Pos(), ( GetUpper()->Prt() ).SSize() );
428 :
429 11951 : if( rRepaint.GetOfst() )
430 1124 : rRepaint.Left( rRepaint.GetOfst() );
431 :
432 11951 : l = rRepaint.GetRightOfst();
433 11951 : if( l && l > rRepaint.Right() )
434 1383 : rRepaint.Right( l );
435 11951 : rRepaint.SetOfst( 0 );
436 11951 : aRet = rRepaint;
437 :
438 : // In case our left edge is the same as the body frame's left edge,
439 : // then extend the rectangle to include the page margin as well,
440 : // otherwise some font will be clipped.
441 11951 : SwLayoutFrm* pBodyFrm = GetUpper();
442 11951 : if (pBodyFrm->IsBodyFrm() && aRet.Left() == (pBodyFrm->Frm().Left() + pBodyFrm->Prt().Left()))
443 7679 : if (SwLayoutFrm* pPageFrm = pBodyFrm->GetUpper())
444 7679 : aRet.Left(pPageFrm->Frm().Left());
445 :
446 11951 : if ( IsRightToLeft() )
447 0 : SwitchLTRtoRTL( aRet );
448 :
449 11951 : if ( IsVertical() )
450 0 : SwitchHorizontalToVertical( aRet );
451 : }
452 14488 : ResetRepaint();
453 :
454 14488 : return aRet;
455 : }
456 :
457 7219 : bool SwTxtFrm::PaintEmpty( const SwRect &rRect, bool bCheck ) const
458 : {
459 7219 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
460 7219 : if( pSh && ( pSh->GetViewOptions()->IsParagraph() || bInitFont ) )
461 : {
462 90 : bInitFont = false;
463 90 : SwTxtFly aTxtFly( this );
464 90 : aTxtFly.SetTopRule();
465 90 : SwRect aRect;
466 90 : if( bCheck && aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) )
467 0 : return false;
468 90 : else if( pSh->GetWin() )
469 : {
470 : SwFont *pFnt;
471 78 : const SwTxtNode& rTxtNode = *GetTxtNode();
472 78 : if ( rTxtNode.HasSwAttrSet() )
473 : {
474 16 : const SwAttrSet *pAttrSet = &( rTxtNode.GetSwAttrSet() );
475 16 : pFnt = new SwFont( pAttrSet, rTxtNode.getIDocumentSettingAccess() );
476 : }
477 : else
478 : {
479 62 : SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pSh );
480 62 : pFnt = new SwFont( aFontAccess.Get()->GetFont() );
481 : }
482 :
483 78 : const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
484 78 : if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
485 : {
486 78 : const sal_uInt16 nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX );
487 78 : if( USHRT_MAX != nRedlPos )
488 : {
489 0 : SwAttrHandler aAttrHandler;
490 0 : aAttrHandler.Init( rTxtNode.GetSwAttrSet(),
491 0 : *rTxtNode.getIDocumentSettingAccess(), NULL );
492 0 : SwRedlineItr aRedln( rTxtNode, *pFnt, aAttrHandler, nRedlPos, true );
493 : }
494 : }
495 :
496 78 : if( pSh->GetViewOptions()->IsParagraph() && Prt().Height() )
497 : {
498 60 : if( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet( SW_LATIN ) &&
499 20 : pFnt->GetName( SW_LATIN ) != numfunc::GetDefBulletFontname() )
500 : {
501 0 : pFnt->SetFamily( FAMILY_DONTKNOW, SW_LATIN );
502 0 : pFnt->SetName( numfunc::GetDefBulletFontname(), SW_LATIN );
503 0 : pFnt->SetStyleName( aEmptyOUStr, SW_LATIN );
504 0 : pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, SW_LATIN );
505 : }
506 20 : pFnt->SetVertical( 0, IsVertical() );
507 20 : SwFrmSwapper aSwapper( this, true );
508 40 : SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
509 20 : aLayoutModeModifier.Modify( IsRightToLeft() );
510 :
511 20 : pFnt->Invalidate();
512 20 : pFnt->ChgPhysFnt( pSh, *pSh->GetOut() );
513 20 : Point aPos = Frm().Pos() + Prt().Pos();
514 :
515 : const SvxLRSpaceItem &rSpace =
516 20 : GetTxtNode()->GetSwAttrSet().GetLRSpace();
517 :
518 20 : if ( rSpace.GetTxtFirstLineOfst() > 0 )
519 0 : aPos.X() += rSpace.GetTxtFirstLineOfst();
520 :
521 : SwSaveClip *pClip;
522 20 : if( IsUndersized() )
523 : {
524 0 : pClip = new SwSaveClip( pSh->GetOut() );
525 0 : pClip->ChgClip( rRect );
526 : }
527 : else
528 20 : pClip = NULL;
529 :
530 20 : aPos.Y() += pFnt->GetAscent( pSh, *pSh->GetOut() );
531 :
532 40 : if ( GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() &&
533 20 : IsInDocBody() )
534 : {
535 20 : SwTextGridItem const*const pGrid(GetGridItem(FindPageFrm()));
536 20 : if ( pGrid )
537 : {
538 : // center character in grid line
539 0 : aPos.Y() += ( pGrid->GetBaseHeight() -
540 0 : pFnt->GetHeight( pSh, *pSh->GetOut() ) ) / 2;
541 :
542 0 : if ( ! pGrid->GetRubyTextBelow() )
543 0 : aPos.Y() += pGrid->GetRubyHeight();
544 : }
545 : }
546 :
547 : // Don't show the paragraph mark for collapsed paragraphs, when they are hidden
548 20 : if ( EmptyHeight( ) > 1 )
549 : {
550 20 : const OUString aTmp( CH_PAR );
551 40 : SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), 0, aTmp, 0, 1 );
552 20 : aDrawInf.SetLeft( rRect.Left() );
553 20 : aDrawInf.SetRight( rRect.Right() );
554 20 : aDrawInf.SetPos( aPos );
555 20 : aDrawInf.SetSpace( 0 );
556 20 : aDrawInf.SetKanaComp( 0 );
557 20 : aDrawInf.SetWrong( NULL );
558 20 : aDrawInf.SetGrammarCheck( NULL );
559 20 : aDrawInf.SetSmartTags( NULL );
560 20 : aDrawInf.SetFrm( this );
561 20 : aDrawInf.SetFont( pFnt );
562 20 : aDrawInf.SetSnapToGrid( false );
563 :
564 20 : pFnt->SetColor(NON_PRINTING_CHARACTER_COLOR);
565 40 : pFnt->_DrawText( aDrawInf );
566 : }
567 40 : delete pClip;
568 : }
569 78 : delete pFnt;
570 78 : return true;
571 12 : }
572 : }
573 : else
574 7129 : return true;
575 12 : return false;
576 : }
577 :
578 27207 : void SwTxtFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
579 : {
580 27207 : ResetRepaint();
581 :
582 : // #i16816# tagged pdf support
583 27207 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
584 :
585 27207 : Num_Info aNumInfo( *this );
586 27207 : SwTaggedPDFHelper aTaggedPDFHelperNumbering( &aNumInfo, 0, 0, *pSh->GetOut() );
587 :
588 27207 : Frm_Info aFrmInfo( *this );
589 54356 : SwTaggedPDFHelper aTaggedPDFHelperParagraph( 0, &aFrmInfo, 0, *pSh->GetOut() );
590 :
591 27207 : if( !IsEmpty() || !PaintEmpty( rRect, true ) )
592 : {
593 : #if OSL_DEBUG_LEVEL > 1
594 : const SwTwips nDbgY = Frm().Top();
595 : (void)nDbgY;
596 : #endif
597 :
598 20012 : if( IsLocked() || IsHiddenNow() || ! Prt().HasArea() )
599 104 : return;
600 :
601 : // It can happen that the IdleCollector withdrew my cached information
602 19966 : if( !HasPara() )
603 : {
604 : OSL_ENSURE( GetValidPosFlag(), "+SwTxtFrm::Paint: no Calc()" );
605 :
606 : // #i29062# pass info that we are currently
607 : // painting.
608 12 : ((SwTxtFrm*)this)->GetFormatted( true );
609 12 : if( IsEmpty() )
610 : {
611 12 : PaintEmpty( rRect, false );
612 12 : return;
613 : }
614 0 : if( !HasPara() )
615 : {
616 : OSL_ENSURE( false, "+SwTxtFrm::Paint: missing format information" );
617 0 : return;
618 : }
619 : }
620 :
621 : // We don't want to be interrupted while painting.
622 : // Do that after thr Format()!
623 19954 : SwTxtFrmLocker aLock((SwTxtFrm*)this);
624 :
625 : // We only paint the part of the TxtFrm which changed, is within the
626 : // range and was requested to paint.
627 : // One could think that the area rRect _needs_ to be painted, although
628 : // rRepaint is set. Indeed, we cannot avoid this problem from a formal
629 : // perspective. Luckily we can assume rRepaint to be empty when we need
630 : // paint the while Frm.
631 39908 : SwTxtLineAccess aAccess( (SwTxtFrm*)this );
632 19954 : SwParaPortion *pPara = aAccess.GetPara();
633 :
634 19954 : SwRepaint &rRepaint = pPara->GetRepaint();
635 :
636 : // Switch off recycling when in the FlyCntFrm.
637 : // A DrawRect is called for repainting the line anyways.
638 19954 : if( rRepaint.GetOfst() )
639 : {
640 4 : const SwFlyFrm *pFly = FindFlyFrm();
641 4 : if( pFly && pFly->IsFlyInCntFrm() )
642 0 : rRepaint.SetOfst( 0 );
643 : }
644 :
645 : // Ge the String for painting. The length is of special interest.
646 :
647 : // Rectangle
648 : OSL_ENSURE( ! IsSwapped(), "A frame is swapped before Paint" );
649 19954 : SwRect aOldRect( rRect );
650 :
651 19954 : SWAP_IF_NOT_SWAPPED( this )
652 :
653 19954 : if ( IsVertical() )
654 0 : SwitchVerticalToHorizontal( (SwRect&)rRect );
655 :
656 19954 : if ( IsRightToLeft() )
657 16 : SwitchRTLtoLTR( (SwRect&)rRect );
658 :
659 39908 : SwTxtPaintInfo aInf( (SwTxtFrm*)this, rRect );
660 19954 : aInf.SetWrongList( ( (SwTxtNode*)GetTxtNode() )->GetWrong() );
661 19954 : aInf.SetGrammarCheckList( ( (SwTxtNode*)GetTxtNode() )->GetGrammarCheck() );
662 19954 : aInf.SetSmartTags( ( (SwTxtNode*)GetTxtNode() )->GetSmartTags() );
663 19954 : aInf.GetTxtFly().SetTopRule();
664 :
665 39908 : SwTxtPainter aLine( (SwTxtFrm*)this, &aInf );
666 : // Optimization: if no free flying Frm overlaps into our line, the
667 : // SwTxtFly just switches off
668 19954 : aInf.GetTxtFly().Relax();
669 :
670 19954 : OutputDevice* pOut = aInf.GetOut();
671 19954 : const bool bOnWin = pSh->GetWin() != 0;
672 :
673 39908 : SwSaveClip aClip( bOnWin || IsUndersized() ? pOut : 0 );
674 :
675 : // Output loop: For each Line ... (which is still visible) ...
676 : // adapt rRect (Top + 1, Bottom - 1)
677 : // Because the Iterator attaches the Lines without a gap to each other
678 19954 : aLine.TwipsToLine( rRect.Top() + 1 );
679 19954 : long nBottom = rRect.Bottom();
680 :
681 19954 : bool bNoPrtLine = 0 == GetMinPrtLine();
682 19954 : if( !bNoPrtLine )
683 : {
684 0 : while ( aLine.Y() < GetMinPrtLine() && aLine.Next() )
685 : ;
686 0 : bNoPrtLine = aLine.Y() >= GetMinPrtLine();
687 : }
688 19954 : if( bNoPrtLine )
689 : {
690 44922 : do
691 : {
692 44922 : aLine.DrawTextLine( rRect, aClip, IsUndersized() );
693 :
694 44922 : } while( aLine.Next() && aLine.Y() <= nBottom );
695 : }
696 :
697 : // Once is enough:
698 19954 : if( aLine.IsPaintDrop() )
699 0 : aLine.PaintDropPortion();
700 :
701 19954 : if( rRepaint.HasArea() )
702 11836 : rRepaint.Clear();
703 :
704 19954 : UNDO_SWAP( this )
705 19954 : (SwRect&)rRect = aOldRect;
706 :
707 19954 : OSL_ENSURE( ! IsSwapped(), "A frame is swapped after Paint" );
708 27149 : }
709 270 : }
710 :
711 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|