LibreOffice Module sw (master)  1
itrform2.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 <memory>
23 #include <com/sun/star/i18n/ScriptType.hpp>
24 #include <editeng/lspcitem.hxx>
25 #include <txtflcnt.hxx>
26 #include <txtftn.hxx>
27 #include <flyfrms.hxx>
28 #include <fmtflcnt.hxx>
29 #include <fmtftn.hxx>
30 #include <ftninfo.hxx>
31 #include <charfmt.hxx>
33 #include <layfrm.hxx>
34 #include <viewsh.hxx>
35 #include <viewopt.hxx>
36 #include <paratr.hxx>
37 #include "itrform2.hxx"
38 #include "porrst.hxx"
39 #include "portab.hxx"
40 #include "porfly.hxx"
41 #include "portox.hxx"
42 #include "porref.hxx"
43 #include "porfld.hxx"
44 #include "porftn.hxx"
45 #include "porhyph.hxx"
46 #include "pordrop.hxx"
47 #include <blink.hxx>
48 #include "redlnitr.hxx"
49 #include <pagefrm.hxx>
50 #include <tgrditem.hxx>
51 #include <doc.hxx>
52 #include "pormulti.hxx"
53 #include <unotools/charclass.hxx>
54 #include <xmloff/odffields.hxx>
56 #include <IMark.hxx>
57 #include <IDocumentMarkAccess.hxx>
58 
59 #include <vector>
60 
61 using namespace ::com::sun::star;
62 
63 namespace {
65  long lcl_CalcOptRepaint( SwTextFormatter &rThis,
66  SwLineLayout const &rCurr,
67  TextFrameIndex nOldLineEnd,
68  const std::vector<long> &rFlyStarts );
70  bool lcl_BuildHiddenPortion(const SwTextSizeInfo& rInf, TextFrameIndex &rPos);
71 
72  // Check whether the two font has the same border
73  bool lcl_HasSameBorder(const SwFont& rFirst, const SwFont& rSecond);
74 }
75 
76 static void ClearFly( SwTextFormatInfo &rInf )
77 {
78  delete rInf.GetFly();
79  rInf.SetFly(nullptr);
80 }
81 
83 {
84  CtorInitTextPainter( pNewFrame, pNewInf );
85  m_pInf = pNewInf;
87  m_pMulti = nullptr;
88 
89  m_bOnceMore = false;
90  m_bFlyInContentBase = false;
91  m_bTruncLines = false;
96  m_pByEndIter.reset();
97  m_pFirstOfBorderMerge = nullptr;
98 
99  if (m_nStart > TextFrameIndex(GetInfo().GetText().getLength()))
100  {
101  OSL_ENSURE( false, "+SwTextFormatter::CTOR: bad offset" );
102  m_nStart = TextFrameIndex(GetInfo().GetText().getLength());
103  }
104 
105 }
106 
108 {
109  // Extremely unlikely, but still possible
110  // e.g.: field splits up, widows start to matter
111  if( GetInfo().GetRest() )
112  {
113  delete GetInfo().GetRest();
114  GetInfo().SetRest(nullptr);
115  }
116 }
117 
119 {
120  // Insert BEHIND the current element
121  if ( m_pCurr )
122  {
123  pLay->SetNext( m_pCurr->GetNext() );
124  m_pCurr->SetNext( pLay );
125  }
126  else
127  m_pCurr = pLay;
128 }
129 
131 {
132  // We want the rest height relative to the page.
133  // If we're in a table, then pFrame->GetUpper() is not the page.
134 
135  // GetFrameRstHeight() is being called with Footnote.
136  // Wrong: const SwFrame *pUpper = pFrame->GetUpper();
137  const SwFrame *pPage = m_pFrame->FindPageFrame();
138  const SwTwips nHeight = pPage->getFrameArea().Top()
139  + pPage->getFramePrintArea().Top()
140  + pPage->getFramePrintArea().Height() - Y();
141  if( 0 > nHeight )
142  return m_pCurr->Height();
143  else
144  return sal_uInt16( nHeight );
145 }
146 
148 {
149  // Save values and initialize rInf
150  SwLinePortion *pUnderflow = rInf.GetUnderflow();
151  if( !pUnderflow )
152  return nullptr;
153 
154  // We format backwards, i.e. attribute changes can happen the next
155  // line again.
156  // Can be seen in 8081.sdw, if you enter text in the first line
157 
158  TextFrameIndex const nSoftHyphPos = rInf.GetSoftHyphPos();
159  TextFrameIndex const nUnderScorePos = rInf.GetUnderScorePos();
160 
161  // Save flys and set to 0, or else segmentation fault
162  // Not ClearFly(rInf) !
163  SwFlyPortion *pFly = rInf.GetFly();
164  rInf.SetFly( nullptr );
165 
166  FeedInf( rInf );
167  rInf.SetLast( m_pCurr );
168  // pUnderflow does not need to be deleted, because it will drown in the following
169  // Truncate()
170  rInf.SetUnderflow(nullptr);
171  rInf.SetSoftHyphPos( nSoftHyphPos );
172  rInf.SetUnderScorePos( nUnderScorePos );
173  rInf.SetPaintOfst( GetLeftMargin() );
174 
175  // We look for the portion with the under-flow position
177  if( pPor != pUnderflow )
178  {
179  // pPrev will be the last portion before pUnderflow,
180  // which still has a real width.
181  // Exception: SoftHyphPortion must not be forgotten, of course!
182  // Although they don't have a width.
183  SwLinePortion *pTmpPrev = pPor;
184  while( pPor && pPor != pUnderflow )
185  {
186  if( !pPor->IsKernPortion() &&
187  ( pPor->Width() || pPor->IsSoftHyphPortion() ) )
188  {
189  while( pTmpPrev != pPor )
190  {
191  pTmpPrev->Move( rInf );
192  rInf.SetLast( pTmpPrev );
193  pTmpPrev = pTmpPrev->GetNextPortion();
194  OSL_ENSURE( pTmpPrev, "Underflow: losing control!" );
195  };
196  }
197  pPor = pPor->GetNextPortion();
198  }
199  pPor = pTmpPrev;
200  if( pPor && // Skip flys and initials when underflow.
201  ( pPor->IsFlyPortion() || pPor->IsDropPortion() ||
202  pPor->IsFlyCntPortion() ) )
203  {
204  pPor->Move( rInf );
205  rInf.SetLast( pPor );
206  rInf.SetStopUnderflow( true );
207  pPor = pUnderflow;
208  }
209  }
210 
211  // What? The under-flow portion is not in the portion chain?
212  OSL_ENSURE( pPor, "SwTextFormatter::Underflow: overflow but underflow" );
213 
214  // Snapshot
215  if ( pPor==rInf.GetLast() )
216  {
217  // We end up here, if the portion triggering the under-flow
218  // spans over the whole line. E.g. if a word spans across
219  // multiple lines and flows into a fly in the second line.
220  rInf.SetFly( pFly );
221  pPor->Truncate();
222  return pPor; // Is that enough?
223  }
224  // End the snapshot
225 
226  // X + Width == 0 with SoftHyph > Line?!
227  if( !pPor || !(rInf.X() + pPor->Width()) )
228  {
229  delete pFly;
230  return nullptr;
231  }
232 
233  // Preparing for Format()
234  // We need to chip off the chain behind pLast, because we Insert after the Format()
235  SeekAndChg( rInf );
236 
237  // line width is adjusted, so that pPor does not fit to current
238  // line anymore
239  rInf.Width( static_cast<sal_uInt16>(rInf.X() + (pPor->Width() ? pPor->Width() - 1 : 0)) );
240  rInf.SetLen( pPor->GetLen() );
241  rInf.SetFull( false );
242  if( pFly )
243  {
244  // We need to recalculate the FlyPortion due to the following reason:
245  // If the base line is lowered by a big font in the middle of the line,
246  // causing overlapping with a fly, the FlyPortion has a wrong size/fixed
247  // size.
248  rInf.SetFly( pFly );
249  CalcFlyWidth( rInf );
250  }
251  rInf.GetLast()->SetNextPortion(nullptr);
252 
253  // The SwLineLayout is an exception to this, which splits at the first
254  // portion change.
255  // Here only the other way around:
256  if( rInf.GetLast() == m_pCurr )
257  {
258  if( pPor->InTextGrp() && !pPor->InExpGrp() )
259  {
260  const PortionType nOldWhich = m_pCurr->GetWhichPor();
261  *static_cast<SwLinePortion*>(m_pCurr) = *pPor;
263  m_pCurr->SetWhichPor( nOldWhich );
264  pPor->SetNextPortion( nullptr );
265  delete pPor;
266  pPor = m_pCurr;
267  }
268  }
269 
270  // Make sure that m_pFirstOfBorderMerge does not point to a portion which
271  // will be deleted by Truncate() below.
272  SwLinePortion* pNext = pPor->GetNextPortion();
273  while (pNext)
274  {
275  if (pNext == m_pFirstOfBorderMerge)
276  {
277  m_pFirstOfBorderMerge = nullptr;
278  break;
279  }
280  pNext = pNext->GetNextPortion();
281  }
282  pPor->Truncate();
283  SwLinePortion *const pRest( rInf.GetRest() );
284  if (pRest && pRest->InFieldGrp() &&
285  static_cast<SwFieldPortion*>(pRest)->IsNoLength())
286  {
287  // HACK: decrement again, so we pick up the suffix in next line!
288  m_pByEndIter->PrevAttr();
289  }
290  delete pRest;
291  rInf.SetRest(nullptr);
292  return pPor;
293 }
294 
296  SwLinePortion *pPor )
297 {
298  SwLinePortion *pLast = nullptr;
299  // The new portion is inserted, but everything's different for
300  // LineLayout...
301  if( pPor == m_pCurr )
302  {
303  if ( m_pCurr->GetNextPortion() )
304  {
305  pLast = pPor;
306  pPor = m_pCurr->GetNextPortion();
307  }
308 
309  // i#112181 - Prevent footnote anchor being wrapped to next line
310  // without preceding word
312  }
313  else
314  {
315  pLast = rInf.GetLast();
316  if( pLast->GetNextPortion() )
317  {
318  while( pLast->GetNextPortion() )
319  pLast = pLast->GetNextPortion();
320  rInf.SetLast( pLast );
321  }
322  pLast->Insert( pPor );
323 
325 
326  // Adjust maxima
327  if( m_pCurr->Height() < pPor->Height() )
328  m_pCurr->Height( pPor->Height() );
329  if( m_pCurr->GetAscent() < pPor->GetAscent() )
330  m_pCurr->SetAscent( pPor->GetAscent() );
331  }
332 
333  // Sometimes chains are constructed (e.g. by hyphenate)
334  rInf.SetLast( pPor );
335  while( pPor )
336  {
337  if (!pPor->IsDropPortion())
338  MergeCharacterBorder(*pPor, pLast, rInf);
339 
340  pPor->Move( rInf );
341  rInf.SetLast( pPor );
342  pLast = pPor;
343  pPor = pPor->GetNextPortion();
344  }
345 }
346 
348 {
349  OSL_ENSURE( rInf.GetText().getLength() < COMPLETE_STRING,
350  "SwTextFormatter::BuildPortions: bad text length in info" );
351 
352  rInf.ChkNoHyph( CntEndHyph(), CntMidHyph() );
353 
354  // First NewTextPortion() decides whether pCurr ends up in pPor.
355  // We need to make sure that the font is being set in any case.
356  // This is done automatically in CalcAscent.
357  rInf.SetLast( m_pCurr );
358  rInf.ForcedLeftMargin( 0 );
359 
360  OSL_ENSURE( m_pCurr->FindLastPortion() == m_pCurr, "pLast supposed to equal pCurr" );
361 
362  if( !m_pCurr->GetAscent() && !m_pCurr->Height() )
363  CalcAscent( rInf, m_pCurr );
364 
365  SeekAndChg( rInf );
366 
367  // Width() is shortened in CalcFlyWidth if we have a FlyPortion
368  OSL_ENSURE( !rInf.X() || m_pMulti, "SwTextFormatter::BuildPortion X=0?" );
369  CalcFlyWidth( rInf );
370  SwFlyPortion *pFly = rInf.GetFly();
371  if( pFly )
372  {
373  if ( 0 < pFly->GetFix() )
374  ClearFly( rInf );
375  else
376  rInf.SetFull(true);
377  }
378 
379  SwLinePortion *pPor = NewPortion( rInf );
380 
381  // Asian grid stuff
382  SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
383  const bool bHasGrid = pGrid && rInf.SnapToGrid() &&
384  GRID_LINES_CHARS == pGrid->GetGridType();
385 
386 
387  const SwDoc & rDoc = rInf.GetTextFrame()->GetDoc();
388  const sal_uInt16 nGridWidth = bHasGrid ? GetGridWidth(*pGrid, rDoc) : 0;
389 
390  // used for grid mode only:
391  // the pointer is stored, because after formatting of non-asian text,
392  // the width of the kerning portion has to be adjusted
393  // Inserting a SwKernPortion before a SwTabPortion isn't necessary
394  // and will break the SwTabPortion.
395  SwKernPortion* pGridKernPortion = nullptr;
396 
397  bool bFull = false;
398  SwTwips nUnderLineStart = 0;
399  rInf.Y( Y() );
400 
401  while( pPor && !rInf.IsStop() )
402  {
403  OSL_ENSURE(rInf.GetLen() < TextFrameIndex(COMPLETE_STRING) &&
404  rInf.GetIdx() <= TextFrameIndex(rInf.GetText().getLength()),
405  "SwTextFormatter::BuildPortions: bad length in info" );
406 
407  // We have to check the script for fields in order to set the
408  // correct nActual value for the font.
409  if( pPor->InFieldGrp() )
410  static_cast<SwFieldPortion*>(pPor)->CheckScript( rInf );
411 
412  if( ! bHasGrid && rInf.HasScriptSpace() &&
413  rInf.GetLast() && rInf.GetLast()->InTextGrp() &&
414  rInf.GetLast()->Width() && !rInf.GetLast()->InNumberGrp() )
415  {
416  SwFontScript nNxtActual = rInf.GetFont()->GetActual();
417  SwFontScript nLstActual = nNxtActual;
418  sal_uInt16 nLstHeight = static_cast<sal_uInt16>(rInf.GetFont()->GetHeight());
419  bool bAllowBehind = false;
420  const CharClass& rCC = GetAppCharClass();
421 
422  // are there any punctuation characters on both sides
423  // of the kerning portion?
424  if ( pPor->InFieldGrp() )
425  {
426  OUString aAltText;
427  if ( static_cast<SwFieldPortion*>(pPor)->GetExpText( rInf, aAltText ) &&
428  !aAltText.isEmpty() )
429  {
430  bAllowBehind = rCC.isLetterNumeric( aAltText, 0 );
431 
432  const SwFont* pTmpFnt = static_cast<SwFieldPortion*>(pPor)->GetFont();
433  if ( pTmpFnt )
434  nNxtActual = pTmpFnt->GetActual();
435  }
436  }
437  else
438  {
439  const OUString& rText = rInf.GetText();
440  sal_Int32 nIdx = sal_Int32(rInf.GetIdx());
441  bAllowBehind = nIdx < rText.getLength() && rCC.isLetterNumeric(rText, nIdx);
442  }
443 
444  const SwLinePortion* pLast = rInf.GetLast();
445  if ( bAllowBehind && pLast )
446  {
447  bool bAllowBefore = false;
448 
449  if ( pLast->InFieldGrp() )
450  {
451  OUString aAltText;
452  if ( static_cast<const SwFieldPortion*>(pLast)->GetExpText( rInf, aAltText ) &&
453  !aAltText.isEmpty() )
454  {
455  bAllowBefore = rCC.isLetterNumeric( aAltText, aAltText.getLength() - 1 );
456 
457  const SwFont* pTmpFnt = static_cast<const SwFieldPortion*>(pLast)->GetFont();
458  if ( pTmpFnt )
459  {
460  nLstActual = pTmpFnt->GetActual();
461  nLstHeight = static_cast<sal_uInt16>(pTmpFnt->GetHeight());
462  }
463  }
464  }
465  else if ( rInf.GetIdx() )
466  {
467  bAllowBefore = rCC.isLetterNumeric(rInf.GetText(), sal_Int32(rInf.GetIdx()) - 1);
468  // Note: ScriptType returns values in [1,4]
469  if ( bAllowBefore )
470  nLstActual = SwFontScript(m_pScriptInfo->ScriptType(rInf.GetIdx() - TextFrameIndex(1)) - 1);
471  }
472 
473  nLstHeight /= 5;
474  // does the kerning portion still fit into the line?
475  if( bAllowBefore && ( nLstActual != nNxtActual ) &&
476  nLstHeight && rInf.X() + nLstHeight <= rInf.Width() &&
477  ! pPor->InTabGrp() )
478  {
479  SwKernPortion* pKrn =
480  new SwKernPortion( *rInf.GetLast(), nLstHeight,
481  pLast->InFieldGrp() && pPor->InFieldGrp() );
482  rInf.GetLast()->SetNextPortion( nullptr );
483  InsertPortion( rInf, pKrn );
484  }
485  }
486  }
487  else if ( bHasGrid && pGrid->IsSnapToChars() && ! pGridKernPortion && ! m_pMulti && ! pPor->InTabGrp() )
488  {
489  // insert a grid kerning portion
490  pGridKernPortion = pPor->IsKernPortion() ?
491  static_cast<SwKernPortion*>(pPor) :
492  new SwKernPortion( *m_pCurr );
493 
494  // if we have a new GridKernPortion, we initially calculate
495  // its size so that its ends on the grid
496  const SwPageFrame* pPageFrame = m_pFrame->FindPageFrame();
497  const SwLayoutFrame* pBody = pPageFrame->FindBodyCont();
498  SwRectFnSet aRectFnSet(pPageFrame);
499 
500  const long nGridOrigin = pBody ?
501  aRectFnSet.GetPrtLeft(*pBody) :
502  aRectFnSet.GetPrtLeft(*pPageFrame);
503 
504  SwTwips nStartX = rInf.X() + GetLeftMargin();
505  if ( aRectFnSet.IsVert() )
506  {
507  Point aPoint( nStartX, 0 );
509  nStartX = aPoint.Y();
510  }
511 
512  const SwTwips nOfst = nStartX - nGridOrigin;
513  if ( nOfst )
514  {
515  const sal_uLong i = ( nOfst > 0 ) ?
516  ( ( nOfst - 1 ) / nGridWidth + 1 ) :
517  0;
518  const SwTwips nKernWidth = i * nGridWidth - nOfst;
519  const SwTwips nRestWidth = rInf.Width() - rInf.X();
520 
521  if ( nKernWidth <= nRestWidth )
522  pGridKernPortion->Width( static_cast<sal_uInt16>(nKernWidth) );
523  }
524 
525  if ( pGridKernPortion != pPor )
526  InsertPortion( rInf, pGridKernPortion );
527  }
528 
529  if( pPor->IsDropPortion() )
530  MergeCharacterBorder(*static_cast<SwDropPortion*>(pPor));
531 
532  // the multi-portion has its own format function
533  if( pPor->IsMultiPortion() && ( !m_pMulti || m_pMulti->IsBidi() ) )
534  bFull = BuildMultiPortion( rInf, *static_cast<SwMultiPortion*>(pPor) );
535  else
536  bFull = pPor->Format( rInf );
537 
538  if( rInf.IsRuby() && !rInf.GetRest() )
539  bFull = true;
540 
541  // if we are underlined, we store the beginning of this underlined
542  // segment for repaint optimization
543  if ( LINESTYLE_NONE != m_pFont->GetUnderline() && ! nUnderLineStart )
544  nUnderLineStart = GetLeftMargin() + rInf.X();
545 
546  if ( pPor->IsFlyPortion() )
547  m_pCurr->SetFly( true );
548  // some special cases, where we have to take care for the repaint
549  // offset:
550  // 1. Underlined portions due to special underline feature
551  // 2. Right Tab
552  // 3. BidiPortions
553  // 4. other Multiportions
554  // 5. DropCaps
555  // 6. Grid Mode
556  else if ( ( ! rInf.GetPaintOfst() || nUnderLineStart < rInf.GetPaintOfst() ) &&
557  // 1. Underlined portions
558  nUnderLineStart &&
559  // reformat is at end of an underlined portion and next portion
560  // is not underlined
561  ( ( rInf.GetReformatStart() == rInf.GetIdx() &&
563  ) ||
564  // reformat is inside portion and portion is underlined
565  ( rInf.GetReformatStart() >= rInf.GetIdx() &&
566  rInf.GetReformatStart() <= rInf.GetIdx() + pPor->GetLen() &&
568  rInf.SetPaintOfst( nUnderLineStart );
569  else if ( ! rInf.GetPaintOfst() &&
570  // 2. Right Tab
571  ( ( pPor->InTabGrp() && !pPor->IsTabLeftPortion() ) ||
572  // 3. BidiPortions
573  ( pPor->IsMultiPortion() && static_cast<SwMultiPortion*>(pPor)->IsBidi() ) ||
574  // 4. Multi Portion and 5. Drop Caps
575  ( ( pPor->IsDropPortion() || pPor->IsMultiPortion() ) &&
576  rInf.GetReformatStart() >= rInf.GetIdx() &&
577  rInf.GetReformatStart() <= rInf.GetIdx() + pPor->GetLen() )
578  // 6. Grid Mode
579  || ( bHasGrid && SwFontScript::CJK != m_pFont->GetActual() )
580  )
581  )
582  // we store the beginning of the critical portion as our
583  // paint offset
584  rInf.SetPaintOfst( GetLeftMargin() + rInf.X() );
585 
586  // under one of these conditions we are allowed to delete the
587  // start of the underline portion
588  if ( IsUnderlineBreak( *pPor, *m_pFont ) )
589  nUnderLineStart = 0;
590 
591  if( pPor->IsFlyCntPortion() || ( pPor->IsMultiPortion() &&
592  static_cast<SwMultiPortion*>(pPor)->HasFlyInContent() ) )
593  SetFlyInCntBase();
594  // bUnderflow needs to be reset or we wrap again at the next softhyphen
595  if ( !bFull )
596  {
597  rInf.ClrUnderflow();
598  if( ! bHasGrid && rInf.HasScriptSpace() && pPor->InTextGrp() &&
599  pPor->GetLen() && !pPor->InFieldGrp() )
600  {
601  // The distance between two different scripts is set
602  // to 20% of the fontheight.
603  TextFrameIndex const nTmp = rInf.GetIdx() + pPor->GetLen();
604  if (nTmp == m_pScriptInfo->NextScriptChg(nTmp - TextFrameIndex(1)) &&
605  nTmp != TextFrameIndex(rInf.GetText().getLength()) &&
606  (m_pScriptInfo->ScriptType(nTmp - TextFrameIndex(1)) == css::i18n::ScriptType::ASIAN ||
607  m_pScriptInfo->ScriptType(nTmp) == css::i18n::ScriptType::ASIAN) )
608  {
609  const sal_uInt16 nDist = static_cast<sal_uInt16>(rInf.GetFont()->GetHeight()/5);
610 
611  if( nDist )
612  {
613  // we do not want a kerning portion if any end
614  // would be a punctuation character
615  const CharClass& rCC = GetAppCharClass();
616  if (rCC.isLetterNumeric(rInf.GetText(), sal_Int32(nTmp) - 1)
617  && rCC.isLetterNumeric(rInf.GetText(), sal_Int32(nTmp)))
618  {
619  // does the kerning portion still fit into the line?
620  if ( rInf.X() + pPor->Width() + nDist <= rInf.Width() )
621  new SwKernPortion( *pPor, nDist );
622  else
623  bFull = true;
624  }
625  }
626  }
627  }
628  }
629 
630  if ( bHasGrid && pGrid->IsSnapToChars() && pPor != pGridKernPortion && ! m_pMulti && ! pPor->InTabGrp() )
631  {
632  TextFrameIndex const nTmp = rInf.GetIdx() + pPor->GetLen();
633  const SwTwips nRestWidth = rInf.Width() - rInf.X() - pPor->Width();
634 
635  const SwFontScript nCurrScript = m_pFont->GetActual(); // pScriptInfo->ScriptType( rInf.GetIdx() );
636  const SwFontScript nNextScript =
637  nTmp >= TextFrameIndex(rInf.GetText().getLength())
639  : m_pScriptInfo->WhichFont(nTmp);
640 
641  // snap non-asian text to grid if next portion is ASIAN or
642  // there are no more portions in this line
643  // be careful when handling an underflow event: the gridkernportion
644  // could have been deleted
645  if ( nRestWidth > 0 && SwFontScript::CJK != nCurrScript &&
646  ! rInf.IsUnderflow() && ( bFull || SwFontScript::CJK == nNextScript ) )
647  {
648  OSL_ENSURE( pGridKernPortion, "No GridKernPortion available" );
649 
650  // calculate size
651  SwLinePortion* pTmpPor = pGridKernPortion->GetNextPortion();
652  sal_uInt16 nSumWidth = pPor->Width();
653  while ( pTmpPor )
654  {
655  nSumWidth = nSumWidth + pTmpPor->Width();
656  pTmpPor = pTmpPor->GetNextPortion();
657  }
658 
659  const SwTwips i = nSumWidth ?
660  ( nSumWidth - 1 ) / nGridWidth + 1 :
661  0;
662  const SwTwips nTmpWidth = i * nGridWidth;
663  const SwTwips nKernWidth = std::min(nTmpWidth - nSumWidth, nRestWidth);
664  const sal_uInt16 nKernWidth_1 = static_cast<sal_uInt16>(nKernWidth / 2);
665 
666  OSL_ENSURE( nKernWidth <= nRestWidth,
667  "Not enough space left for adjusting non-asian text in grid mode" );
668 
669  pGridKernPortion->Width( pGridKernPortion->Width() + nKernWidth_1 );
670  rInf.X( rInf.X() + nKernWidth_1 );
671 
672  if ( ! bFull )
673  new SwKernPortion( *pPor, static_cast<short>(nKernWidth - nKernWidth_1),
674  false, true );
675 
676  pGridKernPortion = nullptr;
677  }
678  else if ( pPor->IsMultiPortion() || pPor->InFixMargGrp() ||
679  pPor->IsFlyCntPortion() || pPor->InNumberGrp() ||
680  pPor->InFieldGrp() || nCurrScript != nNextScript )
681  // next portion should snap to grid
682  pGridKernPortion = nullptr;
683  }
684 
685  rInf.SetFull( bFull );
686 
687  // Restportions from fields with multiple lines don't yet have the right ascent
688  if ( !pPor->GetLen() && !pPor->IsFlyPortion()
689  && !pPor->IsGrfNumPortion() && ! pPor->InNumberGrp()
690  && !pPor->IsMultiPortion() )
691  CalcAscent( rInf, pPor );
692 
693  InsertPortion( rInf, pPor );
694  if (pPor->IsMultiPortion() && (!m_pMulti || m_pMulti->IsBidi()))
695  {
696  (void) rInf.CheckCurrentPosBookmark(); // bookmark was already created inside MultiPortion!
697  }
698  pPor = NewPortion( rInf );
699  }
700 
701  if( !rInf.IsStop() )
702  {
703  // The last right centered, decimal tab
704  SwTabPortion *pLastTab = rInf.GetLastTab();
705  if( pLastTab )
706  pLastTab->FormatEOL( rInf );
707  else if( rInf.GetLast() && rInf.LastKernPortion() )
708  rInf.GetLast()->FormatEOL( rInf );
709  }
711  && static_cast<SwNumberPortion*>(m_pCurr->GetNextPortion())->IsHide() )
712  rInf.SetNumDone( false );
713 
714  // Delete fly in any case
715  ClearFly( rInf );
716 
717  // Reinit the tab overflow flag after the line
718  rInf.SetTabOverflow( false );
719 }
720 
722 {
723  if( SvxAdjust::Left != GetAdjust() && !m_pMulti)
724  {
725  pCurrent->SetFormatAdj(true);
726  if( IsFlyInCntBase() )
727  {
728  CalcAdjLine( pCurrent );
729  // For e.g. centered fly we need to switch the RefPoint
730  // That's why bAlways = true
731  UpdatePos( pCurrent, GetTopLeft(), GetStart(), true );
732  }
733  }
734 }
735 
737 {
738  bool bCalc = false;
739  if ( pPor->InFieldGrp() && static_cast<SwFieldPortion*>(pPor)->GetFont() )
740  {
741  // Numbering + InterNetFields can keep an own font, then their size is
742  // independent from hard attribute values
743  SwFont* pFieldFnt = static_cast<SwFieldPortion*>(pPor)->m_pFont.get();
744  SwFontSave aSave( rInf, pFieldFnt );
745  pPor->Height( rInf.GetTextHeight() );
746  pPor->SetAscent( rInf.GetAscent() );
747  bCalc = true;
748  }
749  // i#89179
750  // tab portion representing the list tab of a list label gets the
751  // same height and ascent as the corresponding number portion
752  else if ( pPor->InTabGrp() && pPor->GetLen() == TextFrameIndex(0) &&
753  rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
754  static_cast<const SwNumberPortion*>(rInf.GetLast())->HasFont() )
755  {
756  const SwLinePortion* pLast = rInf.GetLast();
757  pPor->Height( pLast->Height() );
758  pPor->SetAscent( pLast->GetAscent() );
759  }
760  else if (pPor->GetWhichPor() == PortionType::Bookmark
761  && rInf.GetIdx() == TextFrameIndex(rInf.GetText().getLength()))
762  {
763  // bookmark at end of paragraph: *don't* advance iterator, use the
764  // current font instead; it's possible that there's a font size on the
765  // paragraph and it's overridden on the last line of the paragraph and
766  // we don't want to apply it via SwBookmarkPortion and grow the line
767  // height (example: n758883.docx)
768  SwLinePortion const*const pLast = rInf.GetLast();
769  assert(pLast);
770  pPor->Height( pLast->Height() );
771  pPor->SetAscent( pLast->GetAscent() );
772  }
773  else
774  {
775  const SwLinePortion *pLast = rInf.GetLast();
776  bool bChg = false;
777 
778  // In empty lines the attributes are switched on via SeekStart
779  const bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
780  if ( pPor->IsQuoVadisPortion() )
781  bChg = SeekStartAndChg( rInf, true );
782  else
783  {
784  if( bFirstPor )
785  {
786  if( !rInf.GetText().isEmpty() )
787  {
788  if ( pPor->GetLen() || !rInf.GetIdx()
789  || ( m_pCurr != pLast && !pLast->IsFlyPortion() )
790  || !m_pCurr->IsRest() ) // instead of !rInf.GetRest()
791  bChg = SeekAndChg( rInf );
792  else
793  bChg = SeekAndChgBefore( rInf );
794  }
795  else if ( m_pMulti )
796  // do not open attributes starting at 0 in empty multi
797  // portions (rotated numbering followed by a footnote
798  // can cause trouble, because the footnote attribute
799  // starts at 0, but if we open it, the attribute handler
800  // cannot handle it.
801  bChg = false;
802  else
803  bChg = SeekStartAndChg( rInf );
804  }
805  else
806  bChg = SeekAndChg( rInf );
807  }
808  if( bChg || bFirstPor || !pPor->GetAscent()
809  || !rInf.GetLast()->InTextGrp() )
810  {
811  pPor->SetAscent( rInf.GetAscent() );
812  pPor->Height( rInf.GetTextHeight() );
813  bCalc = true;
814  }
815  else
816  {
817  pPor->Height( pLast->Height() );
818  pPor->SetAscent( pLast->GetAscent() );
819  }
820  }
821 
822  if( pPor->InTextGrp() && bCalc )
823  {
824  pPor->SetAscent(pPor->GetAscent() +
825  rInf.GetFont()->GetTopBorderSpace());
826  pPor->Height(pPor->Height() +
827  rInf.GetFont()->GetTopBorderSpace() +
828  rInf.GetFont()->GetBottomBorderSpace() );
829  }
830 }
831 
832 namespace {
833 
834 class SwMetaPortion : public SwTextPortion
835 {
836 public:
837  SwMetaPortion() { SetWhichPor( PortionType::Meta ); }
838  virtual void Paint( const SwTextPaintInfo &rInf ) const override;
839 };
840 
841 }
842 
843 void SwMetaPortion::Paint( const SwTextPaintInfo &rInf ) const
844 {
845  if ( Width() )
846  {
847  rInf.DrawViewOpt( *this, PortionType::Meta );
848  SwTextPortion::Paint( rInf );
849  }
850 }
851 
852 namespace sw::mark {
854  {
855  const IFieldmark::parameter_map_t* const pParameters = pBM->GetParameters();
856  sal_Int32 nCurrentIdx = 0;
857  const IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find(OUString(ODF_FORMDROPDOWN_RESULT));
858  if(pResult != pParameters->end())
859  pResult->second >>= nCurrentIdx;
860 
861  const IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(OUString(ODF_FORMDROPDOWN_LISTENTRY));
862  if (pListEntries != pParameters->end())
863  {
864  uno::Sequence< OUString > vListEntries;
865  pListEntries->second >>= vListEntries;
866  if (nCurrentIdx < vListEntries.getLength())
867  return vListEntries[nCurrentIdx];
868  }
869 
870  static const sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
871  return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH);
872  }
873 }
874 
876 {
877  SwTextPortion *pPor = nullptr;
878  if( GetFnt()->IsTox() )
879  {
880  pPor = new SwToxPortion;
881  }
882  else if ( GetFnt()->IsInputField() )
883  {
884  pPor = new SwTextInputFieldPortion();
885  }
886  else
887  {
888  if( GetFnt()->IsRef() )
889  pPor = new SwRefPortion;
890  else if (GetFnt()->IsMeta())
891  {
892  pPor = new SwMetaPortion;
893  }
894  else
895  {
896  // Only at the End!
897  // If pCurr does not have a width, it can however already have content.
898  // E.g. for non-displayable characters
899 
900  auto const ch(rInf.GetText()[sal_Int32(rInf.GetIdx())]);
901  SwTextFrame const*const pFrame(rInf.GetTextFrame());
902  SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx()));
903  sw::mark::IFieldmark *pBM = pFrame->GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
904  if(pBM != nullptr && pBM->GetFieldname( ) == ODF_FORMDATE)
905  {
906  if (ch == CH_TXT_ATR_FIELDSTART)
907  pPor = new SwFieldFormDatePortion(pBM, true);
908  else if (ch == CH_TXT_ATR_FIELDSEP)
909  pPor = new SwFieldMarkPortion(); // it's added in DateFieldmark?
910  else if (ch == CH_TXT_ATR_FIELDEND)
911  pPor = new SwFieldFormDatePortion(pBM, false);
912  }
913  else if (ch == CH_TXT_ATR_FIELDSTART)
914  pPor = new SwFieldMarkPortion();
915  else if (ch == CH_TXT_ATR_FIELDSEP)
916  pPor = new SwFieldMarkPortion();
917  else if (ch == CH_TXT_ATR_FIELDEND)
918  pPor = new SwFieldMarkPortion();
919  else if (ch == CH_TXT_ATR_FORMELEMENT)
920  {
921  OSL_ENSURE(pBM != nullptr, "Where is my form field bookmark???");
922  if (pBM != nullptr)
923  {
924  if (pBM->GetFieldname( ) == ODF_FORMCHECKBOX)
925  {
926  pPor = new SwFieldFormCheckboxPortion();
927  }
928  else if (pBM->GetFieldname( ) == ODF_FORMDROPDOWN)
929  {
931  }
932  /* we need to check for ODF_FORMTEXT for scenario having FormFields inside FORMTEXT.
933  * Otherwise file will crash on open.
934  */
935  else if (pBM->GetFieldname( ) == ODF_FORMTEXT)
936  {
937  pPor = new SwFieldMarkPortion();
938  }
939  }
940  }
941  if( !pPor )
942  {
943  if( !rInf.X() && !m_pCurr->GetNextPortion() && !m_pCurr->GetLen() )
944  pPor = m_pCurr;
945  else
946  pPor = new SwTextPortion;
947  }
948  }
949  }
950  return pPor;
951 }
952 
953 // We calculate the length, the following portion limits are defined:
954 // 1) Tabs
955 // 2) Linebreaks
956 // 3) CH_TXTATR_BREAKWORD / CH_TXTATR_INWORD
957 // 4) next attribute change
958 
960 {
961  // If we're at the line's beginning, we take pCurr
962  // If pCurr is not derived from SwTextPortion, we need to duplicate
963  Seek( rInf.GetIdx() );
964  SwTextPortion *pPor = WhichTextPor( rInf );
965 
966  // until next attribute change:
967  const TextFrameIndex nNextAttr = GetNextAttr();
968  TextFrameIndex nNextChg = std::min(nNextAttr, TextFrameIndex(rInf.GetText().getLength()));
969 
970  // end of script type:
971  const TextFrameIndex nNextScript = m_pScriptInfo->NextScriptChg(rInf.GetIdx());
972  nNextChg = std::min( nNextChg, nNextScript );
973 
974  // end of direction:
975  const TextFrameIndex nNextDir = m_pScriptInfo->NextDirChg(rInf.GetIdx());
976  nNextChg = std::min( nNextChg, nNextDir );
977 
978  // hidden change (potentially via bookmark):
979  const TextFrameIndex nNextHidden = m_pScriptInfo->NextHiddenChg(rInf.GetIdx());
980  nNextChg = std::min( nNextChg, nNextHidden );
981 
982  // bookmarks
983  const TextFrameIndex nNextBookmark = m_pScriptInfo->NextBookmark(rInf.GetIdx());
984  nNextChg = std::min(nNextChg, nNextBookmark);
985 
986  // Turbo boost:
987  // We assume that font characters are not larger than twice
988  // as wide as height.
989  // Very crazy: we need to take the ascent into account.
990 
991  // Mind the trap! GetSize() contains the wished-for height, the real height
992  // is only known in CalcAscent!
993 
994  // The ratio is even crazier: a blank in Times New Roman has an ascent of
995  // 182, a height of 200 and a width of 53!
996  // It follows that a line with a lot of blanks is processed incorrectly.
997  // Therefore we increase from factor 2 to 8 (due to negative kerning).
998 
999  pPor->SetLen(TextFrameIndex(1));
1000  CalcAscent( rInf, pPor );
1001 
1002  const SwFont* pTmpFnt = rInf.GetFont();
1003  sal_Int32 nExpect = std::min( sal_Int32( pTmpFnt->GetHeight() ),
1004  sal_Int32( pPor->GetAscent() ) ) / 8;
1005  if ( !nExpect )
1006  nExpect = 1;
1007  nExpect = sal_Int32(rInf.GetIdx()) + (rInf.GetLineWidth() / nExpect);
1008  if (TextFrameIndex(nExpect) > rInf.GetIdx() && nNextChg > TextFrameIndex(nExpect))
1009  nNextChg = TextFrameIndex(std::min(nExpect, rInf.GetText().getLength()));
1010 
1011  // we keep an invariant during method calls:
1012  // there are no portion ending characters like hard spaces
1013  // or tabs in [ nLeftScanIdx, nRightScanIdx ]
1014  if ( m_nLeftScanIdx <= rInf.GetIdx() && rInf.GetIdx() <= m_nRightScanIdx )
1015  {
1016  if ( nNextChg > m_nRightScanIdx )
1017  nNextChg = m_nRightScanIdx =
1018  rInf.ScanPortionEnd( m_nRightScanIdx, nNextChg );
1019  }
1020  else
1021  {
1022  m_nLeftScanIdx = rInf.GetIdx();
1023  nNextChg = m_nRightScanIdx =
1024  rInf.ScanPortionEnd( rInf.GetIdx(), nNextChg );
1025  }
1026 
1027  pPor->SetLen( nNextChg - rInf.GetIdx() );
1028  rInf.SetLen( pPor->GetLen() );
1029  return pPor;
1030 }
1031 
1032 // first portions have no length
1034 {
1035  SwLinePortion *pPor = nullptr;
1036 
1037  if( rInf.GetRest() )
1038  {
1039  // Tabs and fields
1040  if( '\0' != rInf.GetHookChar() )
1041  return nullptr;
1042 
1043  pPor = rInf.GetRest();
1044  if( pPor->IsErgoSumPortion() )
1045  rInf.SetErgoDone(true);
1046  else
1047  if( pPor->IsFootnoteNumPortion() )
1048  rInf.SetFootnoteDone(true);
1049  else
1050  if( pPor->InNumberGrp() )
1051  rInf.SetNumDone(true);
1052 
1053  rInf.SetRest(nullptr);
1054  m_pCurr->SetRest( true );
1055  return pPor;
1056  }
1057 
1058  // We can stand in the follow, it's crucial that
1059  // pFrame->GetOffset() == 0!
1060  if( rInf.GetIdx() )
1061  {
1062  // We now too can elongate FootnotePortions and ErgoSumPortions
1063 
1064  // 1. The ErgoSumTexts
1065  if( !rInf.IsErgoDone() )
1066  {
1067  if( m_pFrame->IsInFootnote() && !m_pFrame->GetIndPrev() )
1068  pPor = NewErgoSumPortion( rInf );
1069  rInf.SetErgoDone( true );
1070  }
1071 
1072  // 2. Arrow portions
1073  if( !pPor && !rInf.IsArrowDone() )
1074  {
1075  if( m_pFrame->GetOffset() && !m_pFrame->IsFollow() &&
1076  rInf.GetIdx() == m_pFrame->GetOffset() )
1077  pPor = new SwArrowPortion( *m_pCurr );
1078  rInf.SetArrowDone( true );
1079  }
1080 
1081  // 3. Kerning portions at beginning of line in grid mode
1082  if ( ! pPor && ! m_pCurr->GetNextPortion() )
1083  {
1084  SwTextGridItem const*const pGrid(
1085  GetGridItem(GetTextFrame()->FindPageFrame()));
1086  if ( pGrid )
1087  pPor = new SwKernPortion( *m_pCurr );
1088  }
1089 
1090  // 4. The line rests (multiline fields)
1091  if( !pPor )
1092  {
1093  pPor = rInf.GetRest();
1094  // Only for pPor of course
1095  if( pPor )
1096  {
1097  m_pCurr->SetRest( true );
1098  rInf.SetRest(nullptr);
1099  }
1100  }
1101  }
1102  else
1103  {
1104  // 5. The foot note count
1105  if( !rInf.IsFootnoteDone() )
1106  {
1107  OSL_ENSURE( ( ! rInf.IsMulti() && ! m_pMulti ) || m_pMulti->HasRotation(),
1108  "Rotated number portion trouble" );
1109 
1110  const bool bFootnoteNum = m_pFrame->IsFootnoteNumFrame();
1111  rInf.GetParaPortion()->SetFootnoteNum( bFootnoteNum );
1112  if( bFootnoteNum )
1113  pPor = NewFootnoteNumPortion( rInf );
1114  rInf.SetFootnoteDone( true );
1115  }
1116 
1117  // 6. The ErgoSumTexts of course also exist in the TextMaster,
1118  // it's crucial whether the SwFootnoteFrame is aFollow
1119  if( !rInf.IsErgoDone() && !pPor && ! rInf.IsMulti() )
1120  {
1121  if( m_pFrame->IsInFootnote() && !m_pFrame->GetIndPrev() )
1122  pPor = NewErgoSumPortion( rInf );
1123  rInf.SetErgoDone( true );
1124  }
1125 
1126  // 7. The numbering
1127  if( !rInf.IsNumDone() && !pPor )
1128  {
1129  OSL_ENSURE( ( ! rInf.IsMulti() && ! m_pMulti ) || m_pMulti->HasRotation(),
1130  "Rotated number portion trouble" );
1131 
1132  // If we're in the follow, then of course not
1134  pPor = NewNumberPortion( rInf );
1135  rInf.SetNumDone( true );
1136  }
1137  // 8. The DropCaps
1138  if( !pPor && GetDropFormat() && ! rInf.IsMulti() )
1139  pPor = NewDropPortion( rInf );
1140 
1141  // 9. Kerning portions at beginning of line in grid mode
1142  if ( !pPor && !m_pCurr->GetNextPortion() )
1143  {
1144  SwTextGridItem const*const pGrid(
1145  GetGridItem(GetTextFrame()->FindPageFrame()));
1146  if ( pGrid )
1147  pPor = new SwKernPortion( *m_pCurr );
1148  }
1149  }
1150 
1151  // 10. Decimal tab portion at the beginning of each line in table cells
1152  if ( !pPor && !m_pCurr->GetNextPortion() &&
1153  GetTextFrame()->IsInTab() &&
1155  {
1156  pPor = NewTabPortion( rInf, true );
1157  }
1158 
1159  // 11. suffix of meta-field
1160  if (!pPor)
1161  {
1162  pPor = TryNewNoLengthPortion(rInf);
1163  }
1164 
1165  // 12. bookmarks
1166  // check this *last* so that BuildMultiPortion() can find it!
1167  if (!pPor && rInf.CheckCurrentPosBookmark())
1168  {
1169  auto const bookmark(m_pScriptInfo->GetBookmark(rInf.GetIdx()));
1170  if (static_cast<bool>(bookmark))
1171  {
1172  sal_Unicode mark;
1175  {
1176  //mark = u'\u2336'; // not in OpenSymbol :(
1177  mark = '|';
1178  // hmm ... paint U+2345 over U+2346 should be same width?
1179  // and U+237F // or U+2E20/U+2E21
1180  }
1181  else if (bookmark & SwScriptInfo::MarkKind::Start)
1182  {
1183  mark = '[';
1184  }
1185  else if (bookmark & SwScriptInfo::MarkKind::End)
1186  {
1187  mark = ']';
1188  }
1189  else
1190  {
1191  assert(bookmark & SwScriptInfo::MarkKind::Point);
1192  mark = '|';
1193  }
1194  pPor = new SwBookmarkPortion(rInf.GetLast(), mark);
1195  }
1196  }
1197 
1198  return pPor;
1199 }
1200 
1201 static bool lcl_OldFieldRest( const SwLineLayout* pCurr )
1202 {
1203  if( !pCurr->GetNext() )
1204  return false;
1205  const SwLinePortion *pPor = pCurr->GetNext()->GetNextPortion();
1206  bool bRet = false;
1207  while( pPor && !bRet )
1208  {
1209  bRet = (pPor->InFieldGrp() && static_cast<const SwFieldPortion*>(pPor)->IsFollow()) ||
1210  (pPor->IsMultiPortion() && static_cast<const SwMultiPortion*>(pPor)->IsFollowField());
1211  if( !pPor->GetLen() )
1212  break;
1213  pPor = pPor->GetNextPortion();
1214  }
1215  return bRet;
1216 }
1217 
1218 /* NewPortion sets rInf.nLen
1219  * A SwTextPortion is limited by a tab, break, txtatr or attr change
1220  * We can have three cases:
1221  * 1) The line is full and the wrap was not emulated
1222  * -> return 0;
1223  * 2) The line is full and a wrap was emulated
1224  * -> Reset width and return new FlyPortion
1225  * 3) We need to construct a new portion
1226  * -> CalcFlyWidth emulates the width and return portion, if needed
1227  */
1228 
1230 {
1231  // Underflow takes precedence
1232  rInf.SetStopUnderflow( false );
1233  if( rInf.GetUnderflow() )
1234  {
1235  OSL_ENSURE( rInf.IsFull(), "SwTextFormatter::NewPortion: underflow but not full" );
1236  return Underflow( rInf );
1237  }
1238 
1239  // If the line is full, flys and Underflow portions could be waiting ...
1240  if( rInf.IsFull() )
1241  {
1242  // LineBreaks and Flys (bug05.sdw)
1243  // IsDummy()
1244  if( rInf.IsNewLine() && (!rInf.GetFly() || !m_pCurr->IsDummy()) )
1245  return nullptr;
1246 
1247  // When the text bumps into the Fly, or when the Fly comes first because
1248  // it juts out over the left edge, GetFly() is returned.
1249  // When IsFull() and no GetFly() is available, naturally zero is returned.
1250  if( rInf.GetFly() )
1251  {
1252  if( rInf.GetLast()->IsBreakPortion() )
1253  {
1254  delete rInf.GetFly();
1255  rInf.SetFly( nullptr );
1256  }
1257 
1258  return rInf.GetFly();
1259  }
1260 
1261  // A nasty special case: A frame without wrap overlaps the Footnote area.
1262  // We must declare the Footnote portion as rest of line, so that
1263  // SwTextFrame::Format doesn't abort (the text mass already was formatted).
1264  if( rInf.GetRest() )
1265  rInf.SetNewLine( true );
1266  else
1267  {
1268  // When the next line begins with a rest of a field, but now no
1269  // rest remains, the line must definitely be formatted anew!
1270  if( lcl_OldFieldRest( GetCurr() ) )
1271  rInf.SetNewLine( true );
1272  else
1273  {
1274  SwLinePortion *pFirst = WhichFirstPortion( rInf );
1275  if( pFirst )
1276  {
1277  rInf.SetNewLine( true );
1278  if( pFirst->InNumberGrp() )
1279  rInf.SetNumDone( false) ;
1280  delete pFirst;
1281  }
1282  }
1283  }
1284 
1285  return nullptr;
1286  }
1287 
1288  SwLinePortion *pPor = WhichFirstPortion( rInf );
1289 
1290  // Check for Hidden Portion:
1291  if ( !pPor )
1292  {
1293  TextFrameIndex nEnd = rInf.GetIdx();
1294  if ( ::lcl_BuildHiddenPortion( rInf, nEnd ) )
1295  pPor = new SwHiddenTextPortion( nEnd - rInf.GetIdx() );
1296  }
1297 
1298  if( !pPor )
1299  {
1300  if( ( !m_pMulti || m_pMulti->IsBidi() ) &&
1301  // i#42734
1302  // No multi portion if there is a hook character waiting:
1303  ( !rInf.GetRest() || '\0' == rInf.GetHookChar() ) )
1304  {
1305  // We open a multiportion part, if we enter a multi-line part
1306  // of the paragraph.
1307  TextFrameIndex nEnd = rInf.GetIdx();
1308  std::unique_ptr<SwMultiCreator> pCreate = rInf.GetMultiCreator( nEnd, m_pMulti );
1309  if( pCreate )
1310  {
1311  SwMultiPortion* pTmp = nullptr;
1312 
1313  if ( SwMultiCreatorId::Bidi == pCreate->nId )
1314  pTmp = new SwBidiPortion( nEnd, pCreate->nLevel );
1315  else if ( SwMultiCreatorId::Ruby == pCreate->nId )
1316  {
1317  pTmp = new SwRubyPortion( *pCreate, *rInf.GetFont(),
1319  nEnd, TextFrameIndex(0), rInf );
1320  }
1321  else if( SwMultiCreatorId::Rotate == pCreate->nId )
1322  {
1323  pTmp = new SwRotatedPortion( *pCreate, nEnd,
1324  GetTextFrame()->IsRightToLeft() );
1326  }
1327  else
1328  pTmp = new SwDoubleLinePortion( *pCreate, nEnd );
1329 
1330  pCreate.reset();
1331  CalcFlyWidth( rInf );
1332 
1333  return pTmp;
1334  }
1335  }
1336  // Tabs and Fields
1337  sal_Unicode cChar = rInf.GetHookChar();
1338 
1339  if( cChar )
1340  {
1341  /* We fetch cChar again to be sure that the tab is pending now and
1342  * didn't move to the next line (as happens behind frames).
1343  * However, when a FieldPortion is in the rest, we must naturally fetch
1344  * the cChar from the field content, e.g. DecimalTabs and fields (22615)
1345  */
1346  if( !rInf.GetRest() || !rInf.GetRest()->InFieldGrp() )
1347  cChar = rInf.GetChar( rInf.GetIdx() );
1348  rInf.ClearHookChar();
1349  }
1350  else
1351  {
1352  if (rInf.GetIdx() >= TextFrameIndex(rInf.GetText().getLength()))
1353  {
1354  rInf.SetFull(true);
1355  CalcFlyWidth( rInf );
1356  return pPor;
1357  }
1358  cChar = rInf.GetChar( rInf.GetIdx() );
1359  }
1360 
1361  switch( cChar )
1362  {
1363  case CH_TAB:
1364  pPor = NewTabPortion( rInf, false ); break;
1365 
1366  case CH_BREAK:
1367  pPor = new SwBreakPortion( *rInf.GetLast() ); break;
1368 
1369  case CHAR_SOFTHYPHEN: // soft hyphen
1370  pPor = new SwSoftHyphPortion; break;
1371 
1372  case CHAR_HARDBLANK: // no-break space
1373  // Please check tdf#115067 if you want to edit the char
1374  pPor = new SwBlankPortion( cChar ); break;
1375 
1376  case CHAR_HARDHYPHEN: // non-breaking hyphen
1377  pPor = new SwBlankPortion( '-' ); break;
1378 
1379  case CHAR_ZWSP: // zero width space
1380  case CHAR_ZWNBSP : // word joiner
1381  pPor = new SwControlCharPortion( cChar ); break;
1382 
1383  case CH_TXTATR_BREAKWORD:
1384  case CH_TXTATR_INWORD:
1385  if( rInf.HasHint( rInf.GetIdx() ) )
1386  {
1387  pPor = NewExtraPortion( rInf );
1388  break;
1389  }
1390  [[fallthrough]];
1391  default :
1392  {
1393  SwTabPortion* pLastTabPortion = rInf.GetLastTab();
1394  if ( pLastTabPortion && cChar == rInf.GetTabDecimal() )
1395  {
1396  // Abandon dec. tab position if line is full
1397  // We have a decimal tab portion in the line and the next character has to be
1398  // aligned at the tab stop position. We store the width from the beginning of
1399  // the tab stop portion up to the portion containing the decimal separator:
1400  if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT) /*rInf.GetVsh()->IsTabCompat();*/ &&
1401  PortionType::TabDecimal == pLastTabPortion->GetWhichPor() )
1402  {
1403  OSL_ENSURE( rInf.X() >= pLastTabPortion->GetFix(), "Decimal tab stop position cannot be calculated" );
1404  const sal_uInt16 nWidthOfPortionsUpToDecimalPosition = static_cast<sal_uInt16>(rInf.X() - pLastTabPortion->GetFix() );
1405  static_cast<SwTabDecimalPortion*>(pLastTabPortion)->SetWidthOfPortionsUpToDecimalPosition( nWidthOfPortionsUpToDecimalPosition );
1406  rInf.SetTabDecimal( 0 );
1407  }
1408  else
1409  rInf.SetFull( rInf.GetLastTab()->Format( rInf ) );
1410  }
1411 
1412  if( rInf.GetRest() )
1413  {
1414  if( rInf.IsFull() )
1415  {
1416  rInf.SetNewLine(true);
1417  return nullptr;
1418  }
1419  pPor = rInf.GetRest();
1420  rInf.SetRest(nullptr);
1421  }
1422  else
1423  {
1424  if( rInf.IsFull() )
1425  return nullptr;
1426  pPor = NewTextPortion( rInf );
1427  }
1428  break;
1429  }
1430  }
1431 
1432  // if a portion is created despite there being a pending RestPortion,
1433  // then it is a field which has been split (e.g. because it contains a Tab)
1434  if( pPor && rInf.GetRest() )
1435  pPor->SetLen(TextFrameIndex(0));
1436 
1437  // robust:
1438  if( !pPor || rInf.IsStop() )
1439  {
1440  delete pPor;
1441  return nullptr;
1442  }
1443  }
1444 
1445  assert(pPor && "can only reach here with pPor existing");
1446 
1447  // Special portions containing numbers (footnote anchor, footnote number,
1448  // numbering) can be contained in a rotated portion, if the user
1449  // choose a rotated character attribute.
1450  if (!m_pMulti)
1451  {
1452  if ( pPor->IsFootnotePortion() )
1453  {
1454  const SwTextFootnote* pTextFootnote = static_cast<SwFootnotePortion*>(pPor)->GetTextFootnote();
1455 
1456  if ( pTextFootnote )
1457  {
1458  SwFormatFootnote& rFootnote = const_cast<SwFormatFootnote&>(pTextFootnote->GetFootnote());
1459  const SwDoc *const pDoc = &rInf.GetTextFrame()->GetDoc();
1460  const SwEndNoteInfo* pInfo;
1461  if( rFootnote.IsEndNote() )
1462  pInfo = &pDoc->GetEndNoteInfo();
1463  else
1464  pInfo = &pDoc->GetFootnoteInfo();
1465  const SwAttrSet& rSet = pInfo->GetAnchorCharFormat(const_cast<SwDoc&>(*pDoc))->GetAttrSet();
1466 
1467  const SfxPoolItem* pItem;
1468  sal_uInt16 nDir = 0;
1469  if( SfxItemState::SET == rSet.GetItemState( RES_CHRATR_ROTATE,
1470  true, &pItem ))
1471  nDir = static_cast<const SvxCharRotateItem*>(pItem)->GetValue();
1472 
1473  if ( 0 != nDir )
1474  {
1475  delete pPor;
1476  pPor = new SwRotatedPortion(rInf.GetIdx() + TextFrameIndex(1),
1477  900 == nDir
1478  ? DIR_BOTTOM2TOP
1479  : DIR_TOP2BOTTOM );
1480  }
1481  }
1482  }
1483  else if ( pPor->InNumberGrp() )
1484  {
1485  const SwFont* pNumFnt = static_cast<SwFieldPortion*>(pPor)->GetFont();
1486 
1487  if ( pNumFnt )
1488  {
1489  sal_uInt16 nDir = pNumFnt->GetOrientation( rInf.GetTextFrame()->IsVertical() );
1490  if ( 0 != nDir )
1491  {
1492  delete pPor;
1493  pPor = new SwRotatedPortion(TextFrameIndex(0), 900 == nDir
1494  ? DIR_BOTTOM2TOP
1495  : DIR_TOP2BOTTOM );
1496 
1497  rInf.SetNumDone( false );
1498  rInf.SetFootnoteDone( false );
1499  }
1500  }
1501  }
1502  }
1503 
1504  // The font is set in output device,
1505  // the ascent and the height will be calculated.
1506  if( !pPor->GetAscent() && !pPor->Height() )
1507  CalcAscent( rInf, pPor );
1508  rInf.SetLen( pPor->GetLen() );
1509 
1510  // In CalcFlyWidth Width() will be shortened if a FlyPortion is present.
1511  CalcFlyWidth( rInf );
1512 
1513  // One must not forget that pCurr as GetLast() must provide reasonable values:
1514  if( !m_pCurr->Height() )
1515  {
1516  OSL_ENSURE( m_pCurr->Height(), "SwTextFormatter::NewPortion: limbo dance" );
1517  m_pCurr->Height( pPor->Height() );
1518  m_pCurr->SetAscent( pPor->GetAscent() );
1519  }
1520 
1521  OSL_ENSURE(pPor->Height(), "SwTextFormatter::NewPortion: something went wrong");
1522  if( pPor->IsPostItsPortion() && rInf.X() >= rInf.Width() && rInf.GetFly() )
1523  {
1524  delete pPor;
1525  pPor = rInf.GetFly();
1526  }
1527  return pPor;
1528 }
1529 
1531 {
1532  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
1533  "SwTextFormatter::FormatLine( nStartPos ) with unswapped frame" );
1534 
1535  // For the formatting routines, we set pOut to the reference device.
1536  SwHookOut aHook( GetInfo() );
1537  if (GetInfo().GetLen() < TextFrameIndex(GetInfo().GetText().getLength()))
1538  GetInfo().SetLen(TextFrameIndex(GetInfo().GetText().getLength()));
1539 
1540  bool bBuild = true;
1541  SetFlyInCntBase( false );
1542  GetInfo().SetLineHeight( 0 );
1543  GetInfo().SetLineNetHeight( 0 );
1544 
1545  // Recycling must be suppressed by changed line height and also
1546  // by changed ascent (lowering of baseline).
1547  const sal_uInt16 nOldHeight = m_pCurr->Height();
1548  const sal_uInt16 nOldAscent = m_pCurr->GetAscent();
1549 
1550  m_pCurr->SetEndHyph( false );
1551  m_pCurr->SetMidHyph( false );
1552 
1553  // fly positioning can make it necessary format a line several times
1554  // for this, we have to keep a copy of our rest portion
1555  SwLinePortion* pField = GetInfo().GetRest();
1556  std::unique_ptr<SwFieldPortion> xSaveField;
1557 
1558  if ( pField && pField->InFieldGrp() && !pField->IsFootnotePortion() )
1559  xSaveField.reset(new SwFieldPortion( *static_cast<SwFieldPortion*>(pField) ));
1560 
1561  // for an optimal repaint rectangle, we want to compare fly portions
1562  // before and after the BuildPortions call
1563  const bool bOptimizeRepaint = AllowRepaintOpt();
1564  TextFrameIndex const nOldLineEnd = nStartPos + m_pCurr->GetLen();
1565  std::vector<long> flyStarts;
1566 
1567  // these are the conditions for a fly position comparison
1568  if ( bOptimizeRepaint && m_pCurr->IsFly() )
1569  {
1571  long nPOfst = 0;
1572  while ( pPor )
1573  {
1574  if ( pPor->IsFlyPortion() )
1575  // insert start value of fly portion
1576  flyStarts.push_back( nPOfst );
1577 
1578  nPOfst += pPor->Width();
1579  pPor = pPor->GetNextPortion();
1580  }
1581  }
1582 
1583  // Here soon the underflow check follows.
1584  while( bBuild )
1585  {
1586  GetInfo().SetFootnoteInside( false );
1588 
1589  // These values must not be reset by FormatReset();
1590  const bool bOldNumDone = GetInfo().IsNumDone();
1591  const bool bOldArrowDone = GetInfo().IsArrowDone();
1592  const bool bOldErgoDone = GetInfo().IsErgoDone();
1593 
1594  // besides other things, this sets the repaint offset to 0
1595  FormatReset( GetInfo() );
1596 
1597  GetInfo().SetNumDone( bOldNumDone );
1598  GetInfo().SetArrowDone( bOldArrowDone );
1599  GetInfo().SetErgoDone( bOldErgoDone );
1600 
1601  // build new portions for this line
1602  BuildPortions( GetInfo() );
1603 
1604  if( GetInfo().IsStop() )
1605  {
1607  m_pCurr->Height( GetFrameRstHeight() + 1 );
1609  m_pCurr->Width(0);
1610  m_pCurr->Truncate();
1611  return nStartPos;
1612  }
1613  else if( GetInfo().IsDropInit() )
1614  {
1615  DropInit();
1616  GetInfo().SetDropInit( false );
1617  }
1618 
1619  m_pCurr->CalcLine( *this, GetInfo() );
1621 
1622  //i#120864 For Special case that at the first calculation couldn't get
1623  //correct height. And need to recalculate for the right height.
1624  SwLinePortion* pPorTmp = m_pCurr->GetNextPortion();
1625  if ( IsFlyInCntBase() && (!IsQuick() || (pPorTmp && pPorTmp->IsFlyCntPortion() && !pPorTmp->GetNextPortion() &&
1626  m_pCurr->Height() > pPorTmp->Height())))
1627  {
1628  sal_uInt16 nTmpAscent, nTmpHeight;
1629  CalcAscentAndHeight( nTmpAscent, nTmpHeight );
1630  AlignFlyInCntBase( Y() + long( nTmpAscent ) );
1631  m_pCurr->CalcLine( *this, GetInfo() );
1632  CalcRealHeight();
1633  }
1634 
1635  // bBuild decides if another lap of honor is done
1636  if ( m_pCurr->GetRealHeight() <= GetInfo().GetLineHeight() )
1637  {
1639  bBuild = false;
1640  }
1641  else
1642  {
1643  bBuild = ( GetInfo().GetTextFly().IsOn() && ChkFlyUnderflow(GetInfo()) )
1645  if( bBuild )
1646  {
1647  GetInfo().SetNumDone( bOldNumDone );
1649 
1650  // delete old rest
1651  if ( GetInfo().GetRest() )
1652  {
1653  delete GetInfo().GetRest();
1654  GetInfo().SetRest( nullptr );
1655  }
1656 
1657  // set original rest portion
1658  if ( xSaveField )
1659  GetInfo().SetRest( new SwFieldPortion( *xSaveField ) );
1660 
1662  m_pCurr->Width(0);
1663  m_pCurr->Truncate();
1664  }
1665  }
1666  }
1667 
1668  // In case of compat mode, it's possible that a tab portion is wider after
1669  // formatting than before. If this is the case, we also have to make sure
1670  // the SwLineLayout is wider as well.
1671  if (GetInfo().GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_OVER_MARGIN))
1672  {
1673  sal_uInt16 nSum = 0;
1675 
1676  while (pPor)
1677  {
1678  nSum += pPor->Width();
1679  pPor = pPor->GetNextPortion();
1680  }
1681 
1682  if (nSum > m_pCurr->Width())
1683  m_pCurr->Width(nSum);
1684  }
1685 
1686  // calculate optimal repaint rectangle
1687  if ( bOptimizeRepaint )
1688  {
1689  GetInfo().SetPaintOfst( ::lcl_CalcOptRepaint( *this, *m_pCurr, nOldLineEnd, flyStarts ) );
1690  flyStarts.clear();
1691  }
1692  else
1693  // Special case: we do not allow an optimization of the repaint
1694  // area, but during formatting the repaint offset is set to indicate
1695  // a maximum value for the offset. This value has to be reset:
1696  GetInfo().SetPaintOfst( 0 );
1697 
1698  // This corrects the start of the reformat range if something has
1699  // moved to the next line. Otherwise IsFirstReformat in AllowRepaintOpt
1700  // will give us a wrong result if we have to reformat another line
1701  GetInfo().GetParaPortion()->GetReformat().LeftMove( GetInfo().GetIdx() );
1702 
1703  // delete master copy of rest portion
1704  xSaveField.reset();
1705 
1706  TextFrameIndex const nNewStart = nStartPos + m_pCurr->GetLen();
1707 
1708  // adjust text if kana compression is enabled
1709  if ( GetInfo().CompressLine() )
1710  {
1711  SwTwips nRepaintOfst = CalcKanaAdj( m_pCurr );
1712 
1713  // adjust repaint offset
1714  if ( nRepaintOfst < GetInfo().GetPaintOfst() )
1715  GetInfo().SetPaintOfst( nRepaintOfst );
1716  }
1717 
1719 
1720  if( nOldHeight != m_pCurr->Height() || nOldAscent != m_pCurr->GetAscent() )
1721  {
1722  SetFlyInCntBase();
1723  GetInfo().SetPaintOfst( 0 ); // changed line height => no recycling
1724  // all following line must be painted and when Flys are around,
1725  // also formatted
1726  GetInfo().SetShift( true );
1727  }
1728 
1729  if ( IsFlyInCntBase() && !IsQuick() )
1731 
1732  return nNewStart;
1733 }
1734 
1736 {
1737  do
1738  {
1739  CalcRealHeight();
1740  } while (Next());
1741 }
1742 
1743 void SwTextFormatter::CalcRealHeight( bool bNewLine )
1744 {
1745  sal_uInt16 nLineHeight = m_pCurr->Height();
1746  m_pCurr->SetClipping( false );
1747 
1748  SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
1749  if ( pGrid && GetInfo().SnapToGrid() )
1750  {
1751  const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
1752  const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
1753  const bool bRubyTop = ! pGrid->GetRubyTextBelow();
1754 
1755  nLineHeight = nGridWidth + nRubyHeight;
1756  const sal_uInt16 nAmpRatio = (m_pCurr->Height() + nLineHeight - 1)/nLineHeight;
1757  nLineHeight *= nAmpRatio;
1758 
1759  const sal_uInt16 nAsc = m_pCurr->GetAscent() +
1760  ( bRubyTop ?
1761  ( nLineHeight - m_pCurr->Height() + nRubyHeight ) / 2 :
1762  ( nLineHeight - m_pCurr->Height() - nRubyHeight ) / 2 );
1763 
1764  m_pCurr->Height( nLineHeight );
1765  m_pCurr->SetAscent( nAsc );
1767 
1768  // we ignore any line spacing options except from ...
1769  const SvxLineSpacingItem* pSpace = m_aLineInf.GetLineSpacing();
1770  if ( ! IsParaLine() && pSpace &&
1771  SvxInterLineSpaceRule::Prop == pSpace->GetInterLineSpaceRule() )
1772  {
1773  sal_uLong nTmp = pSpace->GetPropLineSpace();
1774 
1775  if( nTmp < 100 )
1776  nTmp = 100;
1777 
1778  nTmp *= nLineHeight;
1779  nLineHeight = static_cast<sal_uInt16>(nTmp / 100);
1780  }
1781 
1782  m_pCurr->SetRealHeight( nLineHeight );
1783  return;
1784  }
1785 
1786  // The dummy flag is set on lines that only contain flyportions, these shouldn't
1787  // consider register-true and so on. Unfortunately an empty line can be at
1788  // the end of a paragraph (empty paragraphs or behind a Shift-Return),
1789  // which should consider the register.
1790  if (!m_pCurr->IsDummy() || (!m_pCurr->GetNext()
1791  && GetStart() >= TextFrameIndex(GetTextFrame()->GetText().getLength())
1792  && !bNewLine))
1793  {
1794  const SvxLineSpacingItem *pSpace = m_aLineInf.GetLineSpacing();
1795  if( pSpace )
1796  {
1797  switch( pSpace->GetLineSpaceRule() )
1798  {
1799  case SvxLineSpaceRule::Auto:
1800  // shrink first line of paragraph too on spacing < 100%
1801  if (IsParaLine() &&
1802  pSpace->GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
1804  {
1805  long nTmp = pSpace->GetPropLineSpace();
1806  // Word will render < 50% too but it's just not readable
1807  if( nTmp < 50 )
1808  nTmp = nTmp ? 50 : 100;
1809  if (nTmp<100) { // code adapted from fixed line height
1810  nTmp *= nLineHeight;
1811  nTmp /= 100;
1812  if( !nTmp )
1813  ++nTmp;
1814  nLineHeight = static_cast<sal_uInt16>(nTmp);
1815  sal_uInt16 nAsc = ( 4 * nLineHeight ) / 5; // 80%
1816 #if 0
1817  // could do clipping here (like Word does)
1818  // but at 0.5 its unreadable either way...
1819  if( nAsc < pCurr->GetAscent() ||
1820  nLineHeight - nAsc < pCurr->Height() -
1821  pCurr->GetAscent() )
1822  pCurr->SetClipping( true );
1823 #endif
1824  m_pCurr->SetAscent( nAsc );
1825  m_pCurr->Height( nLineHeight );
1827  }
1828  }
1829  break;
1830  case SvxLineSpaceRule::Min:
1831  {
1832  if( nLineHeight < pSpace->GetLineHeight() )
1833  nLineHeight = pSpace->GetLineHeight();
1834  break;
1835  }
1836  case SvxLineSpaceRule::Fix:
1837  {
1838  nLineHeight = pSpace->GetLineHeight();
1839  const sal_uInt16 nAsc = ( 4 * nLineHeight ) / 5; // 80%
1840  if( nAsc < m_pCurr->GetAscent() ||
1841  nLineHeight - nAsc < m_pCurr->Height() - m_pCurr->GetAscent() )
1842  m_pCurr->SetClipping( true );
1843  m_pCurr->Height( nLineHeight );
1844  m_pCurr->SetAscent( nAsc );
1846  }
1847  break;
1848  default: OSL_FAIL( ": unknown LineSpaceRule" );
1849  }
1850  // Note: for the _first_ line the line spacing of the previous
1851  // paragraph is applied in SwFlowFrame::CalcUpperSpace()
1852  if( !IsParaLine() )
1853  switch( pSpace->GetInterLineSpaceRule() )
1854  {
1855  case SvxInterLineSpaceRule::Off:
1856  break;
1857  case SvxInterLineSpaceRule::Prop:
1858  {
1859  long nTmp = pSpace->GetPropLineSpace();
1860  // 50% is the minimum, if 0% we switch to the
1861  // default value 100% ...
1862  if( nTmp < 50 )
1863  nTmp = nTmp ? 50 : 100;
1864 
1865  nTmp *= nLineHeight;
1866  nTmp /= 100;
1867  if( !nTmp )
1868  ++nTmp;
1869  nLineHeight = static_cast<sal_uInt16>(nTmp);
1870  break;
1871  }
1872  case SvxInterLineSpaceRule::Fix:
1873  {
1874  nLineHeight = nLineHeight + pSpace->GetInterLineSpace();
1875  break;
1876  }
1877  default: OSL_FAIL( ": unknown InterLineSpaceRule" );
1878  }
1879  }
1880 
1881  if( IsRegisterOn() )
1882  {
1883  SwTwips nTmpY = Y() + m_pCurr->GetAscent() + nLineHeight - m_pCurr->Height();
1884  SwRectFnSet aRectFnSet(m_pFrame);
1885  if ( aRectFnSet.IsVert() )
1886  nTmpY = m_pFrame->SwitchHorizontalToVertical( nTmpY );
1887  nTmpY = aRectFnSet.YDiff( nTmpY, RegStart() );
1888  const sal_uInt16 nDiff = sal_uInt16( nTmpY % RegDiff() );
1889  if( nDiff )
1890  nLineHeight += RegDiff() - nDiff;
1891  }
1892  }
1893  m_pCurr->SetRealHeight( nLineHeight );
1894 }
1895 
1897 {
1898  // delete Fly in any case!
1899  ClearFly( rInf );
1900  rInf.Init();
1901 
1902  rInf.ChkNoHyph( CntEndHyph(), CntMidHyph() );
1903  rInf.SetRoot( m_pCurr );
1904  rInf.SetLineStart( m_nStart );
1905  rInf.SetIdx( m_nStart );
1906  rInf.Left( Left() );
1907  rInf.Right( Right() );
1908  rInf.First( FirstLeft() );
1909  rInf.LeftMargin(GetLeftMargin());
1910 
1911  rInf.RealWidth( sal_uInt16(rInf.Right() - GetLeftMargin()) );
1912  rInf.Width( rInf.RealWidth() );
1913  if( const_cast<SwTextFormatter*>(this)->GetRedln() )
1914  {
1915  const_cast<SwTextFormatter*>(this)->GetRedln()->Clear( const_cast<SwTextFormatter*>(this)->GetFnt() );
1916  const_cast<SwTextFormatter*>(this)->GetRedln()->Reset();
1917  }
1918 }
1919 
1921 {
1922  m_pFirstOfBorderMerge = nullptr;
1923  m_pCurr->Truncate();
1924  m_pCurr->Init();
1925  if( pBlink && m_pCurr->IsBlinking() )
1926  pBlink->Delete( m_pCurr );
1927 
1928  // delete pSpaceAdd and pKanaComp
1931  m_pCurr->ResetFlags();
1932  FeedInf( rInf );
1933 }
1934 
1936 {
1937  if( m_pDropFormat )
1938  {
1939  const sal_uInt16 nOldDrop = GetDropHeight();
1941  m_bOnceMore = nOldDrop != GetDropHeight();
1942  }
1943  else
1944  m_bOnceMore = false;
1945  return m_bOnceMore;
1946 }
1947 
1949 {
1950  SwTwips nRet = Y() + GetLineHeight();
1951  SwTwips nMin = GetInfo().GetTextFly().GetMinBottom();
1952  if( nMin && ++nMin > nRet )
1953  {
1956  if( nRet + nDist < nMin )
1957  {
1958  const bool bRepaint = HasTruncLines() &&
1959  GetInfo().GetParaPortion()->GetRepaint().Bottom() == nRet-1;
1960  nRet = nMin - nDist;
1961  if( bRepaint )
1962  {
1963  const_cast<SwRepaint&>(GetInfo().GetParaPortion()
1964  ->GetRepaint()).Bottom( nRet-1 );
1965  const_cast<SwTextFormatInfo&>(GetInfo()).SetPaintOfst( 0 );
1966  }
1967  }
1968  }
1969  return nRet;
1970 }
1971 
1972 // FME/OD: This routine does a limited text formatting.
1974 {
1975  FormatReset( GetInfo() );
1976  BuildPortions( GetInfo() );
1977  m_pCurr->CalcLine( *this, GetInfo() );
1978  return m_pCurr->Width();
1979 }
1980 
1981 // determines if the calculation of a repaint offset is allowed
1982 // otherwise each line is painted from 0 (this is a copy of the beginning
1983 // of the former SwTextFormatter::Recycle() function
1985 {
1986  // reformat position in front of current line? Only in this case
1987  // we want to set the repaint offset
1988  bool bOptimizeRepaint = m_nStart < GetInfo().GetReformatStart() &&
1989  m_pCurr->GetLen();
1990 
1991  // a special case is the last line of a block adjusted paragraph:
1992  if ( bOptimizeRepaint )
1993  {
1994  switch( GetAdjust() )
1995  {
1996  case SvxAdjust::Block:
1997  {
1998  if( IsLastBlock() || IsLastCenter() )
1999  bOptimizeRepaint = false;
2000  else
2001  {
2002  // ????: blank in the last master line (blocksat.sdw)
2003  bOptimizeRepaint = nullptr == m_pCurr->GetNext() && !m_pFrame->GetFollow();
2004  if ( bOptimizeRepaint )
2005  {
2007  while ( pPos && !pPos->IsFlyPortion() )
2008  pPos = pPos->GetNextPortion();
2009  bOptimizeRepaint = !pPos;
2010  }
2011  }
2012  break;
2013  }
2014  case SvxAdjust::Center:
2015  case SvxAdjust::Right:
2016  bOptimizeRepaint = false;
2017  break;
2018  default: ;
2019  }
2020  }
2021 
2022  // Again another special case: invisible SoftHyphs
2023  const TextFrameIndex nReformat = GetInfo().GetReformatStart();
2024  if (bOptimizeRepaint && TextFrameIndex(COMPLETE_STRING) != nReformat)
2025  {
2026  const sal_Unicode cCh = nReformat >= TextFrameIndex(GetInfo().GetText().getLength())
2027  ? 0
2028  : GetInfo().GetText()[ sal_Int32(nReformat) ];
2029  bOptimizeRepaint = ( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
2030  || ! GetInfo().HasHint( nReformat );
2031  }
2032 
2033  return bOptimizeRepaint;
2034 }
2035 
2037 {
2038  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
2039  "SwTextFormatter::CalcUnclipped with unswapped frame" );
2040 
2041  long nFlyAsc, nFlyDesc;
2042  m_pCurr->MaxAscentDescent( rTop, rBottom, nFlyAsc, nFlyDesc );
2043  rTop = Y() + GetCurr()->GetAscent();
2044  rBottom = rTop + nFlyDesc;
2045  rTop -= nFlyAsc;
2046 }
2047 
2048 void SwTextFormatter::UpdatePos( SwLineLayout *pCurrent, Point aStart,
2049  TextFrameIndex const nStartIdx, bool bAlways) const
2050 {
2051  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
2052  "SwTextFormatter::UpdatePos with unswapped frame" );
2053 
2054  if( GetInfo().IsTest() )
2055  return;
2056  SwLinePortion *pFirst = pCurrent->GetFirstPortion();
2057  SwLinePortion *pPos = pFirst;
2058  SwTextPaintInfo aTmpInf( GetInfo() );
2059  aTmpInf.SetpSpaceAdd( pCurrent->GetpLLSpaceAdd() );
2060  aTmpInf.ResetSpaceIdx();
2061  aTmpInf.SetKanaComp( pCurrent->GetpKanaComp() );
2062  aTmpInf.ResetKanaIdx();
2063 
2064  // The frame's size
2065  aTmpInf.SetIdx( nStartIdx );
2066  aTmpInf.SetPos( aStart );
2067 
2068  long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2069  pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2070 
2071  const sal_uInt16 nTmpHeight = pCurrent->GetRealHeight();
2072  sal_uInt16 nAscent = pCurrent->GetAscent() + nTmpHeight - pCurrent->Height();
2074  if( GetMulti() )
2075  {
2076  aTmpInf.SetDirection( GetMulti()->GetDirection() );
2077  if( GetMulti()->HasRotation() )
2078  {
2079  nFlags |= AsCharFlags::Rotate;
2080  if( GetMulti()->IsRevers() )
2081  {
2082  nFlags |= AsCharFlags::Reverse;
2083  aTmpInf.X( aTmpInf.X() - nAscent );
2084  }
2085  else
2086  aTmpInf.X( aTmpInf.X() + nAscent );
2087  }
2088  else
2089  {
2090  if ( GetMulti()->IsBidi() )
2091  nFlags |= AsCharFlags::Bidi;
2092  aTmpInf.Y( aTmpInf.Y() + nAscent );
2093  }
2094  }
2095  else
2096  aTmpInf.Y( aTmpInf.Y() + nAscent );
2097 
2098  while( pPos )
2099  {
2100  // We only know one case where changing the position (caused by the
2101  // adjustment) could be relevant for a portion: We need to SetRefPoint
2102  // for FlyCntPortions.
2103  if( ( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
2104  && ( bAlways || !IsQuick() ) )
2105  {
2106  pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
2107 
2108  if( pPos->IsGrfNumPortion() )
2109  {
2110  if( !nFlyAsc && !nFlyDesc )
2111  {
2112  nTmpAscent = nAscent;
2113  nFlyAsc = nAscent;
2114  nTmpDescent = nTmpHeight - nAscent;
2115  nFlyDesc = nTmpDescent;
2116  }
2117  static_cast<SwGrfNumPortion*>(pPos)->SetBase( nTmpAscent, nTmpDescent,
2118  nFlyAsc, nFlyDesc );
2119  }
2120  else
2121  {
2122  Point aBase( aTmpInf.GetPos() );
2123  if ( GetInfo().GetTextFrame()->IsVertical() )
2125 
2126  static_cast<SwFlyCntPortion*>(pPos)->SetBase( *aTmpInf.GetTextFrame(),
2127  aBase, nTmpAscent, nTmpDescent, nFlyAsc,
2128  nFlyDesc, nFlags );
2129  }
2130  }
2131  if( pPos->IsMultiPortion() && static_cast<SwMultiPortion*>(pPos)->HasFlyInContent() )
2132  {
2133  OSL_ENSURE( !GetMulti(), "Too much multi" );
2134  const_cast<SwTextFormatter*>(this)->m_pMulti = static_cast<SwMultiPortion*>(pPos);
2135  SwLineLayout *pLay = &GetMulti()->GetRoot();
2136  Point aSt( aTmpInf.X(), aStart.Y() );
2137 
2138  if ( GetMulti()->HasBrackets() )
2139  {
2140  OSL_ENSURE( GetMulti()->IsDouble(), "Brackets only for doubles");
2141  aSt.AdjustX(static_cast<SwDoubleLinePortion*>(GetMulti())->PreWidth() );
2142  }
2143  else if( GetMulti()->HasRotation() )
2144  {
2145  aSt.AdjustY(pCurrent->GetAscent() - GetMulti()->GetAscent() );
2146  if( GetMulti()->IsRevers() )
2147  aSt.AdjustX(GetMulti()->Width() );
2148  else
2149  aSt.AdjustY(GetMulti()->Height() );
2150  }
2151  else if ( GetMulti()->IsBidi() )
2152  // jump to end of the bidi portion
2153  aSt.AdjustX(pLay->Width() );
2154 
2155  TextFrameIndex nStIdx = aTmpInf.GetIdx();
2156  do
2157  {
2158  UpdatePos( pLay, aSt, nStIdx, bAlways );
2159  nStIdx = nStIdx + pLay->GetLen();
2160  aSt.AdjustY(pLay->Height() );
2161  pLay = pLay->GetNext();
2162  } while ( pLay );
2163  const_cast<SwTextFormatter*>(this)->m_pMulti = nullptr;
2164  }
2165  pPos->Move( aTmpInf );
2166  pPos = pPos->GetNextPortion();
2167  }
2168 }
2169 
2170 void SwTextFormatter::AlignFlyInCntBase( long nBaseLine ) const
2171 {
2172  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
2173  "SwTextFormatter::AlignFlyInCntBase with unswapped frame" );
2174 
2175  if( GetInfo().IsTest() )
2176  return;
2177  SwLinePortion *pFirst = m_pCurr->GetFirstPortion();
2178  SwLinePortion *pPos = pFirst;
2179  AsCharFlags nFlags = AsCharFlags::None;
2180  if( GetMulti() && GetMulti()->HasRotation() )
2181  {
2182  nFlags |= AsCharFlags::Rotate;
2183  if( GetMulti()->IsRevers() )
2184  nFlags |= AsCharFlags::Reverse;
2185  }
2186 
2187  long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2188 
2189  while( pPos )
2190  {
2191  if( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
2192  {
2193  m_pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
2194 
2195  if( pPos->IsGrfNumPortion() )
2196  static_cast<SwGrfNumPortion*>(pPos)->SetBase( nTmpAscent, nTmpDescent,
2197  nFlyAsc, nFlyDesc );
2198  else
2199  {
2200  Point aBase;
2201  if ( GetInfo().GetTextFrame()->IsVertical() )
2202  {
2203  nBaseLine = GetInfo().GetTextFrame()->SwitchHorizontalToVertical( nBaseLine );
2204  aBase = Point( nBaseLine, static_cast<SwFlyCntPortion*>(pPos)->GetRefPoint().Y() );
2205  }
2206  else
2207  aBase = Point( static_cast<SwFlyCntPortion*>(pPos)->GetRefPoint().X(), nBaseLine );
2208 
2209  static_cast<SwFlyCntPortion*>(pPos)->SetBase( *GetInfo().GetTextFrame(), aBase, nTmpAscent, nTmpDescent,
2210  nFlyAsc, nFlyDesc, nFlags );
2211  }
2212  }
2213  pPos = pPos->GetNextPortion();
2214  }
2215 }
2216 
2218 {
2219  OSL_ENSURE( rInf.GetTextFly().IsOn(), "SwTextFormatter::ChkFlyUnderflow: why?" );
2220  if( GetCurr() )
2221  {
2222  // First we check, whether a fly overlaps with the line.
2223  // = GetLineHeight()
2224  const sal_uInt16 nHeight = GetCurr()->GetRealHeight();
2225  SwRect aLine( GetLeftMargin(), Y(), rInf.RealWidth(), nHeight );
2226 
2227  SwRect aLineVert( aLine );
2228  if ( m_pFrame->IsVertical() )
2229  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2230  SwRect aInter( rInf.GetTextFly().GetFrame( aLineVert ) );
2231  if ( m_pFrame->IsVertical() )
2233 
2234  if( !aInter.HasArea() )
2235  return false;
2236 
2237  // We now check every portion that could have lowered for overlapping
2238  // with the fly.
2239  const SwLinePortion *pPos = GetCurr()->GetFirstPortion();
2240  aLine.Pos().setY( Y() + GetCurr()->GetRealHeight() - GetCurr()->Height() );
2241  aLine.Height( GetCurr()->Height() );
2242 
2243  while( pPos )
2244  {
2245  aLine.Width( pPos->Width() );
2246 
2247  aLineVert = aLine;
2248  if ( m_pFrame->IsVertical() )
2249  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2250  aInter = rInf.GetTextFly().GetFrame( aLineVert );
2251  if ( m_pFrame->IsVertical() )
2253 
2254  // New flys from below?
2255  if( !pPos->IsFlyPortion() )
2256  {
2257  if( aInter.IsOver( aLine ) )
2258  {
2259  aInter.Intersection_( aLine );
2260  if( aInter.HasArea() )
2261  {
2262  // To be evaluated during reformat of this line:
2263  // RealHeight including spacing
2264  rInf.SetLineHeight( nHeight );
2265  // Height without extra spacing
2266  rInf.SetLineNetHeight( m_pCurr->Height() );
2267  return true;
2268  }
2269  }
2270  }
2271  else
2272  {
2273  // The fly portion is not intersected by a fly anymore
2274  if ( ! aInter.IsOver( aLine ) )
2275  {
2276  rInf.SetLineHeight( nHeight );
2277  rInf.SetLineNetHeight( m_pCurr->Height() );
2278  return true;
2279  }
2280  else
2281  {
2282  aInter.Intersection_( aLine );
2283 
2284  // No area means a fly has become invalid because of
2285  // lowering the line => reformat the line
2286  // we also have to reformat the line, if the fly size
2287  // differs from the intersection interval's size.
2288  if( ! aInter.HasArea() ||
2289  static_cast<const SwFlyPortion*>(pPos)->GetFixWidth() != aInter.Width() )
2290  {
2291  rInf.SetLineHeight( nHeight );
2292  rInf.SetLineNetHeight( m_pCurr->Height() );
2293  return true;
2294  }
2295  }
2296  }
2297 
2298  aLine.Left( aLine.Left() + pPos->Width() );
2299  pPos = pPos->GetNextPortion();
2300  }
2301  }
2302  return false;
2303 }
2304 
2306 {
2307  if( GetMulti() || rInf.GetFly() )
2308  return;
2309 
2310  SwTextFly& rTextFly = rInf.GetTextFly();
2311  if( !rTextFly.IsOn() || rInf.IsIgnoreFly() )
2312  return;
2313 
2314  const SwLinePortion *pLast = rInf.GetLast();
2315 
2316  long nAscent;
2317  long nTop = Y();
2318  long nHeight;
2319 
2320  if( rInf.GetLineHeight() )
2321  {
2322  // Real line height has already been calculated, we only have to
2323  // search for intersections in the lower part of the strip
2324  nAscent = m_pCurr->GetAscent();
2325  nHeight = rInf.GetLineNetHeight();
2326  nTop += rInf.GetLineHeight() - nHeight;
2327  }
2328  else
2329  {
2330  // We make a first guess for the lines real height
2331  if ( ! m_pCurr->GetRealHeight() )
2332  CalcRealHeight();
2333 
2334  nAscent = pLast->GetAscent();
2335  nHeight = pLast->Height();
2336 
2337  if ( m_pCurr->GetRealHeight() > nHeight )
2338  nTop += m_pCurr->GetRealHeight() - nHeight;
2339  else
2340  // Important for fixed space between lines
2341  nHeight = m_pCurr->GetRealHeight();
2342  }
2343 
2344  const long nLeftMar = GetLeftMargin();
2345  const long nLeftMin = (rInf.X() || GetDropLeft()) ? nLeftMar : GetLeftMin();
2346 
2347  SwRect aLine( rInf.X() + nLeftMin, nTop, rInf.RealWidth() - rInf.X()
2348  + nLeftMar - nLeftMin , nHeight );
2349 
2350  // tdf#116486: consider also the upper margin from getFramePrintArea because intersections
2351  // with this additional space should lead to repositioning of paragraphs
2352  // For compatibility we grab a related compat flag:
2354  {
2355  const long nUpper = m_pFrame->getFramePrintArea().Top();
2356  // Increase the rectangle
2357  if( nUpper > 0 && nTop >= nUpper )
2358  aLine.SubTop( nUpper );
2359  }
2360  SwRect aLineVert( aLine );
2361  if ( m_pFrame->IsRightToLeft() )
2362  m_pFrame->SwitchLTRtoRTL( aLineVert );
2363 
2364  if ( m_pFrame->IsVertical() )
2365  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2366 
2367  // GetFrame(...) determines and returns the intersection rectangle
2368  SwRect aInter( rTextFly.GetFrame( aLineVert ) );
2369 
2370  if ( m_pFrame->IsRightToLeft() )
2371  m_pFrame->SwitchRTLtoLTR( aInter );
2372 
2373  if ( m_pFrame->IsVertical() )
2375 
2376  if (!aInter.IsEmpty() && aInter.Bottom() < nTop)
2377  {
2378  // Intersects with the frame area (with upper margin), but not with the print area (without
2379  // upper margin). Don't reserve space for the fly portion in this case, text is allowed to
2380  // flow there.
2381  aInter.Height(0);
2382  }
2383 
2384  if( !aInter.IsOver( aLine ) )
2385  return;
2386 
2387  aLine.Left( rInf.X() + nLeftMar );
2388  bool bForced = false;
2389  if( aInter.Left() <= nLeftMin )
2390  {
2391  SwTwips nFrameLeft = GetTextFrame()->getFrameArea().Left();
2392  if( GetTextFrame()->getFramePrintArea().Left() < 0 )
2393  nFrameLeft += GetTextFrame()->getFramePrintArea().Left();
2394  if( aInter.Left() < nFrameLeft )
2395  aInter.Left( nFrameLeft );
2396 
2397  long nAddMar = 0;
2398  if ( m_pFrame->IsRightToLeft() )
2399  {
2400  nAddMar = m_pFrame->getFrameArea().Right() - Right();
2401  if ( nAddMar < 0 )
2402  nAddMar = 0;
2403  }
2404  else
2405  nAddMar = nLeftMar - nFrameLeft;
2406 
2407  aInter.Width( aInter.Width() + nAddMar );
2408  // For a negative first line indent, we set this flag to show
2409  // that the indentation/margin has been moved.
2410  // This needs to be respected by the DefaultTab at the zero position.
2411  if( IsFirstTextLine() && HasNegFirst() )
2412  bForced = true;
2413  }
2414  aInter.Intersection( aLine );
2415  if( !aInter.HasArea() )
2416  return;
2417 
2418  const bool bFullLine = aLine.Left() == aInter.Left() &&
2419  aLine.Right() == aInter.Right();
2420 
2421  // Although no text is left, we need to format another line,
2422  // because also empty lines need to avoid a Fly with no wrapping.
2423  if (bFullLine && rInf.GetIdx() == TextFrameIndex(rInf.GetText().getLength()))
2424  {
2425  rInf.SetNewLine( true );
2426  // We know that for dummies, it holds ascent == height
2427  m_pCurr->SetDummy(true);
2428  }
2429 
2430  // aInter becomes frame-local
2431  aInter.Pos().AdjustX( -nLeftMar );
2432  SwFlyPortion *pFly = new SwFlyPortion( aInter );
2433  if( bForced )
2434  {
2436  rInf.ForcedLeftMargin( static_cast<sal_uInt16>(aInter.Width()) );
2437  }
2438 
2439  if( bFullLine )
2440  {
2441  // In order to properly flow around Flys with different
2442  // wrapping attributes, we need to increase by units of line height.
2443  // The last avoiding line should be adjusted in height, so that
2444  // we don't get a frame spacing effect.
2445  // It is important that ascent == height, because the FlyPortion
2446  // values are transferred to pCurr in CalcLine and IsDummy() relies
2447  // on this behaviour.
2448  // To my knowledge we only have two places where DummyLines can be
2449  // created: here and in MakeFlyDummies.
2450  // IsDummy() is evaluated in IsFirstTextLine(), when moving lines
2451  // and in relation with DropCaps.
2452  pFly->Height( sal_uInt16(aInter.Height()) );
2453 
2454  // nNextTop now contains the margin's bottom edge, which we avoid
2455  // or the next margin's top edge, which we need to respect.
2456  // That means we can comfortably grow up to this value; that's how
2457  // we save a few empty lines.
2458  long nNextTop = rTextFly.GetNextTop();
2459  if ( m_pFrame->IsVertical() )
2460  nNextTop = m_pFrame->SwitchVerticalToHorizontal( nNextTop );
2461  if( nNextTop > aInter.Bottom() )
2462  {
2463  SwTwips nH = nNextTop - aInter.Top();
2464  if( nH < SAL_MAX_UINT16 )
2465  pFly->Height( sal_uInt16( nH ) );
2466  }
2467  if( nAscent < pFly->Height() )
2468  pFly->SetAscent( sal_uInt16(nAscent) );
2469  else
2470  pFly->SetAscent( pFly->Height() );
2471  }
2472  else
2473  {
2474  if (rInf.GetIdx() == TextFrameIndex(rInf.GetText().getLength()))
2475  {
2476  // Don't use nHeight, or we have a huge descent
2477  pFly->Height( pLast->Height() );
2478  pFly->SetAscent( pLast->GetAscent() );
2479  }
2480  else
2481  {
2482  pFly->Height( sal_uInt16(aInter.Height()) );
2483  if( nAscent < pFly->Height() )
2484  pFly->SetAscent( sal_uInt16(nAscent) );
2485  else
2486  pFly->SetAscent( pFly->Height() );
2487  }
2488  }
2489 
2490  rInf.SetFly( pFly );
2491 
2492  if( pFly->GetFix() < rInf.Width() )
2493  rInf.Width( pFly->GetFix() );
2494 
2495  SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
2496  if ( !pGrid )
2497  return;
2498 
2499  const SwPageFrame* pPageFrame = m_pFrame->FindPageFrame();
2500  const SwLayoutFrame* pBody = pPageFrame->FindBodyCont();
2501 
2502  SwRectFnSet aRectFnSet(pPageFrame);
2503 
2504  const long nGridOrigin = pBody ?
2505  aRectFnSet.GetPrtLeft(*pBody) :
2506  aRectFnSet.GetPrtLeft(*pPageFrame);
2507 
2508  const SwDoc & rDoc = rInf.GetTextFrame()->GetDoc();
2509  const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, rDoc);
2510 
2511  SwTwips nStartX = GetLeftMargin();
2512  if ( aRectFnSet.IsVert() )
2513  {
2514  Point aPoint( nStartX, 0 );
2516  nStartX = aPoint.Y();
2517  }
2518 
2519  const SwTwips nOfst = nStartX - nGridOrigin;
2520  const SwTwips nTmpWidth = rInf.Width() + nOfst;
2521 
2522  const sal_uLong i = nTmpWidth / nGridWidth + 1;
2523 
2524  const long nNewWidth = ( i - 1 ) * nGridWidth - nOfst;
2525  if ( nNewWidth > 0 )
2526  rInf.Width( static_cast<sal_uInt16>(nNewWidth) );
2527  else
2528  rInf.Width( 0 );
2529 
2530 
2531 }
2532 
2534  SwTextAttr *pHint ) const
2535 {
2536  const SwFrame *pFrame = m_pFrame;
2537 
2538  SwFlyInContentFrame *pFly;
2539  SwFrameFormat* pFrameFormat = static_cast<SwTextFlyCnt*>(pHint)->GetFlyCnt().GetFrameFormat();
2540  if( RES_FLYFRMFMT == pFrameFormat->Which() )
2541  pFly = static_cast<SwTextFlyCnt*>(pHint)->GetFlyFrame(pFrame);
2542  else
2543  pFly = nullptr;
2544  // aBase is the document-global position, from which the new extra portion is placed
2545  // aBase.X() = Offset in the line after the current position
2546  // aBase.Y() = LineIter.Y() + Ascent of the current position
2547 
2548  long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2549  // i#11859 - use new method <SwLineLayout::MaxAscentDescent(..)>
2550  // to change line spacing behaviour at paragraph - Compatibility to MS Word
2551  //SwLinePortion *pPos = pCurr->GetFirstPortion();
2552  //lcl_MaxAscDescent( pPos, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2553  m_pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2554 
2555  // If the ascent of the frame is larger than the ascent of the current position,
2556  // we use this one when calculating the base, or the frame would be positioned
2557  // too much to the top, sliding down after all causing a repaint in an area
2558  // he actually never was in.
2559  sal_uInt16 nAscent = 0;
2560 
2561  const bool bTextFrameVertical = GetInfo().GetTextFrame()->IsVertical();
2562 
2563  const bool bUseFlyAscent = pFly && pFly->isFrameAreaPositionValid() &&
2564  0 != ( bTextFrameVertical ?
2565  pFly->GetRefPoint().X() :
2566  pFly->GetRefPoint().Y() );
2567 
2568  if ( bUseFlyAscent )
2569  nAscent = static_cast<sal_uInt16>( std::abs( int( bTextFrameVertical ?
2570  pFly->GetRelPos().X() :
2571  pFly->GetRelPos().Y() ) ) );
2572 
2573  // Check if be prefer to use the ascent of the last portion:
2574  if ( IsQuick() ||
2575  !bUseFlyAscent ||
2576  nAscent < rInf.GetLast()->GetAscent() )
2577  {
2578  nAscent = rInf.GetLast()->GetAscent();
2579  }
2580  else if( nAscent > nFlyAsc )
2581  nFlyAsc = nAscent;
2582 
2583  Point aBase( GetLeftMargin() + rInf.X(), Y() + nAscent );
2585  if( GetMulti() && GetMulti()->HasRotation() )
2586  {
2587  nMode |= AsCharFlags::Rotate;
2588  if( GetMulti()->IsRevers() )
2589  nMode |= AsCharFlags::Reverse;
2590  }
2591 
2592  Point aTmpBase( aBase );
2593  if ( GetInfo().GetTextFrame()->IsVertical() )
2595 
2596  SwFlyCntPortion* pRet(nullptr);
2597  if( pFly )
2598  {
2599  pRet = sw::FlyContentPortion::Create(*GetInfo().GetTextFrame(), pFly, aTmpBase, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode);
2600  // We need to make sure that our font is set again in the OutputDevice
2601  // It could be that the FlyInCnt was added anew and GetFlyFrame() would
2602  // in turn cause, that it'd be created anew again.
2603  // This one's frames get formatted right away, which change the font.
2604  rInf.SelectFont();
2605  if( pRet->GetAscent() > nAscent )
2606  {
2607  aBase.setY( Y() + pRet->GetAscent() );
2608  nMode |= AsCharFlags::UlSpace;
2609  if( !rInf.IsTest() )
2610  {
2611  aTmpBase = aBase;
2612  if ( GetInfo().GetTextFrame()->IsVertical() )
2614 
2615  pRet->SetBase( *rInf.GetTextFrame(), aTmpBase, nTmpAscent,
2616  nTmpDescent, nFlyAsc, nFlyDesc, nMode );
2617  }
2618  }
2619  }
2620  else
2621  {
2622  pRet = sw::DrawFlyCntPortion::Create(*rInf.GetTextFrame(), *pFrameFormat, aTmpBase, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode);
2623  }
2624  return pRet;
2625 }
2626 
2627 /* Drop portion is a special case, because it has parts which aren't portions
2628  but we have handle them just like portions */
2630 {
2631  if( rPortion.GetLines() > 1 )
2632  {
2633  SwDropPortionPart* pCurrPart = rPortion.GetPart();
2634  while( pCurrPart )
2635  {
2636  if( pCurrPart->GetFollow() &&
2637  ::lcl_HasSameBorder(pCurrPart->GetFont(), pCurrPart->GetFollow()->GetFont()) )
2638  {
2639  pCurrPart->SetJoinBorderWithNext(true);
2640  pCurrPart->GetFollow()->SetJoinBorderWithPrev(true);
2641  }
2642  pCurrPart = pCurrPart->GetFollow();
2643  }
2644  }
2645 }
2646 
2648 {
2649  const SwFont aCurFont = *rInf.GetFont();
2650  if( aCurFont.HasBorder() )
2651  {
2652  if (pPrev && pPrev->GetJoinBorderWithNext() )
2653  {
2654  // In some case border merge is called twice to the portion
2655  if( !rPortion.GetJoinBorderWithPrev() )
2656  {
2657  rPortion.SetJoinBorderWithPrev(true);
2658  if( rPortion.InTextGrp() && rPortion.Width() > aCurFont.GetLeftBorderSpace() )
2659  rPortion.Width(rPortion.Width() - aCurFont.GetLeftBorderSpace());
2660  }
2661  }
2662  else
2663  {
2664  rPortion.SetJoinBorderWithPrev(false);
2665  m_pFirstOfBorderMerge = &rPortion;
2666  }
2667 
2668  // Get next portion's font
2669  bool bSeek = false;
2670  if (!rInf.IsFull() && // Not the last portion of the line (in case of line break)
2671  rInf.GetIdx() + rPortion.GetLen() != TextFrameIndex(rInf.GetText().getLength())) // Not the last portion of the paragraph
2672  {
2673  bSeek = Seek(rInf.GetIdx() + rPortion.GetLen());
2674  }
2675  // Don't join the next portion if SwKernPortion sits between two different boxes.
2676  bool bDisconnect = rPortion.IsKernPortion() && !rPortion.GetJoinBorderWithPrev();
2677  // If next portion has the same border then merge
2678  if( bSeek && GetFnt()->HasBorder() && ::lcl_HasSameBorder(aCurFont, *GetFnt()) && !bDisconnect )
2679  {
2680  // In some case border merge is called twice to the portion
2681  if( !rPortion.GetJoinBorderWithNext() )
2682  {
2683  rPortion.SetJoinBorderWithNext(true);
2684  if( rPortion.InTextGrp() && rPortion.Width() > aCurFont.GetRightBorderSpace() )
2685  rPortion.Width(rPortion.Width() - aCurFont.GetRightBorderSpace());
2686  }
2687  }
2688  // If this is the last portion of the merge group then make the real height merge
2689  else
2690  {
2691  rPortion.SetJoinBorderWithNext(false);
2692  if( m_pFirstOfBorderMerge != &rPortion )
2693  {
2694  // Calculate maximum height and ascent
2696  sal_uInt16 nMaxAscent = 0;
2697  sal_uInt16 nMaxHeight = 0;
2698  bool bReachCurrent = false;
2699  while( pActPor )
2700  {
2701  if( nMaxHeight < pActPor->Height() )
2702  nMaxHeight = pActPor->Height();
2703  if( nMaxAscent < pActPor->GetAscent() )
2704  nMaxAscent = pActPor->GetAscent();
2705 
2706  pActPor = pActPor->GetNextPortion();
2707  if( !pActPor && !bReachCurrent )
2708  {
2709  pActPor = &rPortion;
2710  bReachCurrent = true;
2711  }
2712  }
2713 
2714  // Change all portion's height and ascent
2715  pActPor = m_pFirstOfBorderMerge;
2716  bReachCurrent = false;
2717  while( pActPor )
2718  {
2719  if( nMaxHeight > pActPor->Height() )
2720  pActPor->Height(nMaxHeight);
2721  if( nMaxAscent > pActPor->GetAscent() )
2722  pActPor->SetAscent(nMaxAscent);
2723 
2724  pActPor = pActPor->GetNextPortion();
2725  if( !pActPor && !bReachCurrent )
2726  {
2727  pActPor = &rPortion;
2728  bReachCurrent = true;
2729  }
2730  }
2731  m_pFirstOfBorderMerge = nullptr;
2732  }
2733  }
2734  Seek(rInf.GetIdx());
2735  }
2736 }
2737 
2738 namespace {
2739  // calculates and sets optimal repaint offset for the current line
2740  long lcl_CalcOptRepaint( SwTextFormatter &rThis,
2741  SwLineLayout const &rCurr,
2742  TextFrameIndex const nOldLineEnd,
2743  const std::vector<long> &rFlyStarts )
2744  {
2745  SwTextFormatInfo& txtFormatInfo = rThis.GetInfo();
2746  if ( txtFormatInfo.GetIdx() < txtFormatInfo.GetReformatStart() )
2747  // the reformat position is behind our new line, that means
2748  // something of our text has moved to the next line
2749  return 0;
2750 
2751  TextFrameIndex nReformat = std::min(txtFormatInfo.GetReformatStart(), nOldLineEnd);
2752 
2753  // in case we do not have any fly in our line, our repaint position
2754  // is the changed position - 1
2755  if ( rFlyStarts.empty() && ! rCurr.IsFly() )
2756  {
2757  // this is the maximum repaint offset determined during formatting
2758  // for example: the beginning of the first right tab stop
2759  // if this value is 0, this means that we do not have an upper
2760  // limit for the repaint offset
2761  const long nFormatRepaint = txtFormatInfo.GetPaintOfst();
2762 
2763  if (nReformat < txtFormatInfo.GetLineStart() + TextFrameIndex(3))
2764  return 0;
2765 
2766  // step back two positions for smoother repaint
2767  nReformat -= TextFrameIndex(2);
2768 
2769  // i#28795, i#34607, i#38388
2770  // step back more characters, this is required by complex scripts
2771  // e.g., for Khmer (thank you, Javier!)
2772  static const TextFrameIndex nMaxContext(10);
2773  if (nReformat > txtFormatInfo.GetLineStart() + nMaxContext)
2774  nReformat = nReformat - nMaxContext;
2775  else
2776  {
2777  nReformat = txtFormatInfo.GetLineStart();
2778  //reset the margin flag - prevent loops
2780  }
2781 
2782  // Weird situation: Our line used to end with a hole portion
2783  // and we delete some characters at the end of our line. We have
2784  // to take care for repainting the blanks which are not anymore
2785  // covered by the hole portion
2786  while ( nReformat > txtFormatInfo.GetLineStart() &&
2787  CH_BLANK == txtFormatInfo.GetChar( nReformat ) )
2788  --nReformat;
2789 
2790  OSL_ENSURE( nReformat < txtFormatInfo.GetIdx(), "Reformat too small for me!" );
2791  SwRect aRect;
2792 
2793  // Note: GetChareRect is not const. It definitely changes the
2794  // bMulti flag. We have to save and restore the old value.
2795  bool bOldMulti = txtFormatInfo.IsMulti();
2796  rThis.GetCharRect( &aRect, nReformat );
2797  txtFormatInfo.SetMulti( bOldMulti );
2798 
2799  return nFormatRepaint ? std::min( aRect.Left(), nFormatRepaint ) :
2800  aRect.Left();
2801  }
2802  else
2803  {
2804  // nReformat may be wrong, if something around flys has changed:
2805  // we compare the former and the new fly positions in this line
2806  // if anything has changed, we carefully have to adjust the right
2807  // repaint position
2808  long nPOfst = 0;
2809  size_t nCnt = 0;
2810  long nX = 0;
2811  TextFrameIndex nIdx = rThis.GetInfo().GetLineStart();
2812  SwLinePortion* pPor = rCurr.GetFirstPortion();
2813 
2814  while ( pPor )
2815  {
2816  if ( pPor->IsFlyPortion() )
2817  {
2818  // compare start of fly with former start of fly
2819  if (nCnt < rFlyStarts.size() &&
2820  nX == rFlyStarts[ nCnt ] &&
2821  nIdx < nReformat
2822  )
2823  // found fix position, nothing has changed left from nX
2824  nPOfst = nX + pPor->Width();
2825  else
2826  break;
2827 
2828  nCnt++;
2829  }
2830  nX = nX + pPor->Width();
2831  nIdx = nIdx + pPor->GetLen();
2832  pPor = pPor->GetNextPortion();
2833  }
2834 
2835  return nPOfst + rThis.GetLeftMargin();
2836  }
2837  }
2838 
2839  // Determine if we need to build hidden portions
2840  bool lcl_BuildHiddenPortion(const SwTextSizeInfo& rInf, TextFrameIndex & rPos)
2841  {
2842  // Only if hidden text should not be shown:
2843  // if ( rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar() )
2844  const bool bShowInDocView = rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar();
2845  const bool bShowForPrinting = rInf.GetOpt().IsShowHiddenChar( true ) && rInf.GetOpt().IsPrinting();
2846  if (bShowInDocView || bShowForPrinting)
2847  return false;
2848 
2849  const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
2850  TextFrameIndex nHiddenStart;
2851  TextFrameIndex nHiddenEnd;
2852  rSI.GetBoundsOfHiddenRange( rPos, nHiddenStart, nHiddenEnd );
2853  if ( nHiddenEnd )
2854  {
2855  rPos = nHiddenEnd;
2856  return true;
2857  }
2858 
2859  return false;
2860  }
2861 
2862  bool lcl_HasSameBorder(const SwFont& rFirst, const SwFont& rSecond)
2863  {
2864  return
2865  rFirst.GetTopBorder() == rSecond.GetTopBorder() &&
2866  rFirst.GetBottomBorder() == rSecond.GetBottomBorder() &&
2867  rFirst.GetLeftBorder() == rSecond.GetLeftBorder() &&
2868  rFirst.GetRightBorder() == rSecond.GetRightBorder() &&
2869  rFirst.GetTopBorderDist() == rSecond.GetTopBorderDist() &&
2870  rFirst.GetBottomBorderDist() == rSecond.GetBottomBorderDist() &&
2871  rFirst.GetLeftBorderDist() == rSecond.GetLeftBorderDist() &&
2872  rFirst.GetRightBorderDist() == rSecond.GetRightBorderDist() &&
2873  rFirst.GetOrientation() == rSecond.GetOrientation() &&
2874  rFirst.GetShadowColor() == rSecond.GetShadowColor() &&
2875  rFirst.GetShadowWidth() == rSecond.GetShadowWidth() &&
2876  rFirst.GetShadowLocation() == rSecond.GetShadowLocation();
2877  }
2878 
2879 } //end unnamed namespace
2880 
2881 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetHasRotatedPortions(bool bHasRotatedPortions)
Definition: txtftn.cxx:85
virtual bool Format(SwTextFormatInfo &rInf)
Definition: porlin.cxx:240
void SetLineNetHeight(const sal_uInt16 nNew)
Definition: inftxt.hxx:603
bool IsParaLine() const
Definition: itrtxt.hxx:125
SwScriptInfo * m_pScriptInfo
Definition: itratr.hxx:40
std::deque< sal_uInt16 > * GetpKanaComp() const
Definition: porlay.hxx:184
Base class of the Writer layout elements.
Definition: frame.hxx:297
void Move(SwTextPaintInfo &rInf)
Definition: porlin.cxx:271
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
bool LastKernPortion()
Definition: inftxt.cxx:1764
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
bool IsArrowDone() const
Definition: inftxt.hxx:637
SwTwips GetMinBottom() const
Definition: txtfly.hxx:336
SwCharFormat * GetAnchorCharFormat(SwDoc &rDoc) const
Definition: docftn.cxx:183
const SwFormatDrop * m_pDropFormat
Definition: itrform2.hxx:35
void SetRest(const bool bNew)
Definition: porlay.hxx:118
void SwitchVerticalToHorizontal(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from vertical to horizontal layout...
Definition: txtfrm.cxx:578
bool IsRegisterOn() const
Definition: itrtxt.hxx:94
sal_uInt16 GetLeftBorderSpace() const
Definition: swfont.hxx:908
sal_uInt16 GetShadowWidth() const
Definition: swfont.hxx:378
SwFontScript WhichFont(TextFrameIndex nIdx) const
Definition: porlay.cxx:719
void FormatReset(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:1920
const std::optional< editeng::SvxBorderLine > & GetBottomBorder() const
Definition: swfont.hxx:340
SwViewShell * GetVsh()
Definition: inftxt.hxx:228
bool IsFollow() const
Definition: flowfrm.hxx:166
std::map< OUString, css::uno::Any > parameter_map_t
Definition: IMark.hxx:94
void SetArrowDone(const bool bNew)
Definition: inftxt.hxx:638
void SetFormatAdj(const bool bNew)
Definition: porlay.hxx:110
sal_uInt16 GetPropLineSpace() const
bool IsGrfNumPortion() const
Definition: porlin.hxx:111
Marks a position in the document model.
Definition: pam.hxx:35
TextFrameIndex NextScriptChg(TextFrameIndex nPos) const
Definition: porlay.cxx:1612
static FlyContentPortion * Create(const SwTextFrame &rFrame, SwFlyInContentFrame *pFly, const Point &rBase, long nAscent, long nDescent, long nFlyAsc, long nFlyDesc, AsCharFlags nFlags)
Definition: porfly.cxx:271
sal_uInt16 GetLines() const
Definition: pordrop.hxx:88
bool IsUnderflow() const
Definition: inftxt.hxx:589
void SetFly(const bool bNew)
Definition: porlay.hxx:116
SwFlyCntPortion * NewFlyCntPortion(SwTextFormatInfo &rInf, SwTextAttr *pHt) const
Sets a new portion for an object anchored as character.
Definition: itrform2.cxx:2533
bool IsRest() const
Definition: porlay.hxx:119
sal_uInt16 Height() const
Definition: possiz.hxx:44
SwTwips GetPaintOfst() const
Definition: inftxt.hxx:737
SwFont * GetFont()
Definition: inftxt.hxx:238
SwLineLayout * GetNext()
Definition: porlay.hxx:143
bool IsSwapped() const
Definition: txtfrm.hxx:528
bool SeekStartAndChg(SwTextSizeInfo &rInf, const bool bPara=false)
Definition: itrtxt.hxx:323
bool InNumberGrp() const
Definition: porlin.hxx:102
const SwFormatDrop * GetDropFormat() const
Definition: itrform2.hxx:196
bool IsUnderlineBreak(const SwLinePortion &rPor, const SwFont &rFnt)
Definition: itrpaint.cxx:46
void InsertPortion(SwTextFormatInfo &rInf, SwLinePortion *pPor)
Definition: itrform2.cxx:295
TextFrameIndex GetStart() const
Definition: itrtxt.hxx:88
bool IsPrinting() const
Definition: viewopt.hxx:395
bool IsNewLine() const
Definition: itrform2.hxx:177
void SetPos(const Point &rNew)
Definition: inftxt.hxx:436
void SetFootnoteInside(const bool bNew)
Definition: inftxt.hxx:207
TextFrameIndex NextHiddenChg(TextFrameIndex nPos) const
Definition: porlay.cxx:1665
bool IsInFootnote() const
Definition: frame.hxx:927
sal_uInt16 GetTopBorderDist() const
Definition: swfont.hxx:359
bool GetJoinBorderWithPrev() const
Definition: porlin.hxx:168
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:471
sal_uInt16 GetRightBorderSpace() const
Definition: swfont.hxx:893
bool IsRuby() const
Definition: inftxt.hxx:214
static void MergeCharacterBorder(SwDropPortion const &rPortion)
Merge border of the drop portion with modifying the font of the portions' part.
Definition: itrform2.cxx:2629
sal_Unicode GetTabDecimal() const
Definition: inftxt.hxx:623
void CtorInitTextPainter(SwTextFrame *pFrame, SwTextPaintInfo *pInf)
Definition: itrpaint.cxx:63
sal_uInt8 GetLines() const
Definition: paratr.hxx:86
sal_uIntPtr sal_uLong
void SetFootnoteNum(const bool bNew)
Definition: porlay.hxx:297
const SwRect & getFramePrintArea() const
Definition: frame.hxx:178
bool IsStop() const
Definition: itrform2.hxx:174
bool IsFirstTextLine() const
Definition: itrtxt.hxx:120
SwTabPortion * NewTabPortion(SwTextFormatInfo &rInf, bool bAuto) const
Definition: txttab.cxx:62
The purpose of this class is to be the universal interface between formatting/text output and the pos...
Definition: txtfly.hxx:119
void SetLast(SwLinePortion *pNewLast)
Definition: inftxt.hxx:568
SwTabPortion * GetLastTab()
Definition: inftxt.hxx:621
TextFrameIndex GetUnderScorePos() const
Definition: inftxt.hxx:647
SwTwips Left() const
Definition: inftxt.hxx:548
TextFrameIndex ScanPortionEnd(TextFrameIndex nStart, TextFrameIndex nEnd)
Definition: inftxt.cxx:1671
Definition: doc.hxx:186
#define ODF_FORMCHECKBOX
void CalcLine(SwTextFormatter &rLine, SwTextFormatInfo &rInf)
Definition: porlay.cxx:327
sal_uInt16 GetDropHeight() const
Definition: itrtxt.hxx:205
const SwLineLayout & GetRoot() const
Definition: pormulti.hxx:121
bool IsNumDone() const
Definition: inftxt.hxx:635
sal_uInt16 GetTextHeight() const
Definition: inftxt.hxx:719
void Height(long nNew)
Definition: swrect.hxx:190
bool IsErgoDone() const
Definition: inftxt.hxx:633
sal_uInt16 GetLineNetHeight() const
Definition: inftxt.hxx:602
#define CHAR_HARDBLANK
Definition: swtypes.hxx:172
void SetLen(TextFrameIndex const nLen)
Definition: porlin.hxx:75
bool GetRubyTextBelow() const
Definition: tgrditem.hxx:85
TextFrameIndex GetNextAttr() const
Definition: itratr.cxx:728
#define DIR_TOP2BOTTOM
Definition: inftxt.hxx:57
SwFont * m_pFont
Definition: itratr.hxx:39
bool SeekAndChg(SwTextSizeInfo &rInf)
Definition: itrtxt.hxx:310
long SwTwips
Definition: swtypes.hxx:49
void LeftMargin(const SwTwips nNew)
Definition: inftxt.hxx:554
bool HasBorder() const
Check whether font has any border on any side.
Definition: swfont.hxx:923
SwDropPortionPart * GetPart() const
Definition: pordrop.hxx:94
void SetFlyInCntBase(bool bNew=true)
Definition: itrform2.hxx:211
bool IsVert() const
Definition: frame.hxx:1345
static void SetRightMargin(const bool bNew)
Definition: itrtxt.hxx:294
const SwLineLayout * Next()
Definition: itrtxt.cxx:106
sal_uInt16 RealWidth() const
Definition: inftxt.hxx:555
SwLineInfo m_aLineInf
Definition: itrtxt.hxx:33
SwTwips FirstLeft() const
Definition: itrtxt.hxx:182
bool IsEndNote() const
Definition: fmtftn.hxx:74
SwTwips CalcKanaAdj(SwLineLayout *pCurr)
Definition: itradj.cxx:397
void SetKanaComp(std::deque< sal_uInt16 > *pNew)
Definition: inftxt.hxx:329
sal_uInt16 GetFix() const
Definition: porglue.hxx:56
void SetJoinBorderWithPrev(const bool bJoinPrev)
Definition: porlin.hxx:170
void MaxAscentDescent(SwTwips &_orAscent, SwTwips &_orDescent, SwTwips &_orObjAscent, SwTwips &_orObjDescent, const SwLinePortion *_pDontConsiderPortion=nullptr, const bool _bNoFlyCntPorAndLinePor=false) const
determine ascent and descent for positioning of as-character anchored object
Definition: porlay.cxx:604
void SetMulti(const bool bNew)
Definition: inftxt.hxx:211
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
bool InFieldGrp() const
Definition: porlin.hxx:104
bool HasHint(TextFrameIndex nPos) const
Definition: inftxt.cxx:476
SwTwips Y() const
Definition: itrtxt.hxx:90
sal_uInt16 GetOrientation(const bool bVertLayout=false, const bool bVertFormatLRBT=false) const
Definition: swfont.cxx:433
OUString ExpandFieldmark(IFieldmark *pBM)
Definition: itrform2.cxx:853
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:143
SwTwips RegStart() const
Definition: itrtxt.hxx:92
bool IsMulti() const
Definition: inftxt.hxx:210
sal_uInt16 ForcedLeftMargin() const
Definition: inftxt.hxx:557
#define ODF_FORMDROPDOWN_RESULT
bool IsFull() const
Definition: inftxt.hxx:569
const SvxLineSpacingItem * GetLineSpacing() const
Definition: inftxt.hxx:86
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: portxt.cxx:523
bool Seek(TextFrameIndex nPos)
Enables the attributes used at char pos nPos in the logical font.
Definition: itratr.cxx:301
SvxLineSpaceRule GetLineSpaceRule() const
std::vector< long > * GetpLLSpaceAdd() const
Definition: porlay.hxx:179
bool IsLastBlock() const
Definition: itrtxt.hxx:188
#define CHAR_SOFTHYPHEN
Definition: swtypes.hxx:174
long GetLen(const Point &rPnt)
SwTextFormatInfo & GetInfo()
Definition: itrform2.hxx:213
void CalcUnclipped(SwTwips &rTop, SwTwips &rBottom)
Definition: itrform2.cxx:2036
long YDiff(long n1, long n2) const
Definition: frame.hxx:1401
sal_uInt16 RegDiff() const
Definition: itrtxt.hxx:93
void SetFull(const bool bNew)
Definition: inftxt.hxx:570
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:136
SwRect GetFrame(const SwRect &rPortion) const
Definition: txtfly.hxx:356
bool isLetterNumeric(const OUString &rStr, sal_Int32 nPos) const
sal_uInt16 sal_Unicode
Point const & GetRelPos() const
Definition: flyincnt.cxx:193
#define CH_TXTATR_INWORD
Definition: hintids.hxx:137
SwExpandPortion * TryNewNoLengthPortion(SwTextFormatInfo const &rInfo)
Try to create a new portion with zero length, for an end of a hint (where there is no CH_TXTATR)...
Definition: txtfld.cxx:318
sal_uInt16 GetLineHeight() const
void Top(const long nTop)
Definition: swrect.hxx:203
void CalcAdjLine(SwLineLayout *pCurr)
Definition: itradj.cxx:655
bool BuildMultiPortion(SwTextFormatInfo &rInf, SwMultiPortion &rMulti)
Definition: pormulti.cxx:1885
LINESTYLE_NONE
bool IsBreakPortion() const
Definition: porlin.hxx:114
const SwRect & getFrameArea() const
Definition: frame.hxx:177
#define SAL_MAX_UINT16
sal_Unicode GetChar(TextFrameIndex const nPos) const
Definition: inftxt.hxx:247
#define X
virtual ~SwTextFormatter() override
Definition: itrform2.cxx:107
sal_uInt16 GetRightBorderDist() const
Definition: swfont.hxx:361
bool IsInTab() const
Definition: frame.hxx:933
bool HasRotation() const
Definition: pormulti.hxx:147
void SetRoot(SwLineLayout *pNew)
Definition: inftxt.hxx:566
SwTwips Right() const
Definition: itrtxt.hxx:181
void SetClipping(const bool bNew)
Definition: porlay.hxx:137
#define DIR_BOTTOM2TOP
Definition: inftxt.hxx:55
void ResetFlags()
Definition: porlay.cxx:653
virtual parameter_map_t * GetParameters()=0
const Point & GetRefPoint() const
Definition: flyfrms.hxx:218
void Right(const long nRight)
Definition: swrect.hxx:199
bool IsNewLine() const
Definition: inftxt.hxx:584
void CalcRealHeight(bool bNewLine=false)
Definition: itrform2.cxx:1743
bool AllowRepaintOpt() const
Definition: itrform2.cxx:1984
sal_uInt8 m_nContentEndHyph
Definition: itrform2.hxx:37
TextFrameIndex GetLineStart() const
Definition: inftxt.hxx:596
void CalcFlyWidth(SwTextFormatInfo &rInf)
Calculation of the emulated right side.
Definition: itrform2.cxx:2305
This portion represents an as-character anchored fly (shape, frame, etc.)
Definition: porfly.hxx:44
SwFontScript GetActual() const
Definition: swfont.hxx:183
void SetPaintOfst(const SwTwips nNew)
Definition: inftxt.hxx:742
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:848
TextFrameIndex GetOffset() const
Definition: txtfrm.hxx:428
void SetNumDone(const bool bNew)
Definition: inftxt.hxx:636
bool InFixMargGrp() const
Definition: porlin.hxx:108
bool IsIgnoreFly() const
Definition: inftxt.hxx:576
const std::optional< editeng::SvxBorderLine > & GetRightBorder() const
Definition: swfont.hxx:341
bool IsBidi() const
Definition: pormulti.hxx:133
MarkKind GetBookmark(TextFrameIndex nPos) const
Definition: porlay.cxx:1689
This portion represents a part of the paragraph string.
Definition: portxt.hxx:27
SwTwips Y() const
Definition: inftxt.hxx:387
bool IsSoftHyphPortion() const
Definition: porlin.hxx:127
SwTwips First() const
Definition: inftxt.hxx:552
static bool lcl_OldFieldRest(const SwLineLayout *pCurr)
Definition: itrform2.cxx:1201
std::unique_ptr< SwMultiCreator > GetMultiCreator(TextFrameIndex &rPos, SwMultiPortion const *pM) const
Definition: pormulti.cxx:907
TextFrameIndex NextDirChg(const TextFrameIndex nPos, const sal_uInt8 *pLevel=nullptr) const
Definition: porlay.cxx:1638
#define RES_FLYFRMFMT
Definition: hintids.hxx:369
bool IsBlinking() const
Definition: porlay.hxx:121
void CalcAscentAndHeight(sal_uInt16 &rAscent, sal_uInt16 &rHeight) const
Definition: itrtxt.cxx:63
void SetEndHyph(const bool bNew)
Definition: porlay.hxx:112
bool HasScriptSpace() const
Definition: inftxt.hxx:218
void SetRealHeight(sal_uInt16 nNew)
Definition: porlay.hxx:152
const SwViewOption & GetOpt() const
Definition: inftxt.hxx:245
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1290
void UpdatePos(SwLineLayout *pCurr, Point aStart, TextFrameIndex nStartIdx, bool bAlways=false) const
The position of the portions changes with the adjustment.
Definition: itrform2.cxx:2048
bool IsFootnoteNumPortion() const
Definition: porlin.hxx:119
bool m_bFlyInContentBase
Definition: itrform2.hxx:42
TextFrameIndex m_nRightScanIdx
Definition: itrform2.hxx:40
Style of a layout element.
Definition: frmfmt.hxx:57
SwTextInfo * m_pInf
Definition: itrtxt.hxx:35
SwTwips CalcFitToContent_()
Definition: itrform2.cxx:1973
void Bottom()
Definition: itrtxt.cxx:183
bool IsDummy() const
Definition: porlay.hxx:135
void SetBase(const SwTextFrame &rFrame, const Point &rBase, long nLnAscent, long nLnDescent, long nFlyAscent, long nFlyDescent, AsCharFlags nFlags)
After setting the RefPoints, the ascent needs to be recalculated because it is dependent on RelPos...
Definition: porfly.cxx:318
SwFrame * GetIndPrev() const
Definition: frame.hxx:704
bool m_bTruncLines
Definition: itrform2.hxx:43
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
SwTwips Left() const
Definition: itrtxt.hxx:333
int i
SwLinePortion * NewPortion(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:1229
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:78
void Reset()
Definition: redlnitr.hxx:113
SwMultiPortion * m_pMulti
Definition: itrform2.hxx:36
SwTwips GetLineWidth()
Returns the distance between the current horizontal position and the end of the line.
Definition: inftxt.cxx:1792
SwTextFly & GetTextFly()
Definition: inftxt.hxx:390
const sal_Unicode CH_TAB
Definition: swfont.hxx:44
SwPageFrame * FindPageFrame()
Definition: frame.hxx:660
SwParaPortion * GetParaPortion()
Definition: inftxt.hxx:128
void SetWhichPor(const PortionType nNew)
Definition: porlin.hxx:94
SwCharRange & GetReformat()
Definition: porlay.hxx:266
void SetUnderflow(SwLinePortion *pNew)
Definition: inftxt.hxx:607
bool IsFlyPortion() const
Definition: porlin.hxx:125
void RecalcRealHeight()
Definition: itrform2.cxx:1735
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2515
SwNumberPortion * NewNumberPortion(SwTextFormatInfo &rInf) const
Definition: txtfld.cxx:537
sal_uInt16 GetBottomBorderDist() const
Definition: swfont.hxx:360
SwLinePortion * GetFirstPortion() const
Definition: porlay.cxx:668
void CtorInitTextFormatter(SwTextFrame *pFrame, SwTextFormatInfo *pInf)
Definition: itrform2.cxx:82
const sal_Unicode CH_BLANK
Definition: swfont.hxx:42
void SelectFont()
Definition: inftxt.cxx:366
bool IsKernPortion() const
Definition: porlin.hxx:132
long GetHeight() const
Definition: swfont.hxx:283
void FinishKanaComp()
Definition: porlay.hxx:183
SwLinePortion * NewExtraPortion(SwTextFormatInfo &rInf)
Definition: txtfld.cxx:357
sal_uInt16 GetTopBorderSpace() const
Definition: swfont.hxx:863
std::unique_ptr< sw::MergedAttrIterByEnd > m_pByEndIter
Definition: itrform2.hxx:45
void BuildPortions(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:347
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:145
bool HasTruncLines() const
Definition: itrform2.hxx:204
void ResetSpaceIdx()
Definition: inftxt.hxx:443
SwTwips GetLeftMargin() const
Definition: itrtxt.hxx:328
sal_uInt16 Width() const
Definition: inftxt.hxx:534
void FinishSpaceAdd()
Definition: porlay.hxx:168
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2805
const SwFormatDrop * GetDropFormat() const
Definition: inftxt.cxx:1549
void SetJoinBorderWithNext(const bool bJoinNext)
Definition: porlin.hxx:171
PortionType
Definition: txttypes.hxx:23
SvxInterLineSpaceRule GetInterLineSpaceRule() const
void ResetMaxWidthDiff()
Definition: inftxt.hxx:314
void SetUnderScorePos(TextFrameIndex const nNew)
Definition: inftxt.hxx:648
SwFont * GetFnt()
Definition: itratr.hxx:103
bool IsTabLeftPortion() const
Definition: porlin.hxx:117
#define CHAR_ZWSP
Definition: swtypes.hxx:177
const std::optional< editeng::SvxBorderLine > & GetLeftBorder() const
Definition: swfont.hxx:342
sal_uInt16 GetLineHeight() const
Definition: itrtxt.hxx:116
TextFrameIndex GetIdx() const
Definition: inftxt.hxx:278
bool CheckFootnotePortion(SwLineLayout const *pCurr)
Definition: inftxt.hxx:655
bool IsDropPortion() const
Definition: porlin.hxx:121
void SetTabDecimal(const sal_Unicode cNew)
Definition: inftxt.hxx:624
void ClrUnderflow()
Definition: inftxt.hxx:590
bool isFrameAreaPositionValid() const
Definition: frame.hxx:164
bool IsQuick() const
Definition: itrform2.hxx:180
bool ChkFlyUnderflow(SwTextFormatInfo &rInf) const
This is called after the real height of the line has been calculated Therefore it is possible...
Definition: itrform2.cxx:2217
void SetTabOverflow(bool bOverflow)
Definition: inftxt.hxx:668
sal_Unicode GetHookChar() const
Definition: inftxt.hxx:628
const sal_uInt8 & CntMidHyph() const
Definition: itrform2.hxx:220
bool SnapToGrid() const
Definition: inftxt.hxx:222
TextFrameIndex GetLen() const
Definition: porlin.hxx:74
void SetFly(SwFlyPortion *pNew)
Definition: inftxt.hxx:616
A page of the document layout.
Definition: pagefrm.hxx:40
bool InTabGrp() const
Definition: porlin.hxx:100
const SwFormatFootnote & GetFootnote() const
Definition: txatbase.hxx:200
#define ODF_FORMFIELD_DEFAULT_LENGTH
SwTextFrame * GetTextFrame()
Definition: inftxt.hxx:291
void LeftMove(TextFrameIndex const nNew)
Definition: porlay.hxx:47
Point GetTopLeft() const
Definition: itrtxt.hxx:186
SwErgoSumPortion * NewErgoSumPortion(SwTextFormatInfo const &rInf) const
Definition: txtftn.cxx:999
const OUString & GetText() const
Definition: inftxt.hxx:246
bool IsStop() const
Definition: inftxt.hxx:580
short GetInterLineSpace() const
const SwLinePortion * GetUnderflow() const
Definition: inftxt.hxx:605
SwLayoutFrame * FindBodyCont()
Searches the first ContentFrame in BodyText below the page.
Definition: findfrm.cxx:42
void ClearHookChar()
Definition: inftxt.hxx:626
void Truncate()
Definition: porlin.hxx:196
bool HasBrackets() const
Definition: pormulti.hxx:249
const Point & GetPos() const
Definition: inftxt.hxx:435
bool IsMultiPortion() const
Definition: porlin.hxx:134
long GetPrtLeft(const SwFrame &rFrame) const
Definition: frame.hxx:1389
FontLineStyle GetUnderline() const
Definition: swfont.hxx:271
bool HasNegFirst() const
Definition: itrtxt.hxx:194
SwTwips X() const
Definition: inftxt.hxx:385
sal_uInt16 GetLeftBorderDist() const
Definition: swfont.hxx:362
void SwitchLTRtoRTL(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from LTR to RTL layout.
Definition: txtfrm.cxx:681
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:78
SwTextFrame * m_pFrame
Definition: itrtxt.hxx:34
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:50
void SetForcedLeftMargin()
Definition: porlay.hxx:126
bool IsFootnoteNumFrame() const
Am I a FootnoteFrame, with a number at the start of the paragraph?
Definition: txtfrm.hxx:615
void CalcAscent(SwTextFormatInfo &rInf, SwLinePortion *pPor)
Definition: itrform2.cxx:736
TextFrameIndex GetReformatStart() const
Definition: inftxt.hxx:770
SwTwips Right() const
Definition: inftxt.hxx:550
void Left(const long nLeft)
Definition: swrect.hxx:194
void SetSoftHyphPos(TextFrameIndex const nNew)
Definition: inftxt.hxx:610
#define RES_CHRATR_ROTATE
Definition: hintids.hxx:194
bool SeekAndChgBefore(SwTextSizeInfo &rInf)
Definition: itrtxt.hxx:315
void Bottom(const long nBottom)
Definition: swrect.hxx:208
#define CHAR_HARDHYPHEN
Definition: swtypes.hxx:173
TextFrameIndex m_nStart
Definition: itrtxt.hxx:41
TextFrameIndex FormatLine(TextFrameIndex nStart)
Definition: itrform2.cxx:1530
sal_Int16 ScriptType(const TextFrameIndex nPos) const
Definition: porlay.cxx:1625
void SwitchRTLtoLTR(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from RTL to LTR layout.
Definition: txtfrm.hxx:728
virtual bool Format(SwTextFormatInfo &rInf) override
Definition: txttab.cxx:300
SwTwips CalcBottomLine() const
Definition: itrform2.cxx:1948
SwTextPortion * WhichTextPor(SwTextFormatInfo &rInf) const
Definition: itrform2.cxx:875
SwMultiPortion * GetMulti() const
Definition: itrform2.hxx:199
bool IsRevers() const
Definition: pormulti.hxx:148
void SetLen(const TextFrameIndex nNew)
Definition: inftxt.hxx:281
bool InExpGrp() const
Definition: porlin.hxx:107
void SetFixLineHeight()
Definition: porlay.hxx:294
sal_uInt16 GetDropLeft() const
Definition: itrtxt.hxx:204
void CalcAdjustLine(SwLineLayout *pCurr)
Definition: itrform2.cxx:721
void CalcDropHeight(const sal_uInt16 nLines)
Definition: txtdrop.cxx:486
void SetNext(SwLineLayout *pNew)
Definition: porlay.hxx:145
PortionType GetWhichPor() const
Definition: porlin.hxx:95
SvxShadowLocation GetShadowLocation() const
Definition: swfont.hxx:379
SwRepaint & GetRepaint()
Definition: porlay.hxx:264
bool IsFootnotePortion() const
Definition: porlin.hxx:120
void SetFootnoteDone(const bool bNew)
Definition: inftxt.hxx:632
vcl::Window * GetWin() const
Definition: viewsh.hxx:340
SwLinePortion * GetRest()
Definition: inftxt.hxx:582
void SetDummy(const bool bNew)
Definition: porlay.hxx:134
SwLinePortion * FindLastPortion()
Definition: porlin.cxx:181
#define ODF_FORMDROPDOWN_LISTENTRY
bool IsErgoSumPortion() const
Definition: porlin.hxx:115
void ChkNoHyph(const sal_uInt8 bEnd, const sal_uInt8 bMid)
Definition: inftxt.hxx:573
void SetStopUnderflow(const bool bNew)
Definition: inftxt.hxx:205
#define ODF_FORMTEXT
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:175
SvxAdjust GetAdjust() const
Definition: itrtxt.hxx:190
bool IsLastCenter() const
Definition: itrtxt.hxx:189
bool IsFly() const
Definition: porlay.hxx:117
long GetNextTop() const
Definition: txtfly.hxx:346
TextFrameIndex NextBookmark(TextFrameIndex nPos) const
Definition: porlay.cxx:1677
const sal_uInt8 & CntEndHyph() const
Definition: itrform2.hxx:219
bool IsRightToLeft() const
Definition: frame.hxx:965
TextFrameIndex GetLen() const
Definition: inftxt.hxx:280
SwLinePortion * Underflow(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:147
sal_uInt16 GetBottomBorderSpace() const
Definition: swfont.hxx:878
void SetErgoDone(const bool bNew)
Definition: inftxt.hxx:634
void SetDirection(const sal_uInt8 nNew)
Definition: inftxt.hxx:225
void SetShift(const bool bNew)
Definition: inftxt.hxx:587
sal_uInt8 m_nContentMidHyph
Definition: itrform2.hxx:38
void SetLineStart(TextFrameIndex const nNew)
Definition: inftxt.hxx:597
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 GetCharRect(SwRect *, TextFrameIndex, SwCursorMoveState *=nullptr, const long nMax=0)
Definition: itrcrsr.cxx:1168
SwLinePortion * GetLast()
Definition: inftxt.hxx:567
sal_uInt16 GetGridWidth(SwTextGridItem const &, SwDoc const &)
Definition: pagechg.cxx:2529
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
SwNumberPortion * NewFootnoteNumPortion(SwTextFormatInfo const &rInf) const
The portion for the Footnote Numbering in the Footnote Area.
Definition: txtftn.cxx:918
bool CheckCurrentPosBookmark()
Definition: inftxt.cxx:2015
const Color & GetShadowColor() const
Definition: swfont.hxx:377
SwTextPortion * NewTextPortion(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:959
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:147
#define CHAR_ZWNBSP
Definition: swtypes.hxx:178
void SetNextPortion(SwLinePortion *pNew)
Definition: porlin.hxx:76
bool IsSnapToChars() const
Definition: tgrditem.hxx:100
static DrawFlyCntPortion * Create(const SwTextFrame &rFrame, SwFrameFormat const &rFormat, const Point &rBase, long nAsc, long nDescent, long nFlyAsc, long nFlyDesc, AsCharFlags nFlags)
Definition: porfly.cxx:278
void SetJoinBorderWithNext(const bool bJoinNext)
Definition: pordrop.hxx:58
void FeedInf(SwTextFormatInfo &rInf) const
Definition: itrform2.cxx:1896
static bool GetBoundsOfHiddenRange(const SwTextNode &rNode, sal_Int32 nPos, sal_Int32 &rnStartPos, sal_Int32 &rnEndPos, std::vector< sal_Int32 > *pList=nullptr)
Hidden text range information - static and non-version.
Definition: porlay.cxx:1761
const std::optional< editeng::SvxBorderLine > & GetTopBorder() const
Definition: swfont.hxx:339
sal_uInt16 GetRealHeight() const
Definition: porlay.hxx:153
#define ODF_FORMDATE
const SwLineLayout * GetCurr() const
Definition: itrtxt.hxx:83
void SetAscent(const sal_uInt16 nNewAsc)
Definition: porlin.hxx:79
for showing bookmark starts and ends; note that in contrast to SwControlCharPortion these do not have...
Definition: porrst.hxx:157
bool IsVertical() const
Definition: frame.hxx:951
SwDropPortionPart * GetFollow() const
Definition: pordrop.hxx:48
virtual OUString GetFieldname() const =0
void SetNewLine(const bool bNew)
Definition: inftxt.hxx:585
void Insert(SwLineLayout *pLine)
Definition: itrform2.cxx:118
void SetOtherThanFootnoteInside(const bool bNew)
Definition: inftxt.hxx:209
void SetLineHeight(const sal_uInt16 nNew)
Definition: inftxt.hxx:601
SwDoc & GetDoc()
Definition: txtfrm.hxx:450
bool IsOtherThanFootnoteInside() const
Definition: inftxt.hxx:208
bool IsOn() const
Definition: txtfly.hxx:313
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
SwTextGrid GetGridType() const
Definition: tgrditem.hxx:81
bool IsTest() const
Definition: inftxt.hxx:594
bool IsShowHiddenChar(bool bHard=false) const
Definition: viewopt.hxx:293
SwTextFrame * GetTextFrame()
Definition: itrtxt.hxx:134
bool IsFlyInCntBase() const
Definition: itrform2.hxx:210
void ResetKanaIdx()
Definition: inftxt.hxx:326
SwLineLayout * m_pCurr
Definition: itrtxt.hxx:36
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
static void ClearFly(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:76
void SetJoinBorderWithPrev(const bool bJoinPrev)
Definition: pordrop.hxx:57
virtual void FormatEOL(SwTextFormatInfo &rInf)
Definition: porlin.cxx:268
SwLinePortion * m_pFirstOfBorderMerge
Definition: itrform2.hxx:46
TextFrameIndex m_nLeftScanIdx
Definition: itrform2.hxx:39
bool IsQuoVadisPortion() const
Definition: porlin.hxx:116
sal_uInt16 GetBaseHeight() const
Definition: tgrditem.hxx:75
SwFlyPortion * GetFly()
Definition: inftxt.hxx:615
void SetMidHyph(const bool bNew)
Definition: porlay.hxx:114
void DropInit()
Definition: itrcrsr.cxx:348
bool GetJoinBorderWithNext() const
Definition: porlin.hxx:169
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:72
sal_uInt16 GetLineHeight() const
Definition: inftxt.hxx:600
#define CH_TXT_ATR_FIELDSEP
Definition: hintids.hxx:146
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...
void AlignFlyInCntBase(long nBaseLine) const
Set all anchored as character objects to the passed BaseLine (in Y direction).
Definition: itrform2.cxx:2170
void SetRest(SwLinePortion *pNewRest)
Definition: inftxt.hxx:583
CharClass & GetAppCharClass()
Definition: init.cxx:709
sal_uInt16 GetFrameRstHeight() const
Definition: itrform2.cxx:130
void SetDropInit(const bool bNew)
Definition: inftxt.hxx:592
virtual void FormatEOL(SwTextFormatInfo &rInf) override
Definition: txttab.cxx:310
bool IsFlyCntPortion() const
Definition: porlin.hxx:112
sal_uInt16 GetRubyHeight() const
Definition: tgrditem.hxx:78
void Clear(SwFont *pFnt)
Definition: redlnitr.hxx:110
sal_uInt16 & GetAscent()
Definition: porlin.hxx:77
void SetpSpaceAdd(std::vector< long > *pNew)
Definition: inftxt.hxx:451
const SwFootnoteInfo & GetFootnoteInfo() const
Definition: doc.hxx:626
virtual SwLinePortion * Insert(SwLinePortion *pPortion)
Definition: porlin.cxx:171
SwRedlineItr * GetRedln()
Definition: itratr.hxx:81
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
TextFrameIndex GetSoftHyphPos() const
Definition: inftxt.hxx:609
void DrawViewOpt(const SwLinePortion &rPor, PortionType nWhich) const
Definition: inftxt.cxx:1352
bool IsFootnoteDone() const
Definition: inftxt.hxx:631
const SwEndNoteInfo & GetEndNoteInfo() const
Definition: doc.hxx:628
SwLinePortion * WhichFirstPortion(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:1033
bool IsPostItsPortion() const
Definition: porlin.hxx:128
SwDropPortion * NewDropPortion(SwTextFormatInfo &rInf)
Definition: txtdrop.cxx:563
bool CalcOnceMore()
Definition: itrform2.cxx:1935
#define ODF_FORMDROPDOWN
sal_uInt16 GetAscent() const
Definition: inftxt.hxx:713
SwFont & GetFont() const
Definition: pordrop.hxx:50
SwTwips GetLeftMin() const
Definition: itrtxt.hxx:193
void Init(SwLinePortion *pNextPortion=nullptr)
Definition: porlay.cxx:2407
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo