LibreOffice Module sw (master)  1
itrpaint.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 <hintids.hxx>
21 #include <viewopt.hxx>
22 #include <tools/multisel.hxx>
23 #include <editeng/udlnitem.hxx>
24 #include <pagefrm.hxx>
25 #include <tgrditem.hxx>
26 
29 
30 #include <viewsh.hxx>
31 #include "itrpaint.hxx"
32 #include <txtfrm.hxx>
33 #include <swfont.hxx>
34 #include "txtpaint.hxx"
35 #include "portab.hxx"
36 #include <txatbase.hxx>
37 #include <charfmt.hxx>
38 #include "redlnitr.hxx"
39 #include "porrst.hxx"
40 #include "pormulti.hxx"
41 
42 // Returns, if we have an underline breaking situation
43 // Adding some more conditions here means you also have to change them
44 // in SwTextPainter::CheckSpecialUnderline
45 bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
46 {
47  return LINESTYLE_NONE == rFnt.GetUnderline() ||
48  rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
49  rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
50  rPor.IsHolePortion() ||
51  ( rPor.IsMultiPortion() && ! static_cast<const SwMultiPortion&>(rPor).IsBidi() ) ||
52  rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
53  SvxCaseMap::SmallCaps == rFnt.GetCaseMap();
54 }
55 
56 static Color GetUnderColor( const SwFont *pFont )
57 {
58  return pFont->GetUnderColor() == COL_AUTO ?
59  pFont->GetColor() : pFont->GetUnderColor();
60 }
61 
63 {
64  CtorInitTextCursor( pNewFrame, pNewInf );
65  m_pInf = pNewInf;
66  SwFont *pMyFnt = GetFnt();
67  GetInfo().SetFont( pMyFnt );
68  bPaintDrop = false;
69 }
70 
72 {
74  GetInfo().SetPaintOfst( 0 );
75  SwTwips nPaintOfst = rPaint.Left();
76 
77  // nPaintOfst was exactly set to the end, therefore <=
78  // nPaintOfst is document global, therefore add up nLeftMar
79  // const sal_uInt16 nLeftMar = sal_uInt16(GetLeftMargin());
80  // 8310: paint of LineBreaks in empty lines.
81  if( nPaintOfst && m_pCurr->Width() )
82  {
83  SwLinePortion *pLast = nullptr;
84  // 7529 and 4757: not <= nPaintOfst
85  while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
86  < nPaintOfst )
87  {
88  if( pPor->InSpaceGrp() && GetInfo().GetSpaceAdd() )
89  {
90  long nTmp = GetInfo().X() +pPor->Width() +
91  pPor->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
92  if( nTmp + (pPor->Height()/2) >= nPaintOfst )
93  break;
94  GetInfo().X( nTmp );
95  GetInfo().SetIdx( GetInfo().GetIdx() + pPor->GetLen() );
96  }
97  else
98  pPor->Move( GetInfo() );
99  pLast = pPor;
100  pPor = pPor->GetNextPortion();
101  }
102 
103  // 7529: if PostIts return also pLast.
104  if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
105  {
106  pPor = pLast;
107  GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
108  }
109  }
110  return pPor;
111 }
112 
113 // There are two possibilities to output transparent font:
114 // 1) DrawRect on the whole line and DrawText afterwards
115 // (objectively fast, subjectively slow)
116 // 2) For every portion a DrawRect with subsequent DrawText is done
117 // (objectively slow, subjectively fast)
118 // Since the user usually judges subjectively the second method is set as default.
119 void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
120  const bool bUnderSized )
121 {
122 #if OSL_DEBUG_LEVEL > 1
123 // sal_uInt16 nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
124 // sal_uInt16 nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
125 #endif
126 
127  // maybe catch-up adjustment
128  GetAdjusted();
132  GetInfo().ResetKanaIdx();
133  // The size of the frame
134  GetInfo().SetIdx( GetStart() );
135  GetInfo().SetPos( GetTopLeft() );
136 
137  const bool bDrawInWindow = GetInfo().OnWin();
138 
139  // 6882: blank lines can't be optimized by removing them if Formatting Marks are shown
140  const bool bEndPor = GetInfo().GetOpt().IsParagraph() && GetInfo().GetText().isEmpty();
141 
142  SwLinePortion *pPor = bEndPor ? m_pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
143 
144  // Optimization!
145  SwTwips nMaxRight = std::min( rPaint.Right(), Right() );
146  const SwTwips nTmpLeft = GetInfo().X();
147  //compatibility setting: allow tabstop text to exceed right margin
148  if (GetInfo().GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_OVER_MARGIN))
149  {
150  SwLinePortion* pPorIter = pPor;
151  while( pPorIter )
152  {
153  if( pPorIter->InTabGrp() )
154  {
155  const SwTabPortion* pTabPor = static_cast<SwTabPortion*>(pPorIter);
156  const SwTwips nTabPos = nTmpLeft + pTabPor->GetTabPos();
157  if( nMaxRight < nTabPos )
158  {
159  nMaxRight = rPaint.Right();
160  break;
161  }
162  }
163  pPorIter = pPorIter->GetNextPortion();
164  }
165  }
166  if( !bEndPor && nTmpLeft >= nMaxRight )
167  return;
168 
169  // DropCaps!
170  // 7538: of course for the printer, too
171  if( !bPaintDrop )
172  {
173  // 8084: Optimization, less painting
174  // AMA: By 8084 7538 has been revived
175  // bDrawInWindow removed, so that DropCaps also can be printed
176  bPaintDrop = pPor == m_pCurr->GetFirstPortion()
177  && GetDropLines() >= GetLineNr();
178  }
179 
180  sal_uInt16 nTmpHeight, nTmpAscent;
181  CalcAscentAndHeight( nTmpAscent, nTmpHeight );
182 
183  // bClip decides if there's a need to clip
184  // The whole thing must be done before retouching
185 
186  bool bClip = ( bDrawInWindow || bUnderSized ) && !rClip.IsChg();
187  if( bClip && pPor )
188  {
189  // If TopLeft or BottomLeft of the line are outside, the we must clip.
190  // The check for Right() is done in the output loop ...
191 
192  if( GetInfo().GetPos().X() < rPaint.Left() ||
193  GetInfo().GetPos().Y() < rPaint.Top() ||
194  GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
195  {
196  bClip = false;
197  rClip.ChgClip( rPaint, m_pFrame, m_pCurr->HasUnderscore() );
198  }
199 #if OSL_DEBUG_LEVEL > 1
200  static bool bClipAlways = false;
201  if( bClip && bClipAlways )
202  { bClip = false;
203  rClip.ChgClip( rPaint );
204  }
205 #endif
206  }
207 
208  // Alignment
210  Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
211  if ( aPnt1.X() < rPaint.Left() )
212  aPnt1.setX( rPaint.Left() );
213  if ( aPnt1.Y() < rPaint.Top() )
214  aPnt1.setY( rPaint.Top() );
215  Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
216  GetInfo().GetPos().Y() + nTmpHeight );
217  if ( aPnt2.X() > rPaint.Right() )
218  aPnt2.setX( rPaint.Right() );
219  if ( aPnt2.Y() > rPaint.Bottom() )
220  aPnt2.setY( rPaint.Bottom() );
221 
222  const SwRect aLineRect( aPnt1, aPnt2 );
223 
224  if( m_pCurr->IsClipping() )
225  {
226  rClip.ChgClip( aLineRect, m_pFrame );
227  bClip = false;
228  }
229 
230  if( !pPor && !bEndPor )
231  return;
232 
233  // Baseline output also if non-TextPortion (compare TabPor with Fill)
234  // if no special vertical alignment is used,
235  // we calculate Y value for the whole line
236  SwTextGridItem const*const pGrid(GetGridItem(GetTextFrame()->FindPageFrame()));
237  const bool bAdjustBaseLine =
238  GetLineInfo().HasSpecialAlign( GetTextFrame()->IsVertical() ) ||
239  ( nullptr != pGrid );
240  const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
241  if ( ! bAdjustBaseLine )
242  GetInfo().Y( nLineBaseLine );
243 
244  // 7529: Pre-paint post-its
245  if( GetInfo().OnWin() && pPor && !pPor->Width() )
246  {
247  SeekAndChg( GetInfo() );
248 
249  if( bAdjustBaseLine )
250  {
251  const SwTwips nOldY = GetInfo().Y();
252 
253  GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *m_pCurr, nullptr,
254  GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut ),
255  GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut )
256  ) );
257 
258  pPor->PrePaint( GetInfo(), pPor );
259  GetInfo().Y( nOldY );
260  }
261  else
262  pPor->PrePaint( GetInfo(), pPor );
263  }
264 
265  // 7923: EndPortions output chars, too, that's why we change the font
266  if( bEndPor )
268 
269  const bool bRest = m_pCurr->IsRest();
270  bool bFirst = true;
271 
272  SwArrowPortion *pArrow = nullptr;
273  // Reference portion for the paragraph end portion
274  SwLinePortion* pEndTempl = m_pCurr->GetFirstPortion();
275 
276  while( pPor )
277  {
278  bool bSeeked = true;
279  GetInfo().SetLen( pPor->GetLen() );
280 
281  const SwTwips nOldY = GetInfo().Y();
282 
283  if ( bAdjustBaseLine )
284  {
285  GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *m_pCurr, pPor ) );
286 
287  // we store the last portion, because a possible paragraph
288  // end character has the same font as this portion
289  // (only in special vertical alignment case, otherwise the first
290  // portion of the line is used)
291  if ( pPor->Width() && pPor->InTextGrp() )
292  pEndTempl = pPor;
293  }
294 
295  // A special case are GluePortions which output blanks.
296 
297  // 6168: Avoid that the rest of a FieldPortion gets the attributes of the
298  // next portion with SeekAndChgBefore():
299  if( bRest && pPor->InFieldGrp() && !pPor->GetLen() )
301  else if ( pPor->IsQuoVadisPortion() )
302  {
303  // A remark on QuoVadis/ErgoSum:
304  // We use the Font set for the Paragraph for these portions.
305  // Thus, we initialize:
306  TextFrameIndex nOffset = GetInfo().GetIdx();
307  SeekStartAndChg( GetInfo(), true );
308  if( GetRedln() && m_pCurr->HasRedline() )
309  {
310  std::pair<SwTextNode const*, sal_Int32> const pos(
311  GetTextFrame()->MapViewToModel(nOffset));
312  GetRedln()->Seek(*m_pFont, pos.first->GetIndex(), pos.second, 0);
313  }
314  }
315  else if( pPor->InTextGrp() || pPor->InFieldGrp() || pPor->InTabGrp() )
316  SeekAndChg( GetInfo() );
317  else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
318  {
319  // Paragraph symbols should have the same font as the paragraph in front of them,
320  // except for the case that there's redlining in the paragraph
321  if( GetRedln() )
322  SeekAndChg( GetInfo() );
323  else
325  }
326  else
327  bSeeked = false;
328 
329  // bRest = false;
330 
331  // If the end of the portion juts out, it is clipped.
332  // A safety distance of half the height is added, so that
333  // TTF-"f" isn't overlapping into the page margin.
334  if( bClip &&
335  GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
336  {
337  bClip = false;
338  rClip.ChgClip( rPaint, m_pFrame, m_pCurr->HasUnderscore() );
339  }
340 
341  // Portions, which lay "below" the text like post-its
342  SwLinePortion *pNext = pPor->GetNextPortion();
343  if( GetInfo().OnWin() && pNext && !pNext->Width() )
344  {
345  // Fix 11289: Fields were omitted here because of Last!=Owner during
346  // loading Brief.sdw. Now the fields are allowed again,
347  // by bSeeked Last!=Owner is being avoided.
348  if ( !bSeeked )
349  SeekAndChg( GetInfo() );
350  pNext->PrePaint( GetInfo(), pPor );
351  }
352 
353  // We calculate a separate font for underlining.
354  CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
355  SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
356  if ( pUnderLineFnt )
357  {
358  const Point aTmpPoint( GetInfo().X(),
359  bAdjustBaseLine ?
360  pUnderLineFnt->GetPos().Y() :
361  nLineBaseLine );
362  pUnderLineFnt->SetPos( aTmpPoint );
363  }
364 
365  // in extended input mode we do not want a common underline font.
366  SwUnderlineFont* pOldUnderLineFnt = nullptr;
367  if ( GetRedln() && GetRedln()->ExtOn() )
368  {
369  pOldUnderLineFnt = GetInfo().GetUnderFnt();
370  GetInfo().SetUnderFnt( nullptr );
371  }
372 
373  {
374  // #i16816# tagged pdf support
375  Por_Info aPorInfo( *pPor, *this );
376  SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, &aPorInfo, *pOut );
377 
378  if( pPor->IsMultiPortion() )
379  PaintMultiPortion( rPaint, static_cast<SwMultiPortion&>(*pPor) );
380  else
381  pPor->Paint( GetInfo() );
382  }
383 
384  // reset underline font
385  if ( pOldUnderLineFnt )
386  GetInfo().SetUnderFnt( pOldUnderLineFnt );
387 
388  // reset (for special vertical alignment)
389  GetInfo().Y( nOldY );
390 
391  bFirst &= !pPor->GetLen();
392  if( pNext || !pPor->IsMarginPortion() )
393  pPor->Move( GetInfo() );
394  if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
395  pArrow = static_cast<SwArrowPortion*>(pPor);
396 
397  pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
398  // #i16816# tagged pdf support
399  ( GetInfo().GetVsh() &&
401  pNext && pNext->IsHolePortion() ) ?
402  pNext :
403  nullptr;
404  }
405 
406  // delete underline font
407  delete GetInfo().GetUnderFnt();
408  GetInfo().SetUnderFnt( nullptr );
409 
410  // paint remaining stuff
411  if( bDrawInWindow )
412  {
413  // If special vertical alignment is enabled, GetInfo().Y() is the
414  // top of the current line. Therefore is has to be adjusted for
415  // the painting of the remaining stuff. We first store the old value.
416  const SwTwips nOldY = GetInfo().Y();
417 
418  if( !GetNextLine() &&
419  GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreview() &&
420  GetInfo().GetOpt().IsParagraph() && !GetTextFrame()->GetFollow() &&
421  GetInfo().GetIdx() >= TextFrameIndex(GetInfo().GetText().getLength()))
422  {
423  const SwTmpEndPortion aEnd( *pEndTempl );
424  GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut );
425 
426  if ( bAdjustBaseLine )
427  GetInfo().Y( GetInfo().GetPos().Y()
428  + AdjustBaseLine( *m_pCurr, &aEnd ) );
429  GetInfo().X( GetInfo().X() +
430  ( GetCurr()->IsHanging() ? GetCurr()->GetHangingMargin() : 0 ) );
431  aEnd.Paint( GetInfo() );
432  GetInfo().Y( nOldY );
433  }
434  if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreview() )
435  {
436  const bool bNextUndersized =
437  ( GetTextFrame()->GetNext() &&
438  0 == GetTextFrame()->GetNext()->getFramePrintArea().Height() &&
439  GetTextFrame()->GetNext()->IsTextFrame() &&
440  static_cast<SwTextFrame*>(GetTextFrame()->GetNext())->IsUndersized() ) ;
441 
442  if( bUnderSized || bNextUndersized )
443  {
444  if ( bAdjustBaseLine )
445  GetInfo().Y( GetInfo().GetPos().Y() + m_pCurr->GetAscent() );
446 
447  // Left arrow (text overflowing)
448  if( pArrow )
449  GetInfo().DrawRedArrow( *pArrow );
450 
451  // GetInfo().Y() must be current baseline
452  SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTextFrame()->getFrameArea().Bottom();
453  if( ( nDiff > 0 &&
454  (GetEnd() < TextFrameIndex(GetInfo().GetText().getLength()) ||
455  ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
456  (nDiff >= 0 && bNextUndersized) )
457 
458  {
459  // Right arrow (text overflowing)
460  SwArrowPortion aArrow( GetInfo() );
461  GetInfo().DrawRedArrow( aArrow );
462  }
463 
464  GetInfo().Y( nOldY );
465  }
466  }
467  }
468 
469  if( m_pCurr->IsClipping() )
470  rClip.ChgClip( rPaint, m_pFrame );
471 }
472 
474  long nAdjustBaseLine )
475 {
476  // Check if common underline should not be continued
477  if ( IsUnderlineBreak( *pPor, *m_pFont ) )
478  {
479  // delete underline font
480  delete GetInfo().GetUnderFnt();
481  GetInfo().SetUnderFnt( nullptr );
482  return;
483  }
484  // Reuse calculated underline font as much as possible.
485  if (GetInfo().GetUnderFnt() &&
486  GetInfo().GetIdx() + pPor->GetLen() <= GetInfo().GetUnderFnt()->GetEnd() + TextFrameIndex(1))
487  {
488  SwFont &rFont = GetInfo().GetUnderFnt()->GetFont();
489  const Color aColor = GetUnderColor( GetInfo().GetFont() );
490  if ( GetUnderColor( &rFont ) != aColor )
491  rFont.SetColor( aColor );
492  return;
493  }
494 
495  // If current underline matches the common underline font, we continue
496  // to use the common underline font.
497  // Bug 120769:Color of underline display wrongly
498  if ( GetInfo().GetUnderFnt() &&
499  GetInfo().GetUnderFnt()->GetFont().GetUnderline() == GetFnt()->GetUnderline() &&
500  GetInfo().GetFont() && GetInfo().GetFont()->GetUnderColor() != COL_AUTO )
501  return;
502  //Bug 120769(End)
503 
504  OSL_ENSURE( GetFnt() && LINESTYLE_NONE != GetFnt()->GetUnderline(),
505  "CheckSpecialUnderline without underlined font" );
506  MultiSelection aUnderMulti( Range( 0, GetInfo().GetText().getLength() ) );
507  const SwFont* pParaFnt = GetAttrHandler().GetFont();
508  if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
509  aUnderMulti.SelectAll();
510 
511  if (sw::MergedPara const*const pMerged = GetTextFrame()->GetMergedPara())
512  {
513  // first, add the paragraph properties to MultiSelection - if there are
514  // Hints too, they will override the positions if they're added later
515  sal_Int32 nTmp(0);
516  for (auto const& e : pMerged->extents)
517  {
518  const SfxPoolItem* pItem;
519  if (SfxItemState::SET == e.pNode->GetSwAttrSet().GetItemState(
520  RES_CHRATR_UNDERLINE, true, &pItem))
521  {
522  const bool bUnderSelect(m_pFont->GetUnderline() ==
523  static_cast<SvxUnderlineItem const*>(pItem)->GetLineStyle());
524  aUnderMulti.Select(Range(nTmp, nTmp + e.nEnd - e.nStart - 1),
525  bUnderSelect);
526  }
527  nTmp += e.nEnd - e.nStart;
528  }
529  }
530 
531  SwTextNode const* pNode(nullptr);
533  for (SwTextAttr const* pTextAttr = iter.NextAttr(&pNode); pTextAttr;
534  pTextAttr = iter.NextAttr(&pNode))
535  {
536  SvxUnderlineItem const*const pItem =
538 
539  if (pItem)
540  {
541  TextFrameIndex const nStart(
542  GetTextFrame()->MapModelToView(pNode, pTextAttr->GetStart()));
543  TextFrameIndex const nEnd(
544  GetTextFrame()->MapModelToView(pNode, *pTextAttr->End()));
545  if (nEnd > nStart)
546  {
547  const bool bUnderSelect = m_pFont->GetUnderline() == pItem->GetLineStyle();
548  aUnderMulti.Select(Range(sal_Int32(nStart), sal_Int32(nEnd) - 1),
549  bUnderSelect);
550  }
551  }
552  }
553 
554  const TextFrameIndex nIndx = GetInfo().GetIdx();
555  TextFrameIndex nUnderEnd(0);
556  const size_t nCnt = aUnderMulti.GetRangeCount();
557 
558  // find the underline range the current portion is contained in
559  for( size_t i = 0; i < nCnt; ++i )
560  {
561  const Range& rRange = aUnderMulti.GetRange( i );
562  if (nUnderEnd == TextFrameIndex(rRange.Min()))
563  nUnderEnd = TextFrameIndex(rRange.Max());
564  else if (nIndx >= TextFrameIndex(rRange.Min()))
565  {
566  nUnderEnd = TextFrameIndex(rRange.Max());
567  }
568  else
569  break;
570  }
571 
572  if ( GetEnd() && GetEnd() <= nUnderEnd )
573  nUnderEnd = GetEnd() - TextFrameIndex(1);
574 
575  // calculate the new common underline font
576  SwFont* pUnderlineFnt = nullptr;
577  Point aCommonBaseLine;
578 
579  // check, if underlining is not isolated
580  if (nIndx + GetInfo().GetLen() < nUnderEnd + TextFrameIndex(1))
581  {
582  // here starts the algorithm for calculating the underline font
583  SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
584  SwAttrIter aIter(*GetInfo().GetTextFrame()->GetTextNodeFirst(),
585  rScriptInfo, GetTextFrame());
586 
587  TextFrameIndex nTmpIdx = nIndx;
588  sal_uLong nSumWidth = 0;
589  sal_uLong nSumHeight = 0;
590  sal_uLong nBold = 0;
591  sal_uInt16 nMaxBaseLineOfst = 0;
592  int nNumberOfPortions = 0;
593 
594  while (nTmpIdx <= nUnderEnd && pPor)
595  {
596  if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
597  pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
598  pPor->IsHolePortion() ||
599  ( pPor->IsMultiPortion() && ! static_cast<const SwMultiPortion*>(pPor)->IsBidi() ) )
600  break;
601 
602  aIter.Seek( nTmpIdx );
603  if ( aIter.GetFnt()->GetEscapement() < 0 || m_pFont->IsWordLineMode() ||
604  SvxCaseMap::SmallCaps == m_pFont->GetCaseMap() )
605  break;
606 
607  if ( !aIter.GetFnt()->GetEscapement() )
608  {
609  nSumWidth += pPor->Width();
610  const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
611 
612  // If we do not have a common baseline we take the baseline
613  // and the font of the lowest portion.
614  if ( nAdjustBaseLine )
615  {
616  const sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *m_pCurr, pPor );
617  if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
618  {
619  nMaxBaseLineOfst = nTmpBaseLineOfst;
620  nSumHeight = nFontHeight;
621  }
622  }
623  // in horizontal layout we build a weighted sum of the heights
624  else
625  nSumHeight += pPor->Width() * nFontHeight;
626 
627  if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
628  nBold += pPor->Width();
629  }
630 
631  ++nNumberOfPortions;
632 
633  nTmpIdx += pPor->GetLen();
634  pPor = pPor->GetNextPortion();
635  }
636 
637  // resulting height
638  if ( nNumberOfPortions > 1 && nSumWidth )
639  {
640  const sal_uLong nNewFontHeight = nAdjustBaseLine ?
641  nSumHeight :
642  nSumHeight / nSumWidth;
643 
644  pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
645 
646  // font height
647  const SwFontScript nActual = pUnderlineFnt->GetActual();
648  pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
649  nNewFontHeight ), nActual );
650 
651  // font weight
652  if ( 2 * nBold > nSumWidth )
653  pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
654  else
655  pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
656 
657  // common base line
658  aCommonBaseLine.setY( nAdjustBaseLine + nMaxBaseLineOfst );
659  }
660  }
661 
662  // an escaped redlined portion should also have a special underlining
663  if( ! pUnderlineFnt && m_pFont->GetEscapement() > 0 && GetRedln() &&
665  pUnderlineFnt = new SwFont( *m_pFont );
666 
667  delete GetInfo().GetUnderFnt();
668 
669  if ( pUnderlineFnt )
670  {
671  pUnderlineFnt->SetProportion( 100 );
672  pUnderlineFnt->SetEscapement( 0 );
673  pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
674  pUnderlineFnt->SetOverline( LINESTYLE_NONE );
675  const Color aFillColor( COL_TRANSPARENT );
676  pUnderlineFnt->SetFillColor( aFillColor );
677 
678  GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt, nUnderEnd,
679  aCommonBaseLine ) );
680  }
681  else
682  // I'm sorry, we do not have a special underlining font for you.
683  GetInfo().SetUnderFnt( nullptr );
684 }
685 
686 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwAttrHandler & GetAttrHandler()
Definition: itratr.hxx:109
long Width() const
std::deque< sal_uInt16 > * GetpKanaComp() const
Definition: porlay.hxx:184
void Move(SwTextPaintInfo &rInf)
Definition: porlin.cxx:270
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
void SetUnderFnt(SwUnderlineFont *pNew)
Definition: inftxt.hxx:242
SwViewShell * GetVsh()
Definition: inftxt.hxx:228
void GetAdjusted() const
Definition: itrtxt.hxx:250
sal_uInt16 GetLineNr() const
Definition: itrtxt.hxx:87
bool IsClipping() const
Definition: porlay.hxx:138
bool ChkSpecialUnderline() const
Definition: redlnitr.hxx:119
bool InSpaceGrp() const
Definition: porlin.hxx:109
bool IsRest() const
Definition: porlay.hxx:119
sal_uInt16 Height() const
Definition: possiz.hxx:44
bool SeekStartAndChg(SwTextSizeInfo &rInf, const bool bPara=false)
Definition: itrtxt.hxx:323
bool IsUnderlineBreak(const SwLinePortion &rPor, const SwFont &rFnt)
Definition: itrpaint.cxx:45
TextFrameIndex GetStart() const
Definition: itrtxt.hxx:88
const Color & GetUnderColor() const
Definition: swfont.hxx:272
void SetPos(const Point &rNew)
Definition: inftxt.hxx:436
const SfxPoolItem * GetItem(const SwTextAttr &rAttr, sal_uInt16 nWhich)
Extracts pool item of type nWhich from rAttr.
Definition: atrstck.cxx:157
void CtorInitTextPainter(SwTextFrame *pFrame, SwTextPaintInfo *pInf)
Definition: itrpaint.cxx:62
sal_uIntPtr sal_uLong
void SetFillColor(const Color &rColor)
Definition: swfont.hxx:436
const SwRect & getFramePrintArea() const
Definition: frame.hxx:176
void Height(long nNew)
Definition: swrect.hxx:189
short Seek(SwFont &rFnt, sal_uLong nNode, sal_Int32 nNew, sal_Int32 nOld)
Definition: redlnitr.cxx:532
SwFont * m_pFont
Definition: itratr.hxx:39
bool SeekAndChg(SwTextSizeInfo &rInf)
Definition: itrtxt.hxx:310
long SwTwips
Definition: swtypes.hxx:49
bool Select(sal_Int32 nIndex, bool bSelect=true)
const Size & GetSize(SwFontScript nWhich) const
Definition: swfont.hxx:205
void SetKanaComp(std::deque< sal_uInt16 > *pNew)
Definition: inftxt.hxx:329
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
bool InFieldGrp() const
Definition: porlin.hxx:104
SwTwips Y() const
Definition: itrtxt.hxx:90
sal_Int32 GetRangeCount() const
bool Seek(TextFrameIndex nPos)
Enables the attributes used at char pos nPos in the logical font.
Definition: itratr.cxx:301
SwTextAttr const * NextAttr(SwTextNode const **ppNode=nullptr)
Definition: txtfrm.cxx:86
std::vector< long > * GetpLLSpaceAdd() const
Definition: porlay.hxx:179
void SetColor(const Color &rColor)
Definition: swfont.hxx:414
long GetLen(const Point &rPnt)
WEIGHT_BOLD
const SwFont * GetFont() const
Definition: atrhndl.hxx:113
bool IsMarginPortion() const
Definition: porlin.hxx:124
constexpr::Color COL_AUTO(0xFF, 0xFF, 0xFF, 0xFF)
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
virtual void Paint(const SwTextPaintInfo &rInf) const =0
void Top(const long nTop)
Definition: swrect.hxx:202
LINESTYLE_NONE
bool IsBreakPortion() const
Definition: porlin.hxx:114
const SwRect & getFrameArea() const
Definition: frame.hxx:175
void setX(long nX)
size_t pos
#define X
SwTwips Right() const
Definition: itrtxt.hxx:181
long GetSpaceAdd() const
Definition: inftxt.hxx:447
SwTextPaintInfo & GetInfo()
Definition: itrpaint.hxx:57
bool IsTextFrame() const
Definition: frame.hxx:1210
const SwLineLayout * GetNextLine() const
Definition: itrtxt.cxx:132
oslFileHandle & pOut
SvxCaseMap GetCaseMap() const
Definition: swfont.hxx:279
Describes parts of multiple text nodes, which will form a text frame, even when redlines are hidden a...
Definition: txtfrm.hxx:958
void Right(const long nRight)
Definition: swrect.hxx:198
void ChgPhysFnt(SwViewShell const *pSh, OutputDevice &rOut)
Definition: swfont.cxx:969
void setY(long nY)
void SetStrikeout(const FontStrikeout eStrikeout)
Definition: swfont.hxx:575
SwFontScript GetActual() const
Definition: swfont.hxx:183
void SetPaintOfst(const SwTwips nNew)
Definition: inftxt.hxx:741
SwTwips Y() const
Definition: inftxt.hxx:387
bool bPaintDrop
Definition: itrpaint.hxx:29
void CalcAscentAndHeight(sal_uInt16 &rAscent, sal_uInt16 &rHeight) const
Definition: itrtxt.cxx:63
const SwViewOption & GetOpt() const
Definition: inftxt.hxx:245
void PaintMultiPortion(const SwRect &rPaint, SwMultiPortion &rMulti, const SwMultiPortion *pEnvPor=nullptr)
Definition: pormulti.cxx:1495
SwTextInfo * m_pInf
Definition: itrtxt.hxx:35
sal_uInt16 AdjustBaseLine(const SwLineLayout &rLine, const SwLinePortion *pPor, sal_uInt16 nPorHeight=0, sal_uInt16 nAscent=0, const bool bAutoToCentered=false) const
Definition: itrtxt.cxx:212
SwLinePortion * CalcPaintOfst(const SwRect &rPaint)
Definition: itrpaint.cxx:71
const SwLineLayout * GetPrevLine()
Definition: itrtxt.cxx:142
const SwLineInfo & GetLineInfo() const
Definition: itrtxt.hxx:128
const Point & GetPos() const
Definition: swfont.hxx:975
vcl::RenderContext * GetOut()
Definition: inftxt.hxx:231
void SetFont(SwFont *pNew)
Definition: inftxt.hxx:240
SwParaPortion * GetParaPortion()
Definition: inftxt.hxx:128
bool IsFlyPortion() const
Definition: porlin.hxx:125
TextFrameIndex MapModelToView(MergedPara const &, SwTextNode const *pNode, sal_Int32 nIndex)
Definition: txtfrm.cxx:1173
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2514
int i
SwLinePortion * GetFirstPortion() const
Definition: porlay.cxx:667
long GetHeight() const
Definition: swfont.hxx:283
bool IsParagraph(bool bHard=false) const
Definition: viewopt.hxx:229
std::pair< SwTextNode *, sal_Int32 > MapViewToModel(MergedPara const &, TextFrameIndex nIndex)
Definition: txtfrm.cxx:1154
SwFont & GetFont()
Definition: swfont.hxx:970
TextFrameIndex GetEnd() const
Definition: swfont.hxx:976
WEIGHT_NORMAL
void ResetSpaceIdx()
Definition: inftxt.hxx:443
void SetEscapement(const short nNewEsc)
Definition: swfont.hxx:784
#define RES_CHRATR_UNDERLINE
Definition: hintids.hxx:83
sal_uInt16 GetTabPos() const
Definition: portab.hxx:39
static Color GetUnderColor(const SwFont *pFont)
Definition: itrpaint.cxx:56
SwFont * GetFnt()
Definition: itratr.hxx:103
TextFrameIndex GetIdx() const
Definition: inftxt.hxx:278
void SetWeight(const FontWeight eWeight, const SwFontScript nWhich)
Definition: swfont.hxx:532
bool IsPDFExport() const
Definition: viewopt.hxx:378
void PrePaint(const SwTextPaintInfo &rInf, const SwLinePortion *pLast) const
Definition: porlin.cxx:79
const Color & GetColor() const
Definition: swfont.hxx:276
TextFrameIndex GetLen() const
Definition: porlin.hxx:74
void SetPos(const Point &rPoint)
Definition: swfont.hxx:978
bool InTabGrp() const
Definition: porlin.hxx:100
long X() const
Point GetTopLeft() const
Definition: itrtxt.hxx:186
const OUString & GetText() const
Definition: inftxt.hxx:246
const Range & GetRange(sal_Int32 nRange) const
bool IsHolePortion() const
Definition: porlin.hxx:126
SwUnderlineFont * GetUnderFnt() const
Definition: inftxt.hxx:243
const Point & GetPos() const
Definition: inftxt.hxx:435
bool IsMultiPortion() const
Definition: porlin.hxx:134
FontLineStyle GetUnderline() const
Definition: swfont.hxx:271
FontLineStyle GetLineStyle() const
SwTwips X() const
Definition: inftxt.hxx:385
SwTextFrame * m_pFrame
Definition: itrtxt.hxx:34
void CheckSpecialUnderline(const SwLinePortion *pPor, long nAdjustBaseLine=0)
Definition: itrpaint.cxx:473
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:50
long Max() const
void CtorInitTextCursor(SwTextFrame *pFrame, SwTextSizeInfo *pInf)
Definition: itrcrsr.cxx:382
void Left(const long nLeft)
Definition: swrect.hxx:193
bool SeekAndChgBefore(SwTextSizeInfo &rInf)
Definition: itrtxt.hxx:315
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
void Bottom(const long nBottom)
Definition: swrect.hxx:207
FontWeight GetWeight() const
Definition: swfont.hxx:284
void SetLen(const TextFrameIndex nNew)
Definition: inftxt.hxx:281
void SetSize(const Size &rSize, const SwFontScript nWhich)
Definition: swfont.hxx:737
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:426
bool HasSpecialAlign(bool bVert) const
Definition: inftxt.hxx:93
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porrst.cxx:56
bool OnWin() const
Definition: inftxt.hxx:199
bool InTextGrp() const
Definition: porlin.hxx:98
sal_uInt16 Width() const
Definition: possiz.hxx:46
SwScriptInfo & GetScriptInfo()
Definition: porlay.hxx:270
SwFontScript
Definition: swfont.hxx:122
double getLength(const B2DPolygon &rCandidate)
void DrawRedArrow(const SwLinePortion &rPor) const
Definition: inftxt.cxx:1054
bool IsChg() const
Definition: txtpaint.hxx:48
const SwLineLayout * GetCurr() const
Definition: itrtxt.hxx:83
bool HasRedline() const
Definition: porlay.hxx:125
bool IsArrowPortion() const
Definition: porlin.hxx:133
SwTextFrame * GetTextFrame()
Definition: itrtxt.hxx:134
void ResetKanaIdx()
Definition: inftxt.hxx:326
bool IsWordLineMode() const
Definition: swfont.hxx:277
SwLineLayout * m_pCurr
Definition: itrtxt.hxx:36
long Min() const
STRIKEOUT_NONE
TextFrameIndex GetEnd() const
Definition: itrtxt.hxx:89
sal_uInt16 GetDropLines() const
Definition: itrtxt.hxx:202
bool IsQuoVadisPortion() const
Definition: porlin.hxx:116
void SelectAll(bool bSelect=true)
void SetProportion(const sal_uInt8 nNewPropr)
Definition: swfont.hxx:765
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:72
void SetIdx(const TextFrameIndex nNew)
Definition: inftxt.hxx:279
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
short GetEscapement() const
Definition: swfont.hxx:278
virtual long CalcSpacing(long nSpaceAdd, const SwTextSizeInfo &rInf) const
Definition: porlin.cxx:307
void SetOverline(const FontLineStyle eOverline)
Definition: swfont.hxx:560
bool IsFlyCntPortion() const
Definition: porlin.hxx:112
sal_uInt16 & GetAscent()
Definition: porlin.hxx:77
void SetpSpaceAdd(std::vector< long > *pNew)
Definition: inftxt.hxx:451
SwRedlineItr * GetRedln()
Definition: itratr.hxx:81
bool HasUnderscore() const
Definition: porlay.hxx:131
long Y() const
void DrawTextLine(const SwRect &rPaint, SwSaveClip &rClip, const bool bUnderSz)
Definition: itrpaint.cxx:119
bool IsPostItsPortion() const
Definition: porlin.hxx:128
void ChgClip(const SwRect &rRect, const SwTextFrame *pFrame=nullptr, bool bEnlargeRect=false)
Definition: txtpaint.hxx:44
SwFrame * GetNext()
Definition: frame.hxx:654