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