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( 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( 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 SwTwips nDist = 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 SwTwips nKernWidth_1 = 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  if (pBM->GetFieldname() == ODF_FORMCHECKBOX)
879  {
880  ::sw::mark::ICheckboxFieldmark const*const pCheckboxFm(
881  dynamic_cast<ICheckboxFieldmark const*>(pBM));
882  assert(pCheckboxFm);
883  return pCheckboxFm->IsChecked()
884  ? OUString(u"\u2612")
885  : OUString(u"\u2610");
886  }
887  assert(pBM->GetFieldname() == ODF_FORMDROPDOWN);
888  const IFieldmark::parameter_map_t* const pParameters = pBM->GetParameters();
889  sal_Int32 nCurrentIdx = 0;
890  const IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find(OUString(ODF_FORMDROPDOWN_RESULT));
891  if(pResult != pParameters->end())
892  pResult->second >>= nCurrentIdx;
893 
894  const IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(OUString(ODF_FORMDROPDOWN_LISTENTRY));
895  if (pListEntries != pParameters->end())
896  {
897  uno::Sequence< OUString > vListEntries;
898  pListEntries->second >>= vListEntries;
899  if (nCurrentIdx < vListEntries.getLength())
900  return vListEntries[nCurrentIdx];
901  }
902 
903  static constexpr OUStringLiteral vEnSpaces = u"\u2002\u2002\u2002\u2002\u2002";
904  return vEnSpaces;
905  }
906 }
907 
909 {
910  SwTextPortion *pPor = nullptr;
911  if( GetFnt()->IsTox() )
912  {
913  pPor = new SwToxPortion;
914  }
915  else if ( GetFnt()->IsInputField() )
916  {
917  if (rInf.GetOpt().IsFieldName())
918  {
919  OUString aFieldName = SwFieldType::GetTypeStr(SwFieldTypesEnum::Input);
920  // assume this is only the *first* portion and follows will be created elsewhere => input field must start at Idx
921  assert(rInf.GetText()[sal_Int32(rInf.GetIdx())] == CH_TXT_ATR_INPUTFIELDSTART);
922  TextFrameIndex nFieldLen(-1);
923  for (TextFrameIndex i = rInf.GetIdx() + TextFrameIndex(1); ; ++i)
924  {
925  assert(rInf.GetText()[sal_Int32(i)] != CH_TXT_ATR_INPUTFIELDSTART); // can't nest
926  if (rInf.GetText()[sal_Int32(i)] == CH_TXT_ATR_INPUTFIELDEND)
927  {
928  nFieldLen = i + TextFrameIndex(1) - rInf.GetIdx();
929  break;
930  }
931  }
932  assert(2 <= sal_Int32(nFieldLen));
933  pPor = new SwFieldPortion(aFieldName, nullptr, false, nFieldLen);
934  }
935  else
936  {
937  pPor = new SwTextInputFieldPortion();
938  }
939  }
940  else
941  {
942  if( GetFnt()->IsRef() )
943  pPor = new SwRefPortion;
944  else if (GetFnt()->IsMeta())
945  {
946  auto pMetaPor = new SwMetaPortion;
947 
948  // set custom LO_EXT_SHADING color, if it exists
949  SwTextFrame const*const pFrame(rInf.GetTextFrame());
950  SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx()));
951  SwPaM aPam(aPosition);
952  uno::Reference<text::XTextContent> const xRet(
954  *aPam.GetNode().GetTextNode(), aPosition.nContent.GetIndex(), false) );
955  if (xRet.is())
956  {
957  const SwDoc & rDoc = rInf.GetTextFrame()->GetDoc();
958  static uno::Reference< uno::XComponentContext > xContext(
960 
961  static uno::Reference< rdf::XURI > xODF_SHADING(
962  rdf::URI::createKnown(xContext, rdf::URIs::LO_EXT_SHADING), uno::UNO_SET_THROW);
963 
964  uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(
965  rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
966 
967  const css::uno::Reference<css::rdf::XResource> xSubject(xRet, uno::UNO_QUERY);
968  const uno::Reference<rdf::XRepository>& xRepository =
969  xDocumentMetadataAccess->getRDFRepository();
970  const uno::Reference<container::XEnumeration> xEnum(
971  xRepository->getStatements(xSubject, xODF_SHADING, nullptr), uno::UNO_SET_THROW);
972 
973  while (xEnum->hasMoreElements())
974  {
975  rdf::Statement stmt;
976  if (!(xEnum->nextElement() >>= stmt)) {
977  throw uno::RuntimeException();
978  }
979  const uno::Reference<rdf::XLiteral> xObject(stmt.Object, uno::UNO_QUERY);
980  if (!xObject.is()) continue;
981  if (xEnum->hasMoreElements()) {
982  SAL_INFO("sw.uno", "ignoring other odf:shading statements");
983  }
984  Color rColor = Color::STRtoRGB(xObject->getValue());
985  pMetaPor->SetShadowColor(rColor);
986  break;
987  }
988  }
989  pPor = pMetaPor;
990  }
991  else
992  {
993  // Only at the End!
994  // If pCurr does not have a width, it can however already have content.
995  // E.g. for non-displayable characters
996 
997  auto const ch(rInf.GetText()[sal_Int32(rInf.GetIdx())]);
998  SwTextFrame const*const pFrame(rInf.GetTextFrame());
999  SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx()));
1000  sw::mark::IFieldmark *pBM = pFrame->GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
1001  if(pBM != nullptr && pBM->GetFieldname( ) == ODF_FORMDATE)
1002  {
1003  if (ch == CH_TXT_ATR_FIELDSTART)
1004  pPor = new SwFieldFormDatePortion(pBM, true);
1005  else if (ch == CH_TXT_ATR_FIELDSEP)
1006  pPor = new SwFieldMarkPortion(); // it's added in DateFieldmark?
1007  else if (ch == CH_TXT_ATR_FIELDEND)
1008  pPor = new SwFieldFormDatePortion(pBM, false);
1009  }
1010  else if (ch == CH_TXT_ATR_FIELDSTART)
1011  pPor = new SwFieldMarkPortion();
1012  else if (ch == CH_TXT_ATR_FIELDSEP)
1013  pPor = new SwFieldMarkPortion();
1014  else if (ch == CH_TXT_ATR_FIELDEND)
1015  pPor = new SwFieldMarkPortion();
1016  else if (ch == CH_TXT_ATR_FORMELEMENT)
1017  {
1018  OSL_ENSURE(pBM != nullptr, "Where is my form field bookmark???");
1019  if (pBM != nullptr)
1020  {
1021  if (pBM->GetFieldname( ) == ODF_FORMCHECKBOX)
1022  {
1023  pPor = new SwFieldFormCheckboxPortion();
1024  }
1025  else if (pBM->GetFieldname( ) == ODF_FORMDROPDOWN)
1026  {
1028  }
1029  /* we need to check for ODF_FORMTEXT for scenario having FormFields inside FORMTEXT.
1030  * Otherwise file will crash on open.
1031  */
1032  else if (pBM->GetFieldname( ) == ODF_FORMTEXT)
1033  {
1034  pPor = new SwFieldMarkPortion();
1035  }
1036  }
1037  }
1038  if( !pPor )
1039  {
1040  if( !rInf.X() && !m_pCurr->GetNextPortion() && !m_pCurr->GetLen() )
1041  pPor = m_pCurr;
1042  else
1043  pPor = new SwTextPortion;
1044  }
1045  }
1046  }
1047  return pPor;
1048 }
1049 
1050 // We calculate the length, the following portion limits are defined:
1051 // 1) Tabs
1052 // 2) Linebreaks
1053 // 3) CH_TXTATR_BREAKWORD / CH_TXTATR_INWORD
1054 // 4) next attribute change
1055 
1057 {
1058  // If we're at the line's beginning, we take pCurr
1059  // If pCurr is not derived from SwTextPortion, we need to duplicate
1060  Seek( rInf.GetIdx() );
1061  SwTextPortion *pPor = WhichTextPor( rInf );
1062 
1063  // until next attribute change:
1064  const TextFrameIndex nNextAttr = GetNextAttr();
1065  TextFrameIndex nNextChg = std::min(nNextAttr, TextFrameIndex(rInf.GetText().getLength()));
1066 
1067  // end of script type:
1068  const TextFrameIndex nNextScript = m_pScriptInfo->NextScriptChg(rInf.GetIdx());
1069  nNextChg = std::min( nNextChg, nNextScript );
1070 
1071  // end of direction:
1072  const TextFrameIndex nNextDir = m_pScriptInfo->NextDirChg(rInf.GetIdx());
1073  nNextChg = std::min( nNextChg, nNextDir );
1074 
1075  // hidden change (potentially via bookmark):
1076  const TextFrameIndex nNextHidden = m_pScriptInfo->NextHiddenChg(rInf.GetIdx());
1077  nNextChg = std::min( nNextChg, nNextHidden );
1078 
1079  // bookmarks
1080  const TextFrameIndex nNextBookmark = m_pScriptInfo->NextBookmark(rInf.GetIdx());
1081  nNextChg = std::min(nNextChg, nNextBookmark);
1082 
1083  // Turbo boost:
1084  // We assume that font characters are not larger than twice
1085  // as wide as height.
1086  // Very crazy: we need to take the ascent into account.
1087 
1088  // Mind the trap! GetSize() contains the wished-for height, the real height
1089  // is only known in CalcAscent!
1090 
1091  // The ratio is even crazier: a blank in Times New Roman has an ascent of
1092  // 182, a height of 200 and a width of 53!
1093  // It follows that a line with a lot of blanks is processed incorrectly.
1094  // Therefore we increase from factor 2 to 8 (due to negative kerning).
1095 
1096  pPor->SetLen(TextFrameIndex(1));
1097  CalcAscent( rInf, pPor );
1098 
1099  const SwFont* pTmpFnt = rInf.GetFont();
1100  sal_Int32 nExpect = std::min( sal_Int32( pTmpFnt->GetHeight() ),
1101  sal_Int32( pPor->GetAscent() ) ) / 8;
1102  if ( !nExpect )
1103  nExpect = 1;
1104  nExpect = sal_Int32(rInf.GetIdx()) + (rInf.GetLineWidth() / nExpect);
1105  if (TextFrameIndex(nExpect) > rInf.GetIdx() && nNextChg > TextFrameIndex(nExpect))
1106  nNextChg = TextFrameIndex(std::min(nExpect, rInf.GetText().getLength()));
1107 
1108  // we keep an invariant during method calls:
1109  // there are no portion ending characters like hard spaces
1110  // or tabs in [ nLeftScanIdx, nRightScanIdx ]
1111  if ( m_nLeftScanIdx <= rInf.GetIdx() && rInf.GetIdx() <= m_nRightScanIdx )
1112  {
1113  if ( nNextChg > m_nRightScanIdx )
1114  nNextChg = m_nRightScanIdx =
1115  rInf.ScanPortionEnd( m_nRightScanIdx, nNextChg );
1116  }
1117  else
1118  {
1119  m_nLeftScanIdx = rInf.GetIdx();
1120  nNextChg = m_nRightScanIdx =
1121  rInf.ScanPortionEnd( rInf.GetIdx(), nNextChg );
1122  }
1123 
1124  pPor->SetLen( nNextChg - rInf.GetIdx() );
1125  rInf.SetLen( pPor->GetLen() );
1126  return pPor;
1127 }
1128 
1129 // first portions have no length
1131 {
1132  SwLinePortion *pPor = nullptr;
1133 
1134  if( rInf.GetRest() )
1135  {
1136  // Tabs and fields
1137  if( '\0' != rInf.GetHookChar() )
1138  return nullptr;
1139 
1140  pPor = rInf.GetRest();
1141  if( pPor->IsErgoSumPortion() )
1142  rInf.SetErgoDone(true);
1143  else
1144  if( pPor->IsFootnoteNumPortion() )
1145  rInf.SetFootnoteDone(true);
1146  else
1147  if( pPor->InNumberGrp() )
1148  rInf.SetNumDone(true);
1149 
1150  rInf.SetRest(nullptr);
1151  m_pCurr->SetRest( true );
1152  return pPor;
1153  }
1154 
1155  // We can stand in the follow, it's crucial that
1156  // pFrame->GetOffset() == 0!
1157  if( rInf.GetIdx() )
1158  {
1159  // We now too can elongate FootnotePortions and ErgoSumPortions
1160 
1161  // 1. The ErgoSumTexts
1162  if( !rInf.IsErgoDone() )
1163  {
1164  if( m_pFrame->IsInFootnote() && !m_pFrame->GetIndPrev() )
1165  pPor = NewErgoSumPortion( rInf );
1166  rInf.SetErgoDone( true );
1167  }
1168 
1169  // 2. Arrow portions
1170  if( !pPor && !rInf.IsArrowDone() )
1171  {
1172  if( m_pFrame->GetOffset() && !m_pFrame->IsFollow() &&
1173  rInf.GetIdx() == m_pFrame->GetOffset() )
1174  pPor = new SwArrowPortion( *m_pCurr );
1175  rInf.SetArrowDone( true );
1176  }
1177 
1178  // 3. Kerning portions at beginning of line in grid mode
1179  if ( ! pPor && ! m_pCurr->GetNextPortion() )
1180  {
1181  SwTextGridItem const*const pGrid(
1182  GetGridItem(GetTextFrame()->FindPageFrame()));
1183  if ( pGrid )
1184  pPor = new SwKernPortion( *m_pCurr );
1185  }
1186 
1187  // 4. The line rests (multiline fields)
1188  if( !pPor )
1189  {
1190  pPor = rInf.GetRest();
1191  // Only for pPor of course
1192  if( pPor )
1193  {
1194  m_pCurr->SetRest( true );
1195  rInf.SetRest(nullptr);
1196  }
1197  }
1198  }
1199  else
1200  {
1201  // 5. The foot note count
1202  if( !rInf.IsFootnoteDone() )
1203  {
1204  OSL_ENSURE( ( ! rInf.IsMulti() && ! m_pMulti ) || m_pMulti->HasRotation(),
1205  "Rotated number portion trouble" );
1206 
1207  const bool bFootnoteNum = m_pFrame->IsFootnoteNumFrame();
1208  rInf.GetParaPortion()->SetFootnoteNum( bFootnoteNum );
1209  if( bFootnoteNum )
1210  pPor = NewFootnoteNumPortion( rInf );
1211  rInf.SetFootnoteDone( true );
1212  }
1213 
1214  // 6. The ErgoSumTexts of course also exist in the TextMaster,
1215  // it's crucial whether the SwFootnoteFrame is aFollow
1216  if( !rInf.IsErgoDone() && !pPor && ! rInf.IsMulti() )
1217  {
1218  if( m_pFrame->IsInFootnote() && !m_pFrame->GetIndPrev() )
1219  pPor = NewErgoSumPortion( rInf );
1220  rInf.SetErgoDone( true );
1221  }
1222 
1223  // 7. The numbering
1224  if( !rInf.IsNumDone() && !pPor )
1225  {
1226  OSL_ENSURE( ( ! rInf.IsMulti() && ! m_pMulti ) || m_pMulti->HasRotation(),
1227  "Rotated number portion trouble" );
1228 
1229  // If we're in the follow, then of course not
1231  pPor = NewNumberPortion( rInf );
1232  rInf.SetNumDone( true );
1233  }
1234  // 8. The DropCaps
1235  if( !pPor && GetDropFormat() && ! rInf.IsMulti() )
1236  pPor = NewDropPortion( rInf );
1237 
1238  // 9. Kerning portions at beginning of line in grid mode
1239  if ( !pPor && !m_pCurr->GetNextPortion() )
1240  {
1241  SwTextGridItem const*const pGrid(
1242  GetGridItem(GetTextFrame()->FindPageFrame()));
1243  if ( pGrid )
1244  pPor = new SwKernPortion( *m_pCurr );
1245  }
1246  }
1247 
1248  // 10. Decimal tab portion at the beginning of each line in table cells
1249  if ( !pPor && !m_pCurr->GetNextPortion() &&
1250  GetTextFrame()->IsInTab() &&
1252  {
1253  pPor = NewTabPortion( rInf, true );
1254  }
1255 
1256  // 11. suffix of meta-field
1257  if (!pPor)
1258  {
1259  pPor = TryNewNoLengthPortion(rInf);
1260  }
1261 
1262  // 12. bookmarks
1263  // check this *last* so that BuildMultiPortion() can find it!
1264  if (!pPor && rInf.CheckCurrentPosBookmark())
1265  {
1266  auto const bookmark(m_pScriptInfo->GetBookmark(rInf.GetIdx()));
1267  if (static_cast<bool>(bookmark))
1268  {
1269  sal_Unicode mark;
1272  {
1273  //mark = u'\u2336'; // not in OpenSymbol :(
1274  mark = '|';
1275  // hmm ... paint U+2345 over U+2346 should be same width?
1276  // and U+237F // or U+2E20/U+2E21
1277  }
1278  else if (bookmark & SwScriptInfo::MarkKind::Start)
1279  {
1280  mark = '[';
1281  }
1282  else if (bookmark & SwScriptInfo::MarkKind::End)
1283  {
1284  mark = ']';
1285  }
1286  else
1287  {
1288  assert(bookmark & SwScriptInfo::MarkKind::Point);
1289  mark = '|';
1290  }
1291  pPor = new SwBookmarkPortion(mark);
1292  }
1293  }
1294 
1295  return pPor;
1296 }
1297 
1298 static bool lcl_OldFieldRest( const SwLineLayout* pCurr )
1299 {
1300  if( !pCurr->GetNext() )
1301  return false;
1302  const SwLinePortion *pPor = pCurr->GetNext()->GetNextPortion();
1303  bool bRet = false;
1304  while( pPor && !bRet )
1305  {
1306  bRet = (pPor->InFieldGrp() && static_cast<const SwFieldPortion*>(pPor)->IsFollow()) ||
1307  (pPor->IsMultiPortion() && static_cast<const SwMultiPortion*>(pPor)->IsFollowField());
1308  if( !pPor->GetLen() )
1309  break;
1310  pPor = pPor->GetNextPortion();
1311  }
1312  return bRet;
1313 }
1314 
1315 /* NewPortion sets rInf.nLen
1316  * A SwTextPortion is limited by a tab, break, txtatr or attr change
1317  * We can have three cases:
1318  * 1) The line is full and the wrap was not emulated
1319  * -> return 0;
1320  * 2) The line is full and a wrap was emulated
1321  * -> Reset width and return new FlyPortion
1322  * 3) We need to construct a new portion
1323  * -> CalcFlyWidth emulates the width and return portion, if needed
1324  */
1325 
1327 {
1328  // Underflow takes precedence
1329  rInf.SetStopUnderflow( false );
1330  if( rInf.GetUnderflow() )
1331  {
1332  OSL_ENSURE( rInf.IsFull(), "SwTextFormatter::NewPortion: underflow but not full" );
1333  return Underflow( rInf );
1334  }
1335 
1336  // If the line is full, flys and Underflow portions could be waiting ...
1337  if( rInf.IsFull() )
1338  {
1339  // LineBreaks and Flys (bug05.sdw)
1340  // IsDummy()
1341  if( rInf.IsNewLine() && (!rInf.GetFly() || !m_pCurr->IsDummy()) )
1342  return nullptr;
1343 
1344  // When the text bumps into the Fly, or when the Fly comes first because
1345  // it juts out over the left edge, GetFly() is returned.
1346  // When IsFull() and no GetFly() is available, naturally zero is returned.
1347  if( rInf.GetFly() )
1348  {
1349  if( rInf.GetLast()->IsBreakPortion() )
1350  {
1351  delete rInf.GetFly();
1352  rInf.SetFly( nullptr );
1353  }
1354 
1355  return rInf.GetFly();
1356  }
1357 
1358  // A nasty special case: A frame without wrap overlaps the Footnote area.
1359  // We must declare the Footnote portion as rest of line, so that
1360  // SwTextFrame::Format doesn't abort (the text mass already was formatted).
1361  if( rInf.GetRest() )
1362  rInf.SetNewLine( true );
1363  else
1364  {
1365  // When the next line begins with a rest of a field, but now no
1366  // rest remains, the line must definitely be formatted anew!
1367  if( lcl_OldFieldRest( GetCurr() ) )
1368  rInf.SetNewLine( true );
1369  else
1370  {
1371  SwLinePortion *pFirst = WhichFirstPortion( rInf );
1372  if( pFirst )
1373  {
1374  rInf.SetNewLine( true );
1375  if( pFirst->InNumberGrp() )
1376  rInf.SetNumDone( false) ;
1377  delete pFirst;
1378  }
1379  }
1380  }
1381 
1382  return nullptr;
1383  }
1384 
1385  SwLinePortion *pPor = WhichFirstPortion( rInf );
1386 
1387  // Check for Hidden Portion:
1388  if ( !pPor )
1389  {
1390  TextFrameIndex nEnd = rInf.GetIdx();
1391  if ( ::lcl_BuildHiddenPortion( rInf, nEnd ) )
1392  pPor = new SwHiddenTextPortion( nEnd - rInf.GetIdx() );
1393  }
1394 
1395  if( !pPor )
1396  {
1397  if( ( !m_pMulti || m_pMulti->IsBidi() ) &&
1398  // i#42734
1399  // No multi portion if there is a hook character waiting:
1400  ( !rInf.GetRest() || '\0' == rInf.GetHookChar() ) )
1401  {
1402  // We open a multiportion part, if we enter a multi-line part
1403  // of the paragraph.
1404  TextFrameIndex nEnd = rInf.GetIdx();
1405  std::optional<SwMultiCreator> pCreate = rInf.GetMultiCreator( nEnd, m_pMulti );
1406  if( pCreate )
1407  {
1408  SwMultiPortion* pTmp = nullptr;
1409 
1410  if ( SwMultiCreatorId::Bidi == pCreate->nId )
1411  pTmp = new SwBidiPortion( nEnd, pCreate->nLevel );
1412  else if ( SwMultiCreatorId::Ruby == pCreate->nId )
1413  {
1414  pTmp = new SwRubyPortion( *pCreate, *rInf.GetFont(),
1416  nEnd, TextFrameIndex(0), rInf );
1417  }
1418  else if( SwMultiCreatorId::Rotate == pCreate->nId )
1419  {
1420  pTmp = new SwRotatedPortion( *pCreate, nEnd,
1421  GetTextFrame()->IsRightToLeft() );
1423  }
1424  else
1425  pTmp = new SwDoubleLinePortion( *pCreate, nEnd );
1426 
1427  pCreate.reset();
1428  CalcFlyWidth( rInf );
1429 
1430  return pTmp;
1431  }
1432  }
1433  // Tabs and Fields
1434  sal_Unicode cChar = rInf.GetHookChar();
1435 
1436  if( cChar )
1437  {
1438  /* We fetch cChar again to be sure that the tab is pending now and
1439  * didn't move to the next line (as happens behind frames).
1440  * However, when a FieldPortion is in the rest, we must naturally fetch
1441  * the cChar from the field content, e.g. DecimalTabs and fields (22615)
1442  */
1443  if( !rInf.GetRest() || !rInf.GetRest()->InFieldGrp() )
1444  cChar = rInf.GetChar( rInf.GetIdx() );
1445  rInf.ClearHookChar();
1446  }
1447  else
1448  {
1449  if (rInf.GetIdx() >= TextFrameIndex(rInf.GetText().getLength()))
1450  {
1451  rInf.SetFull(true);
1452  CalcFlyWidth( rInf );
1453  return pPor;
1454  }
1455  cChar = rInf.GetChar( rInf.GetIdx() );
1456  }
1457 
1458  switch( cChar )
1459  {
1460  case CH_TAB:
1461  pPor = NewTabPortion( rInf, false ); break;
1462 
1463  case CH_BREAK:
1464  pPor = new SwBreakPortion( *rInf.GetLast() ); break;
1465 
1466  case CHAR_SOFTHYPHEN: // soft hyphen
1467  pPor = new SwSoftHyphPortion; break;
1468 
1469  case CHAR_HARDBLANK: // no-break space
1470  // Please check tdf#115067 if you want to edit the char
1471  pPor = new SwBlankPortion( cChar ); break;
1472 
1473  case CHAR_HARDHYPHEN: // non-breaking hyphen
1474  pPor = new SwBlankPortion( '-' ); break;
1475 
1476  case CHAR_ZWSP: // zero width space
1477  case CHAR_WJ : // word joiner
1478  pPor = new SwControlCharPortion( cChar ); break;
1479 
1480  case CH_TXTATR_BREAKWORD:
1481  case CH_TXTATR_INWORD:
1482  if( rInf.HasHint( rInf.GetIdx() ) )
1483  {
1484  pPor = NewExtraPortion( rInf );
1485  break;
1486  }
1487  [[fallthrough]];
1488  default :
1489  {
1490  SwTabPortion* pLastTabPortion = rInf.GetLastTab();
1491  if ( pLastTabPortion && cChar == rInf.GetTabDecimal() )
1492  {
1493  // Abandon dec. tab position if line is full
1494  // We have a decimal tab portion in the line and the next character has to be
1495  // aligned at the tab stop position. We store the width from the beginning of
1496  // the tab stop portion up to the portion containing the decimal separator:
1497  if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT) /*rInf.GetVsh()->IsTabCompat();*/ &&
1498  PortionType::TabDecimal == pLastTabPortion->GetWhichPor() )
1499  {
1500  OSL_ENSURE( rInf.X() >= pLastTabPortion->GetFix(), "Decimal tab stop position cannot be calculated" );
1501  const sal_uInt16 nWidthOfPortionsUpToDecimalPosition = o3tl::narrowing<sal_uInt16>(rInf.X() - pLastTabPortion->GetFix() );
1502  static_cast<SwTabDecimalPortion*>(pLastTabPortion)->SetWidthOfPortionsUpToDecimalPosition( nWidthOfPortionsUpToDecimalPosition );
1503  rInf.SetTabDecimal( 0 );
1504  }
1505  else
1506  rInf.SetFull( rInf.GetLastTab()->Format( rInf ) );
1507  }
1508 
1509  if( rInf.GetRest() )
1510  {
1511  if( rInf.IsFull() )
1512  {
1513  rInf.SetNewLine(true);
1514  return nullptr;
1515  }
1516  pPor = rInf.GetRest();
1517  rInf.SetRest(nullptr);
1518  }
1519  else
1520  {
1521  if( rInf.IsFull() )
1522  return nullptr;
1523  pPor = NewTextPortion( rInf );
1524  }
1525  break;
1526  }
1527  }
1528 
1529  // if a portion is created despite there being a pending RestPortion,
1530  // then it is a field which has been split (e.g. because it contains a Tab)
1531  if( pPor && rInf.GetRest() )
1532  pPor->SetLen(TextFrameIndex(0));
1533 
1534  // robust:
1535  if( !pPor || rInf.IsStop() )
1536  {
1537  delete pPor;
1538  return nullptr;
1539  }
1540  }
1541 
1542  assert(pPor && "can only reach here with pPor existing");
1543 
1544  // Special portions containing numbers (footnote anchor, footnote number,
1545  // numbering) can be contained in a rotated portion, if the user
1546  // choose a rotated character attribute.
1547  if (!m_pMulti)
1548  {
1549  if ( pPor->IsFootnotePortion() )
1550  {
1551  const SwTextFootnote* pTextFootnote = static_cast<SwFootnotePortion*>(pPor)->GetTextFootnote();
1552 
1553  if ( pTextFootnote )
1554  {
1555  SwFormatFootnote& rFootnote = const_cast<SwFormatFootnote&>(pTextFootnote->GetFootnote());
1556  const SwDoc *const pDoc = &rInf.GetTextFrame()->GetDoc();
1557  const SwEndNoteInfo* pInfo;
1558  if( rFootnote.IsEndNote() )
1559  pInfo = &pDoc->GetEndNoteInfo();
1560  else
1561  pInfo = &pDoc->GetFootnoteInfo();
1562  const SwAttrSet& rSet = pInfo->GetAnchorCharFormat(const_cast<SwDoc&>(*pDoc))->GetAttrSet();
1563 
1564  const SfxPoolItem* pItem;
1565  Degree10 nDir(0);
1566  if( SfxItemState::SET == rSet.GetItemState( RES_CHRATR_ROTATE,
1567  true, &pItem ))
1568  nDir = static_cast<const SvxCharRotateItem*>(pItem)->GetValue();
1569 
1570  if ( nDir )
1571  {
1572  delete pPor;
1573  pPor = new SwRotatedPortion(rInf.GetIdx() + TextFrameIndex(1),
1574  900_deg10 == nDir
1575  ? DIR_BOTTOM2TOP
1576  : DIR_TOP2BOTTOM );
1577  }
1578  }
1579  }
1580  else if ( pPor->InNumberGrp() )
1581  {
1582  const SwFont* pNumFnt = static_cast<SwFieldPortion*>(pPor)->GetFont();
1583 
1584  if ( pNumFnt )
1585  {
1586  Degree10 nDir = pNumFnt->GetOrientation( rInf.GetTextFrame()->IsVertical() );
1587  if ( nDir )
1588  {
1589  delete pPor;
1590  pPor = new SwRotatedPortion(TextFrameIndex(0), 900_deg10 == nDir
1591  ? DIR_BOTTOM2TOP
1592  : DIR_TOP2BOTTOM );
1593 
1594  rInf.SetNumDone( false );
1595  rInf.SetFootnoteDone( false );
1596  }
1597  }
1598  }
1599  }
1600 
1601  // The font is set in output device,
1602  // the ascent and the height will be calculated.
1603  if( !pPor->GetAscent() && !pPor->Height() )
1604  CalcAscent( rInf, pPor );
1605  rInf.SetLen( pPor->GetLen() );
1606 
1607  // In CalcFlyWidth Width() will be shortened if a FlyPortion is present.
1608  CalcFlyWidth( rInf );
1609 
1610  // One must not forget that pCurr as GetLast() must provide reasonable values:
1611  if( !m_pCurr->Height() )
1612  {
1613  OSL_ENSURE( m_pCurr->Height(), "SwTextFormatter::NewPortion: limbo dance" );
1614  m_pCurr->Height( pPor->Height(), false );
1615  m_pCurr->SetAscent( pPor->GetAscent() );
1616  }
1617 
1618  OSL_ENSURE(pPor->Height(), "SwTextFormatter::NewPortion: something went wrong");
1619  if( pPor->IsPostItsPortion() && rInf.X() >= rInf.Width() && rInf.GetFly() )
1620  {
1621  delete pPor;
1622  pPor = rInf.GetFly();
1623  }
1624  return pPor;
1625 }
1626 
1628 {
1629  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
1630  "SwTextFormatter::FormatLine( nStartPos ) with unswapped frame" );
1631 
1632  // For the formatting routines, we set pOut to the reference device.
1633  SwHookOut aHook( GetInfo() );
1634  if (GetInfo().GetLen() < TextFrameIndex(GetInfo().GetText().getLength()))
1635  GetInfo().SetLen(TextFrameIndex(GetInfo().GetText().getLength()));
1636 
1637  bool bBuild = true;
1638  SetFlyInCntBase( false );
1639  GetInfo().SetLineHeight( 0 );
1640  GetInfo().SetLineNetHeight( 0 );
1641 
1642  // Recycling must be suppressed by changed line height and also
1643  // by changed ascent (lowering of baseline).
1644  const SwTwips nOldHeight = m_pCurr->Height();
1645  const SwTwips nOldAscent = m_pCurr->GetAscent();
1646 
1647  m_pCurr->SetEndHyph( false );
1648  m_pCurr->SetMidHyph( false );
1649 
1650  // fly positioning can make it necessary format a line several times
1651  // for this, we have to keep a copy of our rest portion
1652  SwLinePortion* pField = GetInfo().GetRest();
1653  std::unique_ptr<SwFieldPortion> xSaveField;
1654 
1655  if ( pField && pField->InFieldGrp() && !pField->IsFootnotePortion() )
1656  xSaveField.reset(new SwFieldPortion( *static_cast<SwFieldPortion*>(pField) ));
1657 
1658  // for an optimal repaint rectangle, we want to compare fly portions
1659  // before and after the BuildPortions call
1660  const bool bOptimizeRepaint = AllowRepaintOpt();
1661  TextFrameIndex const nOldLineEnd = nStartPos + m_pCurr->GetLen();
1662  std::vector<tools::Long> flyStarts;
1663 
1664  // these are the conditions for a fly position comparison
1665  if ( bOptimizeRepaint && m_pCurr->IsFly() )
1666  {
1668  tools::Long nPOfst = 0;
1669  while ( pPor )
1670  {
1671  if ( pPor->IsFlyPortion() )
1672  // insert start value of fly portion
1673  flyStarts.push_back( nPOfst );
1674 
1675  nPOfst += pPor->Width();
1676  pPor = pPor->GetNextPortion();
1677  }
1678  }
1679 
1680  // Here soon the underflow check follows.
1681  while( bBuild )
1682  {
1683  GetInfo().SetFootnoteInside( false );
1685 
1686  // These values must not be reset by FormatReset();
1687  const bool bOldNumDone = GetInfo().IsNumDone();
1688  const bool bOldArrowDone = GetInfo().IsArrowDone();
1689  const bool bOldErgoDone = GetInfo().IsErgoDone();
1690 
1691  // besides other things, this sets the repaint offset to 0
1692  FormatReset( GetInfo() );
1693 
1694  GetInfo().SetNumDone( bOldNumDone );
1695  GetInfo().SetArrowDone( bOldArrowDone );
1696  GetInfo().SetErgoDone( bOldErgoDone );
1697 
1698  // build new portions for this line
1699  BuildPortions( GetInfo() );
1700 
1701  if( GetInfo().IsStop() )
1702  {
1704  m_pCurr->Height( GetFrameRstHeight() + 1, false );
1706  m_pCurr->Width(0);
1707  m_pCurr->Truncate();
1708  return nStartPos;
1709  }
1710  else if( GetInfo().IsDropInit() )
1711  {
1712  DropInit();
1713  GetInfo().SetDropInit( false );
1714  }
1715 
1716  m_pCurr->CalcLine( *this, GetInfo() );
1718 
1719  //i#120864 For Special case that at the first calculation couldn't get
1720  //correct height. And need to recalculate for the right height.
1721  SwLinePortion* pPorTmp = m_pCurr->GetNextPortion();
1722  if ( IsFlyInCntBase() && (!IsQuick() || (pPorTmp && pPorTmp->IsFlyCntPortion() && !pPorTmp->GetNextPortion() &&
1723  m_pCurr->Height() > pPorTmp->Height())))
1724  {
1725  SwTwips nTmpAscent, nTmpHeight;
1726  CalcAscentAndHeight( nTmpAscent, nTmpHeight );
1727  AlignFlyInCntBase( Y() + tools::Long( nTmpAscent ) );
1728  m_pCurr->CalcLine( *this, GetInfo() );
1729  CalcRealHeight();
1730  }
1731 
1732  // bBuild decides if another lap of honor is done
1733  if ( m_pCurr->GetRealHeight() <= GetInfo().GetLineHeight() )
1734  {
1736  bBuild = false;
1737  }
1738  else
1739  {
1740  bBuild = ( GetInfo().GetTextFly().IsOn() && ChkFlyUnderflow(GetInfo()) )
1742  if( bBuild )
1743  {
1744  GetInfo().SetNumDone( bOldNumDone );
1746 
1747  // delete old rest
1748  if ( GetInfo().GetRest() )
1749  {
1750  delete GetInfo().GetRest();
1751  GetInfo().SetRest( nullptr );
1752  }
1753 
1754  // set original rest portion
1755  if ( xSaveField )
1756  GetInfo().SetRest( new SwFieldPortion( *xSaveField ) );
1757 
1759  m_pCurr->Width(0);
1760  m_pCurr->Truncate();
1761  }
1762  }
1763  }
1764 
1765  // In case of compat mode, it's possible that a tab portion is wider after
1766  // formatting than before. If this is the case, we also have to make sure
1767  // the SwLineLayout is wider as well.
1768  if (GetInfo().GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_OVER_MARGIN))
1769  {
1770  sal_uInt16 nSum = 0;
1772 
1773  while (pPor)
1774  {
1775  nSum += pPor->Width();
1776  pPor = pPor->GetNextPortion();
1777  }
1778 
1779  if (nSum > m_pCurr->Width())
1780  m_pCurr->Width(nSum);
1781  }
1782 
1783  // calculate optimal repaint rectangle
1784  if ( bOptimizeRepaint )
1785  {
1786  GetInfo().SetPaintOfst( ::lcl_CalcOptRepaint( *this, *m_pCurr, nOldLineEnd, flyStarts ) );
1787  flyStarts.clear();
1788  }
1789  else
1790  // Special case: we do not allow an optimization of the repaint
1791  // area, but during formatting the repaint offset is set to indicate
1792  // a maximum value for the offset. This value has to be reset:
1793  GetInfo().SetPaintOfst( 0 );
1794 
1795  // This corrects the start of the reformat range if something has
1796  // moved to the next line. Otherwise IsFirstReformat in AllowRepaintOpt
1797  // will give us a wrong result if we have to reformat another line
1798  GetInfo().GetParaPortion()->GetReformat().LeftMove( GetInfo().GetIdx() );
1799 
1800  // delete master copy of rest portion
1801  xSaveField.reset();
1802 
1803  TextFrameIndex const nNewStart = nStartPos + m_pCurr->GetLen();
1804 
1805  // adjust text if kana compression is enabled
1806  if ( GetInfo().CompressLine() )
1807  {
1808  SwTwips nRepaintOfst = CalcKanaAdj( m_pCurr );
1809 
1810  // adjust repaint offset
1811  if ( nRepaintOfst < GetInfo().GetPaintOfst() )
1812  GetInfo().SetPaintOfst( nRepaintOfst );
1813  }
1814 
1816 
1817  if( nOldHeight != m_pCurr->Height() || nOldAscent != m_pCurr->GetAscent() )
1818  {
1819  SetFlyInCntBase();
1820  GetInfo().SetPaintOfst( 0 ); // changed line height => no recycling
1821  // all following line must be painted and when Flys are around,
1822  // also formatted
1823  GetInfo().SetShift( true );
1824  }
1825 
1826  if ( IsFlyInCntBase() && !IsQuick() )
1828 
1829  return nNewStart;
1830 }
1831 
1833 {
1834  do
1835  {
1836  CalcRealHeight();
1837  } while (Next());
1838 }
1839 
1840 void SwTextFormatter::CalcRealHeight( bool bNewLine )
1841 {
1842  SwTwips nLineHeight = m_pCurr->Height();
1843  m_pCurr->SetClipping( false );
1844 
1845  SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
1846  if ( pGrid && GetInfo().SnapToGrid() )
1847  {
1848  const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
1849  const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
1850  const bool bRubyTop = ! pGrid->GetRubyTextBelow();
1851 
1852  nLineHeight = nGridWidth + nRubyHeight;
1853  const sal_uInt16 nAmpRatio = (m_pCurr->Height() + nLineHeight - 1)/nLineHeight;
1854  nLineHeight *= nAmpRatio;
1855 
1856  const sal_uInt16 nAsc = m_pCurr->GetAscent() +
1857  ( bRubyTop ?
1858  ( nLineHeight - m_pCurr->Height() + nRubyHeight ) / 2 :
1859  ( nLineHeight - m_pCurr->Height() - nRubyHeight ) / 2 );
1860 
1861  m_pCurr->Height( nLineHeight, false );
1862  m_pCurr->SetAscent( nAsc );
1864 
1865  // we ignore any line spacing options except from ...
1866  const SvxLineSpacingItem* pSpace = m_aLineInf.GetLineSpacing();
1867  if ( ! IsParaLine() && pSpace &&
1868  SvxInterLineSpaceRule::Prop == pSpace->GetInterLineSpaceRule() )
1869  {
1870  sal_uLong nTmp = pSpace->GetPropLineSpace();
1871 
1872  if( nTmp < 100 )
1873  nTmp = 100;
1874 
1875  nTmp *= nLineHeight;
1876  nLineHeight = nTmp / 100;
1877  }
1878 
1879  m_pCurr->SetRealHeight( nLineHeight );
1880  return;
1881  }
1882 
1883  // The dummy flag is set on lines that only contain flyportions, these shouldn't
1884  // consider register-true and so on. Unfortunately an empty line can be at
1885  // the end of a paragraph (empty paragraphs or behind a Shift-Return),
1886  // which should consider the register.
1887  if (!m_pCurr->IsDummy() || (!m_pCurr->GetNext()
1888  && GetStart() >= TextFrameIndex(GetTextFrame()->GetText().getLength())
1889  && !bNewLine))
1890  {
1891  const SvxLineSpacingItem *pSpace = m_aLineInf.GetLineSpacing();
1892  if( pSpace )
1893  {
1894  switch( pSpace->GetLineSpaceRule() )
1895  {
1896  case SvxLineSpaceRule::Auto:
1897  // shrink first line of paragraph too on spacing < 100%
1898  if (IsParaLine() &&
1899  pSpace->GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
1901  {
1902  tools::Long nTmp = pSpace->GetPropLineSpace();
1903  // Word will render < 50% too but it's just not readable
1904  if( nTmp < 50 )
1905  nTmp = nTmp ? 50 : 100;
1906  if (nTmp<100) { // code adapted from fixed line height
1907  nTmp *= nLineHeight;
1908  nTmp /= 100;
1909  if( !nTmp )
1910  ++nTmp;
1911  nLineHeight = nTmp;
1912  sal_uInt16 nAsc = ( 4 * nLineHeight ) / 5; // 80%
1913 #if 0
1914  // could do clipping here (like Word does)
1915  // but at 0.5 its unreadable either way...
1916  if( nAsc < pCurr->GetAscent() ||
1917  nLineHeight - nAsc < pCurr->Height() -
1918  pCurr->GetAscent() )
1919  pCurr->SetClipping( true );
1920 #endif
1921  m_pCurr->SetAscent( nAsc );
1922  m_pCurr->Height( nLineHeight, false );
1924  }
1925  }
1926  break;
1927  case SvxLineSpaceRule::Min:
1928  {
1929  if( nLineHeight < pSpace->GetLineHeight() )
1930  nLineHeight = pSpace->GetLineHeight();
1931  break;
1932  }
1933  case SvxLineSpaceRule::Fix:
1934  {
1935  nLineHeight = pSpace->GetLineHeight();
1936  const sal_uInt16 nAsc = ( 4 * nLineHeight ) / 5; // 80%
1937  if( nAsc < m_pCurr->GetAscent() ||
1938  nLineHeight - nAsc < m_pCurr->Height() - m_pCurr->GetAscent() )
1939  m_pCurr->SetClipping( true );
1940  m_pCurr->Height( nLineHeight, false );
1941  m_pCurr->SetAscent( nAsc );
1943  }
1944  break;
1945  default: OSL_FAIL( ": unknown LineSpaceRule" );
1946  }
1947  // Note: for the _first_ line the line spacing of the previous
1948  // paragraph is applied in SwFlowFrame::CalcUpperSpace()
1949  if( !IsParaLine() )
1950  switch( pSpace->GetInterLineSpaceRule() )
1951  {
1952  case SvxInterLineSpaceRule::Off:
1953  break;
1954  case SvxInterLineSpaceRule::Prop:
1955  {
1956  tools::Long nTmp = pSpace->GetPropLineSpace();
1957  // 50% is the minimum, if 0% we switch to the
1958  // default value 100% ...
1959  if( nTmp < 50 )
1960  nTmp = nTmp ? 50 : 100;
1961 
1962  // extend line height by (nPropLineSpace - 100) percent of the font height
1963  nTmp -= 100;
1964  nTmp *= m_pCurr->GetTextHeight();
1965  nTmp /= 100;
1966  nTmp += nLineHeight;
1967  if (nTmp < 1)
1968  nTmp = 1;
1969  nLineHeight = nTmp;
1970  break;
1971  }
1972  case SvxInterLineSpaceRule::Fix:
1973  {
1974  nLineHeight = nLineHeight + pSpace->GetInterLineSpace();
1975  break;
1976  }
1977  default: OSL_FAIL( ": unknown InterLineSpaceRule" );
1978  }
1979  }
1980 
1981  if( IsRegisterOn() )
1982  {
1983  SwTwips nTmpY = Y() + m_pCurr->GetAscent() + nLineHeight - m_pCurr->Height();
1984  SwRectFnSet aRectFnSet(m_pFrame);
1985  if ( aRectFnSet.IsVert() )
1986  nTmpY = m_pFrame->SwitchHorizontalToVertical( nTmpY );
1987  nTmpY = aRectFnSet.YDiff( nTmpY, RegStart() );
1988  const sal_uInt16 nDiff = sal_uInt16( nTmpY % RegDiff() );
1989  if( nDiff )
1990  nLineHeight += RegDiff() - nDiff;
1991  }
1992  }
1993  m_pCurr->SetRealHeight( nLineHeight );
1994 }
1995 
1997 {
1998  // delete Fly in any case!
1999  ClearFly( rInf );
2000  rInf.Init();
2001 
2002  rInf.ChkNoHyph( CntEndHyph(), CntMidHyph() );
2003  rInf.SetRoot( m_pCurr );
2004  rInf.SetLineStart( m_nStart );
2005  rInf.SetIdx( m_nStart );
2006  rInf.Left( Left() );
2007  rInf.Right( Right() );
2008  rInf.First( FirstLeft() );
2009  rInf.LeftMargin(GetLeftMargin());
2010 
2011  rInf.RealWidth( sal_uInt16(rInf.Right() - GetLeftMargin()) );
2012  rInf.Width( rInf.RealWidth() );
2013  if( const_cast<SwTextFormatter*>(this)->GetRedln() )
2014  {
2015  const_cast<SwTextFormatter*>(this)->GetRedln()->Clear( const_cast<SwTextFormatter*>(this)->GetFnt() );
2016  const_cast<SwTextFormatter*>(this)->GetRedln()->Reset();
2017  }
2018 }
2019 
2021 {
2022  m_pFirstOfBorderMerge = nullptr;
2023  m_pCurr->Truncate();
2024  m_pCurr->Init();
2025 
2026  // delete pSpaceAdd and pKanaComp
2029  m_pCurr->ResetFlags();
2030  FeedInf( rInf );
2031 }
2032 
2034 {
2035  if( m_pDropFormat )
2036  {
2037  const sal_uInt16 nOldDrop = GetDropHeight();
2039  m_bOnceMore = nOldDrop != GetDropHeight();
2040  }
2041  else
2042  m_bOnceMore = false;
2043  return m_bOnceMore;
2044 }
2045 
2047 {
2048  SwTwips nRet = Y() + GetLineHeight();
2049  SwTwips nMin = GetInfo().GetTextFly().GetMinBottom();
2050  if( nMin && ++nMin > nRet )
2051  {
2054  if( nRet + nDist < nMin )
2055  {
2056  const bool bRepaint = HasTruncLines() &&
2057  GetInfo().GetParaPortion()->GetRepaint().Bottom() == nRet-1;
2058  nRet = nMin - nDist;
2059  if( bRepaint )
2060  {
2061  const_cast<SwRepaint&>(GetInfo().GetParaPortion()
2062  ->GetRepaint()).Bottom( nRet-1 );
2063  const_cast<SwTextFormatInfo&>(GetInfo()).SetPaintOfst( 0 );
2064  }
2065  }
2066  }
2067  return nRet;
2068 }
2069 
2070 // FME/OD: This routine does a limited text formatting.
2072 {
2073  FormatReset( GetInfo() );
2074  BuildPortions( GetInfo() );
2075  m_pCurr->CalcLine( *this, GetInfo() );
2076  return m_pCurr->Width();
2077 }
2078 
2079 // determines if the calculation of a repaint offset is allowed
2080 // otherwise each line is painted from 0 (this is a copy of the beginning
2081 // of the former SwTextFormatter::Recycle() function
2083 {
2084  // reformat position in front of current line? Only in this case
2085  // we want to set the repaint offset
2086  bool bOptimizeRepaint = m_nStart < GetInfo().GetReformatStart() &&
2087  m_pCurr->GetLen();
2088 
2089  // a special case is the last line of a block adjusted paragraph:
2090  if ( bOptimizeRepaint )
2091  {
2092  switch( GetAdjust() )
2093  {
2094  case SvxAdjust::Block:
2095  {
2096  if( IsLastBlock() || IsLastCenter() )
2097  bOptimizeRepaint = false;
2098  else
2099  {
2100  // ????: blank in the last master line (blocksat.sdw)
2101  bOptimizeRepaint = nullptr == m_pCurr->GetNext() && !m_pFrame->GetFollow();
2102  if ( bOptimizeRepaint )
2103  {
2105  while ( pPos && !pPos->IsFlyPortion() )
2106  pPos = pPos->GetNextPortion();
2107  bOptimizeRepaint = !pPos;
2108  }
2109  }
2110  break;
2111  }
2112  case SvxAdjust::Center:
2113  case SvxAdjust::Right:
2114  bOptimizeRepaint = false;
2115  break;
2116  default: ;
2117  }
2118  }
2119 
2120  // Again another special case: invisible SoftHyphs
2121  const TextFrameIndex nReformat = GetInfo().GetReformatStart();
2122  if (bOptimizeRepaint && TextFrameIndex(COMPLETE_STRING) != nReformat)
2123  {
2124  const sal_Unicode cCh = nReformat >= TextFrameIndex(GetInfo().GetText().getLength())
2125  ? 0
2126  : GetInfo().GetText()[ sal_Int32(nReformat) ];
2127  bOptimizeRepaint = ( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
2128  || ! GetInfo().HasHint( nReformat );
2129  }
2130 
2131  return bOptimizeRepaint;
2132 }
2133 
2135 {
2136  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
2137  "SwTextFormatter::CalcUnclipped with unswapped frame" );
2138 
2139  SwTwips nFlyAsc, nFlyDesc;
2140  m_pCurr->MaxAscentDescent( rTop, rBottom, nFlyAsc, nFlyDesc );
2141  rTop = Y() + GetCurr()->GetAscent();
2142  rBottom = rTop + nFlyDesc;
2143  rTop -= nFlyAsc;
2144 }
2145 
2146 void SwTextFormatter::UpdatePos( SwLineLayout *pCurrent, Point aStart,
2147  TextFrameIndex const nStartIdx, bool bAlways) const
2148 {
2149  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
2150  "SwTextFormatter::UpdatePos with unswapped frame" );
2151 
2152  if( GetInfo().IsTest() )
2153  return;
2154  SwLinePortion *pFirst = pCurrent->GetFirstPortion();
2155  SwLinePortion *pPos = pFirst;
2156  SwTextPaintInfo aTmpInf( GetInfo() );
2157  aTmpInf.SetpSpaceAdd( pCurrent->GetpLLSpaceAdd() );
2158  aTmpInf.ResetSpaceIdx();
2159  aTmpInf.SetKanaComp( pCurrent->GetpKanaComp() );
2160  aTmpInf.ResetKanaIdx();
2161 
2162  // The frame's size
2163  aTmpInf.SetIdx( nStartIdx );
2164  aTmpInf.SetPos( aStart );
2165 
2166  SwTwips nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2167  pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2168 
2169  const SwTwips nTmpHeight = pCurrent->GetRealHeight();
2170  SwTwips nAscent = pCurrent->GetAscent() + nTmpHeight - pCurrent->Height();
2172  if( GetMulti() )
2173  {
2174  aTmpInf.SetDirection( GetMulti()->GetDirection() );
2175  if( GetMulti()->HasRotation() )
2176  {
2177  nFlags |= AsCharFlags::Rotate;
2178  if( GetMulti()->IsRevers() )
2179  {
2180  nFlags |= AsCharFlags::Reverse;
2181  aTmpInf.X( aTmpInf.X() - nAscent );
2182  }
2183  else
2184  aTmpInf.X( aTmpInf.X() + nAscent );
2185  }
2186  else
2187  {
2188  if ( GetMulti()->IsBidi() )
2189  nFlags |= AsCharFlags::Bidi;
2190  aTmpInf.Y( aTmpInf.Y() + nAscent );
2191  }
2192  }
2193  else
2194  aTmpInf.Y( aTmpInf.Y() + nAscent );
2195 
2196  while( pPos )
2197  {
2198  // We only know one case where changing the position (caused by the
2199  // adjustment) could be relevant for a portion: We need to SetRefPoint
2200  // for FlyCntPortions.
2201  if( ( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
2202  && ( bAlways || !IsQuick() ) )
2203  {
2204  pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
2205 
2206  if( pPos->IsGrfNumPortion() )
2207  {
2208  if( !nFlyAsc && !nFlyDesc )
2209  {
2210  nTmpAscent = nAscent;
2211  nFlyAsc = nAscent;
2212  nTmpDescent = nTmpHeight - nAscent;
2213  nFlyDesc = nTmpDescent;
2214  }
2215  static_cast<SwGrfNumPortion*>(pPos)->SetBase( nTmpAscent, nTmpDescent,
2216  nFlyAsc, nFlyDesc );
2217  }
2218  else
2219  {
2220  Point aBase( aTmpInf.GetPos() );
2221  if ( GetInfo().GetTextFrame()->IsVertical() )
2223 
2224  static_cast<SwFlyCntPortion*>(pPos)->SetBase( *aTmpInf.GetTextFrame(),
2225  aBase, nTmpAscent, nTmpDescent, nFlyAsc,
2226  nFlyDesc, nFlags );
2227  }
2228  }
2229  if( pPos->IsMultiPortion() && static_cast<SwMultiPortion*>(pPos)->HasFlyInContent() )
2230  {
2231  OSL_ENSURE( !GetMulti(), "Too much multi" );
2232  const_cast<SwTextFormatter*>(this)->m_pMulti = static_cast<SwMultiPortion*>(pPos);
2233  SwLineLayout *pLay = &GetMulti()->GetRoot();
2234  Point aSt( aTmpInf.X(), aStart.Y() );
2235 
2236  if ( GetMulti()->HasBrackets() )
2237  {
2238  OSL_ENSURE( GetMulti()->IsDouble(), "Brackets only for doubles");
2239  aSt.AdjustX(static_cast<SwDoubleLinePortion*>(GetMulti())->PreWidth() );
2240  }
2241  else if( GetMulti()->HasRotation() )
2242  {
2243  aSt.AdjustY(pCurrent->GetAscent() - GetMulti()->GetAscent() );
2244  if( GetMulti()->IsRevers() )
2245  aSt.AdjustX(GetMulti()->Width() );
2246  else
2247  aSt.AdjustY(GetMulti()->Height() );
2248  }
2249  else if ( GetMulti()->IsBidi() )
2250  // jump to end of the bidi portion
2251  aSt.AdjustX(pLay->Width() );
2252 
2253  TextFrameIndex nStIdx = aTmpInf.GetIdx();
2254  do
2255  {
2256  UpdatePos( pLay, aSt, nStIdx, bAlways );
2257  nStIdx = nStIdx + pLay->GetLen();
2258  aSt.AdjustY(pLay->Height() );
2259  pLay = pLay->GetNext();
2260  } while ( pLay );
2261  const_cast<SwTextFormatter*>(this)->m_pMulti = nullptr;
2262  }
2263  pPos->Move( aTmpInf );
2264  pPos = pPos->GetNextPortion();
2265  }
2266 }
2267 
2269 {
2270  OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),
2271  "SwTextFormatter::AlignFlyInCntBase with unswapped frame" );
2272 
2273  if( GetInfo().IsTest() )
2274  return;
2275  SwLinePortion *pFirst = m_pCurr->GetFirstPortion();
2276  SwLinePortion *pPos = pFirst;
2277  AsCharFlags nFlags = AsCharFlags::None;
2278  if( GetMulti() && GetMulti()->HasRotation() )
2279  {
2280  nFlags |= AsCharFlags::Rotate;
2281  if( GetMulti()->IsRevers() )
2282  nFlags |= AsCharFlags::Reverse;
2283  }
2284 
2285  SwTwips nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2286 
2287  while( pPos )
2288  {
2289  if( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
2290  {
2291  m_pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
2292 
2293  if( pPos->IsGrfNumPortion() )
2294  static_cast<SwGrfNumPortion*>(pPos)->SetBase( nTmpAscent, nTmpDescent,
2295  nFlyAsc, nFlyDesc );
2296  else
2297  {
2298  Point aBase;
2299  if ( GetInfo().GetTextFrame()->IsVertical() )
2300  {
2301  nBaseLine = GetInfo().GetTextFrame()->SwitchHorizontalToVertical( nBaseLine );
2302  aBase = Point( nBaseLine, static_cast<SwFlyCntPortion*>(pPos)->GetRefPoint().Y() );
2303  }
2304  else
2305  aBase = Point( static_cast<SwFlyCntPortion*>(pPos)->GetRefPoint().X(), nBaseLine );
2306 
2307  static_cast<SwFlyCntPortion*>(pPos)->SetBase( *GetInfo().GetTextFrame(), aBase, nTmpAscent, nTmpDescent,
2308  nFlyAsc, nFlyDesc, nFlags );
2309  }
2310  }
2311  pPos = pPos->GetNextPortion();
2312  }
2313 }
2314 
2316 {
2317  OSL_ENSURE( rInf.GetTextFly().IsOn(), "SwTextFormatter::ChkFlyUnderflow: why?" );
2318  if( GetCurr() )
2319  {
2320  // First we check, whether a fly overlaps with the line.
2321  // = GetLineHeight()
2322  const sal_uInt16 nHeight = GetCurr()->GetRealHeight();
2323  SwRect aLine( GetLeftMargin(), Y(), rInf.RealWidth(), nHeight );
2324 
2325  SwRect aLineVert( aLine );
2326  if ( m_pFrame->IsVertical() )
2327  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2328  SwRect aInter( rInf.GetTextFly().GetFrame( aLineVert ) );
2329  if ( m_pFrame->IsVertical() )
2331 
2332  if( !aInter.HasArea() )
2333  return false;
2334 
2335  // We now check every portion that could have lowered for overlapping
2336  // with the fly.
2337  const SwLinePortion *pPos = GetCurr()->GetFirstPortion();
2338  aLine.Pos().setY( Y() + GetCurr()->GetRealHeight() - GetCurr()->Height() );
2339  aLine.Height( GetCurr()->Height() );
2340 
2341  while( pPos )
2342  {
2343  aLine.Width( pPos->Width() );
2344 
2345  aLineVert = aLine;
2346  if ( m_pFrame->IsVertical() )
2347  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2348  aInter = rInf.GetTextFly().GetFrame( aLineVert );
2349  if ( m_pFrame->IsVertical() )
2351 
2352  // New flys from below?
2353  if( !pPos->IsFlyPortion() )
2354  {
2355  if( aInter.Overlaps( aLine ) )
2356  {
2357  aInter.Intersection_( aLine );
2358  if( aInter.HasArea() )
2359  {
2360  // To be evaluated during reformat of this line:
2361  // RealHeight including spacing
2362  rInf.SetLineHeight( nHeight );
2363  // Height without extra spacing
2364  rInf.SetLineNetHeight( m_pCurr->Height() );
2365  return true;
2366  }
2367  }
2368  }
2369  else
2370  {
2371  // The fly portion is not intersected by a fly anymore
2372  if ( ! aInter.Overlaps( aLine ) )
2373  {
2374  rInf.SetLineHeight( nHeight );
2375  rInf.SetLineNetHeight( m_pCurr->Height() );
2376  return true;
2377  }
2378  else
2379  {
2380  aInter.Intersection_( aLine );
2381 
2382  // No area means a fly has become invalid because of
2383  // lowering the line => reformat the line
2384  // we also have to reformat the line, if the fly size
2385  // differs from the intersection interval's size.
2386  if( ! aInter.HasArea() ||
2387  static_cast<const SwFlyPortion*>(pPos)->GetFixWidth() != aInter.Width() )
2388  {
2389  rInf.SetLineHeight( nHeight );
2390  rInf.SetLineNetHeight( m_pCurr->Height() );
2391  return true;
2392  }
2393  }
2394  }
2395 
2396  aLine.Left( aLine.Left() + pPos->Width() );
2397  pPos = pPos->GetNextPortion();
2398  }
2399  }
2400  return false;
2401 }
2402 
2404 {
2405  if( GetMulti() || rInf.GetFly() )
2406  return;
2407 
2408  SwTextFly& rTextFly = rInf.GetTextFly();
2409  if( !rTextFly.IsOn() || rInf.IsIgnoreFly() )
2410  return;
2411 
2412  const SwLinePortion *pLast = rInf.GetLast();
2413 
2414  tools::Long nAscent;
2415  tools::Long nTop = Y();
2416  tools::Long nHeight;
2417 
2418  if( rInf.GetLineHeight() )
2419  {
2420  // Real line height has already been calculated, we only have to
2421  // search for intersections in the lower part of the strip
2422  nAscent = m_pCurr->GetAscent();
2423  nHeight = rInf.GetLineNetHeight();
2424  nTop += rInf.GetLineHeight() - nHeight;
2425  }
2426  else
2427  {
2428  // We make a first guess for the lines real height
2429  if ( ! m_pCurr->GetRealHeight() )
2430  CalcRealHeight();
2431 
2432  nAscent = pLast->GetAscent();
2433  nHeight = pLast->Height();
2434 
2435  if ( m_pCurr->GetRealHeight() > nHeight )
2436  nTop += m_pCurr->GetRealHeight() - nHeight;
2437  else
2438  // Important for fixed space between lines
2439  nHeight = m_pCurr->GetRealHeight();
2440  }
2441 
2442  const tools::Long nLeftMar = GetLeftMargin();
2443  const tools::Long nLeftMin = (rInf.X() || GetDropLeft()) ? nLeftMar : GetLeftMin();
2444 
2445  SwRect aLine( rInf.X() + nLeftMin, nTop, rInf.RealWidth() - rInf.X()
2446  + nLeftMar - nLeftMin , nHeight );
2447 
2448  // tdf#116486: consider also the upper margin from getFramePrintArea because intersections
2449  // with this additional space should lead to repositioning of paragraphs
2450  // For compatibility we grab a related compat flag:
2452  && IsFirstTextLine())
2453  {
2454  const tools::Long nUpper = m_pFrame->getFramePrintArea().Top();
2455  // Increase the rectangle
2456  if( nUpper > 0 && nTop >= nUpper )
2457  aLine.SubTop( nUpper );
2458  }
2459  SwRect aLineVert( aLine );
2460  if ( m_pFrame->IsRightToLeft() )
2461  m_pFrame->SwitchLTRtoRTL( aLineVert );
2462 
2463  if ( m_pFrame->IsVertical() )
2464  m_pFrame->SwitchHorizontalToVertical( aLineVert );
2465 
2466  // GetFrame(...) determines and returns the intersection rectangle
2467  SwRect aInter( rTextFly.GetFrame( aLineVert ) );
2468 
2469  if ( m_pFrame->IsRightToLeft() )
2470  m_pFrame->SwitchRTLtoLTR( aInter );
2471 
2472  if ( m_pFrame->IsVertical() )
2474 
2475  if (!aInter.IsEmpty() && aInter.Bottom() < nTop)
2476  {
2477  // Intersects with the frame area (with upper margin), but not with the print area (without
2478  // upper margin). Don't reserve space for the fly portion in this case, text is allowed to
2479  // flow there.
2480  aInter.Height(0);
2481  }
2482 
2483  if( !aInter.Overlaps( aLine ) )
2484  return;
2485 
2486  aLine.Left( rInf.X() + nLeftMar );
2487  bool bForced = false;
2488  if( aInter.Left() <= nLeftMin )
2489  {
2490  SwTwips nFrameLeft = GetTextFrame()->getFrameArea().Left();
2491  if( GetTextFrame()->getFramePrintArea().Left() < 0 )
2492  nFrameLeft += GetTextFrame()->getFramePrintArea().Left();
2493  if( aInter.Left() < nFrameLeft )
2494  aInter.Left( nFrameLeft );
2495 
2496  tools::Long nAddMar = 0;
2497  if ( m_pFrame->IsRightToLeft() )
2498  {
2499  nAddMar = m_pFrame->getFrameArea().Right() - Right();
2500  if ( nAddMar < 0 )
2501  nAddMar = 0;
2502  }
2503  else
2504  nAddMar = nLeftMar - nFrameLeft;
2505 
2506  aInter.Width( aInter.Width() + nAddMar );
2507  // For a negative first line indent, we set this flag to show
2508  // that the indentation/margin has been moved.
2509  // This needs to be respected by the DefaultTab at the zero position.
2510  if( IsFirstTextLine() && HasNegFirst() )
2511  bForced = true;
2512  }
2513  aInter.Intersection( aLine );
2514  if( !aInter.HasArea() )
2515  return;
2516 
2517  const bool bFullLine = aLine.Left() == aInter.Left() &&
2518  aLine.Right() == aInter.Right();
2519 
2520  // Although no text is left, we need to format another line,
2521  // because also empty lines need to avoid a Fly with no wrapping.
2522  if (bFullLine && rInf.GetIdx() == TextFrameIndex(rInf.GetText().getLength()))
2523  {
2524  rInf.SetNewLine( true );
2525  // We know that for dummies, it holds ascent == height
2526  m_pCurr->SetDummy(true);
2527  }
2528 
2529  // aInter becomes frame-local
2530  aInter.Pos().AdjustX( -nLeftMar );
2531  SwFlyPortion *pFly = new SwFlyPortion( aInter );
2532  if( bForced )
2533  {
2535  rInf.ForcedLeftMargin( o3tl::narrowing<sal_uInt16>(aInter.Width()) );
2536  }
2537 
2538  if( bFullLine )
2539  {
2540  // In order to properly flow around Flys with different
2541  // wrapping attributes, we need to increase by units of line height.
2542  // The last avoiding line should be adjusted in height, so that
2543  // we don't get a frame spacing effect.
2544  // It is important that ascent == height, because the FlyPortion
2545  // values are transferred to pCurr in CalcLine and IsDummy() relies
2546  // on this behaviour.
2547  // To my knowledge we only have two places where DummyLines can be
2548  // created: here and in MakeFlyDummies.
2549  // IsDummy() is evaluated in IsFirstTextLine(), when moving lines
2550  // and in relation with DropCaps.
2551  pFly->Height( aInter.Height() );
2552 
2553  // nNextTop now contains the margin's bottom edge, which we avoid
2554  // or the next margin's top edge, which we need to respect.
2555  // That means we can comfortably grow up to this value; that's how
2556  // we save a few empty lines.
2557  tools::Long nNextTop = rTextFly.GetNextTop();
2558  if ( m_pFrame->IsVertical() )
2559  nNextTop = m_pFrame->SwitchVerticalToHorizontal( nNextTop );
2560  if( nNextTop > aInter.Bottom() )
2561  {
2562  SwTwips nH = nNextTop - aInter.Top();
2563  if( nH < SAL_MAX_UINT16 )
2564  pFly->Height( nH );
2565  }
2566  if( nAscent < pFly->Height() )
2567  pFly->SetAscent( nAscent );
2568  else
2569  pFly->SetAscent( pFly->Height() );
2570  }
2571  else
2572  {
2573  if (rInf.GetIdx() == TextFrameIndex(rInf.GetText().getLength()))
2574  {
2575  // Don't use nHeight, or we have a huge descent
2576  pFly->Height( pLast->Height() );
2577  pFly->SetAscent( pLast->GetAscent() );
2578  }
2579  else
2580  {
2581  pFly->Height( aInter.Height() );
2582  if( nAscent < pFly->Height() )
2583  pFly->SetAscent( nAscent );
2584  else
2585  pFly->SetAscent( pFly->Height() );
2586  }
2587  }
2588 
2589  rInf.SetFly( pFly );
2590 
2591  if( pFly->GetFix() < rInf.Width() )
2592  rInf.Width( pFly->GetFix() );
2593 
2594  SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
2595  if ( !pGrid )
2596  return;
2597 
2598  const SwPageFrame* pPageFrame = m_pFrame->FindPageFrame();
2599  const SwLayoutFrame* pBody = pPageFrame->FindBodyCont();
2600 
2601  SwRectFnSet aRectFnSet(pPageFrame);
2602 
2603  const tools::Long nGridOrigin = pBody ?
2604  aRectFnSet.GetPrtLeft(*pBody) :
2605  aRectFnSet.GetPrtLeft(*pPageFrame);
2606 
2607  const SwDoc & rDoc = rInf.GetTextFrame()->GetDoc();
2608  const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, rDoc);
2609 
2610  SwTwips nStartX = GetLeftMargin();
2611  if ( aRectFnSet.IsVert() )
2612  {
2613  Point aPoint( nStartX, 0 );
2615  nStartX = aPoint.Y();
2616  }
2617 
2618  const SwTwips nOfst = nStartX - nGridOrigin;
2619  const SwTwips nTmpWidth = rInf.Width() + nOfst;
2620 
2621  const SwTwips i = nTmpWidth / nGridWidth + 1;
2622 
2623  const SwTwips nNewWidth = ( i - 1 ) * nGridWidth - nOfst;
2624  if ( nNewWidth > 0 )
2625  rInf.Width( nNewWidth );
2626  else
2627  rInf.Width( 0 );
2628 
2629 
2630 }
2631 
2633  SwTextAttr *pHint ) const
2634 {
2635  const SwFrame *pFrame = m_pFrame;
2636 
2637  SwFlyInContentFrame *pFly;
2638  SwFrameFormat* pFrameFormat = static_cast<SwTextFlyCnt*>(pHint)->GetFlyCnt().GetFrameFormat();
2639  if( RES_FLYFRMFMT == pFrameFormat->Which() )
2640  {
2641  // set Lock pFrame to avoid m_pCurr getting deleted
2642  TextFrameLockGuard aGuard(m_pFrame);
2643  pFly = static_cast<SwTextFlyCnt*>(pHint)->GetFlyFrame(pFrame);
2644  }
2645  else
2646  pFly = nullptr;
2647  // aBase is the document-global position, from which the new extra portion is placed
2648  // aBase.X() = Offset in the line after the current position
2649  // aBase.Y() = LineIter.Y() + Ascent of the current position
2650 
2651  SwTwips nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
2652  // i#11859 - use new method <SwLineLayout::MaxAscentDescent(..)>
2653  // to change line spacing behaviour at paragraph - Compatibility to MS Word
2654  //SwLinePortion *pPos = pCurr->GetFirstPortion();
2655  //lcl_MaxAscDescent( pPos, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2656  m_pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
2657 
2658  // If the ascent of the frame is larger than the ascent of the current position,
2659  // we use this one when calculating the base, or the frame would be positioned
2660  // too much to the top, sliding down after all causing a repaint in an area
2661  // he actually never was in.
2662  SwTwips nAscent = 0;
2663 
2664  const bool bTextFrameVertical = GetInfo().GetTextFrame()->IsVertical();
2665 
2666  const bool bUseFlyAscent = pFly && pFly->isFrameAreaPositionValid() &&
2667  0 != ( bTextFrameVertical ?
2668  pFly->GetRefPoint().X() :
2669  pFly->GetRefPoint().Y() );
2670 
2671  if ( bUseFlyAscent )
2672  nAscent = std::abs( int( bTextFrameVertical ?
2673  pFly->GetRelPos().X() :
2674  pFly->GetRelPos().Y() ) );
2675 
2676  // Check if be prefer to use the ascent of the last portion:
2677  if ( IsQuick() ||
2678  !bUseFlyAscent ||
2679  nAscent < rInf.GetLast()->GetAscent() )
2680  {
2681  nAscent = rInf.GetLast()->GetAscent();
2682  }
2683  else if( nAscent > nFlyAsc )
2684  nFlyAsc = nAscent;
2685 
2686  Point aBase( GetLeftMargin() + rInf.X(), Y() + nAscent );
2688  if( GetMulti() && GetMulti()->HasRotation() )
2689  {
2690  nMode |= AsCharFlags::Rotate;
2691  if( GetMulti()->IsRevers() )
2692  nMode |= AsCharFlags::Reverse;
2693  }
2694 
2695  Point aTmpBase( aBase );
2696  if ( GetInfo().GetTextFrame()->IsVertical() )
2698 
2699  SwFlyCntPortion* pRet(nullptr);
2700  if( pFly )
2701  {
2702  pRet = sw::FlyContentPortion::Create(*GetInfo().GetTextFrame(), pFly, aTmpBase, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode);
2703  // We need to make sure that our font is set again in the OutputDevice
2704  // It could be that the FlyInCnt was added anew and GetFlyFrame() would
2705  // in turn cause, that it'd be created anew again.
2706  // This one's frames get formatted right away, which change the font.
2707  rInf.SelectFont();
2708  if( pRet->GetAscent() > nAscent )
2709  {
2710  aBase.setY( Y() + pRet->GetAscent() );
2711  nMode |= AsCharFlags::UlSpace;
2712  if( !rInf.IsTest() )
2713  {
2714  aTmpBase = aBase;
2715  if ( GetInfo().GetTextFrame()->IsVertical() )
2717 
2718  pRet->SetBase( *rInf.GetTextFrame(), aTmpBase, nTmpAscent,
2719  nTmpDescent, nFlyAsc, nFlyDesc, nMode );
2720  }
2721  }
2722  }
2723  else
2724  {
2725  pRet = sw::DrawFlyCntPortion::Create(*rInf.GetTextFrame(), *pFrameFormat, aTmpBase, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode);
2726  }
2727  return pRet;
2728 }
2729 
2730 /* Drop portion is a special case, because it has parts which aren't portions
2731  but we have handle them just like portions */
2733 {
2734  if( rPortion.GetLines() <= 1 )
2735  return;
2736 
2737  SwDropPortionPart* pCurrPart = rPortion.GetPart();
2738  while( pCurrPart )
2739  {
2740  if( pCurrPart->GetFollow() &&
2741  ::lcl_HasSameBorder(pCurrPart->GetFont(), pCurrPart->GetFollow()->GetFont()) )
2742  {
2743  pCurrPart->SetJoinBorderWithNext(true);
2744  pCurrPart->GetFollow()->SetJoinBorderWithPrev(true);
2745  }
2746  pCurrPart = pCurrPart->GetFollow();
2747  }
2748 }
2749 
2751 {
2752  const SwFont aCurFont = *rInf.GetFont();
2753  if( !aCurFont.HasBorder() )
2754  return;
2755 
2756  if (pPrev && pPrev->GetJoinBorderWithNext() )
2757  {
2758  // In some case border merge is called twice to the portion
2759  if( !rPortion.GetJoinBorderWithPrev() )
2760  {
2761  rPortion.SetJoinBorderWithPrev(true);
2762  if( rPortion.InTextGrp() && rPortion.Width() > aCurFont.GetLeftBorderSpace() )
2763  rPortion.Width(rPortion.Width() - aCurFont.GetLeftBorderSpace());
2764  }
2765  }
2766  else
2767  {
2768  rPortion.SetJoinBorderWithPrev(false);
2769  m_pFirstOfBorderMerge = &rPortion;
2770  }
2771 
2772  // Get next portion's font
2773  bool bSeek = false;
2774  if (!rInf.IsFull() && // Not the last portion of the line (in case of line break)
2775  rInf.GetIdx() + rPortion.GetLen() != TextFrameIndex(rInf.GetText().getLength())) // Not the last portion of the paragraph
2776  {
2777  bSeek = Seek(rInf.GetIdx() + rPortion.GetLen());
2778  }
2779  // Don't join the next portion if SwKernPortion sits between two different boxes.
2780  bool bDisconnect = rPortion.IsKernPortion() && !rPortion.GetJoinBorderWithPrev();
2781  // If next portion has the same border then merge
2782  if( bSeek && GetFnt()->HasBorder() && ::lcl_HasSameBorder(aCurFont, *GetFnt()) && !bDisconnect )
2783  {
2784  // In some case border merge is called twice to the portion
2785  if( !rPortion.GetJoinBorderWithNext() )
2786  {
2787  rPortion.SetJoinBorderWithNext(true);
2788  if( rPortion.InTextGrp() && rPortion.Width() > aCurFont.GetRightBorderSpace() )
2789  rPortion.Width(rPortion.Width() - aCurFont.GetRightBorderSpace());
2790  }
2791  }
2792  // If this is the last portion of the merge group then make the real height merge
2793  else
2794  {
2795  rPortion.SetJoinBorderWithNext(false);
2796  if( m_pFirstOfBorderMerge != &rPortion )
2797  {
2798  // Calculate maximum height and ascent
2800  sal_uInt16 nMaxAscent = 0;
2801  sal_uInt16 nMaxHeight = 0;
2802  bool bReachCurrent = false;
2803  while( pActPor )
2804  {
2805  if( nMaxHeight < pActPor->Height() )
2806  nMaxHeight = pActPor->Height();
2807  if( nMaxAscent < pActPor->GetAscent() )
2808  nMaxAscent = pActPor->GetAscent();
2809 
2810  pActPor = pActPor->GetNextPortion();
2811  if( !pActPor && !bReachCurrent )
2812  {
2813  pActPor = &rPortion;
2814  bReachCurrent = true;
2815  }
2816  }
2817 
2818  // Change all portion's height and ascent
2819  pActPor = m_pFirstOfBorderMerge;
2820  bReachCurrent = false;
2821  while( pActPor )
2822  {
2823  if( nMaxHeight > pActPor->Height() )
2824  pActPor->Height(nMaxHeight);
2825  if( nMaxAscent > pActPor->GetAscent() )
2826  pActPor->SetAscent(nMaxAscent);
2827 
2828  pActPor = pActPor->GetNextPortion();
2829  if( !pActPor && !bReachCurrent )
2830  {
2831  pActPor = &rPortion;
2832  bReachCurrent = true;
2833  }
2834  }
2835  m_pFirstOfBorderMerge = nullptr;
2836  }
2837  }
2838  Seek(rInf.GetIdx());
2839 }
2840 
2841 namespace {
2842  // calculates and sets optimal repaint offset for the current line
2843  tools::Long lcl_CalcOptRepaint( SwTextFormatter &rThis,
2844  SwLineLayout const &rCurr,
2845  TextFrameIndex const nOldLineEnd,
2846  const std::vector<tools::Long> &rFlyStarts )
2847  {
2848  SwTextFormatInfo& txtFormatInfo = rThis.GetInfo();
2849  if ( txtFormatInfo.GetIdx() < txtFormatInfo.GetReformatStart() )
2850  // the reformat position is behind our new line, that means
2851  // something of our text has moved to the next line
2852  return 0;
2853 
2854  TextFrameIndex nReformat = std::min(txtFormatInfo.GetReformatStart(), nOldLineEnd);
2855 
2856  // in case we do not have any fly in our line, our repaint position
2857  // is the changed position - 1
2858  if ( rFlyStarts.empty() && ! rCurr.IsFly() )
2859  {
2860  // this is the maximum repaint offset determined during formatting
2861  // for example: the beginning of the first right tab stop
2862  // if this value is 0, this means that we do not have an upper
2863  // limit for the repaint offset
2864  const tools::Long nFormatRepaint = txtFormatInfo.GetPaintOfst();
2865 
2866  if (nReformat < txtFormatInfo.GetLineStart() + TextFrameIndex(3))
2867  return 0;
2868 
2869  // step back two positions for smoother repaint
2870  nReformat -= TextFrameIndex(2);
2871 
2872  // i#28795, i#34607, i#38388
2873  // step back more characters, this is required by complex scripts
2874  // e.g., for Khmer (thank you, Javier!)
2875  static const TextFrameIndex nMaxContext(10);
2876  if (nReformat > txtFormatInfo.GetLineStart() + nMaxContext)
2877  nReformat = nReformat - nMaxContext;
2878  else
2879  {
2880  nReformat = txtFormatInfo.GetLineStart();
2881  //reset the margin flag - prevent loops
2883  }
2884 
2885  // Weird situation: Our line used to end with a hole portion
2886  // and we delete some characters at the end of our line. We have
2887  // to take care for repainting the blanks which are not anymore
2888  // covered by the hole portion
2889  while ( nReformat > txtFormatInfo.GetLineStart() &&
2890  CH_BLANK == txtFormatInfo.GetChar( nReformat ) )
2891  --nReformat;
2892 
2893  OSL_ENSURE( nReformat < txtFormatInfo.GetIdx(), "Reformat too small for me!" );
2894  SwRect aRect;
2895 
2896  // Note: GetChareRect is not const. It definitely changes the
2897  // bMulti flag. We have to save and restore the old value.
2898  bool bOldMulti = txtFormatInfo.IsMulti();
2899  rThis.GetCharRect( &aRect, nReformat );
2900  txtFormatInfo.SetMulti( bOldMulti );
2901 
2902  return nFormatRepaint ? std::min( aRect.Left(), nFormatRepaint ) :
2903  aRect.Left();
2904  }
2905  else
2906  {
2907  // nReformat may be wrong, if something around flys has changed:
2908  // we compare the former and the new fly positions in this line
2909  // if anything has changed, we carefully have to adjust the right
2910  // repaint position
2911  tools::Long nPOfst = 0;
2912  size_t nCnt = 0;
2913  tools::Long nX = 0;
2914  TextFrameIndex nIdx = rThis.GetInfo().GetLineStart();
2915  SwLinePortion* pPor = rCurr.GetFirstPortion();
2916 
2917  while ( pPor )
2918  {
2919  if ( pPor->IsFlyPortion() )
2920  {
2921  // compare start of fly with former start of fly
2922  if (nCnt < rFlyStarts.size() &&
2923  nX == rFlyStarts[ nCnt ] &&
2924  nIdx < nReformat
2925  )
2926  // found fix position, nothing has changed left from nX
2927  nPOfst = nX + pPor->Width();
2928  else
2929  break;
2930 
2931  nCnt++;
2932  }
2933  nX = nX + pPor->Width();
2934  nIdx = nIdx + pPor->GetLen();
2935  pPor = pPor->GetNextPortion();
2936  }
2937 
2938  return nPOfst + rThis.GetLeftMargin();
2939  }
2940  }
2941 
2942  // Determine if we need to build hidden portions
2943  bool lcl_BuildHiddenPortion(const SwTextSizeInfo& rInf, TextFrameIndex & rPos)
2944  {
2945  // Only if hidden text should not be shown:
2946  // if ( rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar() )
2947  const bool bShowInDocView = rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar();
2948  const bool bShowForPrinting = rInf.GetOpt().IsShowHiddenChar( true ) && rInf.GetOpt().IsPrinting();
2949  if (bShowInDocView || bShowForPrinting)
2950  return false;
2951 
2952  const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
2953  TextFrameIndex nHiddenStart;
2954  TextFrameIndex nHiddenEnd;
2955  rSI.GetBoundsOfHiddenRange( rPos, nHiddenStart, nHiddenEnd );
2956  if ( nHiddenEnd )
2957  {
2958  rPos = nHiddenEnd;
2959  return true;
2960  }
2961 
2962  return false;
2963  }
2964 
2965  bool lcl_HasSameBorder(const SwFont& rFirst, const SwFont& rSecond)
2966  {
2967  return
2968  rFirst.GetTopBorder() == rSecond.GetTopBorder() &&
2969  rFirst.GetBottomBorder() == rSecond.GetBottomBorder() &&
2970  rFirst.GetLeftBorder() == rSecond.GetLeftBorder() &&
2971  rFirst.GetRightBorder() == rSecond.GetRightBorder() &&
2972  rFirst.GetTopBorderDist() == rSecond.GetTopBorderDist() &&
2973  rFirst.GetBottomBorderDist() == rSecond.GetBottomBorderDist() &&
2974  rFirst.GetLeftBorderDist() == rSecond.GetLeftBorderDist() &&
2975  rFirst.GetRightBorderDist() == rSecond.GetRightBorderDist() &&
2976  rFirst.GetOrientation() == rSecond.GetOrientation() &&
2977  rFirst.GetShadowColor() == rSecond.GetShadowColor() &&
2978  rFirst.GetShadowWidth() == rSecond.GetShadowWidth() &&
2979  rFirst.GetShadowLocation() == rSecond.GetShadowLocation();
2980  }
2981 
2982 } //end unnamed namespace
2983 
2984 /* 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
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
void SetLineNetHeight(const sal_uInt16 nNew)
Definition: inftxt.hxx:596
virtual void Height(const SwTwips nNew, const bool bText=true) override
Definition: porlay.cxx:199
bool IsParaLine() const
Definition: itrtxt.hxx:125
SwScriptInfo * m_pScriptInfo
Definition: itratr.hxx:40
std::deque< sal_uInt16 > * GetpKanaComp() const
Definition: porlay.hxx:204
Base class of the Writer layout elements.
Definition: frame.hxx:315
void Move(SwTextPaintInfo &rInf)
Definition: porlin.cxx:268
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
bool LastKernPortion()
Definition: inftxt.cxx:1695
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:159
bool IsArrowDone() const
Definition: inftxt.hxx:630
SwTwips GetMinBottom() const
Definition: txtfly.hxx:337
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:130
void SwitchVerticalToHorizontal(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from vertical to horizontal layout...
Definition: txtfrm.cxx:583
bool IsRegisterOn() const
Definition: itrtxt.hxx: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:834
void FormatReset(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:2020
const std::optional< editeng::SvxBorderLine > & GetBottomBorder() const
Definition: swfont.hxx:337
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:224
void Right(const tools::Long nRight)
Definition: swrect.hxx:202
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:122
sal_uInt16 GetPropLineSpace() const
bool IsGrfNumPortion() const
Definition: porlin.hxx:112
Marks a position in the document model.
Definition: pam.hxx:36
TextFrameIndex NextScriptChg(TextFrameIndex nPos) const
Definition: porlay.cxx:1756
sal_uInt16 GetLines() const
Definition: pordrop.hxx:90
bool IsUnderflow() const
Definition: inftxt.hxx:582
void SetFly(const bool bNew)
Definition: porlay.hxx:128
SwFlyCntPortion * NewFlyCntPortion(SwTextFormatInfo &rInf, SwTextAttr *pHt) const
Sets a new portion for an object anchored as character.
Definition: itrform2.cxx:2632
bool IsRest() const
Definition: porlay.hxx:131
SwTwips GetPaintOfst() const
Definition: inftxt.hxx:730
SwFont * GetFont()
Definition: inftxt.hxx:231
SwLineLayout * GetNext()
Definition: porlay.hxx:161
bool IsSwapped() const
Definition: txtfrm.hxx:536
bool SeekStartAndChg(SwTextSizeInfo &rInf, const bool bPara=false)
Definition: itrtxt.hxx:323
SwDocShell * GetDocShell()
Definition: doc.hxx:1352
bool InNumberGrp() const
Definition: porlin.hxx:103
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:197
TextFrameIndex NextHiddenChg(TextFrameIndex nPos) const
Definition: porlay.cxx:1809
bool IsTextPortion() const
Definition: porlin.hxx:133
bool IsInFootnote() const
Definition: frame.hxx:950
sal_uInt16 GetTopBorderDist() const
Definition: swfont.hxx:356
bool GetJoinBorderWithPrev() const
Definition: porlin.hxx:171
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:476
sal_uInt16 GetRightBorderSpace() const
Definition: swfont.hxx: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:2732
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:319
const SwRect & getFramePrintArea() const
Definition: frame.hxx:181
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:120
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:1602
tools::Long GetLen(const Point &rPnt)
Definition: doc.hxx:188
void CalcLine(SwTextFormatter &rLine, SwTextFormatInfo &rInf)
Definition: porlay.cxx:335
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
constexpr OUStringLiteral ODF_FORMDATE
sal_uInt16 GetLineNetHeight() const
Definition: inftxt.hxx:595
#define CHAR_HARDBLANK
Definition: swtypes.hxx:162
void SetLen(TextFrameIndex const nLen)
Definition: porlin.hxx:76
bool GetRubyTextBelow() const
Definition: tgrditem.hxx:85
TextFrameIndex GetNextAttr() const
Definition: itratr.cxx:729
#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:1368
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:58
void SetJoinBorderWithPrev(const bool bJoinPrev)
Definition: porlin.hxx:173
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:699
void SetMulti(const bool bNew)
Definition: inftxt.hxx:204
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
bool InFieldGrp() const
Definition: porlin.hxx:105
bool HasHint(TextFrameIndex nPos) const
Definition: inftxt.cxx:475
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
SwTwips Y() const
Definition: itrtxt.hxx:90
static const OUString & GetTypeStr(SwFieldTypesEnum nTypeId)
Definition: fldbas.cxx:122
OUString ExpandFieldmark(IFieldmark *pBM)
Definition: itrform2.cxx:876
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:178
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:343
sal_uInt16 ForcedLeftMargin() const
Definition: inftxt.hxx:550
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:302
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:2134
sal_uInt16 RegDiff() const
Definition: itrtxt.hxx:93
void SetFull(const bool bNew)
Definition: inftxt.hxx:563
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:171
SwRect GetFrame(const SwRect &rPortion) const
Definition: txtfly.hxx:357
constexpr OUStringLiteral ODF_FORMDROPDOWN_RESULT
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
SwTwips GetTextHeight() const
Definition: porlay.hxx:173
#define CH_TXTATR_INWORD
Definition: hintids.hxx:172
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:1900
LINESTYLE_NONE
bool IsBreakPortion() const
Definition: porlin.hxx:115
const SwRect & getFrameArea() const
Definition: frame.hxx:180
#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:956
#define CH_TXT_ATR_INPUTFIELDSTART
Definition: hintids.hxx:175
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:155
void DrawViewOpt(const SwLinePortion &rPor, PortionType nWhich, const Color *pColor=nullptr) const
Definition: inftxt.cxx:1281
tools::Long GetPrtLeft(const SwFrame &rFrame) const
Definition: frame.hxx:1412
#define DIR_BOTTOM2TOP
Definition: inftxt.hxx:55
void ResetFlags()
Definition: porlay.cxx:765
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:303
void CalcRealHeight(bool bNewLine=false)
Definition: itrform2.cxx:1840
bool AllowRepaintOpt() const
Definition: itrform2.cxx:2082
sal_uInt8 m_nContentEndHyph
Definition: itrform2.hxx:37
TextFrameIndex GetLineStart() const
Definition: inftxt.hxx:589
void CalcFlyWidth(SwTextFormatInfo &rInf)
Calculation of the emulated right side.
Definition: itrform2.cxx:2403
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:296
SwFontScript GetActual() const
Definition: swfont.hxx:182
void SetPaintOfst(const SwTwips nNew)
Definition: inftxt.hxx:735
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:856
TextFrameIndex GetOffset() const
Definition: txtfrm.hxx:439
void SetNumDone(const bool bNew)
Definition: inftxt.hxx:629
bool InFixMargGrp() const
Definition: porlin.hxx:109
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:1833
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:130
SwTwips First() const
Definition: inftxt.hxx:545
static bool lcl_OldFieldRest(const SwLineLayout *pCurr)
Definition: itrform2.cxx:1298
TextFrameIndex NextDirChg(const TextFrameIndex nPos, const sal_uInt8 *pLevel=nullptr) const
Definition: porlay.cxx:1782
constexpr OUStringLiteral ODF_FORMDROPDOWN_LISTENTRY
void SetEndHyph(const bool bNew)
Definition: porlay.hxx:124
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:137
bool HasScriptSpace() const
Definition: inftxt.hxx:211
const SwViewOption & GetOpt() const
Definition: inftxt.hxx:238
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1306
void UpdatePos(SwLineLayout *pCurr, Point aStart, TextFrameIndex nStartIdx, bool bAlways=false) const
The position of the portions changes with the adjustment.
Definition: itrform2.cxx:2146
bool IsFootnoteNumPortion() const
Definition: porlin.hxx:122
bool m_bFlyInContentBase
Definition: itrform2.hxx:42
virtual bool IsChecked() const =0
TextFrameIndex m_nRightScanIdx
Definition: itrform2.hxx:40
Style of a layout element.
Definition: frmfmt.hxx:59
SwTextInfo * m_pInf
Definition: itrtxt.hxx:35
SwTwips CalcFitToContent_()
Definition: itrform2.cxx:2071
void Bottom()
Definition: itrtxt.cxx:185
bool IsDummy() const
Definition: porlay.hxx:153
SwFrame * GetIndPrev() const
Definition: frame.hxx:725
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:1326
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:80
SwTwips GetRealHeight() const
Definition: porlay.hxx:171
void Reset()
Definition: redlnitr.hxx:112
SwMultiPortion * m_pMulti
Definition: itrform2.hxx:36
SwTwips GetLineWidth()
Returns the distance between the current horizontal position and the end of the line.
Definition: inftxt.cxx:1723
SwTextFly & GetTextFly()
Definition: inftxt.hxx:383
const sal_Unicode CH_TAB
Definition: swfont.hxx:44
SwPageFrame * FindPageFrame()
Definition: frame.hxx:681
SwParaPortion * GetParaPortion()
Definition: inftxt.hxx:121
void SetWhichPor(const PortionType nNew)
Definition: porlin.hxx:95
SwCharRange & GetReformat()
Definition: porlay.hxx:288
void SetUnderflow(SwLinePortion *pNew)
Definition: inftxt.hxx:600
bool IsFlyPortion() const
Definition: porlin.hxx:128
void RecalcRealHeight()
Definition: itrform2.cxx:1832
constexpr OUStringLiteral ODF_FORMTEXT
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2581
SwNumberPortion * NewNumberPortion(SwTextFormatInfo &rInf) const
Definition: txtfld.cxx:608
SwNodeOffset GetIndex() const
Definition: node.hxx:292
sal_uInt16 GetBottomBorderDist() const
Definition: swfont.hxx:357
SwLinePortion * GetFirstPortion() const
Definition: porlay.cxx:783
void CtorInitTextFormatter(SwTextFrame *pFrame, SwTextFormatInfo *pInf)
Definition: itrform2.cxx:88
const sal_Unicode CH_BLANK
Definition: swfont.hxx:42
void SelectFont()
Definition: inftxt.cxx:365
bool IsKernPortion() const
Definition: porlin.hxx:135
void FinishKanaComp()
Definition: porlay.hxx:203
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:180
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:188
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2795
css::uno::Reference< css::frame::XModel3 > GetBaseModel() const
const SwFormatDrop * GetDropFormat() const
Definition: inftxt.cxx:1480
void SetJoinBorderWithNext(const bool bJoinNext)
Definition: porlin.hxx:174
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:118
#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:124
void SetTabDecimal(const sal_Unicode cNew)
Definition: inftxt.hxx:617
void ClrUnderflow()
Definition: inftxt.hxx:583
bool isFrameAreaPositionValid() const
Definition: frame.hxx:167
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:2315
tools::Long YDiff(tools::Long n1, tools::Long n2) const
Definition: frame.hxx:1424
void SetTabOverflow(bool bOverflow)
Definition: inftxt.hxx:661
SwTwips Height() const
Definition: possiz.hxx:50
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
vcl::Font GetFont(vcl::Font const &rFont, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
bool SnapToGrid() const
Definition: inftxt.hxx:215
TextFrameIndex GetLen() const
Definition: porlin.hxx:75
void SetFly(SwFlyPortion *pNew)
Definition: inftxt.hxx:609
A page of the document layout.
Definition: pagefrm.hxx:57
bool InTabGrp() const
Definition: porlin.hxx:101
const SwFormatFootnote & GetFootnote() const
Definition: txatbase.hxx:204
SwTextFrame * GetTextFrame()
Definition: inftxt.hxx:284
tools::Long GetNextTop() const
Definition: txtfly.hxx:347
void LeftMove(TextFrameIndex const nNew)
Definition: porlay.hxx:49
Point GetTopLeft() const
Definition: itrtxt.hxx:186
tools::Long SwTwips
Definition: swtypes.hxx:52
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:46
void ClearHookChar()
Definition: inftxt.hxx:619
SwTwips & GetAscent()
Definition: porlin.hxx:78
void Truncate()
Definition: porlin.hxx:201
bool HasBrackets() const
Definition: pormulti.hxx:250
const Point & GetPos() const
Definition: inftxt.hxx:428
bool IsMultiPortion() const
Definition: porlin.hxx:137
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:686
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:51
void SetForcedLeftMargin()
Definition: porlay.hxx:144
bool IsFootnoteNumFrame() const
Am I a FootnoteFrame, with a number at the start of the paragraph?
Definition: txtfrm.hxx:623
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
void CalcAscentAndHeight(SwTwips &rAscent, SwTwips &rHeight) const
Definition: itrtxt.cxx:63
uno::Reference< text::XTextContent > GetNestedTextContent(SwTextNode const &rTextNode, sal_Int32 const nIndex, bool const bParent)
void Bottom(const tools::Long nBottom)
Definition: swrect.hxx:211
#define CHAR_HARDHYPHEN
Definition: swtypes.hxx:163
TextFrameIndex m_nStart
Definition: itrtxt.hxx:41
#define CH_TXT_ATR_INPUTFIELDEND
Definition: hintids.hxx:176
TextFrameIndex FormatLine(TextFrameIndex nStart)
Definition: itrform2.cxx:1627
sal_Int16 ScriptType(const TextFrameIndex nPos) const
Definition: porlay.cxx:1769
void SwitchRTLtoLTR(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from RTL to LTR layout.
Definition: txtfrm.hxx:736
virtual bool Format(SwTextFormatInfo &rInf) override
Definition: txttab.cxx:338
SwTwips CalcBottomLine() const
Definition: itrform2.cxx:2046
SwTextPortion * WhichTextPor(SwTextFormatInfo &rInf) const
Definition: itrform2.cxx:908
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:108
SwTwips Width() const
Definition: possiz.hxx:52
void SetFixLineHeight()
Definition: porlay.hxx:316
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:163
PortionType GetWhichPor() const
Definition: porlin.hxx:96
SvxShadowLocation GetShadowLocation() const
Definition: swfont.hxx:376
SwRepaint & GetRepaint()
Definition: porlay.hxx:286
bool IsFootnotePortion() const
Definition: porlin.hxx:123
void SetFootnoteDone(const bool bNew)
Definition: inftxt.hxx:625
vcl::Window * GetWin() const
Definition: viewsh.hxx:338
SwLinePortion * GetRest()
Definition: inftxt.hxx:575
void SetDummy(const bool bNew)
Definition: porlay.hxx:152
SwLinePortion * FindLastPortion()
Definition: porlin.cxx:178
#define SAL_INFO(area, stream)
bool IsErgoSumPortion() const
Definition: porlin.hxx:116
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:1183
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:129
TextFrameIndex NextBookmark(TextFrameIndex nPos) const
Definition: porlay.cxx:1821
const sal_uInt8 & CntEndHyph() const
Definition: itrform2.hxx:219
bool IsRightToLeft() const
Definition: frame.hxx:988
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
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
virtual editeng::HangulHanjaConversion::ConversionDirection GetDirection(editeng::HangulHanjaConversion::ConversionDirection _eDefaultDirection) const override
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:99
SwScriptInfo & GetScriptInfo()
Definition: porlay.hxx:292
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:2595
void SetpSpaceAdd(std::vector< tools::Long > *pNew)
Definition: inftxt.hxx:444
void SetRealHeight(SwTwips nNew)
Definition: porlay.hxx:170
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:1954
const Color & GetShadowColor() const
Definition: swfont.hxx:374
SwTextPortion * NewTextPortion(SwTextFormatInfo &rInf)
Definition: itrform2.cxx:1056
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:182
void SetNextPortion(SwLinePortion *pNew)
Definition: porlin.hxx:77
bool IsSnapToChars() const
Definition: tgrditem.hxx:100
void SetJoinBorderWithNext(const bool bJoinNext)
Definition: pordrop.hxx:60
void FeedInf(SwTextFormatInfo &rInf) const
Definition: itrform2.cxx:1996
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:1905
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:58
const std::optional< editeng::SvxBorderLine > & GetTopBorder() const
Definition: swfont.hxx:336
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:974
void AlignFlyInCntBase(tools::Long nBaseLine) const
Set all anchored as character objects to the passed BaseLine (in Y direction).
Definition: itrform2.cxx:2268
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 SetLineHeight(const sal_uInt16 nNew)
Definition: inftxt.hxx:594
constexpr OUStringLiteral ODF_FORMCHECKBOX
SwDoc & GetDoc()
Definition: txtfrm.hxx:461
bool IsOtherThanFootnoteInside() const
Definition: inftxt.hxx:201
bool IsOn() const
Definition: txtfly.hxx:314
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:923
SwTextGrid GetGridType() const
Definition: tgrditem.hxx:81
bool IsTest() const
Definition: inftxt.hxx:587
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
SwTwips GetLineHeight() const
Definition: itrtxt.hxx:116
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:117
sal_uInt16 GetBaseHeight() const
Definition: tgrditem.hxx:75
std::vector< tools::Long > * GetpLLSpaceAdd() const
Definition: porlay.hxx:199
SwFlyPortion * GetFly()
Definition: inftxt.hxx:608
void SetMidHyph(const bool bNew)
Definition: porlay.hxx:126
void DropInit()
Definition: itrcrsr.cxx:363
bool GetJoinBorderWithNext() const
Definition: porlin.hxx:172
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:73
sal_uInt16 GetLineHeight() const
Definition: inftxt.hxx:593
#define CH_TXT_ATR_FIELDSEP
Definition: hintids.hxx:181
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:703
sal_uInt16 GetFrameRstHeight() const
Definition: itrform2.cxx:136
constexpr OUStringLiteral ODF_FORMDROPDOWN
void Height(tools::Long nNew)
Definition: swrect.hxx:193
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:113
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
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:1130
bool IsPostItsPortion() const
Definition: porlin.hxx:131
SwDropPortion * NewDropPortion(SwTextFormatInfo &rInf)
Definition: txtdrop.cxx:560
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:856
bool CalcOnceMore()
Definition: itrform2.cxx:2033
sal_uInt16 GetAscent() const
Definition: inftxt.hxx:706
SwFont & GetFont() const
Definition: pordrop.hxx:52
SwTwips GetLeftMin() const
Definition: itrtxt.hxx:193
void Init(SwLinePortion *pNextPortion=nullptr)
Definition: porlay.cxx:2561
void SetAscent(const SwTwips nNewAsc)
Definition: porlin.hxx:80
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo