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