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 <flyfrm.hxx>
22 #include <txatbase.hxx>
23 #include <paratr.hxx>
24 #include <vcl/outdev.hxx>
26 
27 #include "pormulti.hxx"
28 #include <pagefrm.hxx>
29 #include <pagedesc.hxx>
30 #include <tgrditem.hxx>
31 #include "porfld.hxx"
32 
33 #include "itrtxt.hxx"
34 #include <txtfrm.hxx>
35 #include "porfly.hxx"
36 
38 {
39  assert(pNewFrame->GetPara());
40 
41  CtorInitAttrIter( *pNewFrame->GetTextNodeFirst(), pNewFrame->GetPara()->GetScriptInfo(), pNewFrame );
42 
43  SwTextNode const*const pNode = pNewFrame->GetTextNodeForParaProps();
44 
45  m_pFrame = pNewFrame;
46  m_pInf = pNewInf;
47  m_aLineInf.CtorInitLineInfo( pNode->GetSwAttrSet(), *pNode );
50 
51  // Order is important: only execute FillRegister if GetValue!=0
52  m_bRegisterOn = pNode->GetSwAttrSet().GetRegister().GetValue()
54 }
55 
57 {
61  m_bPrev = true;
62  m_pPrev = nullptr;
63  m_nLineNr = 1;
64 }
65 
66 void SwTextIter::CalcAscentAndHeight( sal_uInt16 &rAscent, sal_uInt16 &rHeight ) const
67 {
68  rHeight = GetLineHeight();
69  rAscent = m_pCurr->GetAscent() + rHeight - m_pCurr->Height();
70 }
71 
73 {
74  m_pPrev = nullptr;
75  m_bPrev = true;
77  if( m_pCurr == pLay )
78  return nullptr;
79  while( pLay->GetNext() != m_pCurr )
80  pLay = pLay->GetNext();
81  return m_pPrev = pLay;
82 }
83 
85 {
86  if(! m_bPrev)
87  GetPrev_();
88  return m_pPrev;
89 }
90 
92 {
93  if( !m_bPrev )
94  GetPrev_();
95  if( m_pPrev )
96  {
97  m_bPrev = false;
98  m_pCurr = m_pPrev;
100  m_nY = m_nY - GetLineHeight();
101  if( !m_pCurr->IsDummy() && !(--m_nLineNr) )
102  ++m_nLineNr;
103  return m_pCurr;
104  }
105  else
106  return nullptr;
107 }
108 
110 {
111  if(m_pCurr->GetNext())
112  {
113  m_pPrev = m_pCurr;
114  m_bPrev = true;
116  m_nY += GetLineHeight();
117  if( m_pCurr->GetLen() || ( m_nLineNr>1 && !m_pCurr->IsDummy() ) )
118  ++m_nLineNr;
119  return m_pCurr = m_pCurr->GetNext();
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  bRightMargin = false;
208  bool bPrevious = 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  sal_uInt16 nPorHeight, sal_uInt16 nPorAscent,
218  const bool bAutoToCentered ) const
219 {
220  if ( pPor )
221  {
222  nPorHeight = pPor->Height();
223  nPorAscent = pPor->GetAscent();
224  }
225 
226  sal_uInt16 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.
284  if (GetInfo().GetTextFrame()->IsVertLR() && !GetInfo().GetTextFrame()->IsVertLRBT())
285  nOfst += rLine.Height() - ( rLine.Height() - nPorHeight ) / 2 - nPorAscent;
286  else
287  nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
288  break;
289  }
290  [[fallthrough]];
292  // base line
293  nOfst = nOfst + rLine.GetAscent();
294  break;
295  }
296  }
297 
298  return nOfst;
299 }
300 
302 {
303  while( m_nY + GetLineHeight() <= y && Next() )
304  ;
305  while( m_nY > y && Prev() )
306  ;
307 }
308 
309 // Local helper function to check, if pCurr needs a field rest portion:
310 static bool lcl_NeedsFieldRest( const SwLineLayout* pCurr )
311 {
312  const SwLinePortion *pPor = pCurr->GetNextPortion();
313  bool bRet = false;
314  while( pPor && !bRet )
315  {
316  bRet = pPor->InFieldGrp() && static_cast<const SwFieldPortion*>(pPor)->HasFollow();
317  if( !pPor->GetNextPortion() || !pPor->GetNextPortion()->InFieldGrp() )
318  break;
319  pPor = pPor->GetNextPortion();
320  }
321  return bRet;
322 }
323 
324 void SwTextIter::TruncLines( bool bNoteFollow )
325 {
326  SwLineLayout *pDel = m_pCurr->GetNext();
327  TextFrameIndex const nEnd = m_nStart + m_pCurr->GetLen();
328 
329  if( pDel )
330  {
331  m_pCurr->SetNext( nullptr );
332  if (MaybeHasHints() && bNoteFollow)
333  {
336 
337  // bug 88534: wrong positioning of flys
338  SwTextFrame* pFollow = GetTextFrame()->GetFollow();
339  if ( pFollow && ! pFollow->IsLocked() &&
340  nEnd == pFollow->GetOfst() )
341  {
342  TextFrameIndex nRangeEnd = nEnd;
343  SwLineLayout* pLine = pDel;
344 
345  // determine range to be searched for flys anchored as characters
346  while ( pLine )
347  {
348  nRangeEnd = nRangeEnd + pLine->GetLen();
349  pLine = pLine->GetNext();
350  }
351 
352  // examine hints in range nEnd - (nEnd + nRangeChar)
353  SwTextNode const* pNode(nullptr);
355  for (SwTextAttr const* pHt = iter.NextAttr(&pNode); pHt; pHt = iter.NextAttr(&pNode))
356  {
357  if( RES_TXTATR_FLYCNT == pHt->Which() )
358  {
359  // check if hint is in our range
360  TextFrameIndex const nTmpPos(
361  GetTextFrame()->MapModelToView(pNode, pHt->GetStart()));
362  if ( nEnd <= nTmpPos && nTmpPos < nRangeEnd )
363  pFollow->InvalidateRange_(
364  SwCharRange( nTmpPos, nTmpPos ) );
365  }
366  }
367  }
368  }
369  delete pDel;
370  }
371  if( m_pCurr->IsDummy() &&
372  !m_pCurr->GetLen() &&
373  m_nStart < TextFrameIndex(GetTextFrame()->GetText().getLength()))
374  {
375  m_pCurr->SetRealHeight( 1 );
376  }
377  if (MaybeHasHints())
378  m_pFrame->RemoveFootnote( nEnd );
379 }
380 
381 void SwTextIter::CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
382 {
383  nEndCnt = 0;
384  nMidCnt = 0;
385  if ( m_bPrev && m_pPrev && !m_pPrev->IsEndHyph() && !m_pPrev->IsMidHyph() )
386  return;
388  if( m_pCurr == pLay )
389  return;
390  while( pLay != m_pCurr )
391  {
392  if ( pLay->IsEndHyph() )
393  nEndCnt++;
394  else
395  nEndCnt = 0;
396  if ( pLay->IsMidHyph() )
397  nMidCnt++;
398  else
399  nMidCnt = 0;
400  pLay = pLay->GetNext();
401  }
402 }
403 
404 // Change current output device to formatting device, this has to be done before
405 // formatting.
407  pInf( &rInfo ),
408  pOut( rInfo.GetOut() ),
409  bOnWin( rInfo.OnWin() )
410 {
411  OSL_ENSURE( rInfo.GetRefDev(), "No reference device for text formatting" );
412 
413  // set new values
414  rInfo.SetOut( rInfo.GetRefDev() );
415  rInfo.SetOnWin( false );
416 }
417 
419 {
420  pInf->SetOut( pOut );
421  pInf->SetOnWin( bOnWin );
422 }
423 
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
~SwHookOut()
Definition: itrtxt.cxx:418
void CtorInitTextIter(SwTextFrame *pFrame, SwTextInfo *pInf)
Definition: itrtxt.cxx:37
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:127
static bool bRightMargin
Definition: itrtxt.hxx:268
SwHookOut(SwTextSizeInfo &rInfo)
Definition: itrtxt.cxx:406
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:125
void InvalidateRange_(const SwCharRange &, const long=0)
Definition: txtfrm.cxx:1690
bool m_bRegisterOn
Definition: itrtxt.hxx:45
const SwRect & getFramePrintArea() const
Definition: frame.hxx:176
void SetOnWin(const bool bNew)
Definition: inftxt.hxx:200
SwParaPortion * GetPara()
Definition: txtcache.cxx:89
TextFrameIndex GetOfst() const
Definition: txtfrm.hxx:426
bool GetRubyTextBelow() const
Definition: tgrditem.hxx:85
long SwTwips
Definition: swtypes.hxx:49
void CharToLine(TextFrameIndex)
Definition: itrtxt.cxx:194
const SwLineLayout * Next()
Definition: itrtxt.cxx:109
void Pos(const Point &rNew)
Definition: swrect.hxx:167
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:97
void CtorInitAttrIter(SwTextNode &rTextNode, SwScriptInfo &rScrInf, SwTextFrame const *pFrame=nullptr)
Definition: redlnitr.cxx:382
const SwRect & getFrameArea() const
Definition: frame.hxx:175
void CtorInitLineInfo(const SwAttrSet &rAttrSet, const SwTextNode &rTextNode)
Definition: inftxt.cxx:103
const SwLineLayout * GetNextLine() const
Definition: itrtxt.cxx:135
bool IsSquaredMode() const
Definition: tgrditem.hxx:104
vcl::RenderContext * GetRefDev()
Definition: inftxt.hxx:235
SwLineLayout * GetPrev_()
Definition: itrtxt.cxx:72
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:844
static bool lcl_NeedsFieldRest(const SwLineLayout *pCurr)
Definition: itrtxt.cxx:310
void CalcAscentAndHeight(sal_uInt16 &rAscent, sal_uInt16 &rHeight) const
Definition: itrtxt.cxx:66
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:445
void SetRealHeight(sal_uInt16 nNew)
Definition: porlay.hxx:152
bool m_bPrev
Definition: itrtxt.hxx:44
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1300
SwTextInfo * m_pInf
Definition: itrtxt.hxx:35
void Bottom()
Definition: itrtxt.cxx:186
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:215
bool IsDummy() const
Definition: porlay.hxx:135
const SwLineLayout * GetPrevLine()
Definition: itrtxt.cxx:145
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:658
SwParaPortion * GetParaPortion()
Definition: inftxt.hxx:128
bool const bOnWin
Definition: itrtxt.hxx:304
TextFrameIndex MapModelToView(MergedPara const &, SwTextNode const *pNode, sal_Int32 nIndex)
Definition: txtfrm.cxx:1182
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2514
void Init()
Definition: itrtxt.cxx:56
void TwipsToLine(const SwTwips)
Definition: itrtxt.cxx:301
const SwLineLayout * GetPrev()
Definition: itrtxt.cxx:84
SwTwips m_nFrameStart
Definition: itrtxt.hxx:38
sal_uInt16 GetLineHeight() const
Definition: itrtxt.hxx:116
void TruncLines(bool bNoteFollow=false)
Definition: itrtxt.cxx:324
bool IsLocked() const
Definition: txtfrm.hxx:505
bool FillRegister(SwTwips &rRegStart, sal_uInt16 &rRegDiff)
Determines the start position and step size of the register.
Definition: porrst.cxx:351
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:91
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
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:171
SwScriptInfo & GetScriptInfo()
Definition: porlay.hxx:270
double getLength(const B2DPolygon &rCandidate)
#define RES_TXTATR_FLYCNT
Definition: hintids.hxx:152
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:381
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:203
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:393
sal_uInt16 GetRubyHeight() const
Definition: tgrditem.hxx:78
sal_uInt16 & GetAscent()
Definition: porlin.hxx:77
TextFrameIndex GetTextStart() const
Definition: inftxt.hxx:130