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 
309 
310  SwDoc const& rDoc(GetDoc());
312  const SwLineNumberInfo &rLineInf = rDoc.GetLineNumberInfo();
313  const SwFormatLineNumber &rLineNum = GetAttrSet()->GetLineNumber();
314  bool bLineNum = !IsInTab() && rLineInf.IsPaintLineNumbers() &&
315  ( !IsInFly() || rLineInf.IsCountInFlys() ) && rLineNum.IsCount();
316  sal_Int16 eHor = static_cast<sal_Int16>(SW_MOD()->GetRedlineMarkPos());
317  if (eHor != text::HoriOrientation::NONE
319  || getRootFrame()->IsHideRedlines()))
320  {
322  }
323  bool bRedLine = eHor != text::HoriOrientation::NONE;
324  if ( !bLineNum && !bRedLine )
325  return;
326 
327  if( IsLocked() || IsHiddenNow() || !getFramePrintArea().Height() )
328  return;
330 
331  SwSwapIfNotSwapped swap(const_cast<SwTextFrame *>(this));
332  SwRect rOldRect( rRect );
333 
334  if ( IsVertical() )
335  SwitchVerticalToHorizontal( const_cast<SwRect&>(rRect) );
336 
337  SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
338  aLayoutModeModifier.Modify( false );
339 
340  // #i16816# tagged pdf support
341  SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, *pSh->GetOut() );
342 
343  SwExtraPainter aExtra( this, pSh, rLineInf, rRect, eHor, bLineNum );
344 
345  if( HasPara() )
346  {
347  TextFrameLockGuard aLock(const_cast<SwTextFrame*>(this));
348 
349  SwTextLineAccess aAccess( this );
350  aAccess.GetPara();
351 
352  SwTextPaintInfo aInf( const_cast<SwTextFrame*>(this), rRect );
353 
354  aLayoutModeModifier.Modify( false );
355 
356  SwTextPainter aLine( const_cast<SwTextFrame*>(this), &aInf );
357  bool bNoDummy = !aLine.GetNext(); // Only one empty line!
358 
359  while( aLine.Y() + o3tl::narrowing<SwTwips>(aLine.GetLineHeight()) <= rRect.Top() )
360  {
361  if( !aLine.GetCurr()->IsDummy() &&
362  ( rLineInf.IsCountBlankLines() ||
363  aLine.GetCurr()->HasContent() ) )
364  aExtra.IncLineNr();
365  if( !aLine.Next() )
366  {
367  const_cast<SwRect&>(rRect) = rOldRect;
368  return;
369  }
370  }
371 
372  tools::Long nBottom = rRect.Bottom();
373 
374  bool bNoPrtLine = 0 == GetMinPrtLine();
375  if( !bNoPrtLine )
376  {
377  while ( aLine.Y() < GetMinPrtLine() )
378  {
379  if( ( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasContent() )
380  && !aLine.GetCurr()->IsDummy() )
381  aExtra.IncLineNr();
382  if( !aLine.Next() )
383  break;
384  }
385  bNoPrtLine = aLine.Y() >= GetMinPrtLine();
386  }
387  const bool bIsShowChangesInMargin = pSh->GetViewOptions()->IsShowChangesInMargin();
388  if( bNoPrtLine )
389  {
390  do
391  {
392  if( bNoDummy || !aLine.GetCurr()->IsDummy() )
393  {
394  bool bRed = bRedLine && aLine.GetCurr()->HasRedline();
395  if( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasContent() )
396  {
397  bool bRedInMargin = bIsShowChangesInMargin && bRed;
398  bool bNum = bLineNum && ( aExtra.HasNumber() || aExtra.HasDivider() );
399  if( bRedInMargin || bNum )
400  {
401  sal_uInt32 nTmpHeight, nTmpAscent;
402  aLine.CalcAscentAndHeight( nTmpAscent, nTmpHeight );
403  if ( bRedInMargin )
404  {
405  const OUString* pRedlineText = aLine.GetCurr()->GetRedlineText();
406  if( !pRedlineText->isEmpty() )
407  {
408  aExtra.PaintExtra( aLine.Y(), nTmpAscent,
409  nTmpHeight, bRed, pRedlineText );
410  bRed = false;
411  bNum = false;
412  }
413  }
414  if ( bNum )
415  {
416  aExtra.PaintExtra( aLine.Y(), nTmpAscent, nTmpHeight, bRed );
417  bRed = false;
418  }
419  }
420  aExtra.IncLineNr();
421  }
422  if( bRed )
423  aExtra.PaintRedline( aLine.Y(), aLine.GetLineHeight() );
424  }
425  } while( aLine.Next() && aLine.Y() <= nBottom );
426  }
427  }
428  else
429  {
430  if (SwRedlineTable::npos == rIDRA.GetRedlinePos(*GetTextNodeFirst(), RedlineType::Any))
431  {
432  bRedLine = false;
433  }
434 
435  if( bLineNum && rLineInf.IsCountBlankLines() &&
436  ( aExtra.HasNumber() || aExtra.HasDivider() ) )
437  {
438  aExtra.PaintExtra( getFrameArea().Top()+getFramePrintArea().Top(), aExtra.GetFont()
439  ->GetAscent( pSh, *pSh->GetOut() ), getFramePrintArea().Height(), bRedLine );
440  }
441  else if( bRedLine )
442  aExtra.PaintRedline( getFrameArea().Top()+getFramePrintArea().Top(), getFramePrintArea().Height() );
443  }
444 
445  const_cast<SwRect&>(rRect) = rOldRect;
446 
447 }
448 
450 {
451  // finger layout
452  OSL_ENSURE( isFrameAreaPositionValid(), "+SwTextFrame::GetPaintSwRect: no Calc()" );
453 
454  SwRect aRet( getFramePrintArea() );
455  if ( IsEmpty() || !HasPara() )
456  aRet += getFrameArea().Pos();
457  else
458  {
459  // We return the right paint rect. Use the calculated PaintOfst as the
460  // left margin
461  SwRepaint& rRepaint = GetPara()->GetRepaint();
462  tools::Long l;
463 
464  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
466 
467  if( rRepaint.GetOffset() )
468  rRepaint.Left( rRepaint.GetOffset() );
469 
470  l = rRepaint.GetRightOfst();
471  if( l && l > rRepaint.Right() )
472  rRepaint.Right( l );
473  rRepaint.SetOffset( 0 );
474  aRet = rRepaint;
475 
476  // In case our left edge is the same as the body frame's left edge,
477  // then extend the rectangle to include the page margin as well,
478  // otherwise some font will be clipped.
479  SwLayoutFrame* pBodyFrame = GetUpper();
480  if (pBodyFrame->IsBodyFrame() && aRet.Left() == (pBodyFrame->getFrameArea().Left() + pBodyFrame->getFramePrintArea().Left()))
481  if (SwLayoutFrame* pPageFrame = pBodyFrame->GetUpper())
482  aRet.Left(pPageFrame->getFrameArea().Left());
483 
484  if ( IsRightToLeft() )
485  SwitchLTRtoRTL( aRet );
486 
487  if ( IsVertical() )
489  }
490  ResetRepaint();
491 
492  return aRet;
493 }
494 
495 bool SwTextFrame::PaintEmpty( const SwRect &rRect, bool bCheck ) const
496 {
498  if( pSh && ( pSh->GetViewOptions()->IsParagraph() || bInitFont ) )
499  {
500  bInitFont = false;
501  SwTextFly aTextFly( this );
502  aTextFly.SetTopRule();
503  SwRect aRect;
504  if( bCheck && aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) )
505  return false;
506  else if( pSh->GetWin() )
507  {
508  std::unique_ptr<SwFont> pFnt;
509  RedlineType eRedline = RedlineType::None;
510  const SwTextNode& rTextNode = *GetTextNodeForParaProps();
511  if ( rTextNode.HasSwAttrSet() )
512  {
513  const SwAttrSet *pAttrSet = &( rTextNode.GetSwAttrSet() );
514  pFnt.reset(new SwFont( pAttrSet, rTextNode.getIDocumentSettingAccess() ));
515  }
516  else
517  {
518  SwFontAccess aFontAccess( &rTextNode.GetAnyFormatColl(), pSh );
519  pFnt.reset(new SwFont( aFontAccess.Get()->GetFont() ));
520  }
521 
522  const IDocumentRedlineAccess& rIDRA = rTextNode.getIDocumentRedlineAccess();
524  && !getRootFrame()->IsHideRedlines())
525  {
526  const SwRedlineTable::size_type nRedlPos = rIDRA.GetRedlinePos( rTextNode, RedlineType::Any );
527  if( SwRedlineTable::npos != nRedlPos )
528  {
529  SwAttrHandler aAttrHandler;
530  aAttrHandler.Init( rTextNode.GetSwAttrSet(),
531  *rTextNode.getIDocumentSettingAccess() );
532  SwRedlineItr aRedln(rTextNode, *pFnt, aAttrHandler, nRedlPos, SwRedlineItr::Mode::Show);
533  const SwRangeRedline* pRedline = rIDRA.GetRedlineTable()[nRedlPos];
534  // show redlining only on the inserted/deleted empty paragraph, but not on the next one
535  if ( rTextNode.GetIndex() != pRedline->End()->nNode.GetIndex() )
536  eRedline = pRedline->GetType();
537  // except if the next empty paragraph starts a new redline (e.g. deletion after insertion)
538  else if ( nRedlPos + 1 < rIDRA.GetRedlineTable().size() )
539  {
540  const SwRangeRedline* pNextRedline = rIDRA.GetRedlineTable()[nRedlPos + 1];
541  if ( rTextNode.GetIndex() == pNextRedline->Start()->nNode.GetIndex() )
542  eRedline = pNextRedline->GetType();
543  }
544  }
545  }
546 
547  if( pSh->GetViewOptions()->IsParagraph() && getFramePrintArea().Height() )
548  {
549  if( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet( SwFontScript::Latin ) &&
550  pFnt->GetName( SwFontScript::Latin ) != numfunc::GetDefBulletFontname() )
551  {
552  pFnt->SetFamily( FAMILY_DONTKNOW, SwFontScript::Latin );
554  pFnt->SetStyleName(OUString(), SwFontScript::Latin);
555  pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, SwFontScript::Latin );
556  }
557  pFnt->SetVertical( 0_deg10, IsVertical() );
558  SwFrameSwapper aSwapper( this, true );
559  SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
560  aLayoutModeModifier.Modify( IsRightToLeft() );
561 
562  pFnt->Invalidate();
563  pFnt->ChgPhysFnt( pSh, *pSh->GetOut() );
564  Point aPos = getFrameArea().Pos() + getFramePrintArea().Pos();
565 
566  const SvxLRSpaceItem &rSpace =
568 
569  if ( rSpace.GetTextFirstLineOffset() > 0 )
570  aPos.AdjustX(rSpace.GetTextFirstLineOffset() );
571 
572  std::unique_ptr<SwSaveClip, o3tl::default_delete<SwSaveClip>> xClip;
573  if( IsUndersized() )
574  {
575  xClip.reset(new SwSaveClip( pSh->GetOut() ));
576  xClip->ChgClip( rRect );
577  }
578 
579  aPos.AdjustY(pFnt->GetAscent( pSh, *pSh->GetOut() ) );
580 
581  if (GetTextNodeForParaProps()->GetSwAttrSet().GetParaGrid().GetValue() &&
582  IsInDocBody() )
583  {
584  SwTextGridItem const*const pGrid(GetGridItem(FindPageFrame()));
585  if ( pGrid )
586  {
587  // center character in grid line
588  aPos.AdjustY(( pGrid->GetBaseHeight() -
589  pFnt->GetHeight( pSh, *pSh->GetOut() ) ) / 2 );
590 
591  if ( ! pGrid->GetRubyTextBelow() )
592  aPos.AdjustY(pGrid->GetRubyHeight() );
593  }
594  }
595 
596  // Don't show the paragraph mark for collapsed paragraphs, when they are hidden
597  if ( EmptyHeight( ) > 1 )
598  {
599  SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), CH_PAR, 0, 1 );
600  aDrawInf.SetPos( aPos );
601  aDrawInf.SetSpace( 0 );
602  aDrawInf.SetKanaComp( 0 );
603  aDrawInf.SetWrong( nullptr );
604  aDrawInf.SetGrammarCheck( nullptr );
605  aDrawInf.SetSmartTags( nullptr );
606  aDrawInf.SetFrame( this );
607  aDrawInf.SetFont( pFnt.get() );
608  aDrawInf.SetSnapToGrid( false );
609 
610  // show redline color and settings drawing a background pilcrow,
611  // but keep also other formattings (with neutral pilcrow color)
612  if ( eRedline != RedlineType::None )
613  {
614  pFnt->DrawText_( aDrawInf );
615  if ( eRedline == RedlineType::Delete )
616  pFnt->SetStrikeout( STRIKEOUT_NONE );
617  else
618  pFnt->SetUnderline( LINESTYLE_NONE );
619  }
620 
621  pFnt->SetColor(NON_PRINTING_CHARACTER_COLOR);
622  pFnt->DrawText_( aDrawInf );
623  }
624  }
625  return true;
626  }
627  }
628  else
629  return true;
630  return false;
631 }
632 
633 void SwTextFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const
634 {
635  ResetRepaint();
636 
637  // #i16816# tagged pdf support
639 
640  Num_Info aNumInfo( *this );
641  SwTaggedPDFHelper aTaggedPDFHelperNumbering( &aNumInfo, nullptr, nullptr, rRenderContext );
642 
643  Frame_Info aFrameInfo( *this );
644  SwTaggedPDFHelper aTaggedPDFHelperParagraph( nullptr, &aFrameInfo, nullptr, rRenderContext );
645 
646  if( IsEmpty() && PaintEmpty( rRect, true ) )
647  return;
648 
649  if( IsLocked() || IsHiddenNow() || ! getFramePrintArea().HasArea() )
650  return;
651 
652  // It can happen that the IdleCollector withdrew my cached information
653  if( !HasPara() )
654  {
655  OSL_ENSURE( isFrameAreaPositionValid(), "+SwTextFrame::PaintSwFrame: no Calc()" );
656 
657  // #i29062# pass info that we are currently
658  // painting.
659  const_cast<SwTextFrame*>(this)->GetFormatted( true );
660  if( IsEmpty() )
661  {
662  PaintEmpty( rRect, false );
663  return;
664  }
665  if( !HasPara() )
666  {
667  OSL_ENSURE( false, "+SwTextFrame::PaintSwFrame: missing format information" );
668  return;
669  }
670  }
671 
672  // We don't want to be interrupted while painting.
673  // Do that after thr Format()!
674  TextFrameLockGuard aLock(const_cast<SwTextFrame*>(this));
675 
676  // We only paint the part of the TextFrame which changed, is within the
677  // range and was requested to paint.
678  // One could think that the area rRect _needs_ to be painted, although
679  // rRepaint is set. Indeed, we cannot avoid this problem from a formal
680  // perspective. Luckily we can assume rRepaint to be empty when we need
681  // paint the while Frame.
682  SwTextLineAccess aAccess( this );
683  SwParaPortion *pPara = aAccess.GetPara();
684 
685  SwRepaint &rRepaint = pPara->GetRepaint();
686 
687  // Switch off recycling when in the FlyContentFrame.
688  // A DrawRect is called for repainting the line anyways.
689  if( rRepaint.GetOffset() )
690  {
691  const SwFlyFrame *pFly = FindFlyFrame();
692  if( pFly && pFly->IsFlyInContentFrame() )
693  rRepaint.SetOffset( 0 );
694  }
695 
696  // Ge the String for painting. The length is of special interest.
697 
698  // Rectangle
699  OSL_ENSURE( ! IsSwapped(), "A frame is swapped before Paint" );
700  SwRect aOldRect( rRect );
701 
702  {
703  SwSwapIfNotSwapped swap(const_cast<SwTextFrame *>(this));
704 
705  if ( IsVertical() )
706  SwitchVerticalToHorizontal( const_cast<SwRect&>(rRect) );
707 
708  if ( IsRightToLeft() )
709  SwitchRTLtoLTR( const_cast<SwRect&>(rRect) );
710 
711  SwTextPaintInfo aInf( const_cast<SwTextFrame*>(this), rRect );
712  sw::WrongListIterator iterWrong(*this, &SwTextNode::GetWrong);
714  sw::WrongListIterator iterSmartTags(*this, &SwTextNode::GetSmartTags);
715  if (iterWrong.LooksUseful())
716  {
717  aInf.SetWrongList( &iterWrong );
718  }
719  if (iterGrammar.LooksUseful())
720  {
721  aInf.SetGrammarCheckList( &iterGrammar );
722  }
723  if (iterSmartTags.LooksUseful())
724  {
725  aInf.SetSmartTags( &iterSmartTags );
726  }
727  aInf.GetTextFly().SetTopRule();
728 
729  SwTextPainter aLine( const_cast<SwTextFrame*>(this), &aInf );
730  // Optimization: if no free flying Frame overlaps into our line, the
731  // SwTextFly just switches off
732  aInf.GetTextFly().Relax();
733 
734  OutputDevice* pOut = aInf.GetOut();
735  const bool bOnWin = pSh->GetWin() != nullptr;
736 
737  SwSaveClip aClip( bOnWin || IsUndersized() ? pOut : nullptr );
738 
739  // Output loop: For each Line ... (which is still visible) ...
740  // adapt rRect (Top + 1, Bottom - 1)
741  // Because the Iterator attaches the Lines without a gap to each other
742  aLine.TwipsToLine( rRect.Top() + 1 );
743  tools::Long nBottom = rRect.Bottom();
744 
745  bool bNoPrtLine = 0 == GetMinPrtLine();
746  if( !bNoPrtLine )
747  {
748  while ( aLine.Y() < GetMinPrtLine() && aLine.Next() )
749  ;
750  bNoPrtLine = aLine.Y() >= GetMinPrtLine();
751  }
752  if( bNoPrtLine )
753  {
754  do
755  {
756  aLine.DrawTextLine( rRect, aClip, IsUndersized() );
757 
758  } while( aLine.Next() && aLine.Y() <= nBottom );
759  }
760 
761  // Once is enough:
762  if( aLine.IsPaintDrop() )
763  aLine.PaintDropPortion();
764 
765  if( rRepaint.HasArea() )
766  rRepaint.Clear();
767  }
768 
769  const_cast<SwRect&>(rRect) = aOldRect;
770 
771  OSL_ENSURE( ! IsSwapped(), "A frame is swapped after Paint" );
772 
773 }
774 
775 /* 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:313
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:158
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:582
bool PaintEmpty(const SwRect &, bool bCheck) const
Definition: frmpaint.cxx:495
SwFontScript WhichFont(TextFrameIndex nIdx) const
Definition: porlay.cxx:822
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:939
bool IsInFly() const
Definition: frame.hxx:957
const SwLineNumberInfo & GetLineNumberInfo() const
Definition: lineinfo.cxx:49
bool IsSwapped() const
Definition: txtfrm.hxx:535
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:819
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:50
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:475
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:633
SwParaPortion * GetPara()
Definition: txtcache.cxx:90
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
void CalcAscentAndHeight(sal_uInt32 &rAscent, sal_uInt32 &rHeight) const
Definition: itrtxt.cxx:63
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
sal_uInt32 GetLineHeight() const
Definition: itrtxt.hxx:116
void DrawText_(SwDrawTextInfo &rInf)
Definition: swfont.hxx:314
static bool IsShowChanges(const RedlineFlags eM)
bool IsVertLRBT() const
Definition: frame.hxx:979
size_type size() const
Definition: docary.hxx:266
bool IsHiddenNow() const
Hidden.
Definition: txtfrm.cxx:1362
constexpr tools::Long Width() const
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:668
sal_uInt16 GetAscent(SwViewShell const *pSh, const OutputDevice &rOut)
Definition: swfont.hxx:323
bool IsInTab() const
Definition: frame.hxx:951
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:731
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1107
bool IsFlyInContentFrame() const
Definition: flyfrm.hxx:215
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:708
SwRect GetPaintSwRect()
Page number etc.
Definition: frmpaint.cxx:449
bool IsEmpty() const
Definition: txtfrm.hxx:521
void swap(cow_wrapper< T, P > &a, cow_wrapper< T, P > &b)
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:457
virtual SwRedlineTable::size_type GetRedlinePos(const SwNode &rNode, RedlineType nType) const =0
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1305
#define SW_MOD()
Definition: swmodule.hxx:256
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:678
sal_uLong GetAllLines() const
For displaying the line numbers.
Definition: txtfrm.hxx:667
Helper class which can be used instead of the macros if a function has too many returns.
Definition: txtfrm.hxx:921
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2573
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:676
void TwipsToLine(const SwTwips)
Definition: itrtxt.cxx:300
bool HasArea() const
Definition: swrect.hxx:288
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:2214
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:3365
#define NON_PRINTING_CHARACTER_COLOR
Definition: txtfrm.hxx:51
void PaintOutlineContentVisibilityButton() const
Definition: paintfrm.cxx:4250
void Modify(bool bChgToRTL)
Definition: txtfrm.cxx:713
SwWrongList * GetSmartTags()
Definition: txtedt.cxx:2244
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:451
bool IsLocked() const
Definition: txtfrm.hxx:517
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:685
static tools::Long GetMinPrtLine()
Definition: txtfrm.hxx:611
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:735
bool IsVertLR() const
Definition: frame.hxx:975
general base class for all free-flowing frames
Definition: flyfrm.hxx:78
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:1334
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:423
vcl::Window * GetWin() const
Definition: viewsh.hxx:337
void ResetRepaint() const
Definition: txtfrm.hxx:875
const SvxParaGridItem & GetParaGrid(bool=true) const
Definition: paratr.hxx:220
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:176
const SwPosition * End() const
Definition: pam.hxx:217
bool IsRightToLeft() const
Definition: frame.hxx:983
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:1810
SwWrongList * GetWrong()
Definition: txtedt.cxx:2186
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding)...
Definition: rootfrm.hxx:418
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:715
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:969
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
SwTwips GetOffset() const
Definition: porlay.hxx:70
SwDoc & GetDoc()
Definition: txtfrm.hxx:460
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:1202
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:206
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:677
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:1095
const SwFormatLineNumber & GetLineNumber(bool=true) const
Definition: fmtline.hxx:64