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