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 SwTextFrm* pTextFrm;
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 1152 : inline bool IsClipChg() { return aClip.IsChg(); }
74 : public:
75 : SwExtraPainter( const SwTextFrm *pFrm, SwViewShell *pVwSh,
76 : const SwLineNumberInfo &rLnInf, const SwRect &rRct,
77 : sal_Int16 eHor, bool bLnNm );
78 1374 : ~SwExtraPainter() { delete pFnt; }
79 116 : inline SwFont* GetFont() const { return pFnt; }
80 1855 : inline void IncLineNr() { ++nLineNr; }
81 389 : inline bool HasNumber() { return !( nLineNr % rLineInf.GetCountBy() ); }
82 177 : 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 1374 : SwExtraPainter::SwExtraPainter( const SwTextFrm *pFrm, SwViewShell *pVwSh,
90 : const SwLineNumberInfo &rLnInf, const SwRect &rRct,
91 : sal_Int16 eHor, bool bLnNm )
92 1374 : : aClip( pVwSh->GetWin() || pFrm->IsUndersized() ? pVwSh->GetOut() : 0 )
93 : , aRect( rRct )
94 : , pTextFrm( 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 2748 : , bLineNum( bLnNm )
104 : {
105 1374 : if( pFrm->IsUndersized() )
106 : {
107 0 : SwTwips nBottom = pFrm->Frm().Bottom();
108 0 : if( aRect.Bottom() > nBottom )
109 0 : aRect.Bottom( nBottom );
110 : }
111 1374 : int nVirtPageNum = 0;
112 1374 : 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 237 : nDivider = !rLineInf.GetDivider().isEmpty() ? rLineInf.GetDividerCountBy() : 0;
124 237 : nX = pFrm->Frm().Left();
125 237 : SwCharFormat* pFormat = rLineInf.GetCharFormat( const_cast<IDocumentStylePoolAccess&>(*pFrm->GetNode()->getIDocumentStylePoolAccess()) );
126 : OSL_ENSURE( pFormat, "PaintExtraData without CharFormat" );
127 237 : pFnt = new SwFont( &pFormat->GetAttrSet(), pFrm->GetTextNode()->getIDocumentSettingAccess() );
128 237 : pFnt->Invalidate();
129 237 : pFnt->ChgPhysFnt( pSh, *pSh->GetOut() );
130 237 : pFnt->SetVertical( 0, pFrm->IsVertical() );
131 237 : nLineNr += pFrm->GetAllLines() - pFrm->GetThisLines();
132 237 : LineNumberPosition ePos = rLineInf.GetPos();
133 237 : 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 237 : if( LINENUMBER_POS_LEFT == ePos )
149 : {
150 237 : bGoLeft = true;
151 237 : nX -= rLineInf.GetPosFromLeft();
152 237 : 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 1374 : if( eHor != text::HoriOrientation::NONE )
164 : {
165 1341 : 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 1341 : const SwFrm* pTmpFrm = pFrm->FindTabFrm();
175 1341 : if( !pTmpFrm )
176 945 : pTmpFrm = pFrm;
177 1341 : nRedX = text::HoriOrientation::LEFT == eHor ? pTmpFrm->Frm().Left() - REDLINE_DISTANCE :
178 2682 : pTmpFrm->Frm().Right() + REDLINE_DISTANCE;
179 : }
180 1374 : }
181 :
182 106 : void SwExtraPainter::PaintExtra( SwTwips nY, long nAsc, long nMax, bool bRed )
183 : {
184 : // Line number is stronger than the divider
185 212 : const OUString aTmp( HasNumber() ? rLineInf.GetNumType().GetNumStr( nLineNr )
186 212 : : rLineInf.GetDivider() );
187 :
188 : // Get script type of line numbering:
189 106 : pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmp, 0 ) );
190 :
191 212 : SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), 0, aTmp, 0, aTmp.getLength() );
192 106 : aDrawInf.SetSpace( 0 );
193 106 : aDrawInf.SetWrong( NULL );
194 106 : aDrawInf.SetGrammarCheck( NULL );
195 106 : aDrawInf.SetSmartTags( NULL );
196 106 : aDrawInf.SetLeft( 0 );
197 106 : aDrawInf.SetRight( LONG_MAX );
198 106 : aDrawInf.SetFrm( pTextFrm );
199 106 : aDrawInf.SetFont( pFnt );
200 106 : aDrawInf.SetSnapToGrid( false );
201 106 : aDrawInf.SetIgnoreFrmRTL( true );
202 :
203 106 : bool bTooBig = pFnt->GetSize( pFnt->GetActual() ).Height() > nMax &&
204 106 : pFnt->GetHeight( pSh, *pSh->GetOut() ) > nMax;
205 : SwFont* pTmpFnt;
206 106 : 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 106 : pTmpFnt = GetFont();
218 106 : Point aTmpPos( nX, nY );
219 106 : aTmpPos.Y() += nAsc;
220 106 : bool bPaint = true;
221 106 : if( !IsClipChg() )
222 : {
223 106 : Size aSize = pTmpFnt->_GetTextSize( aDrawInf );
224 106 : if( bGoLeft )
225 106 : aTmpPos.X() -= aSize.Width();
226 : // calculate rectangle containing the line number
227 106 : SwRect aRct( Point( aTmpPos.X(),
228 212 : aTmpPos.Y() - pTmpFnt->GetAscent( pSh, *pSh->GetOut() )
229 318 : ), aSize );
230 106 : if( !aRect.IsInside( aRct ) )
231 : {
232 2 : if( aRct.Intersection( aRect ).IsEmpty() )
233 2 : bPaint = false;
234 : else
235 0 : aClip.ChgClip( aRect, pTextFrm );
236 : }
237 : }
238 0 : else if( bGoLeft )
239 0 : aTmpPos.X() -= pTmpFnt->_GetTextSize( aDrawInf ).Width();
240 106 : aDrawInf.SetPos( aTmpPos );
241 106 : if( bPaint )
242 104 : pTmpFnt->_DrawText( aDrawInf );
243 :
244 106 : if( bTooBig )
245 0 : delete pTmpFnt;
246 106 : if( bRed )
247 : {
248 0 : long nDiff = bGoLeft ? nRedX - nX : nX - nRedX;
249 0 : if( nDiff > REDLINE_MINDIST )
250 0 : PaintRedline( nY, nMax );
251 106 : }
252 106 : }
253 :
254 1046 : void SwExtraPainter::PaintRedline( SwTwips nY, long nMax )
255 : {
256 1046 : Point aStart( nRedX, nY );
257 1046 : Point aEnd( nRedX, nY + nMax );
258 :
259 1046 : if( !IsClipChg() )
260 : {
261 1046 : SwRect aRct( aStart, aEnd );
262 1046 : if( !aRect.IsInside( aRct ) )
263 : {
264 23 : if( aRct.Intersection( aRect ).IsEmpty() )
265 1054 : return;
266 15 : aClip.ChgClip( aRect, pTextFrm );
267 : }
268 : }
269 1038 : const Color aOldCol( pSh->GetOut()->GetLineColor() );
270 1038 : pSh->GetOut()->SetLineColor( SW_MOD()->GetRedlineMarkColor() );
271 :
272 1038 : if ( pTextFrm->IsVertical() )
273 : {
274 0 : pTextFrm->SwitchHorizontalToVertical( aStart );
275 0 : pTextFrm->SwitchHorizontalToVertical( aEnd );
276 : }
277 :
278 1038 : pSh->GetOut()->DrawLine( aStart, aEnd );
279 1038 : pSh->GetOut()->SetLineColor( aOldCol );
280 : }
281 :
282 1398 : void SwTextFrm::PaintExtraData( const SwRect &rRect ) const
283 : {
284 1398 : if( Frm().Top() > rRect.Bottom() || Frm().Bottom() < rRect.Top() )
285 0 : return;
286 :
287 1398 : const SwTextNode& rTextNode = *GetTextNode();
288 1398 : const IDocumentRedlineAccess* pIDRA = rTextNode.getIDocumentRedlineAccess();
289 1398 : const SwLineNumberInfo &rLineInf = rTextNode.GetDoc()->GetLineNumberInfo();
290 1398 : const SwFormatLineNumber &rLineNum = GetAttrSet()->GetLineNumber();
291 2626 : bool bLineNum = !IsInTab() && rLineInf.IsPaintLineNumbers() &&
292 1648 : ( !IsInFly() || rLineInf.IsCountInFlys() ) && rLineNum.IsCount();
293 1398 : sal_Int16 eHor = (sal_Int16)SW_MOD()->GetRedlineMarkPos();
294 1398 : if( eHor != text::HoriOrientation::NONE && !IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
295 57 : eHor = text::HoriOrientation::NONE;
296 1398 : bool bRedLine = eHor != text::HoriOrientation::NONE;
297 1398 : if ( bLineNum || bRedLine )
298 : {
299 1374 : if( IsLocked() || IsHiddenNow() || !Prt().Height() )
300 0 : return;
301 1374 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
302 :
303 1374 : SWAP_IF_NOT_SWAPPED swap(const_cast<SwTextFrm *>(this));
304 1374 : SwRect rOldRect( rRect );
305 :
306 1374 : if ( IsVertical() )
307 0 : SwitchVerticalToHorizontal( (SwRect&)rRect );
308 :
309 2748 : SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
310 1374 : aLayoutModeModifier.Modify( false );
311 :
312 : // #i16816# tagged pdf support
313 2748 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
314 :
315 2748 : SwExtraPainter aExtra( this, pSh, rLineInf, rRect, eHor, bLineNum );
316 :
317 1374 : if( HasPara() )
318 : {
319 1162 : TextFrmLockGuard aLock(const_cast<SwTextFrm*>(this));
320 :
321 2324 : SwTextLineAccess aAccess( this );
322 1162 : aAccess.GetPara();
323 :
324 2324 : SwTextPaintInfo aInf( const_cast<SwTextFrm*>(this), rRect );
325 :
326 1162 : aLayoutModeModifier.Modify( false );
327 :
328 2324 : SwTextPainter aLine( const_cast<SwTextFrm*>(this), &aInf );
329 1162 : bool bNoDummy = !aLine.GetNext(); // Only one empty line!
330 :
331 2324 : while( aLine.Y() + aLine.GetLineHeight() <= rRect.Top() )
332 : {
333 0 : if( !aLine.GetCurr()->IsDummy() &&
334 0 : ( rLineInf.IsCountBlankLines() ||
335 0 : aLine.GetCurr()->HasContent() ) )
336 0 : aExtra.IncLineNr();
337 0 : if( !aLine.Next() )
338 : {
339 0 : (SwRect&)rRect = rOldRect;
340 0 : return;
341 : }
342 : }
343 :
344 1162 : long nBottom = rRect.Bottom();
345 :
346 1162 : bool bNoPrtLine = 0 == GetMinPrtLine();
347 1162 : if( !bNoPrtLine )
348 : {
349 0 : while ( aLine.Y() < GetMinPrtLine() )
350 : {
351 0 : if( ( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasContent() )
352 0 : && !aLine.GetCurr()->IsDummy() )
353 0 : aExtra.IncLineNr();
354 0 : if( !aLine.Next() )
355 0 : break;
356 : }
357 0 : bNoPrtLine = aLine.Y() >= GetMinPrtLine();
358 : }
359 1162 : if( bNoPrtLine )
360 : {
361 1855 : do
362 : {
363 1855 : if( bNoDummy || !aLine.GetCurr()->IsDummy() )
364 : {
365 1855 : bool bRed = bRedLine && aLine.GetCurr()->HasRedline();
366 1855 : if( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasContent() )
367 : {
368 2199 : if( bLineNum &&
369 400 : ( aExtra.HasNumber() || aExtra.HasDivider() ) )
370 : {
371 : sal_uInt16 nTmpHeight, nTmpAscent;
372 96 : aLine.CalcAscentAndHeight( nTmpAscent, nTmpHeight );
373 : aExtra.PaintExtra( aLine.Y(), nTmpAscent,
374 96 : nTmpHeight, bRed );
375 96 : bRed = false;
376 : }
377 1855 : aExtra.IncLineNr();
378 : }
379 1855 : if( bRed )
380 1033 : aExtra.PaintRedline( aLine.Y(), aLine.GetLineHeight() );
381 : }
382 1855 : } while( aLine.Next() && aLine.Y() <= nBottom );
383 1162 : }
384 : }
385 : else
386 : {
387 212 : if ( USHRT_MAX == pIDRA->GetRedlinePos(rTextNode, USHRT_MAX) )
388 199 : bRedLine = false;
389 :
390 257 : if( bLineNum && rLineInf.IsCountBlankLines() &&
391 60 : ( aExtra.HasNumber() || aExtra.HasDivider() ) )
392 : {
393 10 : aExtra.PaintExtra( Frm().Top()+Prt().Top(), aExtra.GetFont()
394 20 : ->GetAscent( pSh, *pSh->GetOut() ), Prt().Height(), bRedLine );
395 : }
396 202 : else if( bRedLine )
397 13 : aExtra.PaintRedline( Frm().Top()+Prt().Top(), Prt().Height() );
398 : }
399 :
400 2748 : (SwRect&)rRect = rOldRect;
401 : }
402 : }
403 :
404 10949 : SwRect SwTextFrm::Paint()
405 : {
406 : #if OSL_DEBUG_LEVEL > 1
407 : const SwTwips nDbgY = Frm().Top();
408 : (void)nDbgY;
409 : #endif
410 :
411 : // finger layout
412 : OSL_ENSURE( GetValidPosFlag(), "+SwTextFrm::Paint: no Calc()" );
413 :
414 10949 : SwRect aRet( Prt() );
415 10949 : if ( IsEmpty() || !HasPara() )
416 1639 : aRet += Frm().Pos();
417 : else
418 : {
419 : // We return the right paint rect. Use the calculated PaintOfst as the
420 : // left margin
421 9310 : SwRepaint& rRepaint = GetPara()->GetRepaint();
422 : long l;
423 :
424 9310 : 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
425 0 : rRepaint.Chg( ( GetUpper()->Frm() ).Pos() + ( GetUpper()->Prt() ).Pos(), ( GetUpper()->Prt() ).SSize() );
426 :
427 9310 : if( rRepaint.GetOfst() )
428 519 : rRepaint.Left( rRepaint.GetOfst() );
429 :
430 9310 : l = rRepaint.GetRightOfst();
431 9310 : if( l && l > rRepaint.Right() )
432 885 : rRepaint.Right( l );
433 9310 : rRepaint.SetOfst( 0 );
434 9310 : aRet = rRepaint;
435 :
436 : // In case our left edge is the same as the body frame's left edge,
437 : // then extend the rectangle to include the page margin as well,
438 : // otherwise some font will be clipped.
439 9310 : SwLayoutFrm* pBodyFrm = GetUpper();
440 9310 : if (pBodyFrm->IsBodyFrm() && aRet.Left() == (pBodyFrm->Frm().Left() + pBodyFrm->Prt().Left()))
441 6528 : if (SwLayoutFrm* pPageFrm = pBodyFrm->GetUpper())
442 6528 : aRet.Left(pPageFrm->Frm().Left());
443 :
444 9310 : if ( IsRightToLeft() )
445 0 : SwitchLTRtoRTL( aRet );
446 :
447 9310 : if ( IsVertical() )
448 0 : SwitchHorizontalToVertical( aRet );
449 : }
450 10949 : ResetRepaint();
451 :
452 10949 : return aRet;
453 : }
454 :
455 5039 : bool SwTextFrm::PaintEmpty( const SwRect &rRect, bool bCheck ) const
456 : {
457 5039 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
458 5039 : if( pSh && ( pSh->GetViewOptions()->IsParagraph() || bInitFont ) )
459 : {
460 90 : bInitFont = false;
461 90 : SwTextFly aTextFly( this );
462 90 : aTextFly.SetTopRule();
463 90 : SwRect aRect;
464 90 : if( bCheck && aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) )
465 0 : return false;
466 90 : else if( pSh->GetWin() )
467 : {
468 : SwFont *pFnt;
469 83 : const SwTextNode& rTextNode = *GetTextNode();
470 83 : if ( rTextNode.HasSwAttrSet() )
471 : {
472 10 : const SwAttrSet *pAttrSet = &( rTextNode.GetSwAttrSet() );
473 10 : pFnt = new SwFont( pAttrSet, rTextNode.getIDocumentSettingAccess() );
474 : }
475 : else
476 : {
477 73 : SwFontAccess aFontAccess( &rTextNode.GetAnyFormatColl(), pSh );
478 73 : pFnt = new SwFont( aFontAccess.Get()->GetFont() );
479 : }
480 :
481 83 : const IDocumentRedlineAccess* pIDRA = rTextNode.getIDocumentRedlineAccess();
482 83 : if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
483 : {
484 82 : const sal_uInt16 nRedlPos = pIDRA->GetRedlinePos( rTextNode, USHRT_MAX );
485 82 : if( USHRT_MAX != nRedlPos )
486 : {
487 0 : SwAttrHandler aAttrHandler;
488 0 : aAttrHandler.Init( rTextNode.GetSwAttrSet(),
489 0 : *rTextNode.getIDocumentSettingAccess(), NULL );
490 0 : SwRedlineItr aRedln( rTextNode, *pFnt, aAttrHandler, nRedlPos, true );
491 : }
492 : }
493 :
494 83 : if( pSh->GetViewOptions()->IsParagraph() && Prt().Height() )
495 : {
496 123 : if( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet( SW_LATIN ) &&
497 41 : pFnt->GetName( SW_LATIN ) != numfunc::GetDefBulletFontname() )
498 : {
499 0 : pFnt->SetFamily( FAMILY_DONTKNOW, SW_LATIN );
500 0 : pFnt->SetName( numfunc::GetDefBulletFontname(), SW_LATIN );
501 0 : pFnt->SetStyleName( aEmptyOUStr, SW_LATIN );
502 0 : pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, SW_LATIN );
503 : }
504 41 : pFnt->SetVertical( 0, IsVertical() );
505 41 : SwFrmSwapper aSwapper( this, true );
506 82 : SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
507 41 : aLayoutModeModifier.Modify( IsRightToLeft() );
508 :
509 41 : pFnt->Invalidate();
510 41 : pFnt->ChgPhysFnt( pSh, *pSh->GetOut() );
511 41 : Point aPos = Frm().Pos() + Prt().Pos();
512 :
513 : const SvxLRSpaceItem &rSpace =
514 41 : GetTextNode()->GetSwAttrSet().GetLRSpace();
515 :
516 41 : if ( rSpace.GetTextFirstLineOfst() > 0 )
517 0 : aPos.X() += rSpace.GetTextFirstLineOfst();
518 :
519 : SwSaveClip *pClip;
520 41 : if( IsUndersized() )
521 : {
522 0 : pClip = new SwSaveClip( pSh->GetOut() );
523 0 : pClip->ChgClip( rRect );
524 : }
525 : else
526 41 : pClip = NULL;
527 :
528 41 : aPos.Y() += pFnt->GetAscent( pSh, *pSh->GetOut() );
529 :
530 82 : if ( GetTextNode()->GetSwAttrSet().GetParaGrid().GetValue() &&
531 41 : IsInDocBody() )
532 : {
533 41 : SwTextGridItem const*const pGrid(GetGridItem(FindPageFrm()));
534 41 : if ( pGrid )
535 : {
536 : // center character in grid line
537 0 : aPos.Y() += ( pGrid->GetBaseHeight() -
538 0 : pFnt->GetHeight( pSh, *pSh->GetOut() ) ) / 2;
539 :
540 0 : if ( ! pGrid->GetRubyTextBelow() )
541 0 : aPos.Y() += pGrid->GetRubyHeight();
542 : }
543 : }
544 :
545 : // Don't show the paragraph mark for collapsed paragraphs, when they are hidden
546 41 : if ( EmptyHeight( ) > 1 )
547 : {
548 41 : const OUString aTmp( CH_PAR );
549 82 : SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), 0, aTmp, 0, 1 );
550 41 : aDrawInf.SetLeft( rRect.Left() );
551 41 : aDrawInf.SetRight( rRect.Right() );
552 41 : aDrawInf.SetPos( aPos );
553 41 : aDrawInf.SetSpace( 0 );
554 41 : aDrawInf.SetKanaComp( 0 );
555 41 : aDrawInf.SetWrong( NULL );
556 41 : aDrawInf.SetGrammarCheck( NULL );
557 41 : aDrawInf.SetSmartTags( NULL );
558 41 : aDrawInf.SetFrm( this );
559 41 : aDrawInf.SetFont( pFnt );
560 41 : aDrawInf.SetSnapToGrid( false );
561 :
562 41 : pFnt->SetColor(NON_PRINTING_CHARACTER_COLOR);
563 82 : pFnt->_DrawText( aDrawInf );
564 : }
565 82 : delete pClip;
566 : }
567 83 : delete pFnt;
568 83 : return true;
569 7 : }
570 : }
571 : else
572 4949 : return true;
573 7 : return false;
574 : }
575 :
576 17715 : void SwTextFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
577 : {
578 17715 : ResetRepaint();
579 :
580 : // #i16816# tagged pdf support
581 17715 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
582 :
583 17715 : Num_Info aNumInfo( *this );
584 17715 : SwTaggedPDFHelper aTaggedPDFHelperNumbering( &aNumInfo, 0, 0, *pSh->GetOut() );
585 :
586 17715 : Frm_Info aFrmInfo( *this );
587 35394 : SwTaggedPDFHelper aTaggedPDFHelperParagraph( 0, &aFrmInfo, 0, *pSh->GetOut() );
588 :
589 17715 : if( !IsEmpty() || !PaintEmpty( rRect, true ) )
590 : {
591 : #if OSL_DEBUG_LEVEL > 1
592 : const SwTwips nDbgY = Frm().Top();
593 : (void)nDbgY;
594 : #endif
595 :
596 12690 : if( IsLocked() || IsHiddenNow() || ! Prt().HasArea() )
597 65 : return;
598 :
599 : // It can happen that the IdleCollector withdrew my cached information
600 12661 : if( !HasPara() )
601 : {
602 : OSL_ENSURE( GetValidPosFlag(), "+SwTextFrm::Paint: no Calc()" );
603 :
604 : // #i29062# pass info that we are currently
605 : // painting.
606 20 : const_cast<SwTextFrm*>(this)->GetFormatted( true );
607 20 : if( IsEmpty() )
608 : {
609 7 : PaintEmpty( rRect, false );
610 7 : return;
611 : }
612 13 : if( !HasPara() )
613 : {
614 : OSL_ENSURE( false, "+SwTextFrm::Paint: missing format information" );
615 0 : return;
616 : }
617 : }
618 :
619 : // We don't want to be interrupted while painting.
620 : // Do that after thr Format()!
621 12654 : TextFrmLockGuard aLock(const_cast<SwTextFrm*>(this));
622 :
623 : // We only paint the part of the TextFrm which changed, is within the
624 : // range and was requested to paint.
625 : // One could think that the area rRect _needs_ to be painted, although
626 : // rRepaint is set. Indeed, we cannot avoid this problem from a formal
627 : // perspective. Luckily we can assume rRepaint to be empty when we need
628 : // paint the while Frm.
629 25308 : SwTextLineAccess aAccess( this );
630 12654 : SwParaPortion *pPara = aAccess.GetPara();
631 :
632 12654 : SwRepaint &rRepaint = pPara->GetRepaint();
633 :
634 : // Switch off recycling when in the FlyCntFrm.
635 : // A DrawRect is called for repainting the line anyways.
636 12654 : if( rRepaint.GetOfst() )
637 : {
638 2 : const SwFlyFrm *pFly = FindFlyFrm();
639 2 : if( pFly && pFly->IsFlyInCntFrm() )
640 0 : rRepaint.SetOfst( 0 );
641 : }
642 :
643 : // Ge the String for painting. The length is of special interest.
644 :
645 : // Rectangle
646 : OSL_ENSURE( ! IsSwapped(), "A frame is swapped before Paint" );
647 12654 : SwRect aOldRect( rRect );
648 :
649 : {
650 12654 : SWAP_IF_NOT_SWAPPED swap(const_cast<SwTextFrm *>(this));
651 :
652 12654 : if ( IsVertical() )
653 0 : SwitchVerticalToHorizontal( (SwRect&)rRect );
654 :
655 12654 : if ( IsRightToLeft() )
656 6 : SwitchRTLtoLTR( (SwRect&)rRect );
657 :
658 25308 : SwTextPaintInfo aInf( const_cast<SwTextFrm*>(this), rRect );
659 12654 : aInf.SetWrongList( const_cast<SwTextNode*>(GetTextNode())->GetWrong() );
660 12654 : aInf.SetGrammarCheckList( const_cast<SwTextNode*>(GetTextNode())->GetGrammarCheck() );
661 12654 : aInf.SetSmartTags( const_cast<SwTextNode*>(GetTextNode())->GetSmartTags() );
662 12654 : aInf.GetTextFly().SetTopRule();
663 :
664 25308 : SwTextPainter aLine( const_cast<SwTextFrm*>(this), &aInf );
665 : // Optimization: if no free flying Frm overlaps into our line, the
666 : // SwTextFly just switches off
667 12654 : aInf.GetTextFly().Relax();
668 :
669 12654 : OutputDevice* pOut = aInf.GetOut();
670 12654 : const bool bOnWin = pSh->GetWin() != 0;
671 :
672 25308 : SwSaveClip aClip( bOnWin || IsUndersized() ? pOut : 0 );
673 :
674 : // Output loop: For each Line ... (which is still visible) ...
675 : // adapt rRect (Top + 1, Bottom - 1)
676 : // Because the Iterator attaches the Lines without a gap to each other
677 12654 : aLine.TwipsToLine( rRect.Top() + 1 );
678 12654 : long nBottom = rRect.Bottom();
679 :
680 12654 : bool bNoPrtLine = 0 == GetMinPrtLine();
681 12654 : if( !bNoPrtLine )
682 : {
683 0 : while ( aLine.Y() < GetMinPrtLine() && aLine.Next() )
684 : ;
685 0 : bNoPrtLine = aLine.Y() >= GetMinPrtLine();
686 : }
687 12654 : if( bNoPrtLine )
688 : {
689 21486 : do
690 : {
691 21486 : aLine.DrawTextLine( rRect, aClip, IsUndersized() );
692 :
693 21486 : } while( aLine.Next() && aLine.Y() <= nBottom );
694 : }
695 :
696 : // Once is enough:
697 12654 : if( aLine.IsPaintDrop() )
698 0 : aLine.PaintDropPortion();
699 :
700 12654 : if( rRepaint.HasArea() )
701 19052 : rRepaint.Clear();
702 : }
703 :
704 12654 : (SwRect&)rRect = aOldRect;
705 :
706 12654 : OSL_ENSURE( ! IsSwapped(), "A frame is swapped after Paint" );
707 17679 : }
708 177 : }
709 :
710 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|