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