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