1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
23 #include <com/sun/star/beans/PropertyValues.hpp>
27 #include <swtypes.hxx>
34 #include <editeng/paravertalignitem.hxx>
36 namespace com::sun::star::linguistic2
{ class XHyphenatedWord
; }
39 class SvxLineSpacingItem
;
49 struct SwMultiCreator
;
51 namespace sw
{ class WrongListIterator
; }
53 #define ARROW_WIDTH 200
54 #define DIR_LEFT2RIGHT 0
55 #define DIR_BOTTOM2TOP 1
56 #define DIR_RIGHT2LEFT 2
57 #define DIR_TOP2BOTTOM 3
59 // Respects the attribute LineSpace when calculating the Height/Ascent
62 friend class SwTextIter
;
64 std::optional
<SvxTabStopItem
> m_oRuler
;
65 const SvxLineSpacingItem
*m_pSpace
;
66 SvxParaVertAlignItem::Align m_nVertAlign
;
67 SwTwips m_nDefTabStop
;
68 bool m_bListTabStopIncluded
;
69 tools::Long m_nListTabStopPosition
;
71 void CtorInitLineInfo( const SwAttrSet
& rAttrSet
,
72 const SwTextNode
& rTextNode
);
74 SW_DLLPUBLIC
SwLineInfo();
75 SW_DLLPUBLIC
~SwLineInfo();
77 // #i24363# tab stops relative to indent - returns the tab stop following nSearchPos or NULL
78 const SvxTabStop
* GetTabStop(const SwTwips nSearchPos
, SwTwips
& nRight
) const;
79 const SvxLineSpacingItem
*GetLineSpacing() const { return m_pSpace
; }
80 SwTwips
GetDefTabStop() const { return m_nDefTabStop
; }
81 void SetDefTabStop(SwTwips nNew
) const
82 { const_cast<SwLineInfo
*>(this)->m_nDefTabStop
= nNew
; }
85 SvxParaVertAlignItem::Align
GetVertAlign() const { return m_nVertAlign
; }
86 bool HasSpecialAlign( bool bVert
) const
88 ( SvxParaVertAlignItem::Align::Baseline
!= m_nVertAlign
) :
89 ( SvxParaVertAlignItem::Align::Baseline
!= m_nVertAlign
&&
90 SvxParaVertAlignItem::Align::Automatic
!= m_nVertAlign
); }
92 sal_uInt16
NumberOfTabStops() const;
94 bool IsListTabStopIncluded() const
96 return m_bListTabStopIncluded
;
98 tools::Long
GetListTabStopPosition() const
100 return m_nListTabStopPosition
;
106 // Implementation in txthyph.cxx
107 friend void SetParaPortion( SwTextInfo
*pInf
, SwParaPortion
*pRoot
);
108 SwParaPortion
*m_pPara
;
109 TextFrameIndex m_nTextStart
; // TextOfst for Follows
118 void CtorInitTextInfo( SwTextFrame
*pFrame
);
119 SwTextInfo( const SwTextInfo
&rInf
);
120 explicit SwTextInfo( SwTextFrame
*pFrame
) { CtorInitTextInfo( pFrame
); }
121 SwParaPortion
*GetParaPortion() { return m_pPara
; }
122 const SwParaPortion
*GetParaPortion() const { return m_pPara
; }
123 TextFrameIndex
GetTextStart() const { return m_nTextStart
; }
126 class SwTextSizeInfo
: public SwTextInfo
129 typedef std::map
<SwLinePortion
const*, SwTwips
> SwTextPortionMap
;
132 // during formatting, a small database is built, mapping portion pointers
133 // to their maximum size (used for kana compression)
134 SwTextPortionMap m_aMaxWidth
;
135 // for each line, an array of compression values is calculated
136 // this array is passed over to the info structure
137 std::deque
<sal_uInt16
>* m_pKanaComp
;
141 // m_pOut is the output device, m_pRef is the device used for formatting
142 VclPtr
<OutputDevice
> m_pOut
;
143 VclPtr
<OutputDevice
> m_pRef
;
145 // performance hack - this is only used by SwTextFormatInfo but
146 // because it's not even possible to dynamic_cast these things
147 // currently it has to be stored here
148 std::shared_ptr
<const vcl::text::TextLayoutCache
> m_pCachedVclData
;
151 SwUnderlineFont
*m_pUnderFnt
; // Font for underlining
152 SwTextFrame
*m_pFrame
;
153 const SwViewOption
*m_pOpt
;
154 const OUString
*m_pText
;
155 TextFrameIndex m_nIdx
;
156 TextFrameIndex m_nLen
;
157 TextFrameIndex m_nMeasureLen
;
158 std::optional
<SwLinePortionLayoutContext
> m_nLayoutContext
;
159 sal_uInt16 m_nKanaIdx
;
162 bool m_bURLNotify
: 1;
163 bool m_bStopUnderflow
: 1; // Underflow was stopped e.g. by a FlyPortion
164 bool m_bFootnoteInside
: 1; // the current line contains a footnote
165 bool m_bOtherThanFootnoteInside
: 1; // the current line contains another portion than a footnote portion.
166 // needed for checking keep together of footnote portion with previous portion
167 bool m_bMulti
: 1; // inside a multiportion
168 bool m_bFirstMulti
: 1; // this flag is used for two purposes:
169 // - the multiportion is the first lineportion
170 // - indicates, if we are currently in second
171 // line of multi portion
172 bool m_bRuby
: 1; // during the formatting of a phonetic line
173 bool m_bHanging
: 1; // formatting of hanging punctuation allowed
174 bool m_bScriptSpace
: 1; // space between different scripts (Asian/Latin)
175 bool m_bForbiddenChars
: 1; // Forbidden start/endline characters
176 bool m_bSnapToGrid
: 1; // paragraph snaps to grid
177 sal_uInt8 m_nDirection
: 2; // writing direction: 0/90/180/270 degree
178 SwTwips m_nExtraSpace
; // extra space before shrinking = nSpacesInLine * (nSpaceWidth/0.8 - nSpaceWidth)
181 void CtorInitTextSizeInfo( OutputDevice
* pRenderContext
, SwTextFrame
*pFrame
,
182 TextFrameIndex nIdx
);
185 SwTextSizeInfo( const SwTextSizeInfo
&rInf
);
186 SwTextSizeInfo( const SwTextSizeInfo
&rInf
, const OUString
* pText
,
187 TextFrameIndex nIdx
= TextFrameIndex(0) );
188 SW_DLLPUBLIC
SwTextSizeInfo(SwTextFrame
*pTextFrame
, TextFrameIndex nIndex
= TextFrameIndex(0));
190 // GetMultiAttr returns the text attribute of the multiportion,
191 // if rPos is inside any multi-line part.
192 // rPos will set to the end of the multi-line part.
193 std::optional
<SwMultiCreator
> GetMultiCreator(TextFrameIndex
&rPos
, SwMultiPortion
const* pM
) const;
195 bool OnWin() const { return m_bOnWin
; }
196 void SetOnWin( const bool bNew
) { m_bOnWin
= bNew
; }
197 bool NotEOL() const { return m_bNotEOL
; }
198 void SetNotEOL( const bool bNew
) { m_bNotEOL
= bNew
; }
199 bool URLNotify() const { return m_bURLNotify
; }
200 bool StopUnderflow() const { return m_bStopUnderflow
; }
201 void SetStopUnderflow( const bool bNew
) { m_bStopUnderflow
= bNew
; }
202 bool IsFootnoteInside() const { return m_bFootnoteInside
; }
203 void SetFootnoteInside( const bool bNew
) { m_bFootnoteInside
= bNew
; }
204 bool IsOtherThanFootnoteInside() const { return m_bOtherThanFootnoteInside
; }
205 void SetOtherThanFootnoteInside( const bool bNew
) { m_bOtherThanFootnoteInside
= bNew
; }
206 bool IsMulti() const { return m_bMulti
; }
207 void SetMulti( const bool bNew
) { m_bMulti
= bNew
; }
208 bool IsFirstMulti() const { return m_bFirstMulti
; }
209 void SetFirstMulti( const bool bNew
) { m_bFirstMulti
= bNew
; }
210 bool IsRuby() const { return m_bRuby
; }
211 void SetRuby( const bool bNew
) { m_bRuby
= bNew
; }
212 bool IsHanging() const { return m_bHanging
; }
213 void SetHanging( const bool bNew
) { m_bHanging
= bNew
; }
214 bool HasScriptSpace() const { return m_bScriptSpace
; }
215 void SetScriptSpace( const bool bNew
) { m_bScriptSpace
= bNew
; }
216 bool HasForbiddenChars() const { return m_bForbiddenChars
; }
217 void SetForbiddenChars( const bool bN
) { m_bForbiddenChars
= bN
; }
218 bool SnapToGrid() const { return m_bSnapToGrid
; }
219 void SetSnapToGrid( const bool bN
) { m_bSnapToGrid
= bN
; }
220 sal_uInt8
GetDirection() const { return m_nDirection
; }
221 void SetDirection( const sal_uInt8 nNew
) { m_nDirection
= nNew
; }
222 bool IsRotated() const { return ( 1 & m_nDirection
); }
224 SwViewShell
*GetVsh() { return m_pVsh
; }
225 const SwViewShell
*GetVsh() const { return m_pVsh
; }
227 vcl::RenderContext
*GetOut() { return m_pOut
; }
228 const vcl::RenderContext
*GetOut() const { return m_pOut
; }
229 void SetOut( OutputDevice
* pNewOut
) { m_pOut
= pNewOut
; }
231 vcl::RenderContext
*GetRefDev() { return m_pRef
; }
232 const vcl::RenderContext
*GetRefDev() const { return m_pRef
; }
234 SwFont
*GetFont() { return m_pFnt
; }
235 const SwFont
*GetFont() const { return m_pFnt
; }
236 void SetFont( SwFont
*pNew
) { m_pFnt
= pNew
; }
238 void SetUnderFnt( SwUnderlineFont
* pNew
) { m_pUnderFnt
= pNew
; }
239 SwUnderlineFont
* GetUnderFnt() const { return m_pUnderFnt
; }
241 const SwViewOption
&GetOpt() const { return *m_pOpt
; }
242 const OUString
&GetText() const { return *m_pText
; }
243 sal_Unicode
GetChar(TextFrameIndex
const nPos
) const {
244 if (m_pText
&& nPos
< TextFrameIndex(m_pText
->getLength())) return (*m_pText
)[sal_Int32(nPos
)];
248 sal_uInt16
GetTextHeight() const;
250 SwPosSize
GetTextSize( OutputDevice
* pOut
, const SwScriptInfo
* pSI
,
251 const OUString
& rText
, TextFrameIndex nIdx
,
252 TextFrameIndex nLen
) const;
253 SwPosSize
GetTextSize(std::optional
<SwLinePortionLayoutContext
> nLayoutContext
254 = std::nullopt
) const;
255 void GetTextSize(const SwScriptInfo
* pSI
, TextFrameIndex nIdx
, TextFrameIndex nLen
,
256 std::optional
<SwLinePortionLayoutContext
> nLayoutContext
,
257 const sal_uInt16 nComp
, SwTwips
& nMinSize
, tools::Long
& nMaxSizeDiff
,
258 SwTwips
& nExtraAscent
, SwTwips
& nExtraDescent
,
259 vcl::text::TextLayoutCache
const* = nullptr) const;
260 inline SwPosSize
GetTextSize(const SwScriptInfo
* pSI
, TextFrameIndex nIdx
,
261 TextFrameIndex nLen
) const;
262 inline SwPosSize
GetTextSize( const OUString
&rText
) const;
264 TextFrameIndex
GetTextBreak( const tools::Long nLineWidth
,
265 const TextFrameIndex nMaxLen
,
266 const sal_uInt16 nComp
,
267 vcl::text::TextLayoutCache
const*) const;
268 TextFrameIndex
GetTextBreak( const tools::Long nLineWidth
,
269 const TextFrameIndex nMaxLen
,
270 const sal_uInt16 nComp
,
271 TextFrameIndex
& rExtraCharPos
,
272 vcl::text::TextLayoutCache
const*) const;
274 sal_uInt16
GetAscent() const;
275 sal_uInt16
GetHangingBaseline() const;
277 TextFrameIndex
GetIdx() const { return m_nIdx
; }
278 void SetIdx(const TextFrameIndex nNew
) { m_nIdx
= nNew
; }
279 TextFrameIndex
GetLen() const { return m_nLen
; }
280 void SetLen(const TextFrameIndex nNew
) { m_nLen
= nNew
; }
281 TextFrameIndex
GetMeasureLen() const { return m_nMeasureLen
; }
282 void SetMeasureLen(const TextFrameIndex nNew
) { m_nMeasureLen
= nNew
; }
283 void SetText( const OUString
&rNew
){ m_pText
= &rNew
; }
285 const std::optional
<SwLinePortionLayoutContext
> & GetLayoutContext() const { return m_nLayoutContext
; }
287 void SetLayoutContext(std::optional
<SwLinePortionLayoutContext
> nNew
)
289 m_nLayoutContext
= nNew
;
292 // No Bullets for the symbol font!
293 bool IsNoSymbol() const
294 { return RTL_TEXTENCODING_SYMBOL
!= m_pFnt
->GetCharSet( m_pFnt
->GetActual() ); }
296 void NoteAnimation() const;
298 // Home is where Your heart is...
299 SwTextFrame
*GetTextFrame() { return m_pFrame
; }
300 const SwTextFrame
*GetTextFrame() const { return m_pFrame
; }
302 bool HasHint(TextFrameIndex nPos
) const;
304 // extra space before shrinking = nSpacesInLine * (nSpaceWidth/0.8 - nSpaceWidth)
305 void SetExtraSpace(SwTwips nVal
) { m_nExtraSpace
= nVal
; }
306 SwTwips
GetExtraSpace() const { return m_nExtraSpace
; }
308 // If Kana Compression is enabled, a minimum and maximum portion width
309 // is calculated. We format lines with minimal size and share remaining
310 // space among compressed kanas.
311 // During formatting, the maximum values of compressible portions are
312 // stored in m_aMaxWidth and discarded after a line has been formatted.
313 void SetMaxWidthDiff(const SwLinePortion
* nKey
, SwTwips nVal
)
315 m_aMaxWidth
.insert( std::make_pair( nKey
, nVal
) );
317 SwTwips
GetMaxWidthDiff(const SwLinePortion
* nKey
)
319 SwTextPortionMap::iterator it
= m_aMaxWidth
.find( nKey
);
321 if( it
!= m_aMaxWidth
.end() )
326 void ResetMaxWidthDiff()
332 return !m_aMaxWidth
.empty();
335 // Feature: Kana Compression
337 sal_uInt16
GetKanaIdx() const { return m_nKanaIdx
; }
338 void ResetKanaIdx(){ m_nKanaIdx
= 0; }
339 void SetKanaIdx( sal_uInt16 nNew
) { m_nKanaIdx
= nNew
; }
340 void IncKanaIdx() { ++m_nKanaIdx
; }
341 void SetKanaComp( std::deque
<sal_uInt16
> *pNew
){ m_pKanaComp
= pNew
; }
342 std::deque
<sal_uInt16
>* GetpKanaComp() const { return m_pKanaComp
; }
343 sal_uInt16
GetKanaComp() const
344 { return ( m_pKanaComp
&& m_nKanaIdx
< m_pKanaComp
->size() )
345 ? (*m_pKanaComp
)[m_nKanaIdx
] : 0; }
347 const std::shared_ptr
<const vcl::text::TextLayoutCache
>& GetCachedVclData() const
349 return m_pCachedVclData
;
351 void SetCachedVclData(std::shared_ptr
<const vcl::text::TextLayoutCache
> const& pCachedVclData
)
353 m_pCachedVclData
= pCachedVclData
;
357 class SwTextPaintInfo
: public SwTextSizeInfo
359 sw::WrongListIterator
*m_pWrongList
;
360 sw::WrongListIterator
*m_pGrammarCheckList
;
361 sw::WrongListIterator
*m_pSmartTags
;
362 std::vector
<tools::Long
>* m_pSpaceAdd
;
363 const SvxBrushItem
*m_pBrushItem
; // For the background
364 SwTextFly m_aTextFly
; // Calculate the FlyFrame
365 Point m_aPos
; // Paint position
366 SwRect m_aPaintRect
; // Original paint rect (from Layout paint)
368 sal_uInt16 m_nSpaceIdx
;
369 void DrawText_(const OUString
&rText
, const SwLinePortion
&rPor
,
370 const TextFrameIndex nIdx
, const TextFrameIndex nLen
,
371 const bool bKern
, const bool bWrong
= false,
372 const bool bSmartTag
= false,
373 const bool bGrammarCheck
= false );
375 SwTextPaintInfo
&operator=(const SwTextPaintInfo
&) = delete;
376 void NotifyURL_(const SwLinePortion
& rPor
) const;
380 : m_pWrongList(nullptr)
381 , m_pGrammarCheckList(nullptr)
382 , m_pSmartTags(nullptr)
383 , m_pSpaceAdd(nullptr)
384 , m_pBrushItem(nullptr)
389 SwTextPaintInfo( const SwTextPaintInfo
&rInf
);
390 SwTextPaintInfo( const SwTextPaintInfo
&rInf
, const OUString
* pText
);
392 void CtorInitTextPaintInfo( OutputDevice
* pRenderContext
, SwTextFrame
*pFrame
, const SwRect
&rPaint
);
394 const SvxBrushItem
*GetBrushItem() const { return m_pBrushItem
; }
396 SwTextPaintInfo( SwTextFrame
*pFrame
, const SwRect
&rPaint
);
398 SwTwips
X() const { return m_aPos
.X(); }
399 void X( const tools::Long nNew
) { m_aPos
.setX(nNew
); }
400 SwTwips
Y() const { return m_aPos
.Y(); }
401 void Y( const SwTwips nNew
) { m_aPos
.setY(nNew
); }
403 SwTextFly
& GetTextFly() { return m_aTextFly
; }
404 const SwTextFly
& GetTextFly() const { return m_aTextFly
; }
405 inline void DrawText( const OUString
&rText
, const SwLinePortion
&rPor
,
406 TextFrameIndex nIdx
= TextFrameIndex(0),
407 TextFrameIndex nLen
= TextFrameIndex(COMPLETE_STRING
),
408 const bool bKern
= false) const;
409 inline void DrawText( const SwLinePortion
&rPor
, TextFrameIndex nLen
,
410 const bool bKern
= false ) const;
411 inline void DrawMarkedText( const SwLinePortion
&rPor
, TextFrameIndex nLen
,
413 const bool bSmartTags
,
414 const bool bGrammarCheck
) const;
416 void DrawRect( const SwRect
&rRect
, bool bRetouche
) const;
418 void DrawTab( const SwLinePortion
&rPor
) const;
419 void DrawLineBreak( const SwLinePortion
&rPor
) const;
420 void DrawRedArrow( const SwLinePortion
&rPor
) const;
421 void DrawPostIts( bool bScript
) const;
422 void DrawBackground( const SwLinePortion
&rPor
, const Color
*pColor
=nullptr ) const;
423 void DrawViewOpt( const SwLinePortion
&rPor
, PortionType nWhich
, const Color
*pColor
=nullptr ) const;
424 void DrawBackBrush( const SwLinePortion
&rPor
) const;
427 * Draw character border around a line portion.
429 * @param[in] rPor line portion around which border have to be drawn.
431 void DrawBorder( const SwLinePortion
&rPor
) const;
433 void DrawCheckBox(const SwFieldFormCheckboxPortion
&rPor
, bool bChecked
) const;
435 void DrawCSDFHighlighting(const SwLinePortion
&rPor
) const;
437 void NotifyURL(const SwLinePortion
& rPor
) const
444 * Calculate the rectangular area where the portion takes place.
445 * @param[in] rPor portion for which the method specify the painting area
446 * @param[out] pRect whole area of the portion
447 * @param[out] pIntersect part of the portion area clipped by OutputDevice's clip region
448 * @param[in] bInsideBox area of portion's content, padding and border, but shadow
449 * is excluded (e.g. for background)
451 void CalcRect( const SwLinePortion
& rPor
, SwRect
* pRect
,
452 SwRect
* pIntersect
= nullptr, const bool bInsideBox
= false ) const;
454 inline SwTwips
GetPaintOfst() const;
455 inline void SetPaintOfst( const SwTwips nNew
);
456 const Point
&GetPos() const { return m_aPos
; }
457 void SetPos( const Point
&rNew
) { m_aPos
= rNew
; }
459 const SwRect
&GetPaintRect() const { return m_aPaintRect
; }
461 // STUFF FOR JUSTIFIED ALIGNMENT
463 sal_uInt16
GetSpaceIdx() const { return m_nSpaceIdx
; }
464 void ResetSpaceIdx(){m_nSpaceIdx
= 0; }
465 void SetSpaceIdx( sal_uInt16 nNew
) { m_nSpaceIdx
= nNew
; }
466 void IncSpaceIdx() { ++m_nSpaceIdx
; }
467 void RemoveFirstSpaceAdd() { m_pSpaceAdd
->erase( m_pSpaceAdd
->begin() ); }
468 tools::Long
GetSpaceAdd( bool bShrink
= false ) const
469 { return ( m_pSpaceAdd
&& m_nSpaceIdx
< m_pSpaceAdd
->size() &&
470 // get shrink data only if asked explicitly, otherwise zero it
471 ( bShrink
|| (*m_pSpaceAdd
)[m_nSpaceIdx
] < LONG_MAX
/2 ) )
472 ? (*m_pSpaceAdd
)[m_nSpaceIdx
] : 0; }
474 void SetpSpaceAdd( std::vector
<tools::Long
>* pNew
){ m_pSpaceAdd
= pNew
; }
475 std::vector
<tools::Long
>* GetpSpaceAdd() const { return m_pSpaceAdd
; }
477 void SetWrongList(sw::WrongListIterator
*const pNew
) { m_pWrongList
= pNew
; }
478 sw::WrongListIterator
* GetpWrongList() const { return m_pWrongList
; }
480 void SetGrammarCheckList(sw::WrongListIterator
*const pNew
) { m_pGrammarCheckList
= pNew
; }
481 sw::WrongListIterator
* GetGrammarCheckList() const { return m_pGrammarCheckList
; }
483 void SetSmartTags(sw::WrongListIterator
*const pNew
) { m_pSmartTags
= pNew
; }
484 sw::WrongListIterator
* GetSmartTags() const { return m_pSmartTags
; }
487 class SwTextFormatInfo
: public SwTextPaintInfo
489 // temporary arguments for hyphenation
490 css::beans::PropertyValues m_aHyphVals
;
492 SwLineLayout
*m_pRoot
; // The Root of the current line (pCurr)
493 SwLinePortion
*m_pLast
; // The last Portion
494 SwFlyPortion
*m_pFly
; // The following FlyPortion
495 SwLinePortion
*m_pUnderflow
; // Underflow: Last Portion
496 SwLinePortion
*m_pRest
; // The Rest is the start of the next Line
498 SwTabPortion
*m_pLastTab
; // The _last_ TabPortion
500 TextFrameIndex m_nSoftHyphPos
; ///< SoftHyphPos for Hyphenation
501 TextFrameIndex m_nLineStart
; ///< Current line start in rText
502 TextFrameIndex m_nLastBookmarkPos
; ///< need to check for bookmarks at every portion
503 // #i34348# Changed type from sal_uInt16 to SwTwips
504 SwTwips m_nLeft
; // Left margin
505 SwTwips m_nRight
; // Right margin
506 SwTwips m_nFirst
; // EZE
507 /// First or left margin, depending on context.
508 SwTwips m_nLeftMargin
= 0;
509 SwTwips m_nRealWidth
; // "real" line width
510 SwTwips m_nWidth
; // "virtual" line width
511 SwTwips m_nLineHeight
; // Final height after CalcLine
512 SwTwips m_nLineNetHeight
; // line height without spacing
513 SwTwips m_nForcedLeftMargin
; // Shift of left margin due to frame
514 SwTwips m_nExtraAscent
= 0; // Enlarge clipping area for glyphs above the line height
515 SwTwips m_nExtraDescent
= 0; // Enlarge clipping area for glyphs below the line height
517 bool m_bFull
: 1; // Line is full
518 bool m_bFootnoteDone
: 1; // Footnote already formatted
519 bool m_bErgoDone
: 1; // ErgoDone already formatted
520 bool m_bNumDone
: 1; // bNumDone already formatted
521 bool m_bArrowDone
: 1; // Arrow to the left for scrolling paragraphs
522 bool m_bStop
: 1; // Cancel immediately, discarding the line
523 bool m_bNewLine
: 1; // Format another line
524 bool m_bShift
: 1; // Position change: Repaint until further notice
525 bool m_bUnderflow
: 1; // Context: Underflow() ?
526 bool m_bInterHyph
: 1; // Interactive hyphenation?
527 bool m_bAutoHyph
: 1; // Automatic hyphenation?
528 bool m_bDropInit
: 1; // Set DropWidth
529 bool m_bQuick
: 1; // FormatQuick()
530 bool m_bNoEndHyph
: 1; // Switch off hyphenation at the line end (due to MaxHyphens)
531 bool m_bNoMidHyph
: 1; // Switch off hyphenation before flys (due to MaxHyphens)
532 bool m_bIgnoreFly
: 1; // FitToContent ignores flys
533 bool m_bFakeLineStart
: 1; // String has been replaced by field portion
534 // info structure only pretends that we are at
535 // the beginning of a line
536 bool m_bTabOverflow
: 1; // Tabs are expanding after the end margin
537 bool m_bTestFormat
: 1; // Test formatting from WouldFit, no notification etc.
539 sal_Unicode m_cTabDecimal
; // the current decimal delimiter
540 sal_Unicode m_cHookChar
; // For tabs in fields etc.
541 sal_uInt8 m_nMaxHyph
; // Max. line count of followup hyphenations
543 // Used to stop justification after center/right/decimal tab stops - see tdf#tdf#106234
551 } m_eLastTabsSeen
= TabSeen::None
;
554 bool InitHyph( const bool bAuto
= false );
555 bool CheckFootnotePortion_( SwLineLayout
const * pCurr
);
558 void CtorInitTextFormatInfo( OutputDevice
* pRenderContext
, SwTextFrame
*pFrame
, const bool bInterHyph
= false,
559 const bool bQuick
= false, const bool bTst
= false );
560 SwTextFormatInfo(OutputDevice
* pRenderContext
, SwTextFrame
*pFrame
, const bool bInterHyphL
= false,
561 const bool bQuickL
= false, const bool bTst
= false);
563 // For the formatting inside a double line in a line (multi-line portion)
564 // we need a modified text-format-info:
565 SwTextFormatInfo( const SwTextFormatInfo
& rInf
, SwLineLayout
& rLay
,
568 SwTwips
Width() const { return m_nWidth
; }
569 void Width(const SwTwips nNew
) { m_nWidth
= nNew
; }
573 * Returns the distance between the current horizontal position and the end
576 SwTwips
GetLineWidth();
578 // Returns the first changed position of the paragraph
579 inline TextFrameIndex
GetReformatStart() const;
582 SwTwips
Left() const { return m_nLeft
; }
583 void Left( const SwTwips nNew
) { m_nLeft
= nNew
; }
584 SwTwips
Right() const { return m_nRight
; }
585 void Right( const SwTwips nNew
) { m_nRight
= nNew
; }
586 SwTwips
First() const { return m_nFirst
; }
587 void First( const SwTwips nNew
) { m_nFirst
= nNew
; }
588 void LeftMargin( const SwTwips nNew
) { m_nLeftMargin
= nNew
; }
589 SwTwips
RealWidth() const { return m_nRealWidth
; }
590 void RealWidth(const SwTwips nNew
) { m_nRealWidth
= nNew
; }
591 SwTwips
ForcedLeftMargin() const { return m_nForcedLeftMargin
; }
592 void ForcedLeftMargin(const SwTwips nN
) { m_nForcedLeftMargin
= nN
; }
594 sal_uInt8
&MaxHyph() { return m_nMaxHyph
; }
595 const sal_uInt8
&MaxHyph() const { return m_nMaxHyph
; }
597 SwLineLayout
*GetRoot() { return m_pRoot
; }
598 const SwLineLayout
*GetRoot() const { return m_pRoot
; }
600 void SetRoot( SwLineLayout
*pNew
) { m_pRoot
= pNew
; }
601 SwLinePortion
*GetLast() { return m_pLast
; }
602 void SetLast(SwLinePortion
* pNewLast
);
603 bool IsFull() const { return m_bFull
; }
604 void SetFull( const bool bNew
) { m_bFull
= bNew
; }
605 bool IsHyphForbud() const
606 { return m_pFly
? m_bNoMidHyph
: m_bNoEndHyph
; }
607 void ChkNoHyph( const sal_uInt8 bEnd
, const sal_uInt8 bMid
)
608 { m_bNoEndHyph
= (m_nMaxHyph
&& bEnd
>= m_nMaxHyph
);
609 m_bNoMidHyph
= (m_nMaxHyph
&& bMid
>= m_nMaxHyph
); }
610 bool IsIgnoreFly() const { return m_bIgnoreFly
; }
611 void SetIgnoreFly( const bool bNew
) { m_bIgnoreFly
= bNew
; }
612 bool IsFakeLineStart() const { return m_bFakeLineStart
; }
613 void SetFakeLineStart( const bool bNew
) { m_bFakeLineStart
= bNew
; }
614 bool IsStop() const { return m_bStop
; }
615 void SetStop( const bool bNew
) { m_bStop
= bNew
; }
616 SwLinePortion
*GetRest() { return m_pRest
; }
617 void SetRest( SwLinePortion
*pNewRest
) { m_pRest
= pNewRest
; }
618 bool IsNewLine() const { return m_bNewLine
; }
619 void SetNewLine( const bool bNew
) { m_bNewLine
= bNew
; }
620 bool IsShift() const { return m_bShift
; }
621 void SetShift( const bool bNew
) { m_bShift
= bNew
; }
622 bool IsInterHyph() const { return m_bInterHyph
; }
623 bool IsUnderflow() const { return m_bUnderflow
; }
624 void ClrUnderflow() { m_bUnderflow
= false; }
625 bool IsDropInit() const { return m_bDropInit
; }
626 void SetDropInit( const bool bNew
) { m_bDropInit
= bNew
; }
627 bool IsQuick() const { return m_bQuick
; }
628 bool IsTest() const { return m_bTestFormat
; }
630 void UpdateTabSeen(PortionType
);
631 bool DontBlockJustify() const
633 return m_eLastTabsSeen
== TabSeen::Center
|| m_eLastTabsSeen
== TabSeen::Right
634 || m_eLastTabsSeen
== TabSeen::Decimal
;
637 TextFrameIndex
GetLineStart() const { return m_nLineStart
; }
638 void SetLineStart(TextFrameIndex
const nNew
) { m_nLineStart
= nNew
; }
640 // these are used during fly calculation
641 SwTwips
GetLineHeight() const { return m_nLineHeight
; }
642 void SetLineHeight(const SwTwips nNew
) { m_nLineHeight
= nNew
; }
643 SwTwips
GetLineNetHeight() const { return m_nLineNetHeight
; }
644 void SetLineNetHeight(const SwTwips nNew
) { m_nLineNetHeight
= nNew
; }
646 const SwLinePortion
*GetUnderflow() const { return m_pUnderflow
; }
647 SwLinePortion
*GetUnderflow() { return m_pUnderflow
; }
648 void SetUnderflow( SwLinePortion
*pNew
)
649 { m_pUnderflow
= pNew
; m_bUnderflow
= true; }
650 TextFrameIndex
GetSoftHyphPos() const { return m_nSoftHyphPos
; }
651 void SetSoftHyphPos(TextFrameIndex
const nNew
) { m_nSoftHyphPos
= nNew
; }
653 inline void SetParaFootnote();
656 SwFlyPortion
*GetFly() { return m_pFly
; }
657 void SetFly( SwFlyPortion
*pNew
) { m_pFly
= pNew
; }
659 inline const SwAttrSet
& GetCharAttr() const;
662 SwTabPortion
*GetLastTab() { return m_pLastTab
; }
663 void SetLastTab( SwTabPortion
*pNew
) { m_pLastTab
= pNew
; }
664 sal_Unicode
GetTabDecimal() const { return m_cTabDecimal
; }
665 void SetTabDecimal( const sal_Unicode cNew
) { m_cTabDecimal
= cNew
;}
667 void ClearHookChar() { m_cHookChar
= 0; }
668 void SetHookChar( const sal_Unicode cNew
) { m_cHookChar
= cNew
; }
669 sal_Unicode
GetHookChar() const { return m_cHookChar
; }
672 bool IsFootnoteDone() const { return m_bFootnoteDone
; }
673 void SetFootnoteDone( const bool bNew
) { m_bFootnoteDone
= bNew
; }
674 bool IsErgoDone() const { return m_bErgoDone
; }
675 void SetErgoDone( const bool bNew
) { m_bErgoDone
= bNew
; }
676 bool IsNumDone() const { return m_bNumDone
; }
677 void SetNumDone( const bool bNew
) { m_bNumDone
= bNew
; }
678 bool IsArrowDone() const { return m_bArrowDone
; }
679 void SetArrowDone( const bool bNew
) { m_bArrowDone
= bNew
; }
681 bool CheckCurrentPosBookmark();
683 // For SwTextPortion::Hyphenate
684 bool ChgHyph( const bool bNew
);
686 // Should the hyphenate helper be discarded?
687 bool IsHyphenate() const;
689 SwTwips
GetExtraAscent() const { return m_nExtraAscent
; }
690 void SetExtraAscent(SwTwips nNew
) { m_nExtraAscent
= std::max(m_nExtraAscent
, nNew
); }
692 SwTwips
GetExtraDescent() const { return m_nExtraDescent
; }
693 void SetExtraDescent(SwTwips nNew
) { m_nExtraDescent
= std::max(m_nExtraDescent
, nNew
); }
695 // Calls HyphenateWord() of Hyphenator
696 css::uno::Reference
< css::linguistic2::XHyphenatedWord
>
697 HyphWord( const OUString
&rText
, const sal_Int32 nMinTrail
);
698 const css::beans::PropertyValues
& GetHyphValues() const;
700 bool CheckFootnotePortion( SwLineLayout
const * pCurr
)
701 { return IsFootnoteInside() && CheckFootnotePortion_( pCurr
); }
703 // Dropcaps called by SwTextFormatter::CTOR
704 const SwFormatDrop
*GetDropFormat() const;
706 // Sets the last SwKernPortion as pLast, if it is followed by empty portions
707 bool LastKernPortion();
709 // Looks for tabs, TabDec, TXTATR and BRK from nIdx until nEnd.
710 // Return: Position; sets cHookChar if necessary
711 TextFrameIndex
ScanPortionEnd(TextFrameIndex nStart
, TextFrameIndex nEnd
);
713 void SetTabOverflow( bool bOverflow
) { m_bTabOverflow
= bOverflow
; }
714 bool IsTabOverflow() const { return m_bTabOverflow
; }
719 * For the text replacement and restoration of SwTextSizeInfo.
720 * The way this is done is a bit of a hack: Although rInf is const we change it
722 * Because rInf is restored again in the DTOR, we can do this.
723 * You could call it a "logical const", if you wish.
725 class SwTextSlot final
728 std::shared_ptr
<const vcl::text::TextLayoutCache
> m_pOldCachedVclData
;
729 const OUString
*pOldText
;
730 sw::WrongListIterator
* m_pOldSmartTagList
;
731 sw::WrongListIterator
* m_pOldGrammarCheckList
;
732 std::unique_ptr
<SwWrongList
> m_pTempList
;
733 std::unique_ptr
<sw::WrongListIterator
> m_pTempIter
;
736 TextFrameIndex nMeasureLen
;
738 SwTextSizeInfo
*pInf
;
741 // The replacement string originates either from the portion via GetExpText()
742 // or from the rCh, if it is not empty.
743 SwTextSlot( const SwTextSizeInfo
*pNew
, const SwLinePortion
*pPor
, bool bTextLen
,
744 bool bExgLists
, OUString
const & rCh
= OUString() );
750 SwTextSizeInfo
*pInf
;
754 SwFontSave( const SwTextSizeInfo
&rInf
, SwFont
*pFnt
,
755 SwAttrIter
* pItr
= nullptr );
759 inline sal_uInt16
SwTextSizeInfo::GetAscent() const
762 return const_cast<SwFont
*>(GetFont())->GetAscent( m_pVsh
, *GetOut() );
765 inline sal_uInt16
SwTextSizeInfo::GetTextHeight() const
768 return const_cast<SwFont
*>(GetFont())->GetHeight(m_pVsh
, *GetOut(), SnapToGrid());
771 inline sal_uInt16
SwTextSizeInfo::GetHangingBaseline() const
774 return const_cast<SwFont
*>(GetFont())->GetHangingBaseline( m_pVsh
, *GetOut() );
777 inline SwPosSize
SwTextSizeInfo::GetTextSize( const OUString
&rText
) const
779 return GetTextSize(m_pOut
, nullptr, rText
, TextFrameIndex(0), TextFrameIndex(rText
.getLength()));
782 inline SwPosSize
SwTextSizeInfo::GetTextSize( const SwScriptInfo
* pSI
,
783 TextFrameIndex
const nNewIdx
,
784 TextFrameIndex
const nNewLen
) const
786 return GetTextSize( m_pOut
, pSI
, *m_pText
, nNewIdx
, nNewLen
);
789 inline SwTwips
SwTextPaintInfo::GetPaintOfst() const
791 return GetParaPortion()->GetRepaint().GetOffset();
794 inline void SwTextPaintInfo::SetPaintOfst( const SwTwips nNew
)
796 GetParaPortion()->GetRepaint().SetOffset( nNew
);
799 inline void SwTextPaintInfo::DrawText( const OUString
&rText
,
800 const SwLinePortion
&rPor
,
801 const TextFrameIndex nStart
, const TextFrameIndex nLength
,
802 const bool bKern
) const
804 const_cast<SwTextPaintInfo
*>(this)->DrawText_( rText
, rPor
, nStart
, nLength
, bKern
);
807 inline void SwTextPaintInfo::DrawText( const SwLinePortion
&rPor
,
808 const TextFrameIndex nLength
, const bool bKern
) const
810 const_cast<SwTextPaintInfo
*>(this)->DrawText_( *m_pText
, rPor
, m_nIdx
, nLength
, bKern
);
813 inline void SwTextPaintInfo::DrawMarkedText( const SwLinePortion
&rPor
,
814 const TextFrameIndex nLength
,
816 const bool bSmartTags
,
817 const bool bGrammarCheck
) const
819 const_cast<SwTextPaintInfo
*>(this)->DrawText_( *m_pText
, rPor
, m_nIdx
, nLength
, false/*bKern*/, bWrong
, bSmartTags
, bGrammarCheck
);
822 inline TextFrameIndex
SwTextFormatInfo::GetReformatStart() const
824 return GetParaPortion()->GetReformat().Start();
827 inline const SwAttrSet
& SwTextFormatInfo::GetCharAttr() const
829 // sw_redlinehide: this is used for numbering/footnote number portions, so:
830 return GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet();
833 inline void SwTextFormatInfo::SetParaFootnote()
835 GetTextFrame()->SetFootnote( true );
838 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */