LibreOffice Module sw (master)  1
porfld.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 
22 #include <com/sun/star/i18n/ScriptType.hpp>
23 #include <com/sun/star/i18n/XBreakIterator.hpp>
24 #include <vcl/graph.hxx>
25 #include <editeng/brushitem.hxx>
26 #include <vcl/metric.hxx>
27 #include <vcl/outdev.hxx>
28 #include <viewopt.hxx>
29 #include <SwPortionHandler.hxx>
30 #include "porlay.hxx"
31 #include "porfld.hxx"
32 #include "inftxt.hxx"
33 #include <fmtornt.hxx>
34 #include <frmatr.hxx>
35 #include <frmtool.hxx>
36 #include <viewsh.hxx>
37 #include <doc.hxx>
39 #include <rootfrm.hxx>
40 #include <breakit.hxx>
41 #include "porftn.hxx"
42 #include <accessibilityoptions.hxx>
43 #include <editeng/lrspitem.hxx>
44 #include <unicode/ubidi.h>
45 #include <bookmrk.hxx>
46 
47 using namespace ::com::sun::star;
48 
50 { return (GetLen() || !m_aExpand.isEmpty() || SwLinePortion::Compress()) ? this : nullptr; }
51 
52 SwFieldPortion *SwFieldPortion::Clone( const OUString &rExpand ) const
53 {
54  std::unique_ptr<SwFont> pNewFnt;
55  if( m_pFont )
56  {
57  pNewFnt.reset(new SwFont( *m_pFont ));
58  }
59  // #i107143#
60  // pass placeholder property to created <SwFieldPortion> instance.
61  SwFieldPortion* pClone = new SwFieldPortion( rExpand, std::move(pNewFnt), m_bPlaceHolder );
62  pClone->SetNextOffset( m_nNextOffset );
63  pClone->m_bNoLength = m_bNoLength;
64  return pClone;
65 }
66 
68 {
69  OSL_ENSURE( pField, "TakeNextOffset: Missing Source" );
70  m_nNextOffset = pField->GetNextOffset();
71  m_aExpand = m_aExpand.replaceAt(0, sal_Int32(m_nNextOffset), "");
72  m_bFollow = true;
73 }
74 
75 SwFieldPortion::SwFieldPortion( const OUString &rExpand, std::unique_ptr<SwFont> pFont, bool bPlaceHold )
76  : m_aExpand(rExpand), m_pFont(std::move(pFont)), m_nNextOffset(0), m_nNextScriptChg(COMPLETE_STRING), m_nViewWidth(0)
77  , m_bFollow( false ), m_bLeft( false), m_bHide( false)
78  , m_bCenter (false), m_bHasFollow( false )
79  , m_bAnimated( false), m_bNoPaint( false)
80  , m_bReplace( false), m_bPlaceHolder( bPlaceHold )
81  , m_bNoLength( false )
82  , m_nAttrFieldType(0)
83 {
85 }
86 
88  : SwExpandPortion( rField )
89  , m_aExpand( rField.GetExp() )
90  , m_nNextOffset( rField.GetNextOffset() )
91  , m_nNextScriptChg( rField.m_nNextScriptChg )
92  , m_nViewWidth( rField.m_nViewWidth )
93  , m_bFollow( rField.IsFollow() )
94  , m_bLeft( rField.IsLeft() )
95  , m_bHide( rField.IsHide() )
96  , m_bCenter( rField.IsCenter() )
97  , m_bHasFollow( rField.HasFollow() )
98  , m_bAnimated ( rField.m_bAnimated )
99  , m_bNoPaint( rField.m_bNoPaint)
100  , m_bReplace( rField.m_bReplace )
101  , m_bPlaceHolder( rField.m_bPlaceHolder )
102  , m_bNoLength( rField.m_bNoLength )
103  , m_nAttrFieldType( rField.m_nAttrFieldType)
104 {
105  if ( rField.HasFont() )
106  m_pFont.reset( new SwFont( *rField.GetFont() ) );
107 
109 }
110 
112 {
113  m_pFont.reset();
114 }
115 
116 sal_uInt16 SwFieldPortion::GetViewWidth( const SwTextSizeInfo &rInf ) const
117 {
118  // even though this is const, nViewWidth should be computed at the very end:
119  SwFieldPortion* pThis = const_cast<SwFieldPortion*>(this);
120  if( !Width() && rInf.OnWin() && !rInf.GetOpt().IsPagePreview() &&
122  {
123  if( !m_nViewWidth )
124  pThis->m_nViewWidth = rInf.GetTextSize(OUString(' ')).Width();
125  }
126  else
127  pThis->m_nViewWidth = 0;
128  return m_nViewWidth;
129 }
130 
131 namespace {
132 
136 class SwFieldSlot
137 {
138  std::shared_ptr<vcl::TextLayoutCache> m_pOldCachedVclData;
139  const OUString *pOldText;
140  OUString aText;
141  TextFrameIndex nIdx;
142  TextFrameIndex nLen;
143  SwTextFormatInfo *pInf;
144  bool bOn;
145 public:
146  SwFieldSlot( const SwTextFormatInfo* pNew, const SwFieldPortion *pPor );
147  ~SwFieldSlot();
148 };
149 
150 }
151 
152 SwFieldSlot::SwFieldSlot( const SwTextFormatInfo* pNew, const SwFieldPortion *pPor )
153  : pOldText(nullptr)
154  , nIdx(0)
155  , nLen(0)
156  , pInf(nullptr)
157 {
158  bOn = pPor->GetExpText( *pNew, aText );
159 
160  // The text will be replaced ...
161  if( bOn )
162  {
163  pInf = const_cast<SwTextFormatInfo*>(pNew);
164  nIdx = pInf->GetIdx();
165  nLen = pInf->GetLen();
166  pOldText = &(pInf->GetText());
167  m_pOldCachedVclData = pInf->GetCachedVclData();
168  pInf->SetLen(TextFrameIndex(aText.getLength()));
169  pInf->SetCachedVclData(nullptr);
170  if( pPor->IsFollow() )
171  {
172  pInf->SetFakeLineStart( nIdx > pInf->GetLineStart() );
173  pInf->SetIdx(TextFrameIndex(0));
174  }
175  else if (nIdx < TextFrameIndex(pOldText->getLength()))
176  {
177  aText = (*pOldText).replaceAt(sal_Int32(nIdx), 1, aText);
178  }
179  pInf->SetText( aText );
180  }
181 }
182 
183 SwFieldSlot::~SwFieldSlot()
184 {
185  if( bOn )
186  {
187  pInf->SetCachedVclData(m_pOldCachedVclData);
188  pInf->SetText( *pOldText );
189  pInf->SetIdx( nIdx );
190  pInf->SetLen( nLen );
191  pInf->SetFakeLineStart( false );
192  }
193 }
194 
196 {
197  OUString aText;
198  if (!GetExpText(rInf, aText) || aText.isEmpty())
199  return;
200 
201  SwFontScript nActual = m_pFont ? m_pFont->GetActual() : rInf.GetFont()->GetActual();
202  sal_uInt16 nScript = g_pBreakIt->GetBreakIter()->getScriptType( aText, 0 );
203  sal_Int32 nChg = 0;
204  if( i18n::ScriptType::WEAK == nScript )
205  {
206  nChg = g_pBreakIt->GetBreakIter()->endOfScript(aText,0,nScript);
207  if (nChg < aText.getLength() && nChg >= 0)
208  nScript = g_pBreakIt->GetBreakIter()->getScriptType( aText, nChg );
209  }
210 
211  // nNextScriptChg will be evaluated during SwFieldPortion::Format()
212 
213  if (nChg < aText.getLength() && nChg >= 0)
215  g_pBreakIt->GetBreakIter()->endOfScript(aText, nChg, nScript));
216  else
217  m_nNextScriptChg = TextFrameIndex(aText.getLength());
218 
219  SwFontScript nTmp;
220  switch ( nScript ) {
221  case i18n::ScriptType::LATIN : nTmp = SwFontScript::Latin; break;
222  case i18n::ScriptType::ASIAN : nTmp = SwFontScript::CJK; break;
223  case i18n::ScriptType::COMPLEX : nTmp = SwFontScript::CTL; break;
224  default: nTmp = nActual;
225  }
226 
227  // #i16354# Change script type for RTL text to CTL.
228  const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
229  // #i98418#
230  const sal_uInt8 nFieldDir = (IsNumberPortion() || IsFootnoteNumPortion())
231  ? rSI.GetDefaultDir()
232  : rSI.DirType(IsFollow() ? rInf.GetIdx() - TextFrameIndex(1) : rInf.GetIdx());
233 
234  {
235  UErrorCode nError = U_ZERO_ERROR;
236  UBiDi* pBidi = ubidi_openSized( aText.getLength(), 0, &nError );
237  ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aText.getStr()), aText.getLength(), nFieldDir, nullptr, &nError );
238  int32_t nEnd;
239  UBiDiLevel nCurrDir;
240  ubidi_getLogicalRun( pBidi, 0, &nEnd, &nCurrDir );
241  ubidi_close( pBidi );
242  const TextFrameIndex nNextDirChg(nEnd);
243  m_nNextScriptChg = std::min( m_nNextScriptChg, nNextDirChg );
244 
245  // #i89825# change the script type also to CTL
246  // if there is no strong LTR char in the LTR run (numbers)
247  if (nCurrDir != UBIDI_RTL &&
248  (UBIDI_LTR != nFieldDir || i18n::ScriptType::COMPLEX == nScript))
249  {
250  nCurrDir = UBIDI_RTL;
251  for( sal_Int32 nCharIdx = 0; nCharIdx < nEnd; ++nCharIdx )
252  {
253  UCharDirection nCharDir = u_charDirection ( aText[ nCharIdx ]);
254  if ( nCharDir == U_LEFT_TO_RIGHT ||
255  nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
256  nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
257  {
258  nCurrDir = UBIDI_LTR;
259  break;
260  }
261  }
262  }
263 
264  if (nCurrDir == UBIDI_RTL)
265  {
266  nTmp = SwFontScript::CTL;
267  // If we decided that this range was RTL after all and the
268  // previous range was complex but clipped to the start of this
269  // range, then extend it to be complex over the additional RTL range
270  if (nScript == i18n::ScriptType::COMPLEX)
271  m_nNextScriptChg = nNextDirChg;
272  }
273  }
274 
275  // #i98418#
276  // keep determined script type for footnote portions as preferred script type.
277  // For footnote portions a font can not be created directly - see footnote
278  // portion format method.
279  if ( IsFootnotePortion() )
280  {
281  static_cast<SwFootnotePortion*>(this)->SetPreferredScriptType( nTmp );
282  }
283  else if ( nTmp != nActual )
284  {
285  if( !m_pFont )
286  m_pFont.reset( new SwFont( *rInf.GetFont() ) );
287  m_pFont->SetActual( nTmp );
288  }
289 
290 }
291 
293 {
294  // Scope wegen aDiffText::DTOR!
295  TextFrameIndex nRest;
296  bool bFull = false;
297  bool bEOL = false;
298  TextFrameIndex const nTextRest = TextFrameIndex(rInf.GetText().getLength()) - rInf.GetIdx();
299  {
300  SwFieldSlot aDiffText( &rInf, this );
301  SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
302  aLayoutModeModifier.SetAuto();
303 
304  // Field portion has to be split in several parts if
305  // 1. There are script/direction changes inside the field
306  // 2. There are portion breaks (tab, break) inside the field:
307  const TextFrameIndex nOldFullLen = rInf.GetLen();
308  TextFrameIndex nFullLen = rInf.ScanPortionEnd(rInf.GetIdx(), rInf.GetIdx() + nOldFullLen) - rInf.GetIdx();
309  if ( m_nNextScriptChg < nFullLen )
310  {
311  nFullLen = m_nNextScriptChg;
312  rInf.SetHookChar( 0 );
313  }
314  rInf.SetLen( nFullLen );
315 
317  rInf.GetUnderScorePos() > rInf.GetIdx() )
318  rInf.SetUnderScorePos( rInf.GetIdx() );
319 
320  if( m_pFont )
321  m_pFont->AllocFontCacheId( rInf.GetVsh(), m_pFont->GetActual() );
322 
323  SwFontSave aSave( rInf, m_pFont.get() );
324 
325  // Length must be 0: the length is set for bFull after format
326  // and passed along in nRest. Or else the old length would be
327  // retained and be used for nRest!
329  TextFrameIndex const nFollow(IsFollow() ? 0 : 1);
330 
331  // As odd is may seem: the query for GetLen() must return false due
332  // to the ExpandPortions _after_ aDiffText (see SoftHyphs), caused
333  // by SetFull.
334  if( !nFullLen )
335  {
336  // Don't Init(), as we need height and ascent
337  Width(0);
338  bFull = rInf.Width() <= rInf.GetPos().X();
339  }
340  else
341  {
342  TextFrameIndex const nOldLineStart = rInf.GetLineStart();
343  if( IsFollow() )
344  rInf.SetLineStart(TextFrameIndex(0));
345  rInf.SetNotEOL( nFullLen == nOldFullLen && nTextRest > nFollow );
346 
347  // the height depending on the fields font is set,
348  // this is required for SwTextGuess::Guess
349  Height( rInf.GetTextHeight() + rInf.GetFont()->GetTopBorderSpace() +
350  rInf.GetFont()->GetBottomBorderSpace() );
351  // If a kerning portion is inserted after our field portion,
352  // the ascent and height must be known
353  SetAscent( rInf.GetAscent() + rInf.GetFont()->GetTopBorderSpace() );
354  bFull = SwTextPortion::Format( rInf );
355  rInf.SetNotEOL( false );
356  rInf.SetLineStart( nOldLineStart );
357  }
358  TextFrameIndex const nTmpLen = GetLen();
359  bEOL = !nTmpLen && nFollow && bFull;
360  nRest = nOldFullLen - nTmpLen;
361 
362  // The char is held in the first position
363  // Unconditionally after format!
364  SetLen( m_bNoLength ? TextFrameIndex(0) : nFollow );
365 
366  if( nRest )
367  {
368  // aExpand has not yet been shortened; the new Ofst is a
369  // result of nRest
370  TextFrameIndex nNextOfst = TextFrameIndex(m_aExpand.getLength()) - nRest;
371 
372  if ( IsQuoVadisPortion() )
373  nNextOfst = nNextOfst + TextFrameIndex(static_cast<SwQuoVadisPortion*>(this)->GetContText().getLength());
374 
375  OUString aNew( m_aExpand.copy(sal_Int32(nNextOfst)) );
376  m_aExpand = m_aExpand.copy(0, sal_Int32(nNextOfst));
377 
378  // These characters should not be contained in the follow
379  // field portion. They are handled via the HookChar mechanism.
380  const sal_Unicode nNew = !aNew.isEmpty() ? aNew[0] : 0;
381  switch (nNew)
382  {
383  case CH_BREAK : bFull = true;
384  [[fallthrough]];
385  case ' ' :
386  case CH_TAB :
387  case CHAR_HARDHYPHEN: // non-breaking hyphen
388  case CHAR_SOFTHYPHEN:
389  case CHAR_HARDBLANK:
390  case CHAR_ZWSP :
391  case CHAR_ZWNBSP :
392  case CH_TXTATR_BREAKWORD:
393  case CH_TXTATR_INWORD:
394  {
395  aNew = aNew.copy( 1 );
396  ++nNextOfst;
397  break;
398  }
399  default: ;
400  }
401 
402  // Even if there is no more text left for a follow field,
403  // we have to build a follow field portion (without font),
404  // otherwise the HookChar mechanism would not work.
405  SwFieldPortion *pField = Clone( aNew );
406  if( !aNew.isEmpty() && !pField->GetFont() )
407  {
408  pField->SetFont( std::make_unique<SwFont>( *rInf.GetFont() ) );
409  }
410  pField->SetFollow( true );
411  SetHasFollow( true );
412 
413  // For a newly created field, nNextOffset contains the Offset
414  // of its start of the original string
415  // If a FollowField is created when formatting, this FollowField's
416  // Offset is being held in nNextOffset
417  m_nNextOffset = m_nNextOffset + nNextOfst;
418  pField->SetNextOffset( m_nNextOffset );
419  rInf.SetRest( pField );
420  }
421  }
422 
423  if( bEOL && rInf.GetLast() && !rInf.GetUnderflow() )
424  rInf.GetLast()->FormatEOL( rInf );
425  return bFull;
426 }
427 
428 void SwFieldPortion::Paint( const SwTextPaintInfo &rInf ) const
429 {
430  SwFontSave aSave( rInf, m_pFont.get() );
431 
432  OSL_ENSURE(GetLen() <= TextFrameIndex(1), "SwFieldPortion::Paint: rest-portion pollution?");
433  if( Width() && ( !m_bPlaceHolder || rInf.GetOpt().IsShowPlaceHolderFields() ) )
434  {
435  // A very liberal use of the background
436  rInf.DrawViewOpt( *this, PortionType::Field );
437  SwExpandPortion::Paint( rInf );
438  }
439 }
440 
441 bool SwFieldPortion::GetExpText( const SwTextSizeInfo &rInf, OUString &rText ) const
442 {
443  rText = m_aExpand;
444  if( rText.isEmpty() && rInf.OnWin() &&
445  !rInf.GetOpt().IsPagePreview() && !rInf.GetOpt().IsReadonly() &&
447  !HasFollow() )
448  rText = " ";
449  return true;
450 }
451 
453 {
454  sal_Int32 nH = 0;
455  sal_Int32 nW = 0;
456  if (m_pFont)
457  {
458  nH = m_pFont->GetSize(m_pFont->GetActual()).Height();
459  nW = m_pFont->GetSize(m_pFont->GetActual()).Width();
460  }
461  rPH.Special( GetLen(), m_aExpand, GetWhichPor(), nH, nW, m_pFont.get() );
462 }
463 
465 {
466  SwFontSave aSave( rInf, m_pFont.get() );
467  SwPosSize aSize( SwExpandPortion::GetTextSize( rInf ) );
468  return aSize;
469 }
470 
471 SwFieldPortion *SwHiddenPortion::Clone(const OUString &rExpand ) const
472 {
473  std::unique_ptr<SwFont> pNewFnt;
474  if( m_pFont )
475  pNewFnt.reset(new SwFont( *m_pFont ));
476  return new SwHiddenPortion( rExpand, std::move(pNewFnt) );
477 }
478 
479 void SwHiddenPortion::Paint( const SwTextPaintInfo &rInf ) const
480 {
481  if( Width() )
482  {
483  SwFontSave aSave( rInf, m_pFont.get() );
484  rInf.DrawViewOpt( *this, PortionType::Hidden );
485  SwExpandPortion::Paint( rInf );
486  }
487 }
488 
489 bool SwHiddenPortion::GetExpText( const SwTextSizeInfo &rInf, OUString &rText ) const
490 {
491  // Do not query for IsHidden()!
492  return SwFieldPortion::GetExpText( rInf, rText );
493 }
494 
495 SwNumberPortion::SwNumberPortion( const OUString &rExpand,
496  std::unique_ptr<SwFont> pFont,
497  const bool bLft,
498  const bool bCntr,
499  const sal_uInt16 nMinDst,
500  const bool bLabelAlignmentPosAndSpaceModeActive )
501  : SwFieldPortion( rExpand, std::move(pFont) ),
502  nFixWidth(0),
503  nMinDist( nMinDst ),
504  mbLabelAlignmentPosAndSpaceModeActive( bLabelAlignmentPosAndSpaceModeActive )
505 {
507  SetLeft( bLft );
508  SetHide( false );
509  SetCenter( bCntr );
510 }
511 
513 {
514  return TextFrameIndex(0);
515 }
516 
517 SwFieldPortion *SwNumberPortion::Clone( const OUString &rExpand ) const
518 {
519  std::unique_ptr<SwFont> pNewFnt;
520  if( m_pFont )
521  pNewFnt.reset(new SwFont( *m_pFont ));
522 
523  return new SwNumberPortion( rExpand, std::move(pNewFnt), IsLeft(), IsCenter(),
525 }
526 
534 {
535  SetHide( false );
536  const bool bFull = SwFieldPortion::Format( rInf );
538  // a numbering portion can be contained in a rotated portion!!!
539  nFixWidth = rInf.IsMulti() ? Height() : Width();
540  rInf.SetNumDone( !rInf.GetRest() );
541  if( rInf.IsNumDone() )
542  {
543 // SetAscent( rInf.GetAscent() );
544  OSL_ENSURE( Height() && nAscent, "NumberPortions without Height | Ascent" );
545 
546  long nDiff( 0 );
547 
549  {
551  // #i32902#
553  {
554  nDiff = rInf.Left()
556  GetSwAttrSet().GetLRSpace().GetTextFirstLineOffset()
557  - rInf.First()
558  + rInf.ForcedLeftMargin();
559  }
560  else
561  {
562  nDiff = rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
563  }
564  }
565  // The text part of the numbering should always at least
566  // start at the left margin
567  if( nDiff < 0 )
568  nDiff = 0;
569  else if ( nDiff > rInf.X() )
570  nDiff -= rInf.X();
571  else
572  nDiff = 0;
573 
574  if( nDiff < nFixWidth + nMinDist )
575  nDiff = nFixWidth + nMinDist;
576 
577  // Numbering evades the Fly, no nDiff in the second round
578  // Tricky special case: FlyFrame is in an Area we're just about to
579  // acquire
580  // The NumberPortion is marked as hidden
581  const bool bFly = rInf.GetFly() ||
582  ( rInf.GetLast() && rInf.GetLast()->IsFlyPortion() );
583  if( nDiff > rInf.Width() )
584  {
585  nDiff = rInf.Width();
586  if ( bFly )
587  SetHide( true );
588  }
589 
590  // A numbering portion can be inside a SwRotatedPortion. Then the
591  // Height has to be changed
592  if ( rInf.IsMulti() )
593  {
594  if ( Height() < nDiff )
595  Height( sal_uInt16( nDiff ) );
596  }
597  else if( Width() < nDiff )
598  Width( sal_uInt16(nDiff) );
599  }
600  return bFull;
601 }
602 
603 
610 {
611 
612  // This caused trouble with flys anchored as characters.
613  // If one of these is numbered but does not fit to the line,
614  // it calls this function, causing a loop because both the number
615  // portion and the fly portion go to the next line
616 // SetHide( true );
617 }
618 
619 
624 void SwNumberPortion::Paint( const SwTextPaintInfo &rInf ) const
625 {
626  if ( IsHide() && rInf.GetParaPortion() && rInf.GetParaPortion()->GetNext() )
627  {
628  SwLinePortion *pTmp = GetNextPortion();
629  while ( pTmp && !pTmp->InTextGrp() )
630  pTmp = pTmp->GetNextPortion();
631  if ( !pTmp )
632  return;
633  }
634 
635  // calculate the width of the number portion, including follows
636  const sal_uInt16 nOldWidth = Width();
637  sal_uInt16 nSumWidth = 0;
638  sal_uInt16 nOffset = 0;
639 
640  const SwLinePortion* pTmp = this;
641  while ( pTmp && pTmp->InNumberGrp() )
642  {
643  nSumWidth = nSumWidth + pTmp->Width();
644  if ( static_cast<const SwNumberPortion*>(pTmp)->HasFollow() )
645  pTmp = pTmp->GetNextPortion();
646  else
647  {
648  nOffset = pTmp->Width() - static_cast<const SwNumberPortion*>(pTmp)->nFixWidth;
649  break;
650  }
651  }
652 
653  // The master portion takes care for painting the background of the
654  // follow field portions
655  if ( ! IsFollow() )
656  {
657  SwNumberPortion *pThis = const_cast<SwNumberPortion*>(this);
658  pThis->Width( nSumWidth );
659  rInf.DrawViewOpt( *this, PortionType::Number );
660  pThis->Width( nOldWidth );
661  }
662 
663  if( !m_aExpand.isEmpty() )
664  {
665  const SwFont *pTmpFnt = rInf.GetFont();
666  bool bPaintSpace = ( LINESTYLE_NONE != pTmpFnt->GetUnderline() ||
667  LINESTYLE_NONE != pTmpFnt->GetOverline() ||
668  STRIKEOUT_NONE != pTmpFnt->GetStrikeout() ) &&
669  !pTmpFnt->IsWordLineMode();
670  if( bPaintSpace && m_pFont )
671  bPaintSpace = ( LINESTYLE_NONE != m_pFont->GetUnderline() ||
672  LINESTYLE_NONE != m_pFont->GetOverline() ||
673  STRIKEOUT_NONE != m_pFont->GetStrikeout() ) &&
674  !m_pFont->IsWordLineMode();
675 
676  SwFontSave aSave( rInf, m_pFont.get() );
677 
678  if( nFixWidth == Width() && ! HasFollow() )
679  SwExpandPortion::Paint( rInf );
680  else
681  {
682  // logical const: reset width
683  SwNumberPortion *pThis = const_cast<SwNumberPortion*>(this);
684  bPaintSpace = bPaintSpace && nFixWidth < nOldWidth;
685  sal_uInt16 nSpaceOffs = nFixWidth;
686  pThis->Width( nFixWidth );
687 
688  if( ( IsLeft() && ! rInf.GetTextFrame()->IsRightToLeft() ) ||
689  ( ! IsLeft() && ! IsCenter() && rInf.GetTextFrame()->IsRightToLeft() ) )
690  SwExpandPortion::Paint( rInf );
691  else
692  {
693  SwTextPaintInfo aInf( rInf );
694  if( nOffset < nMinDist )
695  nOffset = 0;
696  else
697  {
698  if( IsCenter() )
699  {
700  /* #110778# a / 2 * 2 == a is not a tautology */
701  sal_uInt16 nTmpOffset = nOffset;
702  nOffset /= 2;
703  if( nOffset < nMinDist )
704  nOffset = nTmpOffset - nMinDist;
705  }
706  else
707  nOffset = nOffset - nMinDist;
708  }
709  aInf.X( aInf.X() + nOffset );
710  SwExpandPortion::Paint( aInf );
711  if( bPaintSpace )
712  nSpaceOffs = nSpaceOffs + nOffset;
713  }
714  if( bPaintSpace && nOldWidth > nSpaceOffs )
715  {
716  SwTextPaintInfo aInf( rInf );
717  aInf.X( aInf.X() + nSpaceOffs );
718 
719  // #i53199# Adjust position of underline:
720  if ( rInf.GetUnderFnt() )
721  {
722  const Point aNewPos( aInf.GetPos().X(), rInf.GetUnderFnt()->GetPos().Y() );
723  rInf.GetUnderFnt()->SetPos( aNewPos );
724  }
725 
726  pThis->Width( nOldWidth - nSpaceOffs + 12 );
727  {
728  SwTextSlot aDiffText( &aInf, this, true, false, " " );
729  aInf.DrawText( *this, aInf.GetLen(), true );
730  }
731  }
732  pThis->Width( nOldWidth );
733  }
734  }
735 }
736 
738  const OUString& rBulletFollowedBy,
739  std::unique_ptr<SwFont> pFont,
740  const bool bLft,
741  const bool bCntr,
742  const sal_uInt16 nMinDst,
743  const bool bLabelAlignmentPosAndSpaceModeActive )
744  : SwNumberPortion( OUStringChar(cBullet) + rBulletFollowedBy,
745  std::move(pFont), bLft, bCntr, nMinDst,
746  bLabelAlignmentPosAndSpaceModeActive )
747 {
749 }
750 
751 #define GRFNUM_SECURE 10
752 
754  const OUString& rGraphicFollowedBy,
755  const SvxBrushItem* pGrfBrush, OUString const & referer,
756  const SwFormatVertOrient* pGrfOrient, const Size& rGrfSize,
757  const bool bLft, const bool bCntr, const sal_uInt16 nMinDst,
758  const bool bLabelAlignmentPosAndSpaceModeActive ) :
759  SwNumberPortion( rGraphicFollowedBy, nullptr, bLft, bCntr, nMinDst,
760  bLabelAlignmentPosAndSpaceModeActive ),
761  pBrush( new SvxBrushItem(RES_BACKGROUND) ), nId( 0 )
762 {
764  SetAnimated( false );
765  m_bReplace = false;
766  if( pGrfBrush )
767  {
768  pBrush.reset(pGrfBrush->Clone());
769  const Graphic* pGraph = pGrfBrush->GetGraphic(referer);
770  if( pGraph )
771  SetAnimated( pGraph->IsAnimated() );
772  else
773  m_bReplace = true;
774  }
775  if( pGrfOrient )
776  {
777  nYPos = pGrfOrient->GetPos();
778  eOrient = pGrfOrient->GetVertOrient();
779  }
780  else
781  {
782  nYPos = 0;
783  eOrient = text::VertOrientation::TOP;
784  }
785  Width( static_cast<sal_uInt16>(rGrfSize.Width() + 2 * GRFNUM_SECURE) );
786  nFixWidth = Width();
787  nGrfHeight = rGrfSize.Height() + 2 * GRFNUM_SECURE;
788  Height( sal_uInt16(nGrfHeight) );
789  m_bNoPaint = false;
790 }
791 
793 {
794  if ( IsAnimated() )
795  {
796  Graphic* pGraph = const_cast<Graphic*>(pBrush->GetGraphic());
797  if (pGraph)
798  pGraph->StopAnimation( nullptr, nId );
799  }
800  pBrush.reset();
801 }
802 
804 {
805  if ( IsAnimated() )
806  {
807  Graphic* pGraph = const_cast<Graphic*>(pBrush->GetGraphic());
808  if (pGraph)
809  pGraph->StopAnimation( pOut, nId );
810  }
811 }
812 
814 {
815  SetHide( false );
816 // Width( nFixWidth );
817  sal_uInt16 nFollowedByWidth( 0 );
819  {
820  SwFieldPortion::Format( rInf );
821  nFollowedByWidth = Width();
823  }
824  Width( nFixWidth + nFollowedByWidth );
825  const bool bFull = rInf.Width() < rInf.X() + Width();
826  const bool bFly = rInf.GetFly() ||
827  ( rInf.GetLast() && rInf.GetLast()->IsFlyPortion() );
828  SetAscent( GetRelPos() > 0 ? GetRelPos() : 0 );
829  if( GetAscent() > Height() )
830  Height( GetAscent() );
831 
832  if( bFull )
833  {
834  Width( rInf.Width() - static_cast<sal_uInt16>(rInf.X()) );
835  if( bFly )
836  {
838  m_bNoPaint = true;
839  rInf.SetNumDone( false );
840  return true;
841  }
842  }
843  rInf.SetNumDone( true );
844 // long nDiff = rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
846  ? 0
847  : rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
848  // The TextPortion should at least always start on the
849  // left margin
850  if( nDiff < 0 )
851  nDiff = 0;
852  else if ( nDiff > rInf.X() )
853  nDiff -= rInf.X();
854  if( nDiff < nFixWidth + nMinDist )
855  nDiff = nFixWidth + nMinDist;
856 
857  // Numbering evades Fly, no nDiff in the second round
858  // Tricky special case: FlyFrame is in the Area we were just
859  // about to get a hold of.
860  // The NumberPortion is marked as hidden
861  if( nDiff > rInf.Width() )
862  {
863  nDiff = rInf.Width();
864  if( bFly )
865  SetHide( true );
866  }
867 
868  if( Width() < nDiff )
869  Width( sal_uInt16(nDiff) );
870  return bFull;
871 }
872 
873 
878 void SwGrfNumPortion::Paint( const SwTextPaintInfo &rInf ) const
879 {
880  if( m_bNoPaint )
881  return;
882  if ( IsHide() && rInf.GetParaPortion() && rInf.GetParaPortion()->GetNext() )
883  {
884  SwLinePortion *pTmp = GetNextPortion();
885  while ( pTmp && !pTmp->InTextGrp() )
886  pTmp = pTmp->GetNextPortion();
887  if ( !pTmp )
888  return;
889  }
890  Point aPos( rInf.X() + GRFNUM_SECURE, rInf.Y() - GetRelPos() + GRFNUM_SECURE );
891  long nTmpWidth = std::max( long(0), static_cast<long>(nFixWidth - 2 * GRFNUM_SECURE) );
892  Size aSize( nTmpWidth, GetGrfHeight() - 2 * GRFNUM_SECURE );
893 
894  const bool bTmpLeft = mbLabelAlignmentPosAndSpaceModeActive ||
895  ( IsLeft() && ! rInf.GetTextFrame()->IsRightToLeft() ) ||
896  ( ! IsLeft() && ! IsCenter() && rInf.GetTextFrame()->IsRightToLeft() );
897 
898  if( nFixWidth < Width() && !bTmpLeft )
899  {
900  sal_uInt16 nOffset = Width() - nFixWidth;
901  if( nOffset < nMinDist )
902  nOffset = 0;
903  else
904  {
905  if( IsCenter() )
906  {
907  nOffset /= 2;
908  if( nOffset < nMinDist )
909  nOffset = Width() - nFixWidth - nMinDist;
910  }
911  else
912  nOffset = nOffset - nMinDist;
913  }
914  aPos.AdjustX(nOffset );
915  }
916 
917  if( m_bReplace )
918  {
919  const long nTmpH = GetNextPortion() ? GetNextPortion()->GetAscent() : 120;
920  aSize = Size( nTmpH, nTmpH );
921  aPos.setY( rInf.Y() - nTmpH );
922  }
923  SwRect aTmp( aPos, aSize );
924 
925  bool bDraw = true;
926 
927  if ( IsAnimated() )
928  {
929  bDraw = !rInf.GetOpt().IsGraphic();
930  if( !nId )
931  {
932  SetId( reinterpret_cast<sal_IntPtr>( rInf.GetTextFrame() ) );
933  rInf.GetTextFrame()->SetAnimation();
934  }
935  if( aTmp.IsOver( rInf.GetPaintRect() ) && !bDraw )
936  {
937  rInf.NoteAnimation();
938  const SwViewShell* pViewShell = rInf.GetVsh();
939 
940  // virtual device, not pdf export
941  if( OUTDEV_VIRDEV == rInf.GetOut()->GetOutDevType() &&
942  pViewShell && pViewShell->GetWin() )
943  {
944  Graphic* pGraph = const_cast<Graphic*>(pBrush->GetGraphic());
945  if (pGraph)
946  pGraph->StopAnimation(nullptr,nId);
948  }
949 
950  else if ( pViewShell &&
952  !pViewShell->IsPreview() &&
953  // #i9684# Stop animation during printing/pdf export.
954  pViewShell->GetWin() )
955  {
956  Graphic* pGraph = const_cast<Graphic*>(pBrush->GetGraphic());
957  if (pGraph)
958  {
959  pGraph->StartAnimation(
960  const_cast<OutputDevice*>(rInf.GetOut()), aPos, aSize, nId );
961  }
962  }
963 
964  // pdf export, printing, preview, stop animations...
965  else
966  bDraw = true;
967  }
968  if( bDraw )
969  {
970 
971  Graphic* pGraph = const_cast<Graphic*>(pBrush->GetGraphic());
972  if (pGraph)
973  pGraph->StopAnimation( nullptr, nId );
974  }
975  }
976 
977  SwRect aRepaint( rInf.GetPaintRect() );
978  const SwTextFrame& rFrame = *rInf.GetTextFrame();
979  if( rFrame.IsVertical() )
980  {
981  rFrame.SwitchHorizontalToVertical( aTmp );
982  rFrame.SwitchHorizontalToVertical( aRepaint );
983  }
984 
985  if( rFrame.IsRightToLeft() )
986  {
987  rFrame.SwitchLTRtoRTL( aTmp );
988  rFrame.SwitchLTRtoRTL( aRepaint );
989  }
990 
991  if( bDraw && aTmp.HasArea() )
992  {
993  DrawGraphic( pBrush.get(), const_cast<OutputDevice*>(rInf.GetOut()),
994  aTmp, aRepaint, m_bReplace ? GRFNUM_REPLACE : GRFNUM_YES );
995  }
996 }
997 
998 void SwGrfNumPortion::SetBase( long nLnAscent, long nLnDescent,
999  long nFlyAsc, long nFlyDesc )
1000 {
1002  {
1003  SetRelPos( 0 );
1004  if ( GetOrient() == text::VertOrientation::CENTER )
1005  SetRelPos( GetGrfHeight() / 2 );
1006  else if ( GetOrient() == text::VertOrientation::TOP )
1008  else if ( GetOrient() == text::VertOrientation::BOTTOM )
1009  ;
1010  else if ( GetOrient() == text::VertOrientation::CHAR_CENTER )
1011  SetRelPos( ( GetGrfHeight() + nLnAscent - nLnDescent ) / 2 );
1012  else if ( GetOrient() == text::VertOrientation::CHAR_TOP )
1013  SetRelPos( nLnAscent );
1014  else if ( GetOrient() == text::VertOrientation::CHAR_BOTTOM )
1015  SetRelPos( GetGrfHeight() - nLnDescent );
1016  else
1017  {
1018  if( GetGrfHeight() >= nFlyAsc + nFlyDesc )
1019  {
1020  // If I'm as large as the line, I do not need to adjust
1021  // at the line; I'll leave the max. ascent unchanged
1022  SetRelPos( nFlyAsc );
1023  }
1024  else if ( GetOrient() == text::VertOrientation::LINE_CENTER )
1025  SetRelPos( ( GetGrfHeight() + nFlyAsc - nFlyDesc ) / 2 );
1026  else if ( GetOrient() == text::VertOrientation::LINE_TOP )
1027  SetRelPos( nFlyAsc );
1028  else if ( GetOrient() == text::VertOrientation::LINE_BOTTOM )
1029  SetRelPos( GetGrfHeight() - nFlyDesc );
1030  }
1031  }
1032 }
1033 
1035 {
1036  OSL_ENSURE( HasAnimation(), "SwTextFrame::StopAnimation: Which Animation?" );
1037  if( HasPara() )
1038  {
1039  SwLineLayout *pLine = GetPara();
1040  while( pLine )
1041  {
1042  SwLinePortion *pPor = pLine->GetNextPortion();
1043  while( pPor )
1044  {
1045  if( pPor->IsGrfNumPortion() )
1046  static_cast<SwGrfNumPortion*>(pPor)->StopAnimation( pOut );
1047  // The NumberPortion is always at the first char,
1048  // which means we can cancel as soon as we've reached a portion
1049  // with a length > 0
1050  pPor = pPor->GetLen() ? nullptr : pPor->GetNextPortion();
1051  }
1052  pLine = pLine->GetLen() ? nullptr : pLine->GetNext();
1053  }
1054  }
1055 }
1056 
1061  : SwFieldPortion( rText )
1062  , nUpPos(0)
1063  , nLowPos(0)
1064  , nProportion(55)
1065 {
1066  SetLen(TextFrameIndex(1));
1068  if( m_aExpand.getLength() > 6 )
1069  m_aExpand = m_aExpand.copy( 0, 6 );
1070 
1071  // Initialization of the scripttype array,
1072  // the arrays of width and position are filled by the format function
1073  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
1074 
1075  SwFontScript nScr = SW_SCRIPTS;
1076  for( sal_Int32 i = 0; i < rText.getLength(); ++i )
1077  {
1078  switch ( g_pBreakIt->GetBreakIter()->getScriptType( rText, i ) ) {
1079  case i18n::ScriptType::LATIN : nScr = SwFontScript::Latin; break;
1080  case i18n::ScriptType::ASIAN : nScr = SwFontScript::CJK; break;
1081  case i18n::ScriptType::COMPLEX : nScr = SwFontScript::CTL; break;
1082  }
1083  aScrType[i] = nScr;
1084  }
1085 }
1086 
1088 {
1089  OSL_ENSURE(GetLen() <= TextFrameIndex(1), "SwFieldPortion::Paint: rest-portion pollution?");
1090  if( !Width() )
1091  return;
1092 
1093  rInf.DrawBackBrush( *this );
1094  rInf.DrawViewOpt( *this, PortionType::Field );
1095 
1096  // do we have to repaint a post it portion?
1097  if( rInf.OnWin() && mpNextPortion && !mpNextPortion->Width() )
1098  mpNextPortion->PrePaint( rInf, this );
1099 
1100  const sal_Int32 nCount = m_aExpand.getLength();
1101  if( !nCount )
1102  return;
1103  OSL_ENSURE( nCount < 7, "Too much combined characters" );
1104 
1105  // the first character of the second row
1106  const sal_Int32 nTop = ( nCount + 1 ) / 2;
1107 
1108  SwFont aTmpFont( *rInf.GetFont() );
1109  aTmpFont.SetProportion( nProportion ); // a smaller font
1110  SwFontSave aFontSave( rInf, &aTmpFont );
1111 
1112  Point aOldPos = rInf.GetPos();
1113  Point aOutPos( aOldPos.X(), aOldPos.Y() - nUpPos );// Y of the first row
1114  for( sal_Int32 i = 0 ; i < nCount; ++i )
1115  {
1116  if( i == nTop ) // change the row
1117  aOutPos.setY( aOldPos.Y() + nLowPos ); // Y of the second row
1118  aOutPos.setX( aOldPos.X() + aPos[i] ); // X position
1119  const SwFontScript nAct = aScrType[i]; // script type
1120  aTmpFont.SetActual( nAct );
1121 
1122  // if there're more than 4 characters to display, we choose fonts
1123  // with 2/3 of the original font width.
1124  if( aWidth[ nAct ] )
1125  {
1126  Size aTmpSz = aTmpFont.GetSize( nAct );
1127  if( aTmpSz.Width() != aWidth[ nAct ] )
1128  {
1129  aTmpSz.setWidth( aWidth[ nAct ] );
1130  aTmpFont.SetSize( aTmpSz, nAct );
1131  }
1132  }
1133  const_cast<SwTextPaintInfo&>(rInf).SetPos( aOutPos );
1134  rInf.DrawText(m_aExpand, *this, TextFrameIndex(i), TextFrameIndex(1));
1135  }
1136  // rInf is const, so we have to take back our manipulations
1137  const_cast<SwTextPaintInfo&>(rInf).SetPos( aOldPos );
1138 
1139 }
1140 
1142 {
1143  const sal_Int32 nCount = m_aExpand.getLength();
1144  if( !nCount )
1145  {
1146  Width( 0 );
1147  return false;
1148  }
1149 
1150  OSL_ENSURE( nCount < 7, "Too much combined characters" );
1151 
1152  // If there are leading "weak"-scripttyped characters in this portion,
1153  // they get the actual scripttype.
1154  for( sal_Int32 i = 0; i < nCount && SW_SCRIPTS == aScrType[i]; ++i )
1155  aScrType[i] = rInf.GetFont()->GetActual();
1156  if( nCount > 4 )
1157  {
1158  // more than four? Ok, then we need the 2/3 font width
1159  for( sal_Int32 i = 0; i < m_aExpand.getLength(); ++i )
1160  {
1161  OSL_ENSURE( aScrType[i] < SW_SCRIPTS, "Combined: Script fault" );
1162  if( !aWidth[ aScrType[i] ] )
1163  {
1164  rInf.GetOut()->SetFont( rInf.GetFont()->GetFnt( aScrType[i] ) );
1165  aWidth[ aScrType[i] ] =
1166  static_cast<sal_uInt16>(2 * rInf.GetOut()->GetFontMetric().GetFontSize().Width() / 3);
1167  }
1168  }
1169  }
1170 
1171  const sal_Int32 nTop = ( nCount + 1 ) / 2; // the first character of the second line
1172  SwViewShell *pSh = rInf.GetTextFrame()->getRootFrame()->GetCurrShell();
1173  SwFont aTmpFont( *rInf.GetFont() );
1174  SwFontSave aFontSave( rInf, &aTmpFont );
1175  nProportion = 55;
1176  // In nMainAscent/Descent we store the ascent and descent
1177  // of the original surrounding font
1178  sal_uInt16 nMaxDescent, nMaxAscent, nMaxWidth;
1179  sal_uInt16 nMainDescent = rInf.GetFont()->GetHeight( pSh, *rInf.GetOut() );
1180  const sal_uInt16 nMainAscent = rInf.GetFont()->GetAscent( pSh, *rInf.GetOut() );
1181  nMainDescent = nMainDescent - nMainAscent;
1182  // we start with a 50% font, but if we notice that the combined portion
1183  // becomes bigger than the surrounding font, we check 45% and maybe 40%.
1184  do
1185  {
1186  nProportion -= 5;
1187  aTmpFont.SetProportion( nProportion );
1188  memset( &aPos, 0, sizeof(aPos) );
1189  nMaxDescent = 0;
1190  nMaxAscent = 0;
1191  nMaxWidth = 0;
1192  nUpPos = nLowPos = 0;
1193 
1194  // Now we get the width of all characters.
1195  // The ascent and the width of the first line are stored in the
1196  // ascent member of the portion, the descent in nLowPos.
1197  // The ascent, descent and width of the second line are stored in the
1198  // local nMaxAscent, nMaxDescent and nMaxWidth variables.
1199  for( sal_Int32 i = 0; i < nCount; ++i )
1200  {
1201  SwFontScript nScrp = aScrType[i];
1202  aTmpFont.SetActual( nScrp );
1203  if( aWidth[ nScrp ] )
1204  {
1205  Size aFontSize( aTmpFont.GetSize( nScrp ) );
1206  aFontSize.setWidth( aWidth[ nScrp ] );
1207  aTmpFont.SetSize( aFontSize, nScrp );
1208  }
1209 
1210  SwDrawTextInfo aDrawInf(pSh, *rInf.GetOut(), m_aExpand, i, 1);
1211  Size aSize = aTmpFont.GetTextSize_( aDrawInf );
1212  const sal_uInt16 nAsc = aTmpFont.GetAscent( pSh, *rInf.GetOut() );
1213  aPos[ i ] = static_cast<sal_uInt16>(aSize.Width());
1214  if( i == nTop ) // enter the second line
1215  {
1216  nLowPos = nMaxDescent;
1217  Height( nMaxDescent + nMaxAscent );
1218  Width( nMaxWidth );
1219  SetAscent( nMaxAscent );
1220  nMaxAscent = 0;
1221  nMaxDescent = 0;
1222  nMaxWidth = 0;
1223  }
1224  nMaxWidth = nMaxWidth + aPos[ i ];
1225  if( nAsc > nMaxAscent )
1226  nMaxAscent = nAsc;
1227  if( aSize.Height() - nAsc > nMaxDescent )
1228  nMaxDescent = static_cast<sal_uInt16>(aSize.Height() - nAsc);
1229  }
1230  // for one or two characters we double the width of the portion
1231  if( nCount < 3 )
1232  {
1233  nMaxWidth *= 2;
1234  Width( 2*Width() );
1235  if( nCount < 2 )
1236  {
1237  Height( nMaxAscent + nMaxDescent );
1238  nLowPos = nMaxDescent;
1239  }
1240  }
1241  Height( Height() + nMaxDescent + nMaxAscent );
1242  nUpPos = nMaxAscent;
1243  SetAscent( Height() - nMaxDescent - nLowPos );
1244  } while( nProportion > 40 && ( GetAscent() > nMainAscent ||
1245  Height() - GetAscent() > nMainDescent ) );
1246  // if the combined portion is smaller than the surrounding text,
1247  // the portion grows. This looks better, if there's a character background.
1248  if( GetAscent() < nMainAscent )
1249  {
1250  Height( Height() + nMainAscent - GetAscent() );
1251  SetAscent( nMainAscent );
1252  }
1253  if( Height() < nMainAscent + nMainDescent )
1254  Height( nMainAscent + nMainDescent );
1255 
1256  // We calculate the x positions of the characters in both lines...
1257  sal_uInt16 nTopDiff = 0;
1258  sal_uInt16 nBotDiff = 0;
1259  if( nMaxWidth > Width() )
1260  {
1261  nTopDiff = ( nMaxWidth - Width() ) / 2;
1262  Width( nMaxWidth );
1263  }
1264  else
1265  nBotDiff = ( Width() - nMaxWidth ) / 2;
1266  switch( nTop)
1267  {
1268  case 3: aPos[1] = aPos[0] + nTopDiff;
1269  [[fallthrough]];
1270  case 2: aPos[nTop-1] = Width() - aPos[nTop-1];
1271  }
1272  aPos[0] = 0;
1273  switch( nCount )
1274  {
1275  case 5: aPos[4] = aPos[3] + nBotDiff;
1276  [[fallthrough]];
1277  case 3: aPos[nTop] = nBotDiff; break;
1278  case 6: aPos[4] = aPos[3] + nBotDiff;
1279  [[fallthrough]];
1280  case 4: aPos[nTop] = 0;
1281  [[fallthrough]];
1282  case 2: aPos[nCount-1] = Width() - aPos[nCount-1];
1283  }
1284 
1285  // Does the combined portion fit the line?
1286  const bool bFull = rInf.Width() < rInf.X() + Width();
1287  if( bFull )
1288  {
1289  if( rInf.GetLineStart() == rInf.GetIdx() && (!rInf.GetLast()->InFieldGrp()
1290  || !static_cast<SwFieldPortion*>(rInf.GetLast())->IsFollow() ) )
1291  Width( static_cast<sal_uInt16>( rInf.Width() - rInf.X() ) );
1292  else
1293  {
1294  Truncate();
1295  Width( 0 );
1296  SetLen(TextFrameIndex(0));
1297  if( rInf.GetLast() )
1298  rInf.GetLast()->FormatEOL( rInf );
1299  }
1300  }
1301  return bFull;
1302 }
1303 
1304 sal_uInt16 SwCombinedPortion::GetViewWidth( const SwTextSizeInfo &rInf ) const
1305 {
1306  if( !GetLen() ) // for the dummy part at the end of the line, where
1307  return 0; // the combined portion doesn't fit.
1308  return SwFieldPortion::GetViewWidth( rInf );
1309 }
1310 
1311 SwFieldPortion *SwFieldFormDropDownPortion::Clone(const OUString &rExpand) const
1312 {
1313  return new SwFieldFormDropDownPortion(m_pFieldMark, rExpand);
1314 }
1315 
1317 {
1318  SwFieldPortion::Paint( rInf );
1319 
1320  ::sw::mark::DropDownFieldmark* pDropDownField = dynamic_cast< ::sw::mark::DropDownFieldmark* >(m_pFieldMark);
1321  if(pDropDownField)
1322  {
1323  SwRect aPaintArea;
1324  rInf.CalcRect( *this, &aPaintArea );
1325  pDropDownField->SetPortionPaintArea(aPaintArea);
1326  }
1327 }
1328 
1329 SwFieldPortion *SwFieldFormDatePortion::Clone(const OUString &/*rExpand*/) const
1330 {
1332 }
1333 
1335 {
1336  SwFieldPortion::Paint( rInf );
1337 
1338  ::sw::mark::DateFieldmark* pDateField = dynamic_cast< ::sw::mark::DateFieldmark* >(m_pFieldMark);
1339  if(pDateField)
1340  {
1341  SwRect aPaintArea;
1342  rInf.CalcRect( *this, &aPaintArea );
1343  if(m_bStart)
1344  pDateField->SetPortionPaintAreaStart(aPaintArea);
1345  else
1346  pDateField->SetPortionPaintAreaEnd(aPaintArea);
1347  }
1348 }
1349 
1350 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
Fieldmark representing a date form field.
Definition: bookmrk.hxx:308
OutDevType GetOutDevType() const
SwFieldPortion(const SwFieldPortion &rField)
Definition: porfld.cxx:87
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
SwNumberPortion(const OUString &rExpand, std::unique_ptr< SwFont > pFnt, const bool bLeft, const bool bCenter, const sal_uInt16 nMinDst, const bool bLabelAlignmentPosAndSpaceModeActive)
Definition: porfld.cxx:495
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:151
bool m_bFollow
Definition: porfld.hxx:39
SwViewShell * GetVsh()
Definition: inftxt.hxx:228
void DrawBackBrush(const SwLinePortion &rPor) const
Definition: inftxt.cxx:1154
bool IsGrfNumPortion() const
Definition: porlin.hxx:111
bool IsPagePreview() const
Definition: viewopt.hxx:608
bool m_bNoPaint
Definition: porfld.hxx:45
void DrawGraphic(const SvxBrushItem *, vcl::RenderContext *, const SwRect &rOrg, const SwRect &rOut, const sal_uInt8 nGrfNum=GRFNUM_NO, const bool bConsiderBackgroundTransparency=false)
Definition: paintfrm.cxx:1810
void StopAnimation(OutputDevice *pOut)
Stops the animations within numberings.
Definition: porfld.cxx:1034
sal_uInt16 Height() const
Definition: possiz.hxx:44
SwFont * GetFont()
Definition: inftxt.hxx:238
SwLineLayout * GetNext()
Definition: porlay.hxx:143
const SwAccessibilityOptions * GetAccessibilityOptions() const
Definition: viewsh.hxx:434
OUTDEV_VIRDEV
bool IsAnimated() const
Definition: porfld.hxx:181
bool InNumberGrp() const
Definition: porlin.hxx:102
bool HasPara() const
Definition: txtfrm.hxx:814
SwTwips GetRelPos() const
Definition: porfld.hxx:186
void SetCenter(bool bNew)
Definition: porfld.hxx:86
long Height() const
bool IsGraphic() const
Definition: viewopt.hxx:306
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porexp.cxx:64
bool HasFont() const
Definition: porfld.hxx:62
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:471
#define SW_SCRIPTS
Definition: swfont.hxx:128
The SwPortionHandler interface implements a visitor for the layout engine's text portions.
bool IsCenter() const
Definition: porfld.hxx:85
TextFrameIndex GetUnderScorePos() const
Definition: inftxt.hxx:647
SwTwips Left() const
Definition: inftxt.hxx:548
virtual bool Format(SwTextFormatInfo &rInf) override
We can create multiple NumFields Tricky, if one enters enough previous-text in the dialog box to caus...
Definition: porfld.cxx:533
TextFrameIndex ScanPortionEnd(TextFrameIndex nStart, TextFrameIndex nEnd)
Definition: inftxt.cxx:1632
bool IsNumDone() const
Definition: inftxt.hxx:635
sal_uInt16 GetTextHeight() const
Definition: inftxt.hxx:719
SwParaPortion * GetPara()
Definition: txtcache.cxx:89
sal_uInt16 m_nViewWidth
Definition: porfld.hxx:38
sal_Int16 nId
#define CHAR_HARDBLANK
Definition: swtypes.hxx:172
void SetLen(TextFrameIndex const nLen)
Definition: porlin.hxx:75
sw::mark::IFieldmark * m_pFieldMark
Definition: porfld.hxx:250
std::unique_ptr< SwFont > m_pFont
Definition: porfld.hxx:35
void DrawText(const OUString &rText, const SwLinePortion &rPor, TextFrameIndex nIdx=TextFrameIndex(0), TextFrameIndex nLen=TextFrameIndex(COMPLETE_STRING), const bool bKern=false) const
Definition: inftxt.hxx:747
void SetAnimation() const
Definition: txtfrm.hxx:526
void NoteAnimation() const
Definition: inftxt.cxx:373
FontStrikeout GetStrikeout() const
Definition: swfont.hxx:275
std::unique_ptr< SvxBrushItem > pBrush
Definition: porfld.hxx:157
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
bool InFieldGrp() const
Definition: porlin.hxx:104
virtual SvxBrushItem * Clone(SfxItemPool *pPool=nullptr) const override
void SetPortionPaintAreaEnd(const SwRect &rPortionPaintArea)
Definition: bookmrk.cxx:754
SwPosSize GetTextSize(OutputDevice *pOut, const SwScriptInfo *pSI, const OUString &rText, TextFrameIndex nIdx, TextFrameIndex nLen) const
Definition: inftxt.cxx:382
sal_uInt8 nProportion
Definition: porfld.hxx:206
bool IsMulti() const
Definition: inftxt.hxx:210
sal_uInt8 DirType(const TextFrameIndex nPos) const
Definition: porlay.cxx:1649
sal_uInt16 ForcedLeftMargin() const
Definition: inftxt.hxx:557
SwFontScript aScrType[6]
Definition: porfld.hxx:203
void SetHookChar(const sal_Unicode cNew)
Definition: inftxt.hxx:627
virtual SwFieldPortion * Clone(const OUString &rExpand) const override
Definition: porfld.cxx:1329
virtual SwLinePortion * Compress()
Definition: porlin.cxx:56
virtual ~SwFieldPortion() override
Definition: porfld.cxx:111
#define CHAR_SOFTHYPHEN
Definition: swtypes.hxx:174
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:170
sal_uInt16 sal_Unicode
bool IsReadonly() const
Definition: viewopt.hxx:436
SwTwips GetGrfHeight() const
Definition: porfld.hxx:187
#define CH_TXTATR_INWORD
Definition: hintids.hxx:171
virtual ~SwGrfNumPortion() override
Definition: porfld.cxx:792
#define GRFNUM_YES
Definition: frmtool.hxx:55
LINESTYLE_NONE
void SetFollow(bool bNew)
Definition: porfld.hxx:77
sal_uInt16 GetAscent(SwViewShell const *pSh, const OutputDevice &rOut)
Definition: swfont.hxx:326
void SetHasFollow(bool bNew)
Definition: porfld.hxx:89
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
int nCount
FontMetric GetFontMetric() const
const Graphic * GetGraphic(OUString const &referer=OUString()) const
SwTwips nYPos
Definition: porfld.hxx:159
virtual bool Format(SwTextFormatInfo &rInf) override
Definition: portxt.cxx:438
void StopAnimation(OutputDevice *pOutputDevice, long nExtraData)
virtual bool GetExpText(const SwTextSizeInfo &rInf, OUString &rText) const override
Definition: porfld.cxx:441
TextFrameIndex GetLineStart() const
Definition: inftxt.hxx:596
bool m_bNoLength
Definition: porfld.hxx:48
sal_Int16 GetOrient() const
Definition: porfld.hxx:188
bool IsAnimated() const
SwFontScript GetActual() const
Definition: swfont.hxx:183
virtual bool Format(SwTextFormatInfo &rInf) override
We can create multiple NumFields Tricky, if one enters enough previous-text in the dialog box to caus...
Definition: porfld.cxx:813
void SetNumDone(const bool bNew)
Definition: inftxt.hxx:636
SwTwips Y() const
Definition: inftxt.hxx:387
virtual void Special(TextFrameIndex nLength, const OUString &rText, PortionType nType, sal_Int32 nHeight=0, sal_Int32 nWidth=0, const SwFont *pFont=nullptr)=0
special portion.
virtual SwFieldPortion * Clone(const OUString &rExpand) const override
Definition: porfld.cxx:1311
SwTwips First() const
Definition: inftxt.hxx:552
SwCombinedPortion(const OUString &rExpand)
Initializes the script array and clears the width array.
Definition: porfld.cxx:1060
SwGrfNumPortion(const OUString &rGraphicFollowedBy, const SvxBrushItem *pGrfBrush, OUString const &referer, const SwFormatVertOrient *pGrfOrient, const Size &rGrfSize, const bool bLeft, const bool bCenter, const sal_uInt16 nMinDst, const bool bLabelAlignmentPosAndSpaceModeActive)
Definition: porfld.cxx:753
void CheckScript(const SwTextSizeInfo &rInf)
Definition: porfld.cxx:195
const SwViewOption & GetOpt() const
Definition: inftxt.hxx:245
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1290
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porfld.cxx:1087
void SetAnimated(bool bNew)
Definition: porfld.hxx:182
bool IsFootnoteNumPortion() const
Definition: porlin.hxx:119
void SetLeft(bool bNew)
Definition: porfld.hxx:80
sal_uInt16 nAscent
Definition: porlin.hxx:57
void SetRelPos(SwTwips nNew)
Definition: porfld.hxx:183
int i
virtual bool GetExpText(const SwTextSizeInfo &rInf, OUString &rText) const override
Definition: porfld.cxx:489
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:78
void SetBase(long nLnAscent, long nLnDescent, long nFlyAscent, long nFlyDescent)
Definition: porfld.cxx:998
sal_uInt16 nMinDist
Definition: porfld.hxx:124
const Point & GetPos() const
Definition: swfont.hxx:975
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porfld.cxx:1316
void TakeNextOffset(const SwFieldPortion *pField)
Definition: porfld.cxx:67
bool IsHide() const
Definition: porfld.hxx:82
vcl::RenderContext * GetOut()
Definition: inftxt.hxx:231
const sal_Unicode CH_TAB
Definition: swfont.hxx:44
TextFrameIndex m_nNextOffset
Definition: porfld.hxx:36
SwParaPortion * GetParaPortion()
Definition: inftxt.hxx:128
void SetWhichPor(const PortionType nNew)
Definition: porlin.hxx:94
bool IsFlyPortion() const
Definition: porlin.hxx:125
bool IsPreview() const
Definition: viewsh.hxx:491
FontLineStyle GetOverline() const
Definition: swfont.hxx:273
long GetHeight() const
Definition: swfont.hxx:283
bool IsNumberPortion() const
Definition: porlin.hxx:135
sal_uInt16 GetTopBorderSpace() const
Definition: swfont.hxx:863
bool HasArea() const
Definition: swrect.hxx:288
SwFieldFormDatePortion(sw::mark::IFieldmark *pFieldMark, bool bStart)
Definition: porfld.hxx:238
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porfld.cxx:1334
virtual SwFieldPortion * Clone(const OUString &rExpand) const override
Definition: porfld.cxx:471
void CalcRect(const SwLinePortion &rPor, SwRect *pRect, SwRect *pIntersect=nullptr, const bool bInsideBox=false) const
Calculate the rectangular area where the portion takes place.
Definition: inftxt.cxx:752
sal_uInt16 Width() const
Definition: inftxt.hxx:534
const Size & GetFontSize() const
TextFrameIndex m_nNextScriptChg
Definition: porfld.hxx:37
void SetUnderScorePos(TextFrameIndex const nNew)
Definition: inftxt.hxx:648
#define CHAR_ZWSP
Definition: swtypes.hxx:177
bool IsLeft() const
Definition: porfld.hxx:79
TextFrameIndex GetIdx() const
Definition: inftxt.hxx:278
void StartAnimation(OutputDevice *pOutDev, const Point &rDestPt, const Size &rDestSize, long nExtraData=0, OutputDevice *pFirstFrameOutDev=nullptr)
virtual SwLinePortion * Compress() override
Definition: porfld.cxx:49
virtual bool Format(SwTextFormatInfo &rInf) override
Definition: porfld.cxx:1141
OUString m_aExpand
Definition: porfld.hxx:34
virtual void HandlePortion(SwPortionHandler &rPH) const override
Definition: porfld.cxx:452
void SetPortionPaintAreaStart(const SwRect &rPortionPaintArea)
Definition: bookmrk.cxx:745
void PrePaint(const SwTextPaintInfo &rInf, const SwLinePortion *pLast) const
Definition: porlin.cxx:76
bool mbLabelAlignmentPosAndSpaceModeActive
Definition: porfld.hxx:125
static bool IsFieldShadings()
Definition: viewopt.hxx:644
virtual TextFrameIndex GetModelPositionForViewPoint(sal_uInt16 nOfst) const override
the parameter is actually SwTwips apparently?
Definition: porfld.cxx:512
sal_uInt16 nFixWidth
Definition: porfld.hxx:123
TextFrameIndex GetLen() const
Definition: porlin.hxx:74
#define GRFNUM_SECURE
Definition: porfld.cxx:751
void SetPos(const Point &rPoint)
Definition: swfont.hxx:978
SwHiddenPortion(const OUString &rExpand, std::unique_ptr< SwFont > pFntL=nullptr)
Definition: porfld.hxx:110
SwTextFrame * GetTextFrame()
Definition: inftxt.hxx:291
void InvalidateWindows(const SwRect &rRect)
Definition: viewsh.cxx:541
const OUString & GetText() const
Definition: inftxt.hxx:246
void SetHide(bool bNew)
Definition: porfld.hxx:83
const SwLinePortion * GetUnderflow() const
Definition: inftxt.hxx:605
SwUnderlineFont * GetUnderFnt() const
Definition: inftxt.hxx:243
void Truncate()
Definition: porlin.hxx:196
SwLinePortion * mpNextPortion
Definition: porlin.hxx:54
const Point & GetPos() const
Definition: inftxt.hxx:435
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:62
FontLineStyle GetUnderline() const
Definition: swfont.hxx:271
SwTwips X() const
Definition: inftxt.hxx:385
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:50
virtual void FormatEOL(SwTextFormatInfo &rInf) override
A FormatEOL indicates that the subsequent text did not fit onto the line anymore. ...
Definition: porfld.cxx:609
virtual bool Format(SwTextFormatInfo &rInf) override
Definition: porfld.cxx:292
#define CHAR_HARDHYPHEN
Definition: swtypes.hxx:173
constexpr TypedWhichId< SvxBrushItem > RES_BACKGROUND(105)
void SetLen(const TextFrameIndex nNew)
Definition: inftxt.hxx:281
For the text replacement and restoration of SwTextSizeInfo.
Definition: inftxt.hxx:680
virtual sal_uInt16 GetViewWidth(const SwTextSizeInfo &rInf) const override
Definition: porfld.cxx:116
unsigned char sal_uInt8
PortionType GetWhichPor() const
Definition: porlin.hxx:95
sw::mark::IFieldmark * m_pFieldMark
Definition: porfld.hxx:232
bool IsFootnotePortion() const
Definition: porlin.hxx:120
vcl::Window * GetWin() const
Definition: viewsh.hxx:340
SwTwips GetPos() const
Definition: fmtornt.hxx:59
void SetFont(const vcl::Font &rNewFont)
SwLinePortion * GetRest()
Definition: inftxt.hxx:582
bool IsFollow() const
Definition: porfld.hxx:76
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:175
bool OnWin() const
Definition: inftxt.hxx:199
bool IsRightToLeft() const
Definition: frame.hxx:965
TextFrameIndex GetLen() const
Definition: inftxt.hxx:280
sal_uInt16 GetBottomBorderSpace() const
Definition: swfont.hxx:878
const SwFont * GetFont() const
Definition: porfld.hxx:64
SwTwips nGrfHeight
Definition: porfld.hxx:160
sal_Int16 eOrient
Definition: porfld.hxx:161
bool HasFollow() const
Definition: porfld.hxx:88
o3tl::enumarray< SwFontScript, sal_uInt16 > aWidth
Definition: porfld.hxx:202
void SetFont(std::unique_ptr< SwFont > pNew)
Definition: porfld.hxx:50
#define GRFNUM_REPLACE
Definition: frmtool.hxx:56
void SetLineStart(TextFrameIndex const nNew)
Definition: inftxt.hxx:597
bool HasAnimation() const
Definition: txtfrm.hxx:528
bool InTextGrp() const
Definition: porlin.hxx:98
sal_uInt16 Width() const
Definition: possiz.hxx:46
SwBulletPortion(const sal_Unicode cCh, const OUString &rBulletFollowedBy, std::unique_ptr< SwFont > pFnt, const bool bLeft, const bool bCenter, const sal_uInt16 nMinDst, const bool bLabelAlignmentPosAndSpaceModeActive)
Definition: porfld.cxx:737
void SetPortionPaintArea(const SwRect &rPortionPaintArea)
Definition: bookmrk.cxx:680
SwScriptInfo & GetScriptInfo()
Definition: porlay.hxx:270
SwFontScript
Definition: swfont.hxx:122
sal_Int16 GetVertOrient() const
Definition: fmtornt.hxx:54
SwLinePortion * GetLast()
Definition: inftxt.hxx:567
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porfld.cxx:479
#define CHAR_ZWNBSP
Definition: swtypes.hxx:178
SwFieldFormDropDownPortion(sw::mark::IFieldmark *pFieldMark, const OUString &rExpand)
Definition: porfld.hxx:221
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porfld.cxx:428
sal_uInt16 nUpPos
Definition: porfld.hxx:204
virtual SwPosSize GetTextSize(const SwTextSizeInfo &rInfo) const override
Definition: porfld.cxx:464
virtual void Paint(const SwTextPaintInfo &rInf) const override
A hidden NumberPortion is not displayed, unless there are TextPortions in this line or there's only o...
Definition: porfld.cxx:878
virtual sal_uInt16 GetViewWidth(const SwTextSizeInfo &rInf) const override
Definition: porfld.cxx:1304
void SetAscent(const sal_uInt16 nNewAsc)
Definition: porlin.hxx:79
void SetNextOffset(TextFrameIndex nNew)
Definition: porfld.hxx:92
sal_uInt16 nLowPos
Definition: porfld.hxx:205
bool m_bReplace
Definition: porfld.hxx:46
SwDoc & GetDoc()
Definition: txtfrm.hxx:452
const SwRect & GetPaintRect() const
Definition: inftxt.hxx:438
virtual SwFieldPortion * Clone(const OUString &rExpand) const
Definition: porfld.cxx:52
virtual SwFieldPortion * Clone(const OUString &rExpand) const override
Definition: porfld.cxx:517
bool IsWordLineMode() const
Definition: swfont.hxx:277
sal_uInt8 GetDefaultDir() const
Definition: scriptinfo.hxx:123
STRIKEOUT_NONE
virtual void FormatEOL(SwTextFormatInfo &rInf)
Definition: porlin.cxx:265
bool IsQuoVadisPortion() const
Definition: porlin.hxx:116
void SetProportion(const sal_uInt8 nNewPropr)
Definition: swfont.hxx:765
SwFlyPortion * GetFly()
Definition: inftxt.hxx:615
bool IsOver(const SwRect &rRect) const
Definition: swrect.cxx:123
virtual void Paint(const SwTextPaintInfo &rInf) const override
A hidden NumberPortion is not displayed, unless there are TextPortions in this line or there's just o...
Definition: porfld.cxx:624
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:72
const bool m_bPlaceHolder
Definition: porfld.hxx:47
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:204
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...
void SetRest(SwLinePortion *pNewRest)
Definition: inftxt.hxx:583
void setWidth(long nWidth)
virtual SwPosSize GetTextSize(const SwTextSizeInfo &rInfo) const override
Definition: porexp.cxx:41
TextFrameIndex GetNextOffset() const
Definition: porfld.hxx:91
void SetId(long nNew) const
Definition: porfld.hxx:184
Fieldmark representing a drop-down form field.
Definition: bookmrk.hxx:291
sal_uInt16 & GetAscent()
Definition: porlin.hxx:77
sal_uInt16 aPos[6]
Definition: porfld.hxx:201
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
SwRootFrame * getRootFrame()
Definition: frame.hxx:659
void DrawViewOpt(const SwLinePortion &rPor, PortionType nWhich) const
Definition: inftxt.cxx:1313
const SvxFont & GetFnt(const SwFontScript nWhich) const
Definition: swfont.hxx:266
void StopAnimation(OutputDevice *pOut)
Definition: porfld.cxx:803
sal_uInt16 GetAscent() const
Definition: inftxt.hxx:713
bool IsShowPlaceHolderFields() const
Definition: viewopt.hxx:614
void SetNotEOL(const bool bNew)
Definition: inftxt.hxx:202