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  pPor = NewPortion( rInf );
695  }
696 
697  if( !rInf.IsStop() )
698  {
699  // The last right centered, decimal tab
700  SwTabPortion *pLastTab = rInf.GetLastTab();
701  if( pLastTab )
702  pLastTab->FormatEOL( rInf );
703  else if( rInf.GetLast() && rInf.LastKernPortion() )
704  rInf.GetLast()->FormatEOL( rInf );
705  }
707  && static_cast<SwNumberPortion*>(m_pCurr->GetNextPortion())->IsHide() )
708  rInf.SetNumDone( false );
709 
710  // Delete fly in any case
711  ClearFly( rInf );
712 
713  // Reinit the tab overflow flag after the line
714  rInf.SetTabOverflow( false );
715 }
716 
718 {
719  if( SvxAdjust::Left != GetAdjust() && !m_pMulti)
720  {
721  pCurrent->SetFormatAdj(true);
722  if( IsFlyInCntBase() )
723  {
724  CalcAdjLine( pCurrent );
725  // For e.g. centered fly we need to switch the RefPoint
726  // That's why bAlways = true
727  UpdatePos( pCurrent, GetTopLeft(), GetStart(), true );
728  }
729  }
730 }
731 
733 {
734  bool bCalc = false;
735  if ( pPor->InFieldGrp() && static_cast<SwFieldPortion*>(pPor)->GetFont() )
736  {
737  // Numbering + InterNetFields can keep an own font, then their size is
738  // independent from hard attribute values
739  SwFont* pFieldFnt = static_cast<SwFieldPortion*>(pPor)->m_pFont.get();
740  SwFontSave aSave( rInf, pFieldFnt );
741  pPor->Height( rInf.GetTextHeight() );
742  pPor->SetAscent( rInf.GetAscent() );
743  bCalc = true;
744  }
745  // i#89179
746  // tab portion representing the list tab of a list label gets the
747  // same height and ascent as the corresponding number portion
748  else if ( pPor->InTabGrp() && pPor->GetLen() == TextFrameIndex(0) &&
749  rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
750  static_cast<const SwNumberPortion*>(rInf.GetLast())->HasFont() )
751  {
752  const SwLinePortion* pLast = rInf.GetLast();
753  pPor->Height( pLast->Height() );
754  pPor->SetAscent( pLast->GetAscent() );
755  }
756  else
757  {
758  const SwLinePortion *pLast = rInf.GetLast();
759  bool bChg = false;
760 
761  // In empty lines the attributes are switched on via SeekStart
762  const bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
763  if ( pPor->IsQuoVadisPortion() )
764  bChg = SeekStartAndChg( rInf, true );
765  else
766  {
767  if( bFirstPor )
768  {
769  if( !rInf.GetText().isEmpty() )
770  {
771  if ( pPor->GetLen() || !rInf.GetIdx()
772  || ( m_pCurr != pLast && !pLast->IsFlyPortion() )
773  || !m_pCurr->IsRest() ) // instead of !rInf.GetRest()
774  bChg = SeekAndChg( rInf );
775  else
776  bChg = SeekAndChgBefore( rInf );
777  }
778  else if ( m_pMulti )
779  // do not open attributes starting at 0 in empty multi
780  // portions (rotated numbering followed by a footnote
781  // can cause trouble, because the footnote attribute
782  // starts at 0, but if we open it, the attribute handler
783  // cannot handle it.
784  bChg = false;
785  else
786  bChg = SeekStartAndChg( rInf );
787  }
788  else
789  bChg = SeekAndChg( rInf );
790  }
791  if( bChg || bFirstPor || !pPor->GetAscent()
792  || !rInf.GetLast()->InTextGrp() )
793  {
794  pPor->SetAscent( rInf.GetAscent() );
795  pPor->Height( rInf.GetTextHeight() );
796  bCalc = true;
797  }
798  else
799  {
800  pPor->Height( pLast->Height() );
801  pPor->SetAscent( pLast->GetAscent() );
802  }
803  }
804 
805  if( pPor->InTextGrp() && bCalc )
806  {
807  pPor->SetAscent(pPor->GetAscent() +
808  rInf.GetFont()->GetTopBorderSpace());
809  pPor->Height(pPor->Height() +
810  rInf.GetFont()->GetTopBorderSpace() +
811  rInf.GetFont()->GetBottomBorderSpace() );
812  }
813 }
814 
815 namespace {
816 
817 class SwMetaPortion : public SwTextPortion
818 {
819 public:
820  SwMetaPortion() { SetWhichPor( PortionType::Meta ); }
821  virtual void Paint( const SwTextPaintInfo &rInf ) const override;
822 };
823 
824 }
825 
826 void SwMetaPortion::Paint( const SwTextPaintInfo &rInf ) const
827 {
828  if ( Width() )
829  {
830  rInf.DrawViewOpt( *this, PortionType::Meta );
831  SwTextPortion::Paint( rInf );
832  }
833 }
834 
835 namespace sw::mark {
837  {
838  const IFieldmark::parameter_map_t* const pParameters = pBM->GetParameters();
839  sal_Int32 nCurrentIdx = 0;
840  const IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find(OUString(ODF_FORMDROPDOWN_RESULT));
841  if(pResult != pParameters->end())
842  pResult->second >>= nCurrentIdx;
843 
844  const IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(OUString(ODF_FORMDROPDOWN_LISTENTRY));
845  if (pListEntries != pParameters->end())
846  {
847  uno::Sequence< OUString > vListEntries;
848  pListEntries->second >>= vListEntries;
849  if (nCurrentIdx < vListEntries.getLength())
850  return vListEntries[nCurrentIdx];
851  }
852 
853  static const sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
854  return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH);
855  }
856 }
857 
859 {
860  SwTextPortion *pPor = nullptr;
861  if( GetFnt()->IsTox() )
862  {
863  pPor = new SwToxPortion;
864  }
865  else if ( GetFnt()->IsInputField() )
866  {
867  pPor = new SwTextInputFieldPortion();
868  }
869  else
870  {
871  if( GetFnt()->IsRef() )
872  pPor = new SwRefPortion;
873  else if (GetFnt()->IsMeta())
874  {
875  pPor = new SwMetaPortion;
876  }
877  else
878  {
879  // Only at the End!
880  // If pCurr does not have a width, it can however already have content.
881  // E.g. for non-displayable characters
882 
883  auto const ch(rInf.GetText()[sal_Int32(rInf.GetIdx())]);
884  SwTextFrame const*const pFrame(rInf.GetTextFrame());
885  SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx()));
886  sw::mark::IFieldmark *pBM = pFrame->GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
887  if(pBM != nullptr && pBM->GetFieldname( ) == ODF_FORMDATE)
888  {
889  if (ch == CH_TXT_ATR_FIELDSTART)
890  pPor = new SwFieldFormDatePortion(pBM, true);
891  else if (ch == CH_TXT_ATR_FIELDSEP)
892  pPor = new SwFieldMarkPortion(); // it's added in DateFieldmark?
893  else if (ch == CH_TXT_ATR_FIELDEND)
894  pPor = new SwFieldFormDatePortion(pBM, false);
895  }
896  else if (ch == CH_TXT_ATR_FIELDSTART)
897  pPor = new SwFieldMarkPortion();
898  else if (ch == CH_TXT_ATR_FIELDSEP)
899  pPor = new SwFieldMarkPortion();
900  else if (ch == CH_TXT_ATR_FIELDEND)
901  pPor = new SwFieldMarkPortion();
902  else if (ch == CH_TXT_ATR_FORMELEMENT)
903  {
904  OSL_ENSURE(pBM != nullptr, "Where is my form field bookmark???");
905  if (pBM != nullptr)
906  {
907  if (pBM->GetFieldname( ) == ODF_FORMCHECKBOX)
908  {
909  pPor = new SwFieldFormCheckboxPortion();
910  }
911  else if (pBM->GetFieldname( ) == ODF_FORMDROPDOWN)
912  {
914  }
915  /* we need to check for ODF_FORMTEXT for scenario having FormFields inside FORMTEXT.
916  * Otherwise file will crash on open.
917  */
918  else if (pBM->GetFieldname( ) == ODF_FORMTEXT)
919  {
920  pPor = new SwFieldMarkPortion();
921  }
922  }
923  }
924  if( !pPor )
925  {
926  if( !rInf.X() && !m_pCurr->GetNextPortion() && !m_pCurr->GetLen() )
927  pPor = m_pCurr;
928  else
929  pPor = new SwTextPortion;
930  }
931  }
932  }
933  return pPor;
934 }
935 
936 // We calculate the length, the following portion limits are defined:
937 // 1) Tabs
938 // 2) Linebreaks
939 // 3) CH_TXTATR_BREAKWORD / CH_TXTATR_INWORD
940 // 4) next attribute change
941 
943 {
944  // If we're at the line's beginning, we take pCurr
945  // If pCurr is not derived from SwTextPortion, we need to duplicate
946  Seek( rInf.GetIdx() );
947  SwTextPortion *pPor = WhichTextPor( rInf );
948 
949  // until next attribute change:
950  const TextFrameIndex nNextAttr = GetNextAttr();
951  TextFrameIndex nNextChg = std::min(nNextAttr, TextFrameIndex(rInf.GetText().getLength()));
952 
953  // end of script type:
954  const TextFrameIndex nNextScript = m_pScriptInfo->NextScriptChg(rInf.GetIdx());
955  nNextChg = std::min( nNextChg, nNextScript );
956 
957  // end of direction:
958  const TextFrameIndex nNextDir = m_pScriptInfo->NextDirChg(rInf.GetIdx());
959  nNextChg = std::min( nNextChg, nNextDir );
960 
961  // hidden change (potentially via bookmark):
962  const TextFrameIndex nNextHidden = m_pScriptInfo->NextHiddenChg(rInf.GetIdx());
963  nNextChg = std::min( nNextChg, nNextHidden );
964 
965  // Turbo boost:
966  // We assume that font characters are not larger than twice
967  // as wide as height.
968  // Very crazy: we need to take the ascent into account.
969 
970  // Mind the trap! GetSize() contains the wished-for height, the real height
971  // is only known in CalcAscent!
972 
973  // The ratio is even crazier: a blank in Times New Roman has an ascent of
974  // 182, a height of 200 and a width of 53!
975  // It follows that a line with a lot of blanks is processed incorrectly.
976  // Therefore we increase from factor 2 to 8 (due to negative kerning).
977 
978  pPor->SetLen(TextFrameIndex(1));
979  CalcAscent( rInf, pPor );
980 
981  const SwFont* pTmpFnt = rInf.GetFont();
982  sal_Int32 nExpect = std::min( sal_Int32( pTmpFnt->GetHeight() ),
983  sal_Int32( pPor->GetAscent() ) ) / 8;
984  if ( !nExpect )
985  nExpect = 1;
986  nExpect = sal_Int32(rInf.GetIdx()) + (rInf.GetLineWidth() / nExpect);
987  if (TextFrameIndex(nExpect) > rInf.GetIdx() && nNextChg > TextFrameIndex(nExpect))
988  nNextChg = TextFrameIndex(std::min(nExpect, rInf.GetText().getLength()));
989 
990  // we keep an invariant during method calls:
991  // there are no portion ending characters like hard spaces
992  // or tabs in [ nLeftScanIdx, nRightScanIdx ]
993  if ( m_nLeftScanIdx <= rInf.GetIdx() && rInf.GetIdx() <= m_nRightScanIdx )
994  {
995  if ( nNextChg > m_nRightScanIdx )
996  nNextChg = m_nRightScanIdx =
997  rInf.ScanPortionEnd( m_nRightScanIdx, nNextChg );
998  }
999  else
1000  {
1001  m_nLeftScanIdx = rInf.GetIdx();
1002  nNextChg = m_nRightScanIdx =
1003  rInf.ScanPortionEnd( rInf.GetIdx(), nNextChg );
1004  }
1005 
1006  pPor->SetLen( nNextChg - rInf.GetIdx() );
1007  rInf.SetLen( pPor->GetLen() );
1008  return pPor;
1009 }
1010 
1012 {
1013  SwLinePortion *pPor = nullptr;
1014 
1015  if( rInf.GetRest() )
1016  {
1017  // Tabs and fields
1018  if( '\0' != rInf.GetHookChar() )
1019  return nullptr;
1020 
1021  pPor = rInf.GetRest();
1022  if( pPor->IsErgoSumPortion() )
1023  rInf.SetErgoDone(true);
1024  else
1025  if( pPor->IsFootnoteNumPortion() )
1026  rInf.SetFootnoteDone(true);
1027  else
1028  if( pPor->InNumberGrp() )
1029  rInf.SetNumDone(true);
1030 
1031  rInf.SetRest(nullptr);
1032  m_pCurr->SetRest( true );
1033  return pPor;
1034  }
1035 
1036  // We can stand in the follow, it's crucial that
1037  // pFrame->GetOfst() == 0!
1038  if( rInf.GetIdx() )
1039  {
1040  // We now too can elongate FootnotePortions and ErgoSumPortions
1041 
1042  // 1. The ErgoSumTexts
1043  if( !rInf.IsErgoDone() )
1044  {
1045  if( m_pFrame->IsInFootnote() && !m_pFrame->GetIndPrev() )
1046  pPor = NewErgoSumPortion( rInf );
1047  rInf.SetErgoDone( true );
1048  }
1049 
1050  // 2. Arrow portions
1051  if( !pPor && !rInf.IsArrowDone() )
1052  {
1053  if( m_pFrame->GetOfst() && !m_pFrame->IsFollow() &&
1054  rInf.GetIdx() == m_pFrame->GetOfst() )
1055  pPor = new SwArrowPortion( *m_pCurr );
1056  rInf.SetArrowDone( true );
1057  }
1058 
1059  // 3. Kerning portions at beginning of line in grid mode
1060  if ( ! pPor && ! m_pCurr->GetNextPortion() )
1061  {
1062  SwTextGridItem const*const pGrid(
1063  GetGridItem(GetTextFrame()->FindPageFrame()));
1064  if ( pGrid )
1065  pPor = new SwKernPortion( *m_pCurr );
1066  }
1067 
1068  // 4. The line rests (multiline fields)
1069  if( !pPor )
1070  {
1071  pPor = rInf.GetRest();
1072  // Only for pPor of course
1073  if( pPor )
1074  {
1075  m_pCurr->SetRest( true );
1076  rInf.SetRest(nullptr);
1077  }
1078  }
1079  }
1080  else
1081  {
1082  // 5. The foot note count
1083  if( !rInf.IsFootnoteDone() )
1084  {
1085  OSL_ENSURE( ( ! rInf.IsMulti() && ! m_pMulti ) || m_pMulti->HasRotation(),
1086  "Rotated number portion trouble" );
1087 
1088  const bool bFootnoteNum = m_pFrame->IsFootnoteNumFrame();
1089  rInf.GetParaPortion()->SetFootnoteNum( bFootnoteNum );
1090  if( bFootnoteNum )
1091  pPor = NewFootnoteNumPortion( rInf );
1092  rInf.SetFootnoteDone( true );
1093  }
1094 
1095  // 6. The ErgoSumTexts of course also exist in the TextMaster,
1096  // it's crucial whether the SwFootnoteFrame is aFollow
1097  if( !rInf.IsErgoDone() && !pPor && ! rInf.IsMulti() )
1098  {
1099  if( m_pFrame->IsInFootnote() && !m_pFrame->GetIndPrev() )
1100  pPor = NewErgoSumPortion( rInf );
1101  rInf.SetErgoDone( true );
1102  }
1103 
1104  // 7. The numbering
1105  if( !rInf.IsNumDone() && !pPor )
1106  {
1107  OSL_ENSURE( ( ! rInf.IsMulti() && ! m_pMulti ) || m_pMulti->HasRotation(),
1108  "Rotated number portion trouble" );
1109 
1110  // If we're in the follow, then of course not
1112  pPor = NewNumberPortion( rInf );
1113  rInf.SetNumDone( true );
1114  }
1115  // 8. The DropCaps
1116  if( !pPor && GetDropFormat() && ! rInf.IsMulti() )
1117  pPor = NewDropPortion( rInf );
1118 
1119  // 9. Kerning portions at beginning of line in grid mode
1120  if ( !pPor && !m_pCurr->GetNextPortion() )
1121  {
1122  SwTextGridItem const*const pGrid(
1123  GetGridItem(GetTextFrame()->FindPageFrame()));
1124  if ( pGrid )
1125  pPor = new SwKernPortion( *m_pCurr );
1126  }
1127  }
1128 
1129  // 10. Decimal tab portion at the beginning of each line in table cells
1130  if ( !pPor && !m_pCurr->GetNextPortion() &&
1131  GetTextFrame()->IsInTab() &&
1133  {
1134  pPor = NewTabPortion( rInf, true );
1135  }
1136 
1137  // 11. suffix of meta-field
1138  if (!pPor)
1139  {
1140  pPor = TryNewNoLengthPortion(rInf);
1141  }
1142 
1143  return pPor;
1144 }
1145 
1146 static bool lcl_OldFieldRest( const SwLineLayout* pCurr )
1147 {
1148  if( !pCurr->GetNext() )
1149  return false;
1150  const SwLinePortion *pPor = pCurr->GetNext()->GetNextPortion();
1151  bool bRet = false;
1152  while( pPor && !bRet )
1153  {
1154  bRet = (pPor->InFieldGrp() && static_cast<const SwFieldPortion*>(pPor)->IsFollow()) ||
1155  (pPor->IsMultiPortion() && static_cast<const SwMultiPortion*>(pPor)->IsFollowField());
1156  if( !pPor->GetLen() )
1157  break;
1158  pPor = pPor->GetNextPortion();
1159  }
1160  return bRet;
1161 }
1162 
1163 /* NewPortion sets rInf.nLen
1164  * A SwTextPortion is limited by a tab, break, txtatr or attr change
1165  * We can have three cases:
1166  * 1) The line is full and the wrap was not emulated
1167  * -> return 0;
1168  * 2) The line is full and a wrap was emulated
1169  * -> Reset width and return new FlyPortion
1170  * 3) We need to construct a new portion
1171  * -> CalcFlyWidth emulates the width and return portion, if needed
1172  */
1173 
1175 {
1176  // Underflow takes precedence
1177  rInf.SetStopUnderflow( false );
1178  if( rInf.GetUnderflow() )
1179  {
1180  OSL_ENSURE( rInf.IsFull(), "SwTextFormatter::NewPortion: underflow but not full" );
1181  return Underflow( rInf );
1182  }
1183 
1184  // If the line is full, flys and Underflow portions could be waiting ...
1185  if( rInf.IsFull() )
1186  {
1187  // LineBreaks and Flys (bug05.sdw)
1188  // IsDummy()
1189  if( rInf.IsNewLine() && (!rInf.GetFly() || !m_pCurr->IsDummy()) )
1190  return nullptr;
1191 
1192  // When the text bumps into the Fly, or when the Fly comes first because
1193  // it juts out over the left edge, GetFly() is returned.
1194  // When IsFull() and no GetFly() is available, naturally zero is returned.
1195  if( rInf.GetFly() )
1196  {
1197  if( rInf.GetLast()->IsBreakPortion() )
1198  {
1199  delete rInf.GetFly();
1200  rInf.SetFly( nullptr );
1201  }
1202 
1203  return rInf.GetFly();
1204  }
1205 
1206  // A nasty special case: A frame without wrap overlaps the Footnote area.
1207  // We must declare the Footnote portion as rest of line, so that
1208  // SwTextFrame::Format doesn't abort (the text mass already was formatted).
1209  if( rInf.GetRest() )
1210  rInf.SetNewLine( true );
1211  else
1212  {
1213  // When the next line begins with a rest of a field, but now no
1214  // rest remains, the line must definitely be formatted anew!
1215  if( lcl_OldFieldRest( GetCurr() ) )
1216  rInf.SetNewLine( true );
1217  else
1218  {
1219  SwLinePortion *pFirst = WhichFirstPortion( rInf );
1220  if( pFirst )
1221  {
1222  rInf.SetNewLine( true );
1223  if( pFirst->InNumberGrp() )
1224  rInf.SetNumDone( false) ;
1225  delete pFirst;
1226  }
1227  }
1228  }
1229 
1230  return nullptr;
1231  }
1232 
1233  SwLinePortion *pPor = WhichFirstPortion( rInf );
1234 
1235  // Check for Hidden Portion:
1236  if ( !pPor )
1237  {
1238  TextFrameIndex nEnd = rInf.GetIdx();
1239  if ( ::lcl_BuildHiddenPortion( rInf, nEnd ) )
1240  pPor = new SwHiddenTextPortion( nEnd - rInf.GetIdx() );
1241  }
1242 
1243  if( !pPor )
1244  {
1245  if( ( !m_pMulti || m_pMulti->IsBidi() ) &&
1246  // i#42734
1247  // No multi portion if there is a hook character waiting:
1248  ( !rInf.GetRest() || '\0' == rInf.GetHookChar() ) )
1249  {
1250  // We open a multiportion part, if we enter a multi-line part
1251  // of the paragraph.
1252  TextFrameIndex nEnd = rInf.GetIdx();
1253  std::unique_ptr<SwMultiCreator> pCreate = rInf.GetMultiCreator( nEnd, m_pMulti );
1254  if( pCreate )
1255  {
1256  SwMultiPortion* pTmp = nullptr;
1257 
1258  if ( SwMultiCreatorId::Bidi == pCreate->nId )
1259  pTmp = new SwBidiPortion( nEnd, pCreate->nLevel );
1260  else if ( SwMultiCreatorId::Ruby == pCreate->nId )
1261  {
1262  pTmp = new SwRubyPortion( *pCreate, *rInf.GetFont(),
1264  nEnd, TextFrameIndex(0), rInf );
1265  }
1266  else if( SwMultiCreatorId::Rotate == pCreate->nId )
1267  {
1268  pTmp = new SwRotatedPortion( *pCreate, nEnd,
1269  GetTextFrame()->IsRightToLeft() );
1271  }
1272  else
1273  pTmp = new SwDoubleLinePortion( *pCreate, nEnd );
1274 
1275  pCreate.reset();
1276  CalcFlyWidth( rInf );
1277 
1278  return pTmp;
1279  }
1280  }
1281  // Tabs and Fields
1282  sal_Unicode cChar = rInf.GetHookChar();
1283 
1284  if( cChar )
1285  {
1286  /* We fetch cChar again to be sure that the tab is pending now and
1287  * didn't move to the next line (as happens behind frames).
1288  * However, when a FieldPortion is in the rest, we must naturally fetch
1289  * the cChar from the field content, e.g. DecimalTabs and fields (22615)
1290  */
1291  if( !rInf.GetRest() || !rInf.GetRest()->InFieldGrp() )
1292  cChar = rInf.GetChar( rInf.GetIdx() );
1293  rInf.ClearHookChar();
1294  }
1295  else
1296  {
1297  if (rInf.GetIdx() >= TextFrameIndex(rInf.GetText().getLength()))
1298  {
1299  rInf.SetFull(true);
1300  CalcFlyWidth( rInf );
1301  return pPor;
1302  }
1303  cChar = rInf.GetChar( rInf.GetIdx() );
1304  }
1305 
1306  switch( cChar )
1307  {
1308  case CH_TAB:
1309  pPor = NewTabPortion( rInf, false ); break;
1310 
1311  case CH_BREAK:
1312  pPor = new SwBreakPortion( *rInf.GetLast() ); break;
1313 
1314  case CHAR_SOFTHYPHEN: // soft hyphen
1315  pPor = new SwSoftHyphPortion; break;
1316 
1317  case CHAR_HARDBLANK: // no-break space
1318  // Please check tdf#115067 if you want to edit the char
1319  pPor = new SwBlankPortion( cChar ); break;
1320 
1321  case CHAR_HARDHYPHEN: // non-breaking hyphen
1322  pPor = new SwBlankPortion( '-' ); break;
1323 
1324  case CHAR_ZWSP: // zero width space
1325  case CHAR_ZWNBSP : // word joiner
1326  pPor = new SwControlCharPortion( cChar ); break;
1327 
1328  case CH_TXTATR_BREAKWORD:
1329  case CH_TXTATR_INWORD:
1330  if( rInf.HasHint( rInf.GetIdx() ) )
1331  {
1332  pPor = NewExtraPortion( rInf );
1333  break;
1334  }
1335  [[fallthrough]];
1336  default :
1337  {
1338  SwTabPortion* pLastTabPortion = rInf.GetLastTab();
1339  if ( pLastTabPortion && cChar == rInf.GetTabDecimal() )
1340  {
1341  // Abandon dec. tab position if line is full
1342  // We have a decimal tab portion in the line and the next character has to be
1343  // aligned at the tab stop position. We store the width from the beginning of
1344  // the tab stop portion up to the portion containing the decimal separator:
1345  if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT) /*rInf.GetVsh()->IsTabCompat();*/ &&
1346  PortionType::TabDecimal == pLastTabPortion->GetWhichPor() )
1347  {
1348  OSL_ENSURE( rInf.X() >= pLastTabPortion->GetFix(), "Decimal tab stop position cannot be calculated" );
1349  const sal_uInt16 nWidthOfPortionsUpToDecimalPosition = static_cast<sal_uInt16>(rInf.X() - pLastTabPortion->GetFix() );
1350  static_cast<SwTabDecimalPortion*>(pLastTabPortion)->SetWidthOfPortionsUpToDecimalPosition( nWidthOfPortionsUpToDecimalPosition );
1351  rInf.SetTabDecimal( 0 );
1352  }
1353  else
1354  rInf.SetFull( rInf.GetLastTab()->Format( rInf ) );
1355  }
1356 
1357  if( rInf.GetRest() )
1358  {
1359  if( rInf.IsFull() )
1360  {
1361  rInf.SetNewLine(true);
1362  return nullptr;
1363  }
1364  pPor = rInf.GetRest();
1365  rInf.SetRest(nullptr);
1366  }
1367  else
1368  {
1369  if( rInf.IsFull() )
1370  return nullptr;
1371  pPor = NewTextPortion( rInf );
1372  }
1373  break;
1374  }
1375  }
1376 
1377  // if a portion is created despite there being a pending RestPortion,
1378  // then it is a field which has been split (e.g. because it contains a Tab)
1379  if( pPor && rInf.GetRest() )
1380  pPor->SetLen(TextFrameIndex(0));
1381 
1382  // robust:
1383  if( !pPor || rInf.IsStop() )
1384  {
1385  delete pPor;
1386  return nullptr;
1387  }
1388  }
1389 
1390  assert(pPor && "can only reach here with pPor existing");
1391 
1392  // Special portions containing numbers (footnote anchor, footnote number,
1393  // numbering) can be contained in a rotated portion, if the user
1394  // choose a rotated character attribute.
1395  if (!m_pMulti)
1396  {
1397  if ( pPor->IsFootnotePortion() )
1398  {
1399  const SwTextFootnote* pTextFootnote = static_cast<SwFootnotePortion*>(pPor)->GetTextFootnote();
1400 
1401  if ( pTextFootnote )
1402  {
1403  SwFormatFootnote& rFootnote = const_cast<SwFormatFootnote&>(pTextFootnote->GetFootnote());
1404  const SwDoc *const pDoc = &rInf.GetTextFrame()->GetDoc();
1405  const SwEndNoteInfo* pInfo;
1406  if( rFootnote.IsEndNote() )
1407  pInfo = &pDoc->GetEndNoteInfo();
1408  else
1409  pInfo = &pDoc->GetFootnoteInfo();
1410  const SwAttrSet& rSet = pInfo->GetAnchorCharFormat(const_cast<SwDoc&>(*pDoc))->GetAttrSet();
1411 
1412  const SfxPoolItem* pItem;
1413  sal_uInt16 nDir = 0;
1414  if( SfxItemState::SET == rSet.GetItemState( RES_CHRATR_ROTATE,
1415  true, &pItem ))
1416  nDir = static_cast<const SvxCharRotateItem*>(pItem)->GetValue();
1417 
1418  if ( 0 != nDir )
1419  {
1420  delete pPor;
1421  pPor = new SwRotatedPortion(rInf.GetIdx() + TextFrameIndex(1),
1422  900 == nDir
1423  ? DIR_BOTTOM2TOP
1424  : DIR_TOP2BOTTOM );
1425  }
1426  }
1427  }
1428  else if ( pPor->InNumberGrp() )
1429  {
1430  const SwFont* pNumFnt = static_cast<SwFieldPortion*>(pPor)->GetFont();
1431 
1432  if ( pNumFnt )
1433  {
1434  sal_uInt16 nDir = pNumFnt->GetOrientation( rInf.GetTextFrame()->IsVertical() );
1435  if ( 0 != nDir )
1436  {
1437  delete pPor;
1438  pPor = new SwRotatedPortion(TextFrameIndex(0), 900 == nDir
1439  ? DIR_BOTTOM2TOP
1440  : DIR_TOP2BOTTOM );
1441 
1442  rInf.SetNumDone( false );
1443  rInf.SetFootnoteDone( false );
1444  }
1445  }
1446  }
1447  }
1448 
1449  // The font is set in output device,
1450  // the ascent and the height will be calculated.
1451  if( !pPor->GetAscent() && !pPor->Height() )
1452  CalcAscent( rInf, pPor );
1453  rInf.SetLen( pPor->GetLen() );
1454 
1455  // In CalcFlyWidth Width() will be shortened if a FlyPortion is present.
1456  CalcFlyWidth( rInf );
1457 
1458  // One must not forget that pCurr as GetLast() must provide reasonable values:
1459  if( !m_pCurr->Height() )
1460  {
1461  OSL_ENSURE( m_pCurr->Height(), "SwTextFormatter::NewPortion: limbo dance" );
1462  m_pCurr->Height( pPor->Height() );
1463  m_pCurr->SetAscent( pPor->GetAscent() );
1464  }
1465 
1466  OSL_ENSURE(pPor->Height(), "SwTextFormatter::NewPortion: something went wrong");
1467  if( pPor->IsPostItsPortion() && rInf.X() >= rInf.Width() && rInf.GetFly() )
1468  {
1469  delete pPor;
1470  pPor = rInf.GetFly();
1471  }
1472  return pPor;
1473 }
1474 
1476 {
1477  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
1478  "SwTextFormatter::FormatLine( nStartPos ) with unswapped frame" );
1479 
1480  // For the formatting routines, we set pOut to the reference device.
1481  SwHookOut aHook( GetInfo() );
1482  if (GetInfo().GetLen() < TextFrameIndex(GetInfo().GetText().getLength()))
1483  GetInfo().SetLen(TextFrameIndex(GetInfo().GetText().getLength()));
1484 
1485  bool bBuild = true;
1486  SetFlyInCntBase( false );
1487  GetInfo().SetLineHeight( 0 );
1488  GetInfo().SetLineNetHeight( 0 );
1489 
1490  // Recycling must be suppressed by changed line height and also
1491  // by changed ascent (lowering of baseline).
1492  const sal_uInt16 nOldHeight = m_pCurr->Height();
1493  const sal_uInt16 nOldAscent = m_pCurr->GetAscent();
1494 
1495  m_pCurr->SetEndHyph( false );
1496  m_pCurr->SetMidHyph( false );
1497 
1498  // fly positioning can make it necessary format a line several times
1499  // for this, we have to keep a copy of our rest portion
1500  SwLinePortion* pField = GetInfo().GetRest();
1501  std::unique_ptr<SwFieldPortion> xSaveField;
1502 
1503  if ( pField && pField->InFieldGrp() && !pField->IsFootnotePortion() )
1504  xSaveField.reset(new SwFieldPortion( *static_cast<SwFieldPortion*>(pField) ));
1505 
1506  // for an optimal repaint rectangle, we want to compare fly portions
1507  // before and after the BuildPortions call
1508  const bool bOptimizeRepaint = AllowRepaintOpt();
1509  TextFrameIndex const nOldLineEnd = nStartPos + m_pCurr->GetLen();
1510  std::vector<long> flyStarts;
1511 
1512  // these are the conditions for a fly position comparison
1513  if ( bOptimizeRepaint && m_pCurr->IsFly() )
1514  {
1516  long nPOfst = 0;
1517  while ( pPor )
1518  {
1519  if ( pPor->IsFlyPortion() )
1520  // insert start value of fly portion
1521  flyStarts.push_back( nPOfst );
1522 
1523  nPOfst += pPor->Width();
1524  pPor = pPor->GetNextPortion();
1525  }
1526  }
1527 
1528  // Here soon the underflow check follows.
1529  while( bBuild )
1530  {
1531  GetInfo().SetFootnoteInside( false );
1533 
1534  // These values must not be reset by FormatReset();
1535  const bool bOldNumDone = GetInfo().IsNumDone();
1536  const bool bOldArrowDone = GetInfo().IsArrowDone();
1537  const bool bOldErgoDone = GetInfo().IsErgoDone();
1538 
1539  // besides other things, this sets the repaint offset to 0
1540  FormatReset( GetInfo() );
1541 
1542  GetInfo().SetNumDone( bOldNumDone );
1543  GetInfo().SetArrowDone( bOldArrowDone );
1544  GetInfo().SetErgoDone( bOldErgoDone );
1545 
1546  // build new portions for this line
1547  BuildPortions( GetInfo() );
1548 
1549  if( GetInfo().IsStop() )
1550  {
1552  m_pCurr->Height( GetFrameRstHeight() + 1 );
1554  m_pCurr->Width(0);
1555  m_pCurr->Truncate();
1556  return nStartPos;
1557  }
1558  else if( GetInfo().IsDropInit() )
1559  {
1560  DropInit();
1561  GetInfo().SetDropInit( false );
1562  }
1563 
1564  m_pCurr->CalcLine( *this, GetInfo() );
1566 
1567  //i#120864 For Special case that at the first calculation couldn't get
1568  //correct height. And need to recalculate for the right height.
1569  SwLinePortion* pPorTmp = m_pCurr->GetNextPortion();
1570  if ( IsFlyInCntBase() && (!IsQuick() || (pPorTmp && pPorTmp->IsFlyCntPortion() && !pPorTmp->GetNextPortion() &&
1571  m_pCurr->Height() > pPorTmp->Height())))
1572  {
1573  sal_uInt16 nTmpAscent, nTmpHeight;
1574  CalcAscentAndHeight( nTmpAscent, nTmpHeight );
1575  AlignFlyInCntBase( Y() + long( nTmpAscent ) );
1576  m_pCurr->CalcLine( *this, GetInfo() );
1577  CalcRealHeight();
1578  }
1579 
1580  // bBuild decides if another lap of honor is done
1581  if ( m_pCurr->GetRealHeight() <= GetInfo().GetLineHeight() )
1582  {
1584  bBuild = false;
1585  }
1586  else
1587  {
1588  bBuild = ( GetInfo().GetTextFly().IsOn() && ChkFlyUnderflow(GetInfo()) )
1590  if( bBuild )
1591  {
1592  GetInfo().SetNumDone( bOldNumDone );
1594 
1595  // delete old rest
1596  if ( GetInfo().GetRest() )
1597  {
1598  delete GetInfo().GetRest();
1599  GetInfo().SetRest( nullptr );
1600  }
1601 
1602  // set original rest portion
1603  if ( xSaveField )
1604  GetInfo().SetRest( new SwFieldPortion( *xSaveField ) );
1605 
1607  m_pCurr->Width(0);
1608  m_pCurr->Truncate();
1609  }
1610  }
1611  }
1612 
1613  // In case of compat mode, it's possible that a tab portion is wider after
1614  // formatting than before. If this is the case, we also have to make sure
1615  // the SwLineLayout is wider as well.
1616  if (GetInfo().GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_OVER_MARGIN))
1617  {
1618  sal_uInt16 nSum = 0;
1620 
1621  while (pPor)
1622  {
1623  nSum += pPor->Width();
1624  pPor = pPor->GetNextPortion();
1625  }
1626 
1627  if (nSum > m_pCurr->Width())
1628  m_pCurr->Width(nSum);
1629  }
1630 
1631  // calculate optimal repaint rectangle
1632  if ( bOptimizeRepaint )
1633  {
1634  GetInfo().SetPaintOfst( ::lcl_CalcOptRepaint( *this, *m_pCurr, nOldLineEnd, flyStarts ) );
1635  flyStarts.clear();
1636  }
1637  else
1638  // Special case: we do not allow an optimization of the repaint
1639  // area, but during formatting the repaint offset is set to indicate
1640  // a maximum value for the offset. This value has to be reset:
1641  GetInfo().SetPaintOfst( 0 );
1642 
1643  // This corrects the start of the reformat range if something has
1644  // moved to the next line. Otherwise IsFirstReformat in AllowRepaintOpt
1645  // will give us a wrong result if we have to reformat another line
1646  GetInfo().GetParaPortion()->GetReformat().LeftMove( GetInfo().GetIdx() );
1647 
1648  // delete master copy of rest portion
1649  xSaveField.reset();
1650 
1651  TextFrameIndex const nNewStart = nStartPos + m_pCurr->GetLen();
1652 
1653  // adjust text if kana compression is enabled
1654  if ( GetInfo().CompressLine() )
1655  {
1656  SwTwips nRepaintOfst = CalcKanaAdj( m_pCurr );
1657 
1658  // adjust repaint offset
1659  if ( nRepaintOfst < GetInfo().GetPaintOfst() )
1660  GetInfo().SetPaintOfst( nRepaintOfst );
1661  }
1662 
1664 
1665  if( nOldHeight != m_pCurr->Height() || nOldAscent != m_pCurr->GetAscent() )
1666  {
1667  SetFlyInCntBase();
1668  GetInfo().SetPaintOfst( 0 ); // changed line height => no recycling
1669  // all following line must be painted and when Flys are around,
1670  // also formatted
1671  GetInfo().SetShift( true );
1672  }
1673 
1674  if ( IsFlyInCntBase() && !IsQuick() )
1676 
1677  return nNewStart;
1678 }
1679 
1681 {
1682  do
1683  {
1684  CalcRealHeight();
1685  } while (Next());
1686 }
1687 
1688 void SwTextFormatter::CalcRealHeight( bool bNewLine )
1689 {
1690  sal_uInt16 nLineHeight = m_pCurr->Height();
1691  m_pCurr->SetClipping( false );
1692 
1693  SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
1694  if ( pGrid && GetInfo().SnapToGrid() )
1695  {
1696  const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
1697  const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
1698  const bool bRubyTop = ! pGrid->GetRubyTextBelow();
1699 
1700  nLineHeight = nGridWidth + nRubyHeight;
1701  const sal_uInt16 nAmpRatio = (m_pCurr->Height() + nLineHeight - 1)/nLineHeight;
1702  nLineHeight *= nAmpRatio;
1703 
1704  const sal_uInt16 nAsc = m_pCurr->GetAscent() +
1705  ( bRubyTop ?
1706  ( nLineHeight - m_pCurr->Height() + nRubyHeight ) / 2 :
1707  ( nLineHeight - m_pCurr->Height() - nRubyHeight ) / 2 );
1708 
1709  m_pCurr->Height( nLineHeight );
1710  m_pCurr->SetAscent( nAsc );
1712 
1713  // we ignore any line spacing options except from ...
1714  const SvxLineSpacingItem* pSpace = m_aLineInf.GetLineSpacing();
1715  if ( ! IsParaLine() && pSpace &&
1716  SvxInterLineSpaceRule::Prop == pSpace->GetInterLineSpaceRule() )
1717  {
1718  sal_uLong nTmp = pSpace->GetPropLineSpace();
1719 
1720  if( nTmp < 100 )
1721  nTmp = 100;
1722 
1723  nTmp *= nLineHeight;
1724  nLineHeight = static_cast<sal_uInt16>(nTmp / 100);
1725  }
1726 
1727  m_pCurr->SetRealHeight( nLineHeight );
1728  return;
1729  }
1730 
1731  // The dummy flag is set on lines that only contain flyportions, these shouldn't
1732  // consider register-true and so on. Unfortunately an empty line can be at
1733  // the end of a paragraph (empty paragraphs or behind a Shift-Return),
1734  // which should consider the register.
1735  if (!m_pCurr->IsDummy() || (!m_pCurr->GetNext()
1736  && GetStart() >= TextFrameIndex(GetTextFrame()->GetText().getLength())
1737  && !bNewLine))
1738  {
1739  const SvxLineSpacingItem *pSpace = m_aLineInf.GetLineSpacing();
1740  if( pSpace )
1741  {
1742  switch( pSpace->GetLineSpaceRule() )
1743  {
1744  case SvxLineSpaceRule::Auto:
1745  // shrink first line of paragraph too on spacing < 100%
1746  if (IsParaLine() &&
1747  pSpace->GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
1749  {
1750  long nTmp = pSpace->GetPropLineSpace();
1751  // Word will render < 50% too but it's just not readable
1752  if( nTmp < 50 )
1753  nTmp = nTmp ? 50 : 100;
1754  if (nTmp<100) { // code adapted from fixed line height
1755  nTmp *= nLineHeight;
1756  nTmp /= 100;
1757  if( !nTmp )
1758  ++nTmp;
1759  nLineHeight = static_cast<sal_uInt16>(nTmp);
1760  sal_uInt16 nAsc = ( 4 * nLineHeight ) / 5; // 80%
1761 #if 0
1762  // could do clipping here (like Word does)
1763  // but at 0.5 its unreadable either way...
1764  if( nAsc < pCurr->GetAscent() ||
1765  nLineHeight - nAsc < pCurr->Height() -
1766  pCurr->GetAscent() )
1767  pCurr->SetClipping( true );
1768 #endif
1769  m_pCurr->SetAscent( nAsc );
1770  m_pCurr->Height( nLineHeight );
1772  }
1773  }
1774  break;
1775  case SvxLineSpaceRule::Min:
1776  {
1777  if( nLineHeight < pSpace->GetLineHeight() )
1778  nLineHeight = pSpace->GetLineHeight();
1779  break;
1780  }
1781  case SvxLineSpaceRule::Fix:
1782  {
1783  nLineHeight = pSpace->GetLineHeight();
1784  const sal_uInt16 nAsc = ( 4 * nLineHeight ) / 5; // 80%
1785  if( nAsc < m_pCurr->GetAscent() ||
1786  nLineHeight - nAsc < m_pCurr->Height() - m_pCurr->GetAscent() )
1787  m_pCurr->SetClipping( true );
1788  m_pCurr->Height( nLineHeight );
1789  m_pCurr->SetAscent( nAsc );
1791  }
1792  break;
1793  default: OSL_FAIL( ": unknown LineSpaceRule" );
1794  }
1795  // Note: for the _first_ line the line spacing of the previous
1796  // paragraph is applied in SwFlowFrame::CalcUpperSpace()
1797  if( !IsParaLine() )
1798  switch( pSpace->GetInterLineSpaceRule() )
1799  {
1800  case SvxInterLineSpaceRule::Off:
1801  break;
1802  case SvxInterLineSpaceRule::Prop:
1803  {
1804  long nTmp = pSpace->GetPropLineSpace();
1805  // 50% is the minimum, if 0% we switch to the
1806  // default value 100% ...
1807  if( nTmp < 50 )
1808  nTmp = nTmp ? 50 : 100;
1809 
1810  nTmp *= nLineHeight;
1811  nTmp /= 100;
1812  if( !nTmp )
1813  ++nTmp;
1814  nLineHeight = static_cast<sal_uInt16>(nTmp);
1815  break;
1816  }
1817  case SvxInterLineSpaceRule::Fix:
1818  {
1819  nLineHeight = nLineHeight + pSpace->GetInterLineSpace();
1820  break;
1821  }
1822  default: OSL_FAIL( ": unknown InterLineSpaceRule" );
1823  }
1824  }
1825 
1826  if( IsRegisterOn() )
1827  {
1828  SwTwips nTmpY = Y() + m_pCurr->GetAscent() + nLineHeight - m_pCurr->Height();
1829  SwRectFnSet aRectFnSet(m_pFrame);
1830  if ( aRectFnSet.IsVert() )
1831  nTmpY = m_pFrame->SwitchHorizontalToVertical( nTmpY );
1832  nTmpY = aRectFnSet.YDiff( nTmpY, RegStart() );
1833  const sal_uInt16 nDiff = sal_uInt16( nTmpY % RegDiff() );
1834  if( nDiff )
1835  nLineHeight += RegDiff() - nDiff;
1836  }
1837  }
1838  m_pCurr->SetRealHeight( nLineHeight );
1839 }
1840 
1842 {
1843  // delete Fly in any case!
1844  ClearFly( rInf );
1845  rInf.Init();
1846 
1847  rInf.ChkNoHyph( CntEndHyph(), CntMidHyph() );
1848  rInf.SetRoot( m_pCurr );
1849  rInf.SetLineStart( m_nStart );
1850  rInf.SetIdx( m_nStart );
1851  rInf.Left( Left() );
1852  rInf.Right( Right() );
1853  rInf.First( FirstLeft() );
1854  rInf.LeftMargin(GetLeftMargin());
1855 
1856  rInf.RealWidth( sal_uInt16(rInf.Right() - GetLeftMargin()) );
1857  rInf.Width( rInf.RealWidth() );
1858  if( const_cast<SwTextFormatter*>(this)->GetRedln() )
1859  {
1860  const_cast<SwTextFormatter*>(this)->GetRedln()->Clear( const_cast<SwTextFormatter*>(this)->GetFnt() );
1861  const_cast<SwTextFormatter*>(this)->GetRedln()->Reset();
1862  }
1863 }
1864 
1866 {
1867  m_pFirstOfBorderMerge = nullptr;
1868  m_pCurr->Truncate();
1869  m_pCurr->Init();
1870  if( pBlink && m_pCurr->IsBlinking() )
1871  pBlink->Delete( m_pCurr );
1872 
1873  // delete pSpaceAdd and pKanaComp
1876  m_pCurr->ResetFlags();
1877  FeedInf( rInf );
1878 }
1879 
1881 {
1882  if( m_pDropFormat )
1883  {
1884  const sal_uInt16 nOldDrop = GetDropHeight();
1886  m_bOnceMore = nOldDrop != GetDropHeight();
1887  }
1888  else
1889  m_bOnceMore = false;
1890  return m_bOnceMore;
1891 }
1892 
1894 {
1895  SwTwips nRet = Y() + GetLineHeight();
1896  SwTwips nMin = GetInfo().GetTextFly().GetMinBottom();
1897  if( nMin && ++nMin > nRet )
1898  {
1901  if( nRet + nDist < nMin )
1902  {
1903  const bool bRepaint = HasTruncLines() &&
1904  GetInfo().GetParaPortion()->GetRepaint().Bottom() == nRet-1;
1905  nRet = nMin - nDist;
1906  if( bRepaint )
1907  {
1908  const_cast<SwRepaint&>(GetInfo().GetParaPortion()
1909  ->GetRepaint()).Bottom( nRet-1 );
1910  const_cast<SwTextFormatInfo&>(GetInfo()).SetPaintOfst( 0 );
1911  }
1912  }
1913  }
1914  return nRet;
1915 }
1916 
1917 // FME/OD: This routine does a limited text formatting.
1919 {
1920  FormatReset( GetInfo() );
1921  BuildPortions( GetInfo() );
1922  m_pCurr->CalcLine( *this, GetInfo() );
1923  return m_pCurr->Width();
1924 }
1925 
1926 // determines if the calculation of a repaint offset is allowed
1927 // otherwise each line is painted from 0 (this is a copy of the beginning
1928 // of the former SwTextFormatter::Recycle() function
1930 {
1931  // reformat position in front of current line? Only in this case
1932  // we want to set the repaint offset
1933  bool bOptimizeRepaint = m_nStart < GetInfo().GetReformatStart() &&
1934  m_pCurr->GetLen();
1935 
1936  // a special case is the last line of a block adjusted paragraph:
1937  if ( bOptimizeRepaint )
1938  {
1939  switch( GetAdjust() )
1940  {
1941  case SvxAdjust::Block:
1942  {
1943  if( IsLastBlock() || IsLastCenter() )
1944  bOptimizeRepaint = false;
1945  else
1946  {
1947  // ????: blank in the last master line (blocksat.sdw)
1948  bOptimizeRepaint = nullptr == m_pCurr->GetNext() && !m_pFrame->GetFollow();
1949  if ( bOptimizeRepaint )
1950  {
1952  while ( pPos && !pPos->IsFlyPortion() )
1953  pPos = pPos->GetNextPortion();
1954  bOptimizeRepaint = !pPos;
1955  }
1956  }
1957  break;
1958  }
1959  case SvxAdjust::Center:
1960  case SvxAdjust::Right:
1961  bOptimizeRepaint = false;
1962  break;
1963  default: ;
1964  }
1965  }
1966 
1967  // Again another special case: invisible SoftHyphs
1968  const TextFrameIndex nReformat = GetInfo().GetReformatStart();
1969  if (bOptimizeRepaint && TextFrameIndex(COMPLETE_STRING) != nReformat)
1970  {
1971  const sal_Unicode cCh = nReformat >= TextFrameIndex(GetInfo().GetText().getLength())
1972  ? 0
1973  : GetInfo().GetText()[ sal_Int32(nReformat) ];
1974  bOptimizeRepaint = ( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
1975  || ! GetInfo().HasHint( nReformat );
1976  }
1977 
1978  return bOptimizeRepaint;
1979 }
1980 
1982 {
1983  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
1984  "SwTextFormatter::CalcUnclipped with unswapped frame" );
1985 
1986  long nFlyAsc, nFlyDesc;
1987  m_pCurr->MaxAscentDescent( rTop, rBottom, nFlyAsc, nFlyDesc );
1988  rTop = Y() + GetCurr()->GetAscent();
1989  rBottom = rTop + nFlyDesc;
1990  rTop -= nFlyAsc;
1991 }
1992 
1994  TextFrameIndex const nStartIdx, bool bAlways) const
1995 {
1996  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
1997  "SwTextFormatter::UpdatePos with unswapped frame" );
1998 
1999  if( GetInfo().IsTest() )
2000  return;
2001  SwLinePortion *pFirst = pCurrent->GetFirstPortion();
2002  SwLinePortion *pPos = pFirst;
2003  SwTextPaintInfo aTmpInf( GetInfo() );
2004  aTmpInf.SetpSpaceAdd( pCurrent->GetpLLSpaceAdd() );
2005  aTmpInf.ResetSpaceIdx();
2006  aTmpInf.SetKanaComp( pCurrent->GetpKanaComp() );
2007  aTmpInf.ResetKanaIdx();
2008 
2009  // The frame's size
2010  aTmpInf.SetIdx( nStartIdx );
2011  aTmpInf.SetPos( aStart );
2012 
2013  long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2014  pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2015 
2016  const sal_uInt16 nTmpHeight = pCurrent->GetRealHeight();
2017  sal_uInt16 nAscent = pCurrent->GetAscent() + nTmpHeight - pCurrent->Height();
2019  if( GetMulti() )
2020  {
2021  aTmpInf.SetDirection( GetMulti()->GetDirection() );
2022  if( GetMulti()->HasRotation() )
2023  {
2024  nFlags |= AsCharFlags::Rotate;
2025  if( GetMulti()->IsRevers() )
2026  {
2027  nFlags |= AsCharFlags::Reverse;
2028  aTmpInf.X( aTmpInf.X() - nAscent );
2029  }
2030  else
2031  aTmpInf.X( aTmpInf.X() + nAscent );
2032  }
2033  else
2034  {
2035  if ( GetMulti()->IsBidi() )
2036  nFlags |= AsCharFlags::Bidi;
2037  aTmpInf.Y( aTmpInf.Y() + nAscent );
2038  }
2039  }
2040  else
2041  aTmpInf.Y( aTmpInf.Y() + nAscent );
2042 
2043  while( pPos )
2044  {
2045  // We only know one case where changing the position (caused by the
2046  // adjustment) could be relevant for a portion: We need to SetRefPoint
2047  // for FlyCntPortions.
2048  if( ( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
2049  && ( bAlways || !IsQuick() ) )
2050  {
2051  pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
2052 
2053  if( pPos->IsGrfNumPortion() )
2054  {
2055  if( !nFlyAsc && !nFlyDesc )
2056  {
2057  nTmpAscent = nAscent;
2058  nFlyAsc = nAscent;
2059  nTmpDescent = nTmpHeight - nAscent;
2060  nFlyDesc = nTmpDescent;
2061  }
2062  static_cast<SwGrfNumPortion*>(pPos)->SetBase( nTmpAscent, nTmpDescent,
2063  nFlyAsc, nFlyDesc );
2064  }
2065  else
2066  {
2067  Point aBase( aTmpInf.GetPos() );
2068  if ( GetInfo().GetTextFrame()->IsVertical() )
2070 
2071  static_cast<SwFlyCntPortion*>(pPos)->SetBase( *aTmpInf.GetTextFrame(),
2072  aBase, nTmpAscent, nTmpDescent, nFlyAsc,
2073  nFlyDesc, nFlags );
2074  }
2075  }
2076  if( pPos->IsMultiPortion() && static_cast<SwMultiPortion*>(pPos)->HasFlyInContent() )
2077  {
2078  OSL_ENSURE( !GetMulti(), "Too much multi" );
2079  const_cast<SwTextFormatter*>(this)->m_pMulti = static_cast<SwMultiPortion*>(pPos);
2080  SwLineLayout *pLay = &GetMulti()->GetRoot();
2081  Point aSt( aTmpInf.X(), aStart.Y() );
2082 
2083  if ( GetMulti()->HasBrackets() )
2084  {
2085  OSL_ENSURE( GetMulti()->IsDouble(), "Brackets only for doubles");
2086  aSt.AdjustX(static_cast<SwDoubleLinePortion*>(GetMulti())->PreWidth() );
2087  }
2088  else if( GetMulti()->HasRotation() )
2089  {
2090  aSt.AdjustY(pCurrent->GetAscent() - GetMulti()->GetAscent() );
2091  if( GetMulti()->IsRevers() )
2092  aSt.AdjustX(GetMulti()->Width() );
2093  else
2094  aSt.AdjustY(GetMulti()->Height() );
2095  }
2096  else if ( GetMulti()->IsBidi() )
2097  // jump to end of the bidi portion
2098  aSt.AdjustX(pLay->Width() );
2099 
2100  TextFrameIndex nStIdx = aTmpInf.GetIdx();
2101  do
2102  {
2103  UpdatePos( pLay, aSt, nStIdx, bAlways );
2104  nStIdx = nStIdx + pLay->GetLen();
2105  aSt.AdjustY(pLay->Height() );
2106  pLay = pLay->GetNext();
2107  } while ( pLay );
2108  const_cast<SwTextFormatter*>(this)->m_pMulti = nullptr;
2109  }
2110  pPos->Move( aTmpInf );
2111  pPos = pPos->GetNextPortion();
2112  }
2113 }
2114 
2115 void SwTextFormatter::AlignFlyInCntBase( long nBaseLine ) const
2116 {
2117  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
2118  "SwTextFormatter::AlignFlyInCntBase with unswapped frame" );
2119 
2120  if( GetInfo().IsTest() )
2121  return;
2122  SwLinePortion *pFirst = m_pCurr->GetFirstPortion();
2123  SwLinePortion *pPos = pFirst;
2124  AsCharFlags nFlags = AsCharFlags::None;
2125  if( GetMulti() && GetMulti()->HasRotation() )
2126  {
2127  nFlags |= AsCharFlags::Rotate;
2128  if( GetMulti()->IsRevers() )
2129  nFlags |= AsCharFlags::Reverse;
2130  }
2131 
2132  long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2133 
2134  while( pPos )
2135  {
2136  if( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
2137  {
2138  m_pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
2139 
2140  if( pPos->IsGrfNumPortion() )
2141  static_cast<SwGrfNumPortion*>(pPos)->SetBase( nTmpAscent, nTmpDescent,
2142  nFlyAsc, nFlyDesc );
2143  else
2144  {
2145  Point aBase;
2146  if ( GetInfo().GetTextFrame()->IsVertical() )
2147  {
2148  nBaseLine = GetInfo().GetTextFrame()->SwitchHorizontalToVertical( nBaseLine );
2149  aBase = Point( nBaseLine, static_cast<SwFlyCntPortion*>(pPos)->GetRefPoint().Y() );
2150  }
2151  else
2152  aBase = Point( static_cast<SwFlyCntPortion*>(pPos)->GetRefPoint().X(), nBaseLine );
2153 
2154  static_cast<SwFlyCntPortion*>(pPos)->SetBase( *GetInfo().GetTextFrame(), aBase, nTmpAscent, nTmpDescent,
2155  nFlyAsc, nFlyDesc, nFlags );
2156  }
2157  }
2158  pPos = pPos->GetNextPortion();
2159  }
2160 }
2161 
2163 {
2164  OSL_ENSURE( rInf.GetTextFly().IsOn(), "SwTextFormatter::ChkFlyUnderflow: why?" );
2165  if( GetCurr() )
2166  {
2167  // First we check, whether a fly overlaps with the line.
2168  // = GetLineHeight()
2169  const sal_uInt16 nHeight = GetCurr()->GetRealHeight();
2170  SwRect aLine( GetLeftMargin(), Y(), rInf.RealWidth(), nHeight );
2171 
2172  SwRect aLineVert( aLine );
2173  if ( m_pFrame->IsVertical() )
2174  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2175  SwRect aInter( rInf.GetTextFly().GetFrame( aLineVert ) );
2176  if ( m_pFrame->IsVertical() )
2178 
2179  if( !aInter.HasArea() )
2180  return false;
2181 
2182  // We now check every portion that could have lowered for overlapping
2183  // with the fly.
2184  const SwLinePortion *pPos = GetCurr()->GetFirstPortion();
2185  aLine.Pos().setY( Y() + GetCurr()->GetRealHeight() - GetCurr()->Height() );
2186  aLine.Height( GetCurr()->Height() );
2187 
2188  while( pPos )
2189  {
2190  aLine.Width( pPos->Width() );
2191 
2192  aLineVert = aLine;
2193  if ( m_pFrame->IsVertical() )
2194  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2195  aInter = rInf.GetTextFly().GetFrame( aLineVert );
2196  if ( m_pFrame->IsVertical() )
2198 
2199  // New flys from below?
2200  if( !pPos->IsFlyPortion() )
2201  {
2202  if( aInter.IsOver( aLine ) )
2203  {
2204  aInter.Intersection_( aLine );
2205  if( aInter.HasArea() )
2206  {
2207  // To be evaluated during reformat of this line:
2208  // RealHeight including spacing
2209  rInf.SetLineHeight( nHeight );
2210  // Height without extra spacing
2211  rInf.SetLineNetHeight( m_pCurr->Height() );
2212  return true;
2213  }
2214  }
2215  }
2216  else
2217  {
2218  // The fly portion is not intersected by a fly anymore
2219  if ( ! aInter.IsOver( aLine ) )
2220  {
2221  rInf.SetLineHeight( nHeight );
2222  rInf.SetLineNetHeight( m_pCurr->Height() );
2223  return true;
2224  }
2225  else
2226  {
2227  aInter.Intersection_( aLine );
2228 
2229  // No area means a fly has become invalid because of
2230  // lowering the line => reformat the line
2231  // we also have to reformat the line, if the fly size
2232  // differs from the intersection interval's size.
2233  if( ! aInter.HasArea() ||
2234  static_cast<const SwFlyPortion*>(pPos)->GetFixWidth() != aInter.Width() )
2235  {
2236  rInf.SetLineHeight( nHeight );
2237  rInf.SetLineNetHeight( m_pCurr->Height() );
2238  return true;
2239  }
2240  }
2241  }
2242 
2243  aLine.Left( aLine.Left() + pPos->Width() );
2244  pPos = pPos->GetNextPortion();
2245  }
2246  }
2247  return false;
2248 }
2249 
2251 {
2252  if( GetMulti() || rInf.GetFly() )
2253  return;
2254 
2255  SwTextFly& rTextFly = rInf.GetTextFly();
2256  if( !rTextFly.IsOn() || rInf.IsIgnoreFly() )
2257  return;
2258 
2259  const SwLinePortion *pLast = rInf.GetLast();
2260 
2261  long nAscent;
2262  long nTop = Y();
2263  long nHeight;
2264 
2265  if( rInf.GetLineHeight() )
2266  {
2267  // Real line height has already been calculated, we only have to
2268  // search for intersections in the lower part of the strip
2269  nAscent = m_pCurr->GetAscent();
2270  nHeight = rInf.GetLineNetHeight();
2271  nTop += rInf.GetLineHeight() - nHeight;
2272  }
2273  else
2274  {
2275  // We make a first guess for the lines real height
2276  if ( ! m_pCurr->GetRealHeight() )
2277  CalcRealHeight();
2278 
2279  nAscent = pLast->GetAscent();
2280  nHeight = pLast->Height();
2281 
2282  if ( m_pCurr->GetRealHeight() > nHeight )
2283  nTop += m_pCurr->GetRealHeight() - nHeight;
2284  else
2285  // Important for fixed space between lines
2286  nHeight = m_pCurr->GetRealHeight();
2287  }
2288 
2289  const long nLeftMar = GetLeftMargin();
2290  const long nLeftMin = (rInf.X() || GetDropLeft()) ? nLeftMar : GetLeftMin();
2291 
2292  SwRect aLine( rInf.X() + nLeftMin, nTop, rInf.RealWidth() - rInf.X()
2293  + nLeftMar - nLeftMin , nHeight );
2294 
2295  // tdf#116486: consider also the upper margin from getFramePrintArea because intersections
2296  // with this additional space should lead to repositioning of paragraphs
2297  // For compatibility we grab a related compat flag:
2299  {
2300  const long nUpper = m_pFrame->getFramePrintArea().Top();
2301  // Increase the rectangle
2302  if( nUpper > 0 && nTop >= nUpper )
2303  aLine.SubTop( nUpper );
2304  }
2305  SwRect aLineVert( aLine );
2306  if ( m_pFrame->IsRightToLeft() )
2307  m_pFrame->SwitchLTRtoRTL( aLineVert );
2308 
2309  if ( m_pFrame->IsVertical() )
2310  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2311 
2312  // GetFrame(...) determines and returns the intersection rectangle
2313  SwRect aInter( rTextFly.GetFrame( aLineVert ) );
2314 
2315  if ( m_pFrame->IsRightToLeft() )
2316  m_pFrame->SwitchRTLtoLTR( aInter );
2317 
2318  if ( m_pFrame->IsVertical() )
2320 
2321  if (!aInter.IsEmpty() && aInter.Bottom() < nTop)
2322  {
2323  // Intersects with the frame area (with upper margin), but not with the print area (without
2324  // upper margin). Don't reserve space for the fly portion in this case, text is allowed to
2325  // flow there.
2326  aInter.Height(0);
2327  }
2328 
2329  if( !aInter.IsOver( aLine ) )
2330  return;
2331 
2332  aLine.Left( rInf.X() + nLeftMar );
2333  bool bForced = false;
2334  if( aInter.Left() <= nLeftMin )
2335  {
2336  SwTwips nFrameLeft = GetTextFrame()->getFrameArea().Left();
2337  if( GetTextFrame()->getFramePrintArea().Left() < 0 )
2338  nFrameLeft += GetTextFrame()->getFramePrintArea().Left();
2339  if( aInter.Left() < nFrameLeft )
2340  aInter.Left( nFrameLeft );
2341 
2342  long nAddMar = 0;
2343  if ( m_pFrame->IsRightToLeft() )
2344  {
2345  nAddMar = m_pFrame->getFrameArea().Right() - Right();
2346  if ( nAddMar < 0 )
2347  nAddMar = 0;
2348  }
2349  else
2350  nAddMar = nLeftMar - nFrameLeft;
2351 
2352  aInter.Width( aInter.Width() + nAddMar );
2353  // For a negative first line indent, we set this flag to show
2354  // that the indentation/margin has been moved.
2355  // This needs to be respected by the DefaultTab at the zero position.
2356  if( IsFirstTextLine() && HasNegFirst() )
2357  bForced = true;
2358  }
2359  aInter.Intersection( aLine );
2360  if( !aInter.HasArea() )
2361  return;
2362 
2363  const bool bFullLine = aLine.Left() == aInter.Left() &&
2364  aLine.Right() == aInter.Right();
2365 
2366  // Although no text is left, we need to format another line,
2367  // because also empty lines need to avoid a Fly with no wrapping.
2368  if (bFullLine && rInf.GetIdx() == TextFrameIndex(rInf.GetText().getLength()))
2369  {
2370  rInf.SetNewLine( true );
2371  // We know that for dummies, it holds ascent == height
2372  m_pCurr->SetDummy(true);
2373  }
2374 
2375  // aInter becomes frame-local
2376  aInter.Pos().AdjustX( -nLeftMar );
2377  SwFlyPortion *pFly = new SwFlyPortion( aInter );
2378  if( bForced )
2379  {
2381  rInf.ForcedLeftMargin( static_cast<sal_uInt16>(aInter.Width()) );
2382  }
2383 
2384  if( bFullLine )
2385  {
2386  // In order to properly flow around Flys with different
2387  // wrapping attributes, we need to increase by units of line height.
2388  // The last avoiding line should be adjusted in height, so that
2389  // we don't get a frame spacing effect.
2390  // It is important that ascent == height, because the FlyPortion
2391  // values are transferred to pCurr in CalcLine and IsDummy() relies
2392  // on this behaviour.
2393  // To my knowledge we only have two places where DummyLines can be
2394  // created: here and in MakeFlyDummies.
2395  // IsDummy() is evaluated in IsFirstTextLine(), when moving lines
2396  // and in relation with DropCaps.
2397  pFly->Height( sal_uInt16(aInter.Height()) );
2398 
2399  // nNextTop now contains the margin's bottom edge, which we avoid
2400  // or the next margin's top edge, which we need to respect.
2401  // That means we can comfortably grow up to this value; that's how
2402  // we save a few empty lines.
2403  long nNextTop = rTextFly.GetNextTop();
2404  if ( m_pFrame->IsVertical() )
2405  nNextTop = m_pFrame->SwitchVerticalToHorizontal( nNextTop );
2406  if( nNextTop > aInter.Bottom() )
2407  {
2408  SwTwips nH = nNextTop - aInter.Top();
2409  if( nH < SAL_MAX_UINT16 )
2410  pFly->Height( sal_uInt16( nH ) );
2411  }
2412  if( nAscent < pFly->Height() )
2413  pFly->SetAscent( sal_uInt16(nAscent) );
2414  else
2415  pFly->SetAscent( pFly->Height() );
2416  }
2417  else
2418  {
2419  if (rInf.GetIdx() == TextFrameIndex(rInf.GetText().getLength()))
2420  {
2421  // Don't use nHeight, or we have a huge descent
2422  pFly->Height( pLast->Height() );
2423  pFly->SetAscent( pLast->GetAscent() );
2424  }
2425  else
2426  {
2427  pFly->Height( sal_uInt16(aInter.Height()) );
2428  if( nAscent < pFly->Height() )
2429  pFly->SetAscent( sal_uInt16(nAscent) );
2430  else
2431  pFly->SetAscent( pFly->Height() );
2432  }
2433  }
2434 
2435  rInf.SetFly( pFly );
2436 
2437  if( pFly->GetFix() < rInf.Width() )
2438  rInf.Width( pFly->GetFix() );
2439 
2440  SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
2441  if ( !pGrid )
2442  return;
2443 
2444  const SwPageFrame* pPageFrame = m_pFrame->FindPageFrame();
2445  const SwLayoutFrame* pBody = pPageFrame->FindBodyCont();
2446 
2447  SwRectFnSet aRectFnSet(pPageFrame);
2448 
2449  const long nGridOrigin = pBody ?
2450  aRectFnSet.GetPrtLeft(*pBody) :
2451  aRectFnSet.GetPrtLeft(*pPageFrame);
2452 
2453  const SwDoc & rDoc = rInf.GetTextFrame()->GetDoc();
2454  const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, rDoc);
2455 
2456  SwTwips nStartX = GetLeftMargin();
2457  if ( aRectFnSet.IsVert() )
2458  {
2459  Point aPoint( nStartX, 0 );
2461  nStartX = aPoint.Y();
2462  }
2463 
2464  const SwTwips nOfst = nStartX - nGridOrigin;
2465  const SwTwips nTmpWidth = rInf.Width() + nOfst;
2466 
2467  const sal_uLong i = nTmpWidth / nGridWidth + 1;
2468 
2469  const long nNewWidth = ( i - 1 ) * nGridWidth - nOfst;
2470  if ( nNewWidth > 0 )
2471  rInf.Width( static_cast<sal_uInt16>(nNewWidth) );
2472  else
2473  rInf.Width( 0 );
2474 
2475 
2476 }
2477 
2479  SwTextAttr *pHint ) const
2480 {
2481  const SwFrame *pFrame = m_pFrame;
2482 
2483  SwFlyInContentFrame *pFly;
2484  SwFrameFormat* pFrameFormat = static_cast<SwTextFlyCnt*>(pHint)->GetFlyCnt().GetFrameFormat();
2485  if( RES_FLYFRMFMT == pFrameFormat->Which() )
2486  pFly = static_cast<SwTextFlyCnt*>(pHint)->GetFlyFrame(pFrame);
2487  else
2488  pFly = nullptr;
2489  // aBase is the document-global position, from which the new extra portion is placed
2490  // aBase.X() = Offset in the line after the current position
2491  // aBase.Y() = LineIter.Y() + Ascent of the current position
2492 
2493  long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2494  // i#11859 - use new method <SwLineLayout::MaxAscentDescent(..)>
2495  // to change line spacing behaviour at paragraph - Compatibility to MS Word
2496  //SwLinePortion *pPos = pCurr->GetFirstPortion();
2497  //lcl_MaxAscDescent( pPos, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2498  m_pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2499 
2500  // If the ascent of the frame is larger than the ascent of the current position,
2501  // we use this one when calculating the base, or the frame would be positioned
2502  // too much to the top, sliding down after all causing a repaint in an area
2503  // he actually never was in.
2504  sal_uInt16 nAscent = 0;
2505 
2506  const bool bTextFrameVertical = GetInfo().GetTextFrame()->IsVertical();
2507 
2508  const bool bUseFlyAscent = pFly && pFly->isFrameAreaPositionValid() &&
2509  0 != ( bTextFrameVertical ?
2510  pFly->GetRefPoint().X() :
2511  pFly->GetRefPoint().Y() );
2512 
2513  if ( bUseFlyAscent )
2514  nAscent = static_cast<sal_uInt16>( std::abs( int( bTextFrameVertical ?
2515  pFly->GetRelPos().X() :
2516  pFly->GetRelPos().Y() ) ) );
2517 
2518  // Check if be prefer to use the ascent of the last portion:
2519  if ( IsQuick() ||
2520  !bUseFlyAscent ||
2521  nAscent < rInf.GetLast()->GetAscent() )
2522  {
2523  nAscent = rInf.GetLast()->GetAscent();
2524  }
2525  else if( nAscent > nFlyAsc )
2526  nFlyAsc = nAscent;
2527 
2528  Point aBase( GetLeftMargin() + rInf.X(), Y() + nAscent );
2530  if( GetMulti() && GetMulti()->HasRotation() )
2531  {
2532  nMode |= AsCharFlags::Rotate;
2533  if( GetMulti()->IsRevers() )
2534  nMode |= AsCharFlags::Reverse;
2535  }
2536 
2537  Point aTmpBase( aBase );
2538  if ( GetInfo().GetTextFrame()->IsVertical() )
2540 
2541  SwFlyCntPortion* pRet(nullptr);
2542  if( pFly )
2543  {
2544  pRet = sw::FlyContentPortion::Create(*GetInfo().GetTextFrame(), pFly, aTmpBase, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode);
2545  // We need to make sure that our font is set again in the OutputDevice
2546  // It could be that the FlyInCnt was added anew and GetFlyFrame() would
2547  // in turn cause, that it'd be created anew again.
2548  // This one's frames get formatted right away, which change the font.
2549  rInf.SelectFont();
2550  if( pRet->GetAscent() > nAscent )
2551  {
2552  aBase.setY( Y() + pRet->GetAscent() );
2553  nMode |= AsCharFlags::UlSpace;
2554  if( !rInf.IsTest() )
2555  {
2556  aTmpBase = aBase;
2557  if ( GetInfo().GetTextFrame()->IsVertical() )
2559 
2560  pRet->SetBase( *rInf.GetTextFrame(), aTmpBase, nTmpAscent,
2561  nTmpDescent, nFlyAsc, nFlyDesc, nMode );
2562  }
2563  }
2564  }
2565  else
2566  {
2567  pRet = sw::DrawFlyCntPortion::Create(*rInf.GetTextFrame(), *pFrameFormat, aTmpBase, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode);
2568  }
2569  return pRet;
2570 }
2571 
2572 /* Drop portion is a special case, because it has parts which aren't portions
2573  but we have handle them just like portions */
2575 {
2576  if( rPortion.GetLines() > 1 )
2577  {
2578  SwDropPortionPart* pCurrPart = rPortion.GetPart();
2579  while( pCurrPart )
2580  {
2581  if( pCurrPart->GetFollow() &&
2582  ::lcl_HasSameBorder(pCurrPart->GetFont(), pCurrPart->GetFollow()->GetFont()) )
2583  {
2584  pCurrPart->SetJoinBorderWithNext(true);
2585  pCurrPart->GetFollow()->SetJoinBorderWithPrev(true);
2586  }
2587  pCurrPart = pCurrPart->GetFollow();
2588  }
2589  }
2590 }
2591 
2593 {
2594  const SwFont aCurFont = *rInf.GetFont();
2595  if( aCurFont.HasBorder() )
2596  {
2597  if (pPrev && pPrev->GetJoinBorderWithNext() )
2598  {
2599  // In some case border merge is called twice to the portion
2600  if( !rPortion.GetJoinBorderWithPrev() )
2601  {
2602  rPortion.SetJoinBorderWithPrev(true);
2603  if( rPortion.InTextGrp() && rPortion.Width() > aCurFont.GetLeftBorderSpace() )
2604  rPortion.Width(rPortion.Width() - aCurFont.GetLeftBorderSpace());
2605  }
2606  }
2607  else
2608  {
2609  rPortion.SetJoinBorderWithPrev(false);
2610  m_pFirstOfBorderMerge = &rPortion;
2611  }
2612 
2613  // Get next portion's font
2614  bool bSeek = false;
2615  if (!rInf.IsFull() && // Not the last portion of the line (in case of line break)
2616  rInf.GetIdx() + rPortion.GetLen() != TextFrameIndex(rInf.GetText().getLength())) // Not the last portion of the paragraph
2617  {
2618  bSeek = Seek(rInf.GetIdx() + rPortion.GetLen());
2619  }
2620  // Don't join the next portion if SwKernPortion sits between two different boxes.
2621  bool bDisconnect = rPortion.IsKernPortion() && !rPortion.GetJoinBorderWithPrev();
2622  // If next portion has the same border then merge
2623  if( bSeek && GetFnt()->HasBorder() && ::lcl_HasSameBorder(aCurFont, *GetFnt()) && !bDisconnect )
2624  {
2625  // In some case border merge is called twice to the portion
2626  if( !rPortion.GetJoinBorderWithNext() )
2627  {
2628  rPortion.SetJoinBorderWithNext(true);
2629  if( rPortion.InTextGrp() && rPortion.Width() > aCurFont.GetRightBorderSpace() )
2630  rPortion.Width(rPortion.Width() - aCurFont.GetRightBorderSpace());
2631  }
2632  }
2633  // If this is the last portion of the merge group then make the real height merge
2634  else
2635  {
2636  rPortion.SetJoinBorderWithNext(false);
2637  if( m_pFirstOfBorderMerge != &rPortion )
2638  {
2639  // Calculate maximum height and ascent
2641  sal_uInt16 nMaxAscent = 0;
2642  sal_uInt16 nMaxHeight = 0;
2643  bool bReachCurrent = false;
2644  while( pActPor )
2645  {
2646  if( nMaxHeight < pActPor->Height() )
2647  nMaxHeight = pActPor->Height();
2648  if( nMaxAscent < pActPor->GetAscent() )
2649  nMaxAscent = pActPor->GetAscent();
2650 
2651  pActPor = pActPor->GetNextPortion();
2652  if( !pActPor && !bReachCurrent )
2653  {
2654  pActPor = &rPortion;
2655  bReachCurrent = true;
2656  }
2657  }
2658 
2659  // Change all portion's height and ascent
2660  pActPor = m_pFirstOfBorderMerge;
2661  bReachCurrent = false;
2662  while( pActPor )
2663  {
2664  if( nMaxHeight > pActPor->Height() )
2665  pActPor->Height(nMaxHeight);
2666  if( nMaxAscent > pActPor->GetAscent() )
2667  pActPor->SetAscent(nMaxAscent);
2668 
2669  pActPor = pActPor->GetNextPortion();
2670  if( !pActPor && !bReachCurrent )
2671  {
2672  pActPor = &rPortion;
2673  bReachCurrent = true;
2674  }
2675  }
2676  m_pFirstOfBorderMerge = nullptr;
2677  }
2678  }
2679  Seek(rInf.GetIdx());
2680  }
2681 }
2682 
2683 namespace {
2684  // calculates and sets optimal repaint offset for the current line
2685  long lcl_CalcOptRepaint( SwTextFormatter &rThis,
2686  SwLineLayout const &rCurr,
2687  TextFrameIndex const nOldLineEnd,
2688  const std::vector<long> &rFlyStarts )
2689  {
2690  SwTextFormatInfo& txtFormatInfo = rThis.GetInfo();
2691  if ( txtFormatInfo.GetIdx() < txtFormatInfo.GetReformatStart() )
2692  // the reformat position is behind our new line, that means
2693  // something of our text has moved to the next line
2694  return 0;
2695 
2696  TextFrameIndex nReformat = std::min(txtFormatInfo.GetReformatStart(), nOldLineEnd);
2697 
2698  // in case we do not have any fly in our line, our repaint position
2699  // is the changed position - 1
2700  if ( rFlyStarts.empty() && ! rCurr.IsFly() )
2701  {
2702  // this is the maximum repaint offset determined during formatting
2703  // for example: the beginning of the first right tab stop
2704  // if this value is 0, this means that we do not have an upper
2705  // limit for the repaint offset
2706  const long nFormatRepaint = txtFormatInfo.GetPaintOfst();
2707 
2708  if (nReformat < txtFormatInfo.GetLineStart() + TextFrameIndex(3))
2709  return 0;
2710 
2711  // step back two positions for smoother repaint
2712  nReformat -= TextFrameIndex(2);
2713 
2714  // i#28795, i#34607, i#38388
2715  // step back more characters, this is required by complex scripts
2716  // e.g., for Khmer (thank you, Javier!)
2717  static const TextFrameIndex nMaxContext(10);
2718  if (nReformat > txtFormatInfo.GetLineStart() + nMaxContext)
2719  nReformat = nReformat - nMaxContext;
2720  else
2721  {
2722  nReformat = txtFormatInfo.GetLineStart();
2723  //reset the margin flag - prevent loops
2725  }
2726 
2727  // Weird situation: Our line used to end with a hole portion
2728  // and we delete some characters at the end of our line. We have
2729  // to take care for repainting the blanks which are not anymore
2730  // covered by the hole portion
2731  while ( nReformat > txtFormatInfo.GetLineStart() &&
2732  CH_BLANK == txtFormatInfo.GetChar( nReformat ) )
2733  --nReformat;
2734 
2735  OSL_ENSURE( nReformat < txtFormatInfo.GetIdx(), "Reformat too small for me!" );
2736  SwRect aRect;
2737 
2738  // Note: GetChareRect is not const. It definitely changes the
2739  // bMulti flag. We have to save and restore the old value.
2740  bool bOldMulti = txtFormatInfo.IsMulti();
2741  rThis.GetCharRect( &aRect, nReformat );
2742  txtFormatInfo.SetMulti( bOldMulti );
2743 
2744  return nFormatRepaint ? std::min( aRect.Left(), nFormatRepaint ) :
2745  aRect.Left();
2746  }
2747  else
2748  {
2749  // nReformat may be wrong, if something around flys has changed:
2750  // we compare the former and the new fly positions in this line
2751  // if anything has changed, we carefully have to adjust the right
2752  // repaint position
2753  long nPOfst = 0;
2754  size_t nCnt = 0;
2755  long nX = 0;
2756  TextFrameIndex nIdx = rThis.GetInfo().GetLineStart();
2757  SwLinePortion* pPor = rCurr.GetFirstPortion();
2758 
2759  while ( pPor )
2760  {
2761  if ( pPor->IsFlyPortion() )
2762  {
2763  // compare start of fly with former start of fly
2764  if (nCnt < rFlyStarts.size() &&
2765  nX == rFlyStarts[ nCnt ] &&
2766  nIdx < nReformat
2767  )
2768  // found fix position, nothing has changed left from nX
2769  nPOfst = nX + pPor->Width();
2770  else
2771  break;
2772 
2773  nCnt++;
2774  }
2775  nX = nX + pPor->Width();
2776  nIdx = nIdx + pPor->GetLen();
2777  pPor = pPor->GetNextPortion();
2778  }
2779 
2780  return nPOfst + rThis.GetLeftMargin();
2781  }
2782  }
2783 
2784  // Determine if we need to build hidden portions
2785  bool lcl_BuildHiddenPortion(const SwTextSizeInfo& rInf, TextFrameIndex & rPos)
2786  {
2787  // Only if hidden text should not be shown:
2788  // if ( rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar() )
2789  const bool bShowInDocView = rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar();
2790  const bool bShowForPrinting = rInf.GetOpt().IsShowHiddenChar( true ) && rInf.GetOpt().IsPrinting();
2791  if (bShowInDocView || bShowForPrinting)
2792  return false;
2793 
2794  const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
2795  TextFrameIndex nHiddenStart;
2796  TextFrameIndex nHiddenEnd;
2797  rSI.GetBoundsOfHiddenRange( rPos, nHiddenStart, nHiddenEnd );
2798  if ( nHiddenEnd )
2799  {
2800  rPos = nHiddenEnd;
2801  return true;
2802  }
2803 
2804  return false;
2805  }
2806 
2807  bool lcl_HasSameBorder(const SwFont& rFirst, const SwFont& rSecond)
2808  {
2809  return
2810  rFirst.GetTopBorder() == rSecond.GetTopBorder() &&
2811  rFirst.GetBottomBorder() == rSecond.GetBottomBorder() &&
2812  rFirst.GetLeftBorder() == rSecond.GetLeftBorder() &&
2813  rFirst.GetRightBorder() == rSecond.GetRightBorder() &&
2814  rFirst.GetTopBorderDist() == rSecond.GetTopBorderDist() &&
2815  rFirst.GetBottomBorderDist() == rSecond.GetBottomBorderDist() &&
2816  rFirst.GetLeftBorderDist() == rSecond.GetLeftBorderDist() &&
2817  rFirst.GetRightBorderDist() == rSecond.GetRightBorderDist() &&
2818  rFirst.GetOrientation() == rSecond.GetOrientation() &&
2819  rFirst.GetShadowColor() == rSecond.GetShadowColor() &&
2820  rFirst.GetShadowWidth() == rSecond.GetShadowWidth() &&
2821  rFirst.GetShadowLocation() == rSecond.GetShadowLocation();
2822  }
2823 
2824 } //end unnamed namespace
2825 
2826 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetHasRotatedPortions(bool bHasRotatedPortions)
Definition: txtftn.cxx:85
virtual bool Format(SwTextFormatInfo &rInf)
Definition: porlin.cxx:239
void SetLineNetHeight(const sal_uInt16 nNew)
Definition: inftxt.hxx:602
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:295
void Move(SwTextPaintInfo &rInf)
Definition: porlin.cxx:270
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
bool LastKernPortion()
Definition: inftxt.cxx:1760
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
bool IsArrowDone() const
Definition: inftxt.hxx:636
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:718
void FormatReset(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:1865
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:637
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:1420
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:588
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:2478
bool IsRest() const
Definition: porlay.hxx:119
sal_uInt16 Height() const
Definition: possiz.hxx:44
SwTwips GetPaintOfst() const
Definition: inftxt.hxx:736
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:45
void InsertPortion(SwTextFormatInfo &rInf, SwLinePortion *pPor)
Definition: itrform2.cxx:295
TextFrameIndex GetStart() const
Definition: itrtxt.hxx:88
bool IsPrinting() const
Definition: viewopt.hxx:384
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:1473
bool IsInFootnote() const
Definition: frame.hxx:925
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:2574
sal_Unicode GetTabDecimal() const
Definition: inftxt.hxx:622
void CtorInitTextPainter(SwTextFrame *pFrame, SwTextPaintInfo *pInf)
Definition: itrpaint.cxx:62
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:176
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
const o3tl::optional< editeng::SvxBorderLine > & GetTopBorder() const
Definition: swfont.hxx:339
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:567
SwTabPortion * GetLastTab()
Definition: inftxt.hxx:620
TextFrameIndex GetUnderScorePos() const
Definition: inftxt.hxx:644
SwTwips Left() const
Definition: inftxt.hxx:547
TextFrameIndex ScanPortionEnd(TextFrameIndex nStart, TextFrameIndex nEnd)
Definition: inftxt.cxx:1667
Definition: doc.hxx:185
#define ODF_FORMCHECKBOX
void CalcLine(SwTextFormatter &rLine, SwTextFormatInfo &rInf)
Definition: porlay.cxx:326
sal_uInt16 GetDropHeight() const
Definition: itrtxt.hxx:205
const SwLineLayout & GetRoot() const
Definition: pormulti.hxx:121
bool IsNumDone() const
Definition: inftxt.hxx:634
sal_uInt16 GetTextHeight() const
Definition: inftxt.hxx:717
void Height(long nNew)
Definition: swrect.hxx:189
bool IsErgoDone() const
Definition: inftxt.hxx:632
TextFrameIndex GetOfst() const
Definition: txtfrm.hxx:428
sal_uInt16 GetLineNetHeight() const
Definition: inftxt.hxx:601
#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:727
#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:553
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:1343
static void SetRightMargin(const bool bNew)
Definition: itrtxt.hxx:294
const SwLineLayout * Next()
Definition: itrtxt.cxx:106
sal_uInt16 RealWidth() const
Definition: inftxt.hxx:554
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:393
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:603
void SetMulti(const bool bNew)
Definition: inftxt.hxx:211
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
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:836
#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:556
#define ODF_FORMDROPDOWN_RESULT
bool IsFull() const
Definition: inftxt.hxx:568
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:300
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:1981
long YDiff(long n1, long n2) const
Definition: frame.hxx:1399
sal_uInt16 RegDiff() const
Definition: itrtxt.hxx:93
void SetFull(const bool bNew)
Definition: inftxt.hxx:569
#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:202
void CalcAdjLine(SwLineLayout *pCurr)
Definition: itradj.cxx:651
bool BuildMultiPortion(SwTextFormatInfo &rInf, SwMultiPortion &rMulti)
Definition: pormulti.cxx:1883
LINESTYLE_NONE
bool IsBreakPortion() const
Definition: porlin.hxx:114
const SwRect & getFrameArea() const
Definition: frame.hxx:175
#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:931
bool HasRotation() const
Definition: pormulti.hxx:147
void SetRoot(SwLineLayout *pNew)
Definition: inftxt.hxx:565
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:652
virtual parameter_map_t * GetParameters()=0
const Point & GetRefPoint() const
Definition: flyfrms.hxx:218
void Right(const long nRight)
Definition: swrect.hxx:198
bool IsNewLine() const
Definition: inftxt.hxx:583
void CalcRealHeight(bool bNewLine=false)
Definition: itrform2.cxx:1688
bool AllowRepaintOpt() const
Definition: itrform2.cxx:1929
sal_uInt8 m_nContentEndHyph
Definition: itrform2.hxx:37
TextFrameIndex GetLineStart() const
Definition: inftxt.hxx:595
void CalcFlyWidth(SwTextFormatInfo &rInf)
Calculation of the emulated right side.
Definition: itrform2.cxx:2250
This portion represents an as-character anchored fly (shape, frame, etc.)
Definition: porfly.hxx:44
SwFontScript GetActual() const
Definition: swfont.hxx:183
const o3tl::optional< editeng::SvxBorderLine > & GetBottomBorder() const
Definition: swfont.hxx:340
void SetPaintOfst(const SwTwips nNew)
Definition: inftxt.hxx:741
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:848
void SetNumDone(const bool bNew)
Definition: inftxt.hxx:635
bool InFixMargGrp() const
Definition: porlin.hxx:108
bool IsIgnoreFly() const
Definition: inftxt.hxx:575
bool IsBidi() const
Definition: pormulti.hxx:133
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:551
static bool lcl_OldFieldRest(const SwLineLayout *pCurr)
Definition: itrform2.cxx:1146
std::unique_ptr< SwMultiCreator > GetMultiCreator(TextFrameIndex &rPos, SwMultiPortion const *pM) const
Definition: pormulti.cxx:905
TextFrameIndex NextDirChg(const TextFrameIndex nPos, const sal_uInt8 *pLevel=nullptr) const
Definition: porlay.cxx:1446
#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:1993
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:1918
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:702
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
SwLinePortion * NewPortion(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:1174
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:1788
const o3tl::optional< editeng::SvxBorderLine > & GetLeftBorder() const
Definition: swfont.hxx:342
SwTextFly & GetTextFly()
Definition: inftxt.hxx:390
const sal_Unicode CH_TAB
Definition: swfont.hxx:44
SwPageFrame * FindPageFrame()
Definition: frame.hxx:658
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:606
bool IsFlyPortion() const
Definition: porlin.hxx:125
void RecalcRealHeight()
Definition: itrform2.cxx:1680
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2514
int i
SwNumberPortion * NewNumberPortion(SwTextFormatInfo &rInf) const
Definition: txtfld.cxx:537
sal_uInt16 GetBottomBorderDist() const
Definition: swfont.hxx:360
SwLinePortion * GetFirstPortion() const
Definition: porlay.cxx:667
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:533
void FinishSpaceAdd()
Definition: porlay.hxx:168
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2804
const SwFormatDrop * GetDropFormat() const
Definition: inftxt.cxx:1546
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:645
SwFont * GetFnt()
Definition: itratr.hxx:103
bool IsTabLeftPortion() const
Definition: porlin.hxx:117
#define CHAR_ZWSP
Definition: swtypes.hxx:177
sal_uInt16 GetLineHeight() const
Definition: itrtxt.hxx:116
TextFrameIndex GetIdx() const
Definition: inftxt.hxx:278
bool CheckFootnotePortion(SwLineLayout const *pCurr)
Definition: inftxt.hxx:652
bool IsDropPortion() const
Definition: porlin.hxx:121
void SetTabDecimal(const sal_Unicode cNew)
Definition: inftxt.hxx:623
void ClrUnderflow()
Definition: inftxt.hxx:589
bool isFrameAreaPositionValid() const
Definition: frame.hxx:162
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:2162
void SetTabOverflow(bool bOverflow)
Definition: inftxt.hxx:665
sal_Unicode GetHookChar() const
Definition: inftxt.hxx:627
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:615
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
long X() const
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:579
short GetInterLineSpace() const
const SwLinePortion * GetUnderflow() const
Definition: inftxt.hxx:604
SwLayoutFrame * FindBodyCont()
Searches the first ContentFrame in BodyText below the page.
Definition: findfrm.cxx:42
void ClearHookChar()
Definition: inftxt.hxx:625
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:1387
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:732
TextFrameIndex GetReformatStart() const
Definition: inftxt.hxx:769
SwTwips Right() const
Definition: inftxt.hxx:549
void Left(const long nLeft)
Definition: swrect.hxx:193
void SetSoftHyphPos(TextFrameIndex const nNew)
Definition: inftxt.hxx:609
#define RES_CHRATR_ROTATE
Definition: hintids.hxx:194
bool SeekAndChgBefore(SwTextSizeInfo &rInf)
Definition: itrtxt.hxx:315
void Bottom(const long nBottom)
Definition: swrect.hxx:207
#define CHAR_HARDHYPHEN
Definition: swtypes.hxx:173
TextFrameIndex m_nStart
Definition: itrtxt.hxx:41
TextFrameIndex FormatLine(TextFrameIndex nStart)
Definition: itrform2.cxx:1475
sal_Int16 ScriptType(const TextFrameIndex nPos) const
Definition: porlay.cxx:1433
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:1893
SwTextPortion * WhichTextPor(SwTextFormatInfo &rInf) const
Definition: itrform2.cxx:858
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:717
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:631
vcl::Window * GetWin() const
Definition: viewsh.hxx:340
SwLinePortion * GetRest()
Definition: inftxt.hxx:581
void SetDummy(const bool bNew)
Definition: porlay.hxx:134
SwLinePortion * FindLastPortion()
Definition: porlin.cxx:180
#define ODF_FORMDROPDOWN_LISTENTRY
bool IsErgoSumPortion() const
Definition: porlin.hxx:115
void ChkNoHyph(const sal_uInt8 bEnd, const sal_uInt8 bMid)
Definition: inftxt.hxx:572
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
const sal_uInt8 & CntEndHyph() const
Definition: itrform2.hxx:219
bool IsRightToLeft() const
Definition: frame.hxx:963
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:633
const o3tl::optional< editeng::SvxBorderLine > & GetRightBorder() const
Definition: swfont.hxx:341
void SetDirection(const sal_uInt8 nNew)
Definition: inftxt.hxx:225
void SetShift(const bool bNew)
Definition: inftxt.hxx:586
sal_uInt8 m_nContentMidHyph
Definition: itrform2.hxx:38
void SetLineStart(TextFrameIndex const nNew)
Definition: inftxt.hxx:596
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:566
sal_uInt16 GetGridWidth(SwTextGridItem const &, SwDoc const &)
Definition: pagechg.cxx:2528
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
const Color & GetShadowColor() const
Definition: swfont.hxx:377
SwTextPortion * NewTextPortion(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:942
#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:1841
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:1540
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
bool IsVertical() const
Definition: frame.hxx:949
SwDropPortionPart * GetFollow() const
Definition: pordrop.hxx:48
virtual OUString GetFieldname() const =0
void SetNewLine(const bool bNew)
Definition: inftxt.hxx:584
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:600
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:593
bool IsShowHiddenChar(bool bHard=false) const
Definition: viewopt.hxx:282
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:267
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:614
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:599
#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:2115
void SetRest(SwLinePortion *pNewRest)
Definition: inftxt.hxx:582
CharClass & GetAppCharClass()
Definition: init.cxx:709
sal_uInt16 GetFrameRstHeight() const
Definition: itrform2.cxx:130
void SetDropInit(const bool bNew)
Definition: inftxt.hxx:591
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:624
virtual SwLinePortion * Insert(SwLinePortion *pPortion)
Definition: porlin.cxx:170
SwRedlineItr * GetRedln()
Definition: itratr.hxx:81
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
TextFrameIndex GetSoftHyphPos() const
Definition: inftxt.hxx:608
void DrawViewOpt(const SwLinePortion &rPor, PortionType nWhich) const
Definition: inftxt.cxx:1352
bool IsFootnoteDone() const
Definition: inftxt.hxx:630
const SwEndNoteInfo & GetEndNoteInfo() const
Definition: doc.hxx:626
long Y() const
SwLinePortion * WhichFirstPortion(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:1011
bool IsPostItsPortion() const
Definition: porlin.hxx:128
SwDropPortion * NewDropPortion(SwTextFormatInfo &rInf)
Definition: txtdrop.cxx:563
bool CalcOnceMore()
Definition: itrform2.cxx:1880
#define ODF_FORMDROPDOWN
sal_uInt16 GetAscent() const
Definition: inftxt.hxx:710
SwFont & GetFont() const
Definition: pordrop.hxx:50
SwTwips GetLeftMin() const
Definition: itrtxt.hxx:193
void Init(SwLinePortion *pNextPortion=nullptr)
Definition: porlay.cxx:2186