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