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