LibreOffice Module sw (master)  1
frmpaint.cxx
Go to the documentation of this file.
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 <memory>
21 #include <com/sun/star/text/HoriOrientation.hpp>
22 #include <editeng/pgrditem.hxx>
23 #include <editeng/lrspitem.hxx>
24 #include <tgrditem.hxx>
25 #include <paratr.hxx>
26 
27 #include <fmtline.hxx>
28 #include <lineinfo.hxx>
29 #include <charfmt.hxx>
30 #include <rootfrm.hxx>
31 #include <pagefrm.hxx>
32 #include <viewsh.hxx>
33 #include <viewopt.hxx>
34 #include <frmatr.hxx>
35 #include <txtfrm.hxx>
36 #include "itrpaint.hxx"
37 #include "txtpaint.hxx"
38 #include "txtcache.hxx"
39 #include <flyfrm.hxx>
40 #include "redlnitr.hxx"
41 #include <redline.hxx>
42 #include <swmodule.hxx>
43 #include <tabfrm.hxx>
44 #include <numrule.hxx>
45 #include <wrong.hxx>
46 
48 
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 namespace {
60 
61 class SwExtraPainter
62 {
63  SwSaveClip m_aClip;
64  SwRect m_aRect;
65  const SwTextFrame* m_pTextFrame;
66  SwViewShell *m_pSh;
67  std::unique_ptr<SwFont> m_pFnt;
68  const SwLineNumberInfo &m_rLineInf;
69  SwTwips m_nX;
70  SwTwips m_nRedX;
71  sal_uLong m_nLineNr;
72  sal_uInt16 m_nDivider;
73  bool m_bGoLeft;
74  bool IsClipChg() const { return m_aClip.IsChg(); }
75 
76  SwExtraPainter(const SwExtraPainter&) = delete;
77  SwExtraPainter& operator=(const SwExtraPainter&) = delete;
78 
79 public:
80  SwExtraPainter( const SwTextFrame *pFrame, SwViewShell *pVwSh,
81  const SwLineNumberInfo &rLnInf, const SwRect &rRct,
82  sal_Int16 eHor, bool bLnNm );
83  SwFont* GetFont() const { return m_pFnt.get(); }
84  void IncLineNr() { ++m_nLineNr; }
85  bool HasNumber() const { return !( m_nLineNr % m_rLineInf.GetCountBy() ); }
86  bool HasDivider() const {
87  if( !m_nDivider ) return false;
88  return !(m_nLineNr % m_rLineInf.GetDividerCountBy());
89  }
90 
91  void PaintExtra( SwTwips nY, tools::Long nAsc, tools::Long nMax, bool bRed, const OUString* pRedlineText = nullptr );
92  void PaintRedline( SwTwips nY, tools::Long nMax );
93 };
94 
95 }
96 
97 SwExtraPainter::SwExtraPainter( const SwTextFrame *pFrame, SwViewShell *pVwSh,
98  const SwLineNumberInfo &rLnInf, const SwRect &rRct,
99  sal_Int16 eHor, bool bLineNum )
100  : m_aClip( pVwSh->GetWin() || pFrame->IsUndersized() ? pVwSh->GetOut() : nullptr )
101  , m_aRect( rRct )
102  , m_pTextFrame( pFrame )
103  , m_pSh( pVwSh )
104  , m_rLineInf( rLnInf )
105  , m_nX(0)
106  , m_nRedX(0)
107  , m_nLineNr( 1 )
108  , m_nDivider(0)
109  , m_bGoLeft(false)
110 {
111  if( pFrame->IsUndersized() )
112  {
113  SwTwips nBottom = pFrame->getFrameArea().Bottom();
114  if( m_aRect.Bottom() > nBottom )
115  m_aRect.Bottom( nBottom );
116  }
117  std::optional<bool> oIsRightPage;
118  {
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 false if the numbering is completely
126  outside of the paint rect
127  */
128  m_nDivider = !m_rLineInf.GetDivider().isEmpty() ? m_rLineInf.GetDividerCountBy() : 0;
129  m_nX = pFrame->getFrameArea().Left();
130  SwCharFormat* pFormat = m_rLineInf.GetCharFormat( const_cast<IDocumentStylePoolAccess&>(pFrame->GetDoc().getIDocumentStylePoolAccess()) );
131  OSL_ENSURE( pFormat, "PaintExtraData without CharFormat" );
132  m_pFnt.reset( new SwFont(&pFormat->GetAttrSet(), &pFrame->GetDoc().getIDocumentSettingAccess()) );
133  m_pFnt->Invalidate();
134  m_pFnt->ChgPhysFnt( m_pSh, *m_pSh->GetOut() );
135  m_pFnt->SetVertical( 0_deg10, pFrame->IsVertical() );
136  }
137 
138  if( bLineNum )
139  {
140  m_nLineNr += pFrame->GetAllLines() - pFrame->GetThisLines();
141  LineNumberPosition ePos = m_rLineInf.GetPos();
142  if( ePos != LINENUMBER_POS_LEFT && ePos != LINENUMBER_POS_RIGHT )
143  {
144  if( pFrame->FindPageFrame()->OnRightPage() )
145  {
146  oIsRightPage = true;
147  ePos = ePos == LINENUMBER_POS_INSIDE ?
149  }
150  else
151  {
152  oIsRightPage = false;
153  ePos = ePos == LINENUMBER_POS_OUTSIDE ?
155  }
156  }
157  if( LINENUMBER_POS_LEFT == ePos )
158  {
159  m_bGoLeft = true;
160  m_nX -= m_rLineInf.GetPosFromLeft();
161  }
162  else
163  {
164  m_bGoLeft = false;
165  m_nX += pFrame->getFrameArea().Width() + m_rLineInf.GetPosFromLeft();
166  }
167  }
168  if( eHor == text::HoriOrientation::NONE )
169  return;
170 
171  if( text::HoriOrientation::INSIDE == eHor || text::HoriOrientation::OUTSIDE == eHor )
172  {
173  if (!oIsRightPage)
174  oIsRightPage = pFrame->FindPageFrame()->OnRightPage();
175  if (*oIsRightPage)
176  eHor = eHor == text::HoriOrientation::INSIDE ? text::HoriOrientation::LEFT : text::HoriOrientation::RIGHT;
177  else
178  eHor = eHor == text::HoriOrientation::OUTSIDE ? text::HoriOrientation::LEFT : text::HoriOrientation::RIGHT;
179  }
180  const SwFrame* pTmpFrame = pFrame->FindTabFrame();
181  if( !pTmpFrame )
182  pTmpFrame = pFrame;
183  m_nRedX = text::HoriOrientation::LEFT == eHor ? pTmpFrame->getFrameArea().Left() - REDLINE_DISTANCE :
184  pTmpFrame->getFrameArea().Right() + REDLINE_DISTANCE;
185 }
186 
187 void SwExtraPainter::PaintExtra( SwTwips nY, tools::Long nAsc, tools::Long nMax, bool bRed, const OUString* pRedlineText )
188 {
189  const OUString aTmp( pRedlineText
190  // Tracked change is stronger than the line number
191  ? *pRedlineText
192  : ( HasNumber()
193  // Line number is stronger than the divider
194  ? m_rLineInf.GetNumType().GetNumStr( m_nLineNr )
195  : m_rLineInf.GetDivider() ) );
196 
197  // Get script type of line numbering:
198  m_pFnt->SetActual( SwScriptInfo::WhichFont(0, aTmp) );
199 
200  if ( pRedlineText )
201  {
202  m_pFnt->SetColor(NON_PRINTING_CHARACTER_COLOR);
203  // don't strike out text in Insertions In Margin mode
204  if ( !m_pSh->GetViewOptions()->IsShowChangesInMargin2() )
205  m_pFnt->SetStrikeout( STRIKEOUT_SINGLE );
206  m_pFnt->SetSize( Size( 0, 200), m_pFnt->GetActual() );
207  }
208 
209  SwDrawTextInfo aDrawInf( m_pSh, *m_pSh->GetOut(), aTmp, 0, aTmp.getLength() );
210  aDrawInf.SetSpace( 0 );
211  aDrawInf.SetWrong( nullptr );
212  aDrawInf.SetGrammarCheck( nullptr );
213  aDrawInf.SetSmartTags( nullptr );
214  aDrawInf.SetFrame( m_pTextFrame );
215  aDrawInf.SetFont( m_pFnt.get() );
216  aDrawInf.SetSnapToGrid( false );
217  aDrawInf.SetIgnoreFrameRTL( true );
218 
219  bool bTooBig = m_pFnt->GetSize( m_pFnt->GetActual() ).Height() > nMax &&
220  m_pFnt->GetHeight( m_pSh, *m_pSh->GetOut() ) > nMax;
221  SwFont* pTmpFnt;
222  if( bTooBig )
223  {
224  pTmpFnt = new SwFont( *GetFont() );
225  if( nMax >= 20 )
226  {
227  nMax *= 17;
228  nMax /= 20;
229  }
230  pTmpFnt->SetSize( Size( 0, nMax ), pTmpFnt->GetActual() );
231  }
232  else
233  pTmpFnt = GetFont();
234  Point aTmpPos( m_nX, nY );
235  aTmpPos.AdjustY(nAsc );
236  if ( pRedlineText )
237  {
238  Size aSize = pTmpFnt->GetTextSize_( aDrawInf );
239  aTmpPos.AdjustX( -(aSize.Width()) - 200 );
240  }
241  bool bPaint = true;
242  if( !IsClipChg() )
243  {
244  Size aSize = pTmpFnt->GetTextSize_( aDrawInf );
245  if( m_bGoLeft )
246  aTmpPos.AdjustX( -(aSize.Width()) );
247  // calculate rectangle containing the line number
248  SwRect aRct( Point( aTmpPos.X(),
249  aTmpPos.Y() - pTmpFnt->GetAscent( m_pSh, *m_pSh->GetOut() )
250  ), aSize );
251  if( !m_aRect.IsInside( aRct ) )
252  {
253  if( aRct.Intersection( m_aRect ).IsEmpty() )
254  bPaint = false;
255  else
256  m_aClip.ChgClip( m_aRect, m_pTextFrame );
257  }
258  }
259  else if( m_bGoLeft )
260  aTmpPos.AdjustX( -(pTmpFnt->GetTextSize_( aDrawInf ).Width()) );
261  aDrawInf.SetPos( aTmpPos );
262  if( bPaint )
263  pTmpFnt->DrawText_( aDrawInf );
264 
265  if( bTooBig )
266  delete pTmpFnt;
267  if( bRed )
268  {
269  tools::Long nDiff = m_bGoLeft ? m_nRedX - m_nX : m_nX - m_nRedX;
270  if( nDiff > REDLINE_MINDIST )
271  PaintRedline( nY, nMax );
272  }
273 }
274 
275 void SwExtraPainter::PaintRedline( SwTwips nY, tools::Long nMax )
276 {
277  Point aStart( m_nRedX, nY );
278  Point aEnd( m_nRedX, nY + nMax );
279 
280  if( !IsClipChg() )
281  {
282  SwRect aRct( aStart, aEnd );
283  if( !m_aRect.IsInside( aRct ) )
284  {
285  if( aRct.Intersection( m_aRect ).IsEmpty() )
286  return;
287  m_aClip.ChgClip( m_aRect, m_pTextFrame );
288  }
289  }
290  const Color aOldCol( m_pSh->GetOut()->GetLineColor() );
291  m_pSh->GetOut()->SetLineColor( SW_MOD()->GetRedlineMarkColor() );
292 
293  if ( m_pTextFrame->IsVertical() )
294  {
295  m_pTextFrame->SwitchHorizontalToVertical( aStart );
296  m_pTextFrame->SwitchHorizontalToVertical( aEnd );
297  }
298 
299  m_pSh->GetOut()->DrawLine( aStart, aEnd );
300  m_pSh->GetOut()->SetLineColor( aOldCol );
301 }
302 
303 void SwTextFrame::PaintExtraData( const SwRect &rRect ) const
304 {
305  if( getFrameArea().Top() > rRect.Bottom() || getFrameArea().Bottom() < rRect.Top() )
306  return;
307 
308  SwDoc const& rDoc(GetDoc());
310  const SwLineNumberInfo &rLineInf = rDoc.GetLineNumberInfo();
311  const SwFormatLineNumber &rLineNum = GetAttrSet()->GetLineNumber();
312  bool bLineNum = !IsInTab() && rLineInf.IsPaintLineNumbers() &&
313  ( !IsInFly() || rLineInf.IsCountInFlys() ) && rLineNum.IsCount();
314  sal_Int16 eHor = static_cast<sal_Int16>(SW_MOD()->GetRedlineMarkPos());
315  if (eHor != text::HoriOrientation::NONE
317  || getRootFrame()->IsHideRedlines()))
318  {
320  }
321  bool bRedLine = eHor != text::HoriOrientation::NONE;
322  if ( !bLineNum && !bRedLine )
323  return;
324 
325  if( IsLocked() || IsHiddenNow() || !getFramePrintArea().Height() )
326  return;
328 
329  SwSwapIfNotSwapped swap(const_cast<SwTextFrame *>(this));
330  SwRect rOldRect( rRect );
331 
332  if ( IsVertical() )
333  SwitchVerticalToHorizontal( const_cast<SwRect&>(rRect) );
334 
335  SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
336  aLayoutModeModifier.Modify( false );
337 
338  // #i16816# tagged pdf support
339  SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, *pSh->GetOut() );
340 
341  SwExtraPainter aExtra( this, pSh, rLineInf, rRect, eHor, bLineNum );
342 
343  if( HasPara() )
344  {
345  TextFrameLockGuard aLock(const_cast<SwTextFrame*>(this));
346 
347  SwTextLineAccess aAccess( this );
348  aAccess.GetPara();
349 
350  SwTextPaintInfo aInf( const_cast<SwTextFrame*>(this), rRect );
351 
352  aLayoutModeModifier.Modify( false );
353 
354  SwTextPainter aLine( const_cast<SwTextFrame*>(this), &aInf );
355  bool bNoDummy = !aLine.GetNext(); // Only one empty line!
356 
357  while( aLine.Y() + aLine.GetLineHeight() <= rRect.Top() )
358  {
359  if( !aLine.GetCurr()->IsDummy() &&
360  ( rLineInf.IsCountBlankLines() ||
361  aLine.GetCurr()->HasContent() ) )
362  aExtra.IncLineNr();
363  if( !aLine.Next() )
364  {
365  const_cast<SwRect&>(rRect) = rOldRect;
366  return;
367  }
368  }
369 
370  tools::Long nBottom = rRect.Bottom();
371 
372  bool bNoPrtLine = 0 == GetMinPrtLine();
373  if( !bNoPrtLine )
374  {
375  while ( aLine.Y() < GetMinPrtLine() )
376  {
377  if( ( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasContent() )
378  && !aLine.GetCurr()->IsDummy() )
379  aExtra.IncLineNr();
380  if( !aLine.Next() )
381  break;
382  }
383  bNoPrtLine = aLine.Y() >= GetMinPrtLine();
384  }
385  const bool bIsShowChangesInMargin = pSh->GetViewOptions()->IsShowChangesInMargin();
386  if( bNoPrtLine )
387  {
388  do
389  {
390  if( bNoDummy || !aLine.GetCurr()->IsDummy() )
391  {
392  bool bRed = bRedLine && aLine.GetCurr()->HasRedline();
393  if( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasContent() )
394  {
395  bool bRedInMargin = bIsShowChangesInMargin && bRed;
396  bool bNum = bLineNum && ( aExtra.HasNumber() || aExtra.HasDivider() );
397  if( bRedInMargin || bNum )
398  {
399  sal_uInt16 nTmpHeight, nTmpAscent;
400  aLine.CalcAscentAndHeight( nTmpAscent, nTmpHeight );
401  if ( bRedInMargin )
402  {
403  const OUString* pRedlineText = aLine.GetCurr()->GetRedlineText();
404  if( !pRedlineText->isEmpty() )
405  {
406  aExtra.PaintExtra( aLine.Y(), nTmpAscent,
407  nTmpHeight, bRed, pRedlineText );
408  bRed = false;
409  bNum = false;
410  }
411  }
412  if ( bNum )
413  {
414  aExtra.PaintExtra( aLine.Y(), nTmpAscent, nTmpHeight, bRed );
415  bRed = false;
416  }
417  }
418  aExtra.IncLineNr();
419  }
420  if( bRed )
421  aExtra.PaintRedline( aLine.Y(), aLine.GetLineHeight() );
422  }
423  } while( aLine.Next() && aLine.Y() <= nBottom );
424  }
425  }
426  else
427  {
428  if (SwRedlineTable::npos == rIDRA.GetRedlinePos(*GetTextNodeFirst(), RedlineType::Any))
429  {
430  bRedLine = false;
431  }
432 
433  if( bLineNum && rLineInf.IsCountBlankLines() &&
434  ( aExtra.HasNumber() || aExtra.HasDivider() ) )
435  {
436  aExtra.PaintExtra( getFrameArea().Top()+getFramePrintArea().Top(), aExtra.GetFont()
437  ->GetAscent( pSh, *pSh->GetOut() ), getFramePrintArea().Height(), bRedLine );
438  }
439  else if( bRedLine )
440  aExtra.PaintRedline( getFrameArea().Top()+getFramePrintArea().Top(), getFramePrintArea().Height() );
441  }
442 
443  const_cast<SwRect&>(rRect) = rOldRect;
444 
445 }
446 
448 {
449  // finger layout
450  OSL_ENSURE( isFrameAreaPositionValid(), "+SwTextFrame::GetPaintSwRect: no Calc()" );
451 
452  SwRect aRet( getFramePrintArea() );
453  if ( IsEmpty() || !HasPara() )
454  aRet += getFrameArea().Pos();
455  else
456  {
457  // We return the right paint rect. Use the calculated PaintOfst as the
458  // left margin
459  SwRepaint& rRepaint = GetPara()->GetRepaint();
460  tools::Long l;
461 
462  if ( IsVertLR() && !IsVertLRBT()) // mba: the following line was added, but we don't need it for the existing directions; kept for IsVertLR(), but should be checked
464 
465  if( rRepaint.GetOffset() )
466  rRepaint.Left( rRepaint.GetOffset() );
467 
468  l = rRepaint.GetRightOfst();
469  if( l && l > rRepaint.Right() )
470  rRepaint.Right( l );
471  rRepaint.SetOffset( 0 );
472  aRet = rRepaint;
473 
474  // In case our left edge is the same as the body frame's left edge,
475  // then extend the rectangle to include the page margin as well,
476  // otherwise some font will be clipped.
477  SwLayoutFrame* pBodyFrame = GetUpper();
478  if (pBodyFrame->IsBodyFrame() && aRet.Left() == (pBodyFrame->getFrameArea().Left() + pBodyFrame->getFramePrintArea().Left()))
479  if (SwLayoutFrame* pPageFrame = pBodyFrame->GetUpper())
480  aRet.Left(pPageFrame->getFrameArea().Left());
481 
482  if ( IsRightToLeft() )
483  SwitchLTRtoRTL( aRet );
484 
485  if ( IsVertical() )
487  }
488  ResetRepaint();
489 
490  return aRet;
491 }
492 
493 bool SwTextFrame::PaintEmpty( const SwRect &rRect, bool bCheck ) const
494 {
496  if( pSh && ( pSh->GetViewOptions()->IsParagraph() || bInitFont ) )
497  {
498  bInitFont = false;
499  SwTextFly aTextFly( this );
500  aTextFly.SetTopRule();
501  SwRect aRect;
502  if( bCheck && aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) )
503  return false;
504  else if( pSh->GetWin() )
505  {
506  std::unique_ptr<SwFont> pFnt;
507  RedlineType eRedline = RedlineType::None;
508  const SwTextNode& rTextNode = *GetTextNodeForParaProps();
509  if ( rTextNode.HasSwAttrSet() )
510  {
511  const SwAttrSet *pAttrSet = &( rTextNode.GetSwAttrSet() );
512  pFnt.reset(new SwFont( pAttrSet, rTextNode.getIDocumentSettingAccess() ));
513  }
514  else
515  {
516  SwFontAccess aFontAccess( &rTextNode.GetAnyFormatColl(), pSh );
517  pFnt.reset(new SwFont( aFontAccess.Get()->GetFont() ));
518  }
519 
520  const IDocumentRedlineAccess& rIDRA = rTextNode.getIDocumentRedlineAccess();
522  && !getRootFrame()->IsHideRedlines())
523  {
524  const SwRedlineTable::size_type nRedlPos = rIDRA.GetRedlinePos( rTextNode, RedlineType::Any );
525  if( SwRedlineTable::npos != nRedlPos )
526  {
527  SwAttrHandler aAttrHandler;
528  aAttrHandler.Init( rTextNode.GetSwAttrSet(),
529  *rTextNode.getIDocumentSettingAccess() );
530  SwRedlineItr aRedln(rTextNode, *pFnt, aAttrHandler, nRedlPos, SwRedlineItr::Mode::Show);
531  const SwRangeRedline* pRedline = rIDRA.GetRedlineTable()[nRedlPos];
532  // show redlining only on the inserted/deleted empty paragraph, but not on the next one
533  if ( rTextNode.GetIndex() != pRedline->End()->nNode.GetIndex() )
534  eRedline = pRedline->GetType();
535  // except if the next empty paragraph starts a new redline (e.g. deletion after insertion)
536  else if ( nRedlPos + 1 < rIDRA.GetRedlineTable().size() )
537  {
538  const SwRangeRedline* pNextRedline = rIDRA.GetRedlineTable()[nRedlPos + 1];
539  if ( rTextNode.GetIndex() == pNextRedline->Start()->nNode.GetIndex() )
540  eRedline = pNextRedline->GetType();
541  }
542  }
543  }
544 
545  if( pSh->GetViewOptions()->IsParagraph() && getFramePrintArea().Height() )
546  {
547  if( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet( SwFontScript::Latin ) &&
548  pFnt->GetName( SwFontScript::Latin ) != numfunc::GetDefBulletFontname() )
549  {
550  pFnt->SetFamily( FAMILY_DONTKNOW, SwFontScript::Latin );
552  pFnt->SetStyleName(OUString(), SwFontScript::Latin);
553  pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, SwFontScript::Latin );
554  }
555  pFnt->SetVertical( 0_deg10, IsVertical() );
556  SwFrameSwapper aSwapper( this, true );
557  SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
558  aLayoutModeModifier.Modify( IsRightToLeft() );
559 
560  pFnt->Invalidate();
561  pFnt->ChgPhysFnt( pSh, *pSh->GetOut() );
562  Point aPos = getFrameArea().Pos() + getFramePrintArea().Pos();
563 
564  const SvxLRSpaceItem &rSpace =
566 
567  if ( rSpace.GetTextFirstLineOffset() > 0 )
568  aPos.AdjustX(rSpace.GetTextFirstLineOffset() );
569 
570  std::unique_ptr<SwSaveClip> pClip;
571  if( IsUndersized() )
572  {
573  pClip.reset(new SwSaveClip( pSh->GetOut() ));
574  pClip->ChgClip( rRect );
575  }
576 
577  aPos.AdjustY(pFnt->GetAscent( pSh, *pSh->GetOut() ) );
578 
579  if (GetTextNodeForParaProps()->GetSwAttrSet().GetParaGrid().GetValue() &&
580  IsInDocBody() )
581  {
582  SwTextGridItem const*const pGrid(GetGridItem(FindPageFrame()));
583  if ( pGrid )
584  {
585  // center character in grid line
586  aPos.AdjustY(( pGrid->GetBaseHeight() -
587  pFnt->GetHeight( pSh, *pSh->GetOut() ) ) / 2 );
588 
589  if ( ! pGrid->GetRubyTextBelow() )
590  aPos.AdjustY(pGrid->GetRubyHeight() );
591  }
592  }
593 
594  // Don't show the paragraph mark for collapsed paragraphs, when they are hidden
595  if ( EmptyHeight( ) > 1 )
596  {
597  SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), CH_PAR, 0, 1 );
598  aDrawInf.SetPos( aPos );
599  aDrawInf.SetSpace( 0 );
600  aDrawInf.SetKanaComp( 0 );
601  aDrawInf.SetWrong( nullptr );
602  aDrawInf.SetGrammarCheck( nullptr );
603  aDrawInf.SetSmartTags( nullptr );
604  aDrawInf.SetFrame( this );
605  aDrawInf.SetFont( pFnt.get() );
606  aDrawInf.SetSnapToGrid( false );
607 
608  // show redline color and settings drawing a background pilcrow,
609  // but keep also other formattings (with neutral pilcrow color)
610  if ( eRedline != RedlineType::None )
611  {
612  pFnt->DrawText_( aDrawInf );
613  if ( eRedline == RedlineType::Delete )
614  pFnt->SetStrikeout( STRIKEOUT_NONE );
615  else
616  pFnt->SetUnderline( LINESTYLE_NONE );
617  }
618 
619  pFnt->SetColor(NON_PRINTING_CHARACTER_COLOR);
620  pFnt->DrawText_( aDrawInf );
621  }
622  }
623  return true;
624  }
625  }
626  else
627  return true;
628  return false;
629 }
630 
631 void SwTextFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const
632 {
633  ResetRepaint();
634 
635  // #i16816# tagged pdf support
637 
638  Num_Info aNumInfo( *this );
639  SwTaggedPDFHelper aTaggedPDFHelperNumbering( &aNumInfo, nullptr, nullptr, rRenderContext );
640 
641  Frame_Info aFrameInfo( *this );
642  SwTaggedPDFHelper aTaggedPDFHelperParagraph( nullptr, &aFrameInfo, nullptr, rRenderContext );
643 
644  if( IsEmpty() && PaintEmpty( rRect, true ) )
645  return;
646 
647  if( IsLocked() || IsHiddenNow() || ! getFramePrintArea().HasArea() )
648  return;
649 
650  // It can happen that the IdleCollector withdrew my cached information
651  if( !HasPara() )
652  {
653  OSL_ENSURE( isFrameAreaPositionValid(), "+SwTextFrame::PaintSwFrame: no Calc()" );
654 
655  // #i29062# pass info that we are currently
656  // painting.
657  const_cast<SwTextFrame*>(this)->GetFormatted( true );
658  if( IsEmpty() )
659  {
660  PaintEmpty( rRect, false );
661  return;
662  }
663  if( !HasPara() )
664  {
665  OSL_ENSURE( false, "+SwTextFrame::PaintSwFrame: missing format information" );
666  return;
667  }
668  }
669 
670  // We don't want to be interrupted while painting.
671  // Do that after thr Format()!
672  TextFrameLockGuard aLock(const_cast<SwTextFrame*>(this));
673 
674  // We only paint the part of the TextFrame which changed, is within the
675  // range and was requested to paint.
676  // One could think that the area rRect _needs_ to be painted, although
677  // rRepaint is set. Indeed, we cannot avoid this problem from a formal
678  // perspective. Luckily we can assume rRepaint to be empty when we need
679  // paint the while Frame.
680  SwTextLineAccess aAccess( this );
681  SwParaPortion *pPara = aAccess.GetPara();
682 
683  SwRepaint &rRepaint = pPara->GetRepaint();
684 
685  // Switch off recycling when in the FlyContentFrame.
686  // A DrawRect is called for repainting the line anyways.
687  if( rRepaint.GetOffset() )
688  {
689  const SwFlyFrame *pFly = FindFlyFrame();
690  if( pFly && pFly->IsFlyInContentFrame() )
691  rRepaint.SetOffset( 0 );
692  }
693 
694  // Ge the String for painting. The length is of special interest.
695 
696  // Rectangle
697  OSL_ENSURE( ! IsSwapped(), "A frame is swapped before Paint" );
698  SwRect aOldRect( rRect );
699 
700  {
701  SwSwapIfNotSwapped swap(const_cast<SwTextFrame *>(this));
702 
703  if ( IsVertical() )
704  SwitchVerticalToHorizontal( const_cast<SwRect&>(rRect) );
705 
706  if ( IsRightToLeft() )
707  SwitchRTLtoLTR( const_cast<SwRect&>(rRect) );
708 
709  SwTextPaintInfo aInf( const_cast<SwTextFrame*>(this), rRect );
710  sw::WrongListIterator iterWrong(*this, &SwTextNode::GetWrong);
712  sw::WrongListIterator iterSmartTags(*this, &SwTextNode::GetSmartTags);
713  if (iterWrong.LooksUseful())
714  {
715  aInf.SetWrongList( &iterWrong );
716  }
717  if (iterGrammar.LooksUseful())
718  {
719  aInf.SetGrammarCheckList( &iterGrammar );
720  }
721  if (iterSmartTags.LooksUseful())
722  {
723  aInf.SetSmartTags( &iterSmartTags );
724  }
725  aInf.GetTextFly().SetTopRule();
726 
727  SwTextPainter aLine( const_cast<SwTextFrame*>(this), &aInf );
728  // Optimization: if no free flying Frame overlaps into our line, the
729  // SwTextFly just switches off
730  aInf.GetTextFly().Relax();
731 
732  OutputDevice* pOut = aInf.GetOut();
733  const bool bOnWin = pSh->GetWin() != nullptr;
734 
735  SwSaveClip aClip( bOnWin || IsUndersized() ? pOut : nullptr );
736 
737  // Output loop: For each Line ... (which is still visible) ...
738  // adapt rRect (Top + 1, Bottom - 1)
739  // Because the Iterator attaches the Lines without a gap to each other
740  aLine.TwipsToLine( rRect.Top() + 1 );
741  tools::Long nBottom = rRect.Bottom();
742 
743  bool bNoPrtLine = 0 == GetMinPrtLine();
744  if( !bNoPrtLine )
745  {
746  while ( aLine.Y() < GetMinPrtLine() && aLine.Next() )
747  ;
748  bNoPrtLine = aLine.Y() >= GetMinPrtLine();
749  }
750  if( bNoPrtLine )
751  {
752  do
753  {
754  aLine.DrawTextLine( rRect, aClip, IsUndersized() );
755 
756  } while( aLine.Next() && aLine.Y() <= nBottom );
757  }
758 
759  // Once is enough:
760  if( aLine.IsPaintDrop() )
761  aLine.PaintDropPortion();
762 
763  if( rRepaint.HasArea() )
764  rRepaint.Clear();
765  }
766 
767  const_cast<SwRect&>(rRect) = aOldRect;
768 
769  OSL_ENSURE( ! IsSwapped(), "A frame is swapped after Paint" );
770 
771 }
772 
773 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:338
bool HasContent() const
Definition: porlay.hxx:133
Base class of the Writer layout elements.
Definition: frame.hxx:298
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:157
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:44
void SwitchVerticalToHorizontal(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from vertical to horizontal layout...
Definition: txtfrm.cxx:578
bool PaintEmpty(const SwRect &, bool bCheck) const
Definition: frmpaint.cxx:493
SwFontScript WhichFont(TextFrameIndex nIdx) const
Definition: porlay.cxx:750
sal_uLong GetIndex() const
Definition: node.hxx:291
void Right(const tools::Long nRight)
Definition: swrect.hxx:200
SwTwips EmptyHeight() const
Definition: porrst.cxx:261
bool IsInDocBody() const
Definition: frame.hxx:924
bool IsInFly() const
Definition: frame.hxx:942
const SwLineNumberInfo & GetLineNumberInfo() const
Definition: lineinfo.cxx:49
bool IsSwapped() const
Definition: txtfrm.hxx:532
bool IsAnyObj(const SwRect &rRect) const
true when a frame or DrawObj must be taken in account.
Definition: txtfly.cxx:406
bool HasPara() const
Definition: txtfrm.hxx:816
sal_uInt16 GetCountBy() const
Definition: lineinfo.hxx:74
void Left(const tools::Long nLeft)
Definition: swrect.hxx:195
SwNodeIndex nNode
Definition: pam.hxx:37
SwParaPortion * GetPara()
Definition: txtcache.cxx:49
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:471
sal_uIntPtr sal_uLong
long Long
constexpr OUStringChar CH_PAR
Definition: swfont.hxx:45
FAMILY_DONTKNOW
const SwRect & getFramePrintArea() const
Definition: frame.hxx:179
The purpose of this class is to be the universal interface between formatting/text output and the pos...
Definition: txtfly.hxx:119
Size GetTextSize_(SwDrawTextInfo &rInf)
Definition: swfont.hxx:306
Definition: doc.hxx:187
#define REDLINE_DISTANCE
Definition: frmpaint.cxx:52
virtual void PaintSwFrame(vcl::RenderContext &rRenderContext, SwRect const &, SwPrintData const *const pPrintData=nullptr) const override
Definition: frmpaint.cxx:631
SwParaPortion * GetPara()
Definition: txtcache.cxx:89
void SetPos(const Point &rNew)
Definition: drawfont.hxx:397
bool GetRubyTextBelow() const
Definition: tgrditem.hxx:85
const SwLineLayout * Next()
Definition: itrtxt.cxx:107
void Pos(const Point &rNew)
Definition: swrect.hxx:169
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
void SetGrammarCheckList(sw::WrongListIterator *const pNew)
Definition: inftxt.hxx:450
bool IsCountBlankLines() const
Definition: lineinfo.hxx:83
SwTwips Y() const
Definition: itrtxt.hxx:90
bool IsCountInFlys() const
Definition: lineinfo.hxx:86
css::chart::ChartAxisLabelPosition ePos
Collection of SwLineLayout instances, represents the paragraph text in Writer layout.
Definition: porlay.hxx:247
void DrawText_(SwDrawTextInfo &rInf)
Definition: swfont.hxx:314
static bool IsShowChanges(const RedlineFlags eM)
bool IsVertLRBT() const
Definition: frame.hxx:964
size_type size() const
Definition: docary.hxx:266
bool IsHiddenNow() const
Hidden.
Definition: txtfrm.cxx:1352
LINESTYLE_NONE
const SwRect & getFrameArea() const
Definition: frame.hxx:178
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:426
sal_uLong GetThisLines() const
Definition: txtfrm.hxx:665
sal_uInt16 GetAscent(SwViewShell const *pSh, const OutputDevice &rOut)
Definition: swfont.hxx:323
bool IsInTab() const
Definition: frame.hxx:936
Used by Attribute Iterators to organize attributes on stacks to find the valid attribute in each cate...
Definition: atrhndl.hxx:38
#define REDLINE_MINDIST
Definition: frmpaint.cxx:53
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
bool IsPaintDrop() const
Definition: itrpaint.hxx:56
oslFileHandle & pOut
void Width(tools::Long nNew)
Definition: swrect.hxx:187
bool OnRightPage() const
Definition: frame.hxx:716
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1092
bool IsFlyInContentFrame() const
Definition: flyfrm.hxx:194
SwFontScript GetActual() const
Definition: swfont.hxx:182
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame, use GetBreakItem()/GetPageDescItem() instead.
Definition: findfrm.cxx:675
SwFormatColl & GetAnyFormatColl() const
Definition: node.hxx:711
SwRect GetPaintSwRect()
Page number etc.
Definition: frmpaint.cxx:447
bool IsEmpty() const
Definition: txtfrm.hxx:518
void CalcAscentAndHeight(sal_uInt16 &rAscent, sal_uInt16 &rHeight) const
Definition: itrtxt.cxx:63
void swap(cow_wrapper< T, P > &a, cow_wrapper< T, P > &b)
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:454
virtual SwRedlineTable::size_type GetRedlinePos(const SwNode &rNode, RedlineType nType) const =0
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1295
#define SW_MOD()
Definition: swmodule.hxx:255
const OUString * GetRedlineText() const
Definition: porlay.hxx:141
void Init(const SwAttrSet &rAttrSet, const IDocumentSettingAccess &rIDocumentSettingAccess)
Definition: atrstck.cxx:277
bool IsDummy() const
Definition: porlay.hxx:151
const IDocumentRedlineAccess & getIDocumentRedlineAccess() const
Provides access to the document redline interface.
Definition: node.cxx:2094
vcl::RenderContext * GetOut()
Definition: inftxt.hxx:224
SwTextFly & GetTextFly()
Definition: inftxt.hxx:383
Mutex aLock
SwPageFrame * FindPageFrame()
Definition: frame.hxx:663
sal_uLong GetAllLines() const
For displaying the line numbers.
Definition: txtfrm.hxx:664
Helper class which can be used instead of the macros if a function has too many returns.
Definition: txtfrm.hxx:918
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2567
vector_type::size_type size_type
Definition: docary.hxx:228
bool IsShowChangesInMargin() const
Definition: viewopt.hxx:294
bool IsParagraph(bool bHard=false) const
Definition: viewopt.hxx:236
SwLayoutFrame * GetUpper()
Definition: frame.hxx:661
void TwipsToLine(const SwTwips)
Definition: itrtxt.cxx:300
bool HasArea() const
Definition: swrect.hxx:288
tools::Long Width() const
bool Relax(const SwRect &rRect)
If there is no flying object frame standing in rRect (usually the current row), then we are turning o...
Definition: txtfly.hxx:318
SwGrammarMarkUp * GetGrammarCheck()
Definition: txtedt.cxx:2204
bool IsUndersized() const
Definition: flowfrm.hxx:158
short GetTextFirstLineOffset() const
void SetSpace(tools::Long nNew)
Definition: drawfont.hxx:500
SwTextFrame * GetFormatted(bool bForceQuickFormat=false)
In case the SwLineLayout was cleared out of the s_pTextCache, recreate it.
Definition: txtfrm.cxx:3355
#define NON_PRINTING_CHARACTER_COLOR
Definition: txtfrm.hxx:50
void Modify(bool bChgToRTL)
Definition: txtfrm.cxx:709
sal_uInt16 GetLineHeight() const
Definition: itrtxt.hxx:116
SwWrongList * GetSmartTags()
Definition: txtedt.cxx:2229
const IDocumentSettingAccess * getIDocumentSettingAccess() const
Provides access to the document setting interface.
Definition: node.cxx:2092
bool isFrameAreaPositionValid() const
Definition: frame.hxx:165
bool HasSwAttrSet() const
Definition: node.hxx:453
bool IsLocked() const
Definition: txtfrm.hxx:514
LineNumberPosition
Definition: lineinfo.hxx:29
SwTwips GetRightOfst() const
Definition: porlay.hxx:72
tools::Long SwTwips
Definition: swtypes.hxx:49
const SwPosition * Start() const
Definition: pam.hxx:212
< purpose of derivation from SwClient: character style for displaying the numbers.
Definition: lineinfo.hxx:37
void SetTopRule()
Definition: txtfly.hxx:308
void SwitchLTRtoRTL(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from LTR to RTL layout.
Definition: txtfrm.cxx:681
static tools::Long GetMinPrtLine()
Definition: txtfrm.hxx:608
void Bottom(const tools::Long nBottom)
Definition: swrect.hxx:209
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:335
void SwitchRTLtoLTR(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from RTL to LTR layout.
Definition: txtfrm.hxx:732
bool IsVertLR() const
Definition: frame.hxx:960
general base class for all free-flowing frames
Definition: flyfrm.hxx:60
bool IsPaintLineNumbers() const
Definition: lineinfo.hxx:80
void SetSize(const Size &rSize, const SwFontScript nWhich)
Definition: swfont.hxx:734
SwRepaint & GetRepaint()
Definition: porlay.hxx:282
OUString const & GetDefBulletFontname()
retrieve font family name used for the default bullet list characters
Definition: number.cxx:1329
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:423
vcl::Window * GetWin() const
Definition: viewsh.hxx:337
void ResetRepaint() const
Definition: txtfrm.hxx:872
const SvxParaGridItem & GetParaGrid(bool=true) const
Definition: paratr.hxx:221
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:176
const SwPosition * End() const
Definition: pam.hxx:217
bool IsRightToLeft() const
Definition: frame.hxx:968
void Top(const tools::Long nTop)
Definition: swrect.hxx:204
void SetWrongList(sw::WrongListIterator *const pNew)
Definition: inftxt.hxx:447
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1809
SwWrongList * GetWrong()
Definition: txtedt.cxx:2181
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding)...
Definition: rootfrm.hxx:420
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:718
const SwLineLayout * GetNext() const
Definition: itrtxt.hxx:84
bool IsChg() const
Definition: txtpaint.hxx:54
const SwLineLayout * GetCurr() const
Definition: itrtxt.hxx:83
bool IsVertical() const
Definition: frame.hxx:954
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
SwTwips GetOffset() const
Definition: porlay.hxx:70
SwDoc & GetDoc()
Definition: txtfrm.hxx:457
void Clear()
Definition: swrect.hxx:296
bool HasRedline() const
Definition: porlay.hxx:135
bool IsOn() const
Definition: txtfly.hxx:313
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
RedlineType
bool IsCount() const
Definition: fmtline.hxx:58
void SetOffset(const SwTwips nNew)
Definition: porlay.hxx:71
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:120
STRIKEOUT_NONE
sal_uInt16 GetDividerCountBy() const
Definition: lineinfo.hxx:68
void PaintExtraData(const SwRect &rRect) const
Definition: frmpaint.cxx:303
virtual const SwRedlineTable & GetRedlineTable() const =0
sal_uInt16 GetBaseHeight() const
Definition: tgrditem.hxx:75
void SetSmartTags(sw::WrongListIterator *const pNew)
Definition: inftxt.hxx:453
static bool bInitFont
Definition: frmpaint.cxx:57
bool IsBodyFrame() const
Definition: frame.hxx:1187
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:208
void Chg(const Point &rNP, const Size &rNS)
Definition: swrect.hxx:164
static constexpr size_type npos
Definition: docary.hxx:229
void Height(tools::Long nNew)
Definition: swrect.hxx:191
sal_uInt16 GetRubyHeight() const
Definition: tgrditem.hxx:78
SwRootFrame * getRootFrame()
Definition: frame.hxx:662
void PaintDropPortion()
Definition: txtdrop.cxx:650
void DrawTextLine(const SwRect &rPaint, SwSaveClip &rClip, const bool bUnderSz)
Definition: itrpaint.cxx:120
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1080
const SwFormatLineNumber & GetLineNumber(bool=true) const
Definition: fmtline.hxx:64