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