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