LibreOffice Module sw (master) 1
itrtxt.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 <ndtxt.hxx>
21#include <txatbase.hxx>
22#include <paratr.hxx>
23#include <vcl/outdev.hxx>
25
26#include "pormulti.hxx"
27#include <pagefrm.hxx>
28#include <tgrditem.hxx>
29#include "porfld.hxx"
30#include "porrst.hxx"
31
32#include "itrtxt.hxx"
33#include <txtfrm.hxx>
34
36{
37 assert(pNewFrame->GetPara());
38
39 CtorInitAttrIter( *pNewFrame->GetTextNodeFirst(), pNewFrame->GetPara()->GetScriptInfo(), pNewFrame );
40
41 SwTextNode const*const pNode = pNewFrame->GetTextNodeForParaProps();
42
43 m_pFrame = pNewFrame;
44 m_pInf = pNewInf;
45 m_aLineInf.CtorInitLineInfo( pNode->GetSwAttrSet(), *pNode );
48
49 // Order is important: only execute FillRegister if GetValue!=0
52}
53
55{
59 m_bPrev = true;
60 m_pPrev = nullptr;
61 m_nLineNr = 1;
62}
63
64void SwTextIter::CalcAscentAndHeight( SwTwips &rAscent, SwTwips &rHeight ) const
65{
66 rHeight = GetLineHeight();
67 rAscent = m_pCurr->GetAscent() + rHeight - m_pCurr->Height();
68}
69
71{
72 m_pPrev = nullptr;
73 m_bPrev = true;
75 if( m_pCurr == pLay )
76 return nullptr;
77 while( pLay->GetNext() != m_pCurr )
78 pLay = pLay->GetNext();
79 m_pPrev = pLay;
80 return m_pPrev;
81}
82
84{
85 if(! m_bPrev)
86 GetPrev_();
87 return m_pPrev;
88}
89
91{
92 if( !m_bPrev )
93 GetPrev_();
94 if( m_pPrev )
95 {
96 m_bPrev = false;
100 if( !m_pCurr->IsDummy() && !(--m_nLineNr) )
101 ++m_nLineNr;
102 return m_pCurr;
103 }
104 else
105 return nullptr;
106}
107
109{
110 if(m_pCurr->GetNext())
111 {
113 m_bPrev = true;
115 m_nY += GetLineHeight();
116 if( m_pCurr->GetLen() || ( m_nLineNr>1 && !m_pCurr->IsDummy() ) )
117 ++m_nLineNr;
119 return m_pCurr;
120 }
121 else
122 return nullptr;
123}
124
126{
127 const SwLineLayout *pNext = Next();
128 while( pNext && pNext->IsDummy() && pNext->GetNext() )
129 {
130 pNext = Next();
131 }
132 return pNext;
133}
134
136{
137 const SwLineLayout *pNext = m_pCurr->GetNext();
138 while( pNext && pNext->IsDummy() && pNext->GetNext() )
139 {
140 pNext = pNext->GetNext();
141 }
142 return pNext;
143}
144
146{
147 const SwLineLayout *pRoot = m_pInf->GetParaPortion();
148 if( pRoot == m_pCurr )
149 return nullptr;
150 const SwLineLayout *pLay = pRoot;
151
152 while( pLay->GetNext() != m_pCurr )
153 pLay = pLay->GetNext();
154
155 if( pLay->IsDummy() )
156 {
157 const SwLineLayout *pTmp = pRoot;
158 pLay = pRoot->IsDummy() ? nullptr : pRoot;
159 while( pTmp->GetNext() != m_pCurr )
160 {
161 if( !pTmp->IsDummy() )
162 pLay = pTmp;
163 pTmp = pTmp->GetNext();
164 }
165 }
166
167 // If nothing has changed, then there are only dummy's
168 return pLay;
169}
170
172{
173 const SwLineLayout *pMyPrev = Prev();
174 if( !pMyPrev )
175 return nullptr;
176
177 const SwLineLayout *pLast = pMyPrev;
178 while( pMyPrev && pMyPrev->IsDummy() )
179 {
180 pLast = pMyPrev;
181 pMyPrev = Prev();
182 }
183 return pMyPrev ? pMyPrev : pLast;
184}
185
187{
188 while( Next() )
189 {
190 // nothing
191 }
192}
193
195{
196 while( m_nStart + m_pCurr->GetLen() <= nChar && Next() )
197 ;
198 while( m_nStart > nChar && Prev() )
199 ;
200}
201
202// 1170: takes into account ambiguities:
204{
205 CharToLine( nPosition );
206 if( nPosition != m_nStart )
207 s_bRightMargin = false;
208 bool bPrevious = s_bRightMargin && m_pCurr->GetLen() && GetPrev() &&
209 GetPrev()->GetLen();
210 if (bPrevious && nPosition && CH_BREAK == GetInfo().GetChar(nPosition - TextFrameIndex(1)))
211 bPrevious = false;
212 return bPrevious ? PrevLine() : m_pCurr;
213}
214
216 const SwLinePortion* pPor,
217 SwTwips nPorHeight, SwTwips nPorAscent,
218 const bool bAutoToCentered ) const
219{
220 if ( pPor )
221 {
222 nPorHeight = pPor->Height();
223 nPorAscent = pPor->GetAscent();
224 }
225
226 SwTwips nOfst = rLine.GetRealHeight() - rLine.Height();
227
228 SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
229
230 if ( pGrid && GetInfo().SnapToGrid() && pGrid->IsSquaredMode() )
231 {
232 const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
233 const bool bRubyTop = ! pGrid->GetRubyTextBelow();
234
235 if ( GetInfo().IsMulti() )
236 // we are inside the GetCharRect recursion for multi portions
237 // we center the portion in its surrounding line
238 nOfst = ( m_pCurr->Height() - nPorHeight ) / 2 + nPorAscent;
239 else
240 {
241 // We have to take care for ruby portions.
242 // The ruby portion is NOT centered
243 nOfst = nOfst + nPorAscent;
244
245 if ( ! pPor || ! pPor->IsMultiPortion() ||
246 ! static_cast<const SwMultiPortion*>(pPor)->IsRuby() )
247 {
248 // Portions which are bigger than on grid distance are
249 // centered inside the whole line.
250
251 //for text refactor
252 const sal_uInt16 nLineNet = rLine.Height() - nRubyHeight;
253 //const sal_uInt16 nLineNet = ( nPorHeight > nGridWidth ) ?
254 // rLine.Height() - nRubyHeight :
255 // nGridWidth;
256 nOfst += ( nLineNet - nPorHeight ) / 2;
257 if ( bRubyTop )
258 nOfst += nRubyHeight;
259 }
260 }
261 }
262 else
263 {
264 switch ( GetLineInfo().GetVertAlign() ) {
266 nOfst = nOfst + nPorAscent;
267 break;
269 OSL_ENSURE( rLine.Height() >= nPorHeight, "Portion height > Line height");
270 nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
271 break;
273 nOfst += rLine.Height() - nPorHeight + nPorAscent;
274 break;
276 if ( bAutoToCentered || GetInfo().GetTextFrame()->IsVertical() )
277 {
278 // Vertical text has these cases to calculate the baseline:
279 // - Implicitly TB and RL: the origo is the top right corner, offset is the
280 // ascent.
281 // - (Implicitly TB and) LR: the origo is the top left corner, offset is the
282 // descent.
283 // - BT and LR: the origo is the bottom left corner, offset is the ascent.
285 nOfst += rLine.Height() - ( rLine.Height() - nPorHeight ) / 2 - nPorAscent;
286 else
287 {
288 SwTwips nLineHeight = 0;
289 bool bHadClearingBreak = false;
291 {
292 // Ignore the height of clearing break portions in the automatic
293 // alignment case.
294 const SwLinePortion* pLinePor = rLine.GetFirstPortion();
295 while (pLinePor)
296 {
297 bool bClearingBreak = false;
298 if (pLinePor->IsBreakPortion())
299 {
300 auto pBreakPortion = static_cast<const SwBreakPortion*>(pLinePor);
301 bClearingBreak = pBreakPortion->GetClear() != SwLineBreakClear::NONE;
302 if (bClearingBreak)
303 {
304 bHadClearingBreak = true;
305 }
306 }
307 if (!bClearingBreak && pLinePor->Height() > nLineHeight)
308 {
309 nLineHeight = pLinePor->Height();
310 }
311 pLinePor = pLinePor->GetNextPortion();
312 }
313 }
314
315 if (!bHadClearingBreak)
316 {
317 nLineHeight = rLine.Height();
318 }
319
320 nOfst += ( nLineHeight - nPorHeight ) / 2 + nPorAscent;
321 }
322 break;
323 }
324 [[fallthrough]];
326 // base line
327 if (pPor && pPor->GetHangingBaseline())
328 {
329 nOfst += rLine.GetAscent() // Romn baseline of the line.
330 - rLine.GetHangingBaseline() // Hanging baseline of the line.
331 + pPor->GetHangingBaseline(); // Romn baseline of the portion.
332 }
333 else
334 nOfst = nOfst + rLine.GetAscent();
335 break;
336 }
337 }
338
339 return nOfst;
340}
341
343{
344 while( m_nY + GetLineHeight() <= y && Next() )
345 ;
346 while( m_nY > y && Prev() )
347 ;
348}
349
350// Local helper function to check, if pCurr needs a field rest portion:
351static bool lcl_NeedsFieldRest( const SwLineLayout* pCurr )
352{
353 const SwLinePortion *pPor = pCurr->GetNextPortion();
354 bool bRet = false;
355 while( pPor && !bRet )
356 {
357 bRet = pPor->InFieldGrp() && static_cast<const SwFieldPortion*>(pPor)->HasFollow();
358 if( !pPor->GetNextPortion() || !pPor->GetNextPortion()->InFieldGrp() )
359 break;
360 pPor = pPor->GetNextPortion();
361 }
362 return bRet;
363}
364
365void SwTextIter::TruncLines( bool bNoteFollow )
366{
367 SwLineLayout *pDel = m_pCurr->GetNext();
368 TextFrameIndex const nEnd = m_nStart + m_pCurr->GetLen();
369
370 if( pDel )
371 {
372 m_pCurr->SetNext( nullptr );
373 if (MaybeHasHints() && bNoteFollow)
374 {
377
378 // bug 88534: wrong positioning of flys
379 SwTextFrame* pFollow = GetTextFrame()->GetFollow();
380 if ( pFollow && ! pFollow->IsLocked() &&
381 nEnd == pFollow->GetOffset() )
382 {
383 TextFrameIndex nRangeEnd = nEnd;
384 SwLineLayout* pLine = pDel;
385
386 // determine range to be searched for flys anchored as characters
387 while ( pLine )
388 {
389 nRangeEnd = nRangeEnd + pLine->GetLen();
390 pLine = pLine->GetNext();
391 }
392
393 // examine hints in range nEnd - (nEnd + nRangeChar)
394 SwTextNode const* pNode(nullptr);
396 for (SwTextAttr const* pHt = iter.NextAttr(&pNode); pHt; pHt = iter.NextAttr(&pNode))
397 {
398 if( RES_TXTATR_FLYCNT == pHt->Which() )
399 {
400 // check if hint is in our range
401 TextFrameIndex const nTmpPos(
402 GetTextFrame()->MapModelToView(pNode, pHt->GetStart()));
403 if ( nEnd <= nTmpPos && nTmpPos < nRangeEnd )
404 pFollow->InvalidateRange_(
405 SwCharRange( nTmpPos, nTmpPos ) );
406 }
407 }
408 }
409 }
410 delete pDel;
411 }
412 if( m_pCurr->IsDummy() &&
413 !m_pCurr->GetLen() &&
415 {
417 }
418 if (MaybeHasHints())
419 m_pFrame->RemoveFootnote( nEnd );
420}
421
422void SwTextIter::CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
423{
424 nEndCnt = 0;
425 nMidCnt = 0;
426 if ( m_bPrev && m_pPrev && !m_pPrev->IsEndHyph() && !m_pPrev->IsMidHyph() )
427 return;
429 if( m_pCurr == pLay )
430 return;
431 while( pLay != m_pCurr )
432 {
433 if ( pLay->IsEndHyph() )
434 nEndCnt++;
435 else
436 nEndCnt = 0;
437 if ( pLay->IsMidHyph() )
438 nMidCnt++;
439 else
440 nMidCnt = 0;
441 pLay = pLay->GetNext();
442 }
443}
444
445// Change current output device to formatting device, this has to be done before
446// formatting.
448 pInf( &rInfo ),
449 pOut( rInfo.GetOut() ),
450 bOnWin( rInfo.OnWin() )
451{
452 OSL_ENSURE( rInfo.GetRefDev(), "No reference device for text formatting" );
453
454 // set new values
455 rInfo.SetOut( rInfo.GetRefDev() );
456 rInfo.SetOnWin( false );
457}
458
460{
461 pInf->SetOut( pOut );
462 pInf->SetOnWin( bOnWin );
463}
464
465/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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 GetValue() const
bool MaybeHasHints() const
Definition: itratr.cxx:127
void CtorInitAttrIter(SwTextNode &rTextNode, SwScriptInfo &rScrInf, SwTextFrame const *pFrame=nullptr)
Definition: redlnitr.cxx:582
const SwRegisterItem & GetRegister(bool=true) const
Definition: paratr.hxx:207
SwLineBreakClear GetClear() const
Definition: porrst.cxx:240
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:727
const SwRect & getFrameArea() const
Definition: frame.hxx:179
const SwRect & getFramePrintArea() const
Definition: frame.hxx:180
bool IsVertLRBT() const
Definition: frame.hxx:989
bool IsVertical() const
Definition: frame.hxx:979
bool IsVertLR() const
Definition: frame.hxx:985
SwPageFrame * FindPageFrame()
Definition: frame.hxx:686
SwTextSizeInfo * pInf
Definition: itrtxt.hxx:303
VclPtr< OutputDevice > pOut
Definition: itrtxt.hxx:304
~SwHookOut()
Definition: itrtxt.cxx:459
bool bOnWin
Definition: itrtxt.hxx:305
SwHookOut(SwTextSizeInfo &rInfo)
Definition: itrtxt.cxx:447
void CtorInitLineInfo(const SwAttrSet &rAttrSet, const SwTextNode &rTextNode)
Definition: inftxt.cxx:109
SvxParaVertAlignItem::Align GetVertAlign() const
Definition: inftxt.hxx:85
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:79
bool IsRest() const
Definition: porlay.hxx:129
SwLineLayout * GetNext()
Definition: porlay.hxx:159
SwLinePortion * GetFirstPortion() const
Definition: porlay.cxx:841
virtual void Height(const SwTwips nNew, const bool bText=true) override
Definition: porlay.cxx:231
bool IsMidHyph() const
Definition: porlay.hxx:125
bool IsDummy() const
Definition: porlay.hxx:151
void SetRealHeight(SwTwips nNew)
Definition: porlay.hxx:168
SwTwips GetRealHeight() const
Definition: porlay.hxx:169
bool IsEndHyph() const
Definition: porlay.hxx:123
void SetNext(SwLineLayout *pNew)
Definition: porlay.hxx:161
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:52
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:75
TextFrameIndex GetLen() const
Definition: porlin.hxx:77
SwTwips GetHangingBaseline() const
Definition: porlin.hxx:89
SwTwips & GetAscent()
Definition: porlin.hxx:80
bool IsBreakPortion() const
Definition: porlin.hxx:121
bool IsMultiPortion() const
Definition: porlin.hxx:143
bool InFieldGrp() const
Definition: porlin.hxx:111
void SetFollowField(const bool bNew)
Definition: porlay.hxx:313
SwScriptInfo & GetScriptInfo()
Definition: porlay.hxx:291
SwTwips Height() const
Definition: possiz.hxx:49
void Pos(const Point &rNew)
Definition: swrect.hxx:171
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
const SwLineLayout * CharCursorToLine(TextFrameIndex const nPos)
Definition: itrtxt.cxx:203
static bool s_bRightMargin
Definition: itrtxt.hxx:268
SwTwips AdjustBaseLine(const SwLineLayout &rLine, const SwLinePortion *pPor, SwTwips nPorHeight=0, SwTwips nAscent=0, const bool bAutoToCentered=false) const
Definition: itrtxt.cxx:215
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:889
TextFrameIndex GetOffset() const
Definition: txtfrm.hxx:453
bool FillRegister(SwTwips &rRegStart, sal_uInt16 &rRegDiff)
Determines the start position and step size of the register.
Definition: porrst.cxx:500
void RemoveFootnote(TextFrameIndex nStart, TextFrameIndex nLen=TextFrameIndex(COMPLETE_STRING))
Footnote.
Definition: txtftn.cxx:408
SwParaPortion * GetPara()
Definition: txtcache.cxx:90
bool IsLocked() const
Definition: txtfrm.hxx:535
void InvalidateRange_(const SwCharRange &, const tools::Long=0)
Definition: txtfrm.cxx:1803
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:472
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1390
bool GetRubyTextBelow() const
Definition: tgrditem.hxx:85
bool IsSquaredMode() const
Definition: tgrditem.hxx:104
sal_uInt16 GetRubyHeight() const
Definition: tgrditem.hxx:78
SwParaPortion * GetParaPortion()
Definition: inftxt.hxx:121
TextFrameIndex GetTextStart() const
Definition: inftxt.hxx:123
const SwLineLayout * NextLine()
Definition: itrtxt.cxx:125
SwTwips m_nRegStart
Definition: itrtxt.hxx:40
void Init()
Definition: itrtxt.cxx:54
SwTwips m_nY
Definition: itrtxt.hxx:39
void TruncLines(bool bNoteFollow=false)
Definition: itrtxt.cxx:365
void Bottom()
Definition: itrtxt.cxx:186
const SwLineLayout * PrevLine()
Definition: itrtxt.cxx:171
void TwipsToLine(const SwTwips)
Definition: itrtxt.cxx:342
SwTwips m_nFrameStart
Definition: itrtxt.hxx:38
const SwLineLayout * GetPrevLine()
Definition: itrtxt.cxx:145
SwLineLayout * m_pCurr
Definition: itrtxt.hxx:36
SwTwips GetLineHeight() const
Definition: itrtxt.hxx:116
const SwLineLayout * Next()
Definition: itrtxt.cxx:108
sal_Int32 m_nLineNr
Definition: itrtxt.hxx:43
SwLineLayout * m_pPrev
Definition: itrtxt.hxx:37
SwTextFrame * m_pFrame
Definition: itrtxt.hxx:34
void CharToLine(TextFrameIndex)
Definition: itrtxt.cxx:194
SwTextInfo & GetInfo()
Definition: itrtxt.hxx:96
const SwLineLayout * Prev()
Definition: itrtxt.cxx:90
SwTextFrame * GetTextFrame()
Definition: itrtxt.hxx:134
TextFrameIndex m_nStart
Definition: itrtxt.hxx:41
void CalcAscentAndHeight(SwTwips &rAscent, SwTwips &rHeight) const
Definition: itrtxt.cxx:64
const SwLineInfo & GetLineInfo() const
Definition: itrtxt.hxx:128
const SwLineLayout * GetNextLine() const
Definition: itrtxt.cxx:135
bool m_bRegisterOn
Definition: itrtxt.hxx:45
void CntHyphens(sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
Definition: itrtxt.cxx:422
SwTextInfo * m_pInf
Definition: itrtxt.hxx:35
sal_uInt16 m_nRegDiff
Definition: itrtxt.hxx:42
bool m_bPrev
Definition: itrtxt.hxx:44
SwLineInfo m_aLineInf
Definition: itrtxt.hxx:33
const SwLineLayout * GetPrev()
Definition: itrtxt.cxx:83
SwLineLayout * GetPrev_()
Definition: itrtxt.cxx:70
void CtorInitTextIter(SwTextFrame *pFrame, SwTextInfo *pInf)
Definition: itrtxt.cxx:35
SwTextSizeInfo & GetInfo()
Definition: itrtxt.hxx:216
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
SwTextFrame * GetTextFrame()
Definition: inftxt.hxx:288
vcl::RenderContext * GetRefDev()
Definition: inftxt.hxx:229
void SetOnWin(const bool bNew)
Definition: inftxt.hxx:194
void SetOut(OutputDevice *pNewOut)
Definition: inftxt.hxx:227
SwTextAttr const * NextAttr(SwTextNode const **ppNode=nullptr)
Definition: txtfrm.cxx:91
float y
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(58)
static bool lcl_NeedsFieldRest(const SwLineLayout *pCurr)
Definition: itrtxt.cxx:351
double getLength(const B2DPolygon &rCandidate)
tools::Long SnapToGrid(KernArray &rKernArray, std::u16string_view aText, sal_Int32 nStt, sal_Int32 nLen, tools::Long nGridWidth, bool bForceLeft)
Snap ideographs to text grids: a) Ideographic open brackets are aligned to the rightmost edge of span...
Definition: justify.cxx:176
TextFrameIndex MapModelToView(MergedPara const &, SwTextNode const *pNode, sal_Int32 nIndex)
Definition: txtfrm.cxx:1270
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2676
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
tools::Long SwTwips
Definition: swtypes.hxx:51
unsigned char sal_uInt8
oslFileHandle & pOut