LibreOffice Module sw (master)  1
porlin.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 <vcl/outdev.hxx>
21 #include <SwPortionHandler.hxx>
22 
23 #include "porlin.hxx"
24 #include "inftxt.hxx"
25 #include "pormulti.hxx"
26 #if OSL_DEBUG_LEVEL > 0
27 
28 static bool ChkChain( SwLinePortion *pStart )
29 {
30  SwLinePortion *pPor = pStart->GetNextPortion();
31  sal_uInt16 nCount = 0;
32  while( pPor )
33  {
34  ++nCount;
35  OSL_ENSURE( nCount < 200 && pPor != pStart,
36  "ChkChain(): lost in chains" );
37  if( nCount >= 200 || pPor == pStart )
38  {
39  // the lifesaver
40  pPor = pStart->GetNextPortion();
41  pStart->SetNextPortion(nullptr);
42  pPor->Truncate();
43  pStart->SetNextPortion( pPor );
44  return false;
45  }
46  pPor = pPor->GetNextPortion();
47  }
48  return true;
49 }
50 #endif
51 
53 {
54 }
55 
57 {
58  return GetLen() || Width() ? this : nullptr;
59 }
60 
61 sal_uInt16 SwLinePortion::GetViewWidth( const SwTextSizeInfo & ) const
62 {
63  return 0;
64 }
65 
67  mpNextPortion( nullptr ),
68  mnLineLength( 0 ),
69  mnAscent( 0 ),
70  mnHangingBaseline( 0 ),
71  mnWhichPor( PortionType::NONE ),
72  m_bJoinBorderWithPrev(false),
73  m_bJoinBorderWithNext(false)
74 {
75 }
76 
78  const SwLinePortion* pLast ) const
79 {
80  OSL_ENSURE( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
81  OSL_ENSURE( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");
82 
83  const sal_uInt16 nViewWidth = GetViewWidth( rInf );
84 
85  if( ! nViewWidth )
86  return;
87 
88  const sal_uInt16 nHalfView = nViewWidth / 2;
89  sal_uInt16 nLastWidth = pLast->Width();
90 
91  if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
92  nLastWidth = nLastWidth + o3tl::narrowing<sal_uInt16>(pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf ));
93 
94  sal_uInt16 nPos;
95  SwTextPaintInfo aInf( rInf );
96 
97  const bool bBidiPor = rInf.GetTextFrame()->IsRightToLeft() !=
99 
100  Degree10 nDir = bBidiPor ?
101  1800_deg10 :
102  rInf.GetFont()->GetOrientation( rInf.GetTextFrame()->IsVertical() );
103 
104  // pLast == this *only* for the 1st portion in the line so nLastWidth is 0;
105  // allow this too, will paint outside the frame but might look better...
106  if (nLastWidth > nHalfView || pLast == this)
107  {
108  switch (nDir.get())
109  {
110  case 0:
111  nPos = sal_uInt16( rInf.X() );
112  nPos += nLastWidth - nHalfView;
113  aInf.X( nPos );
114  break;
115  case 900:
116  nPos = sal_uInt16( rInf.Y() );
117  nPos -= nLastWidth - nHalfView;
118  aInf.Y( nPos );
119  break;
120  case 1800:
121  nPos = sal_uInt16( rInf.X() );
122  nPos -= nLastWidth - nHalfView;
123  aInf.X( nPos );
124  break;
125  case 2700:
126  nPos = sal_uInt16( rInf.Y() );
127  nPos += nLastWidth - nHalfView;
128  aInf.Y( nPos );
129  break;
130  }
131  }
132 
133  SwLinePortion *pThis = const_cast<SwLinePortion*>(this);
134  pThis->Width( nViewWidth );
135  Paint( aInf );
136  pThis->Width(0);
137 }
138 
140 {
141  if( GetLen() == rInf.GetLen() )
142  *static_cast<SwPosSize*>(this) = GetTextSize( rInf );
143  else
144  {
145  SwTextSizeInfo aInf( rInf );
146  aInf.SetLen( GetLen() );
147  *static_cast<SwPosSize*>(this) = GetTextSize( aInf );
148  }
149 }
150 
151 // all following portions will be deleted
153 {
155  do
156  {
157  OSL_ENSURE( pPos != this, "SwLinePortion::Truncate: loop" );
158  SwLinePortion *pLast = pPos;
159  pPos = pPos->GetNextPortion();
160  pLast->SetNextPortion( nullptr );
161  delete pLast;
162 
163  } while( pPos );
164 
165  mpNextPortion = nullptr;
166 }
167 
168 // It always will be inserted after us.
170 {
172  SetNextPortion( pIns );
173 #if OSL_DEBUG_LEVEL > 0
174  ChkChain( this );
175 #endif
176  return pIns;
177 }
178 
180 {
181  SwLinePortion *pPos = this;
182  // Find the end and link pLinPortion to the last one...
183  while( pPos->GetNextPortion() )
184  {
185  pPos = pPos->GetNextPortion();
186  }
187  return pPos;
188 }
189 
191 {
192  SwLinePortion *pPos = FindLastPortion();
193  pPos->SetNextPortion( pIns );
194  pIns->SetNextPortion( nullptr );
195 #if OSL_DEBUG_LEVEL > 0
196  ChkChain( this );
197 #endif
198  return pIns;
199 }
200 
202 {
203  SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
204  OSL_ENSURE( pPrev, "SwLinePortion::Cut(): can't cut" );
205  pPrev->SetNextPortion( pVictim->GetNextPortion() );
206  pVictim->SetNextPortion(nullptr);
207  return pVictim;
208 }
209 
211 {
212  OSL_ENSURE( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" );
213  SwLinePortion *pPos = const_cast<SwLinePortion*>(pRoot);
214  while( pPos->GetNextPortion() && pPos->GetNextPortion() != this )
215  {
216  pPos = pPos->GetNextPortion();
217  }
218  OSL_ENSURE( pPos->GetNextPortion(),
219  "SwLinePortion::FindPrevPortion: blowing in the wind");
220  return pPos;
221 }
222 
224 {
225  if( nOfst > ( PrtWidth() / 2 ) )
226  return GetLen();
227  else
228  return TextFrameIndex(0);
229 }
230 
232 {
233  OSL_ENSURE( false, "SwLinePortion::GetTextSize: don't ask me about sizes, "
234  "I'm only a stupid SwLinePortion" );
235  return SwPosSize();
236 }
237 
239 {
240  if( rInf.X() > rInf.Width() )
241  {
242  Truncate();
243  rInf.SetUnderflow( this );
244  return true;
245  }
246 
247  const SwLinePortion *pLast = rInf.GetLast();
248  Height( pLast->Height() );
249  SetAscent( pLast->GetAscent() );
250  const sal_uInt16 nNewWidth = o3tl::narrowing<sal_uInt16>(rInf.X() + PrtWidth());
251  // Only portions with true width can return true
252  // Notes for example never set bFull==true
253  if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
254  {
255  Truncate();
256  if( nNewWidth > rInf.Width() )
257  PrtWidth( nNewWidth - rInf.Width() );
258  rInf.GetLast()->FormatEOL( rInf );
259  return true;
260  }
261  return false;
262 }
263 
264 // Format end of line
265 
267 { }
268 
270 {
271  bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
272  const bool bFrameDir = rInf.GetTextFrame()->IsRightToLeft();
273  bool bCounterDir = ( ! bFrameDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
274  ( bFrameDir && DIR_LEFT2RIGHT == rInf.GetDirection() );
275 
276  if ( InSpaceGrp() && rInf.GetSpaceAdd() )
277  {
278  SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf );
279  if( rInf.IsRotated() )
280  rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
281  else if ( bCounterDir )
282  rInf.X( rInf.X() - nTmp );
283  else
284  rInf.X( rInf.X() + nTmp );
285  }
286  else
287  {
288  if( InFixMargGrp() && !IsMarginPortion() )
289  {
290  rInf.IncSpaceIdx();
291  rInf.IncKanaIdx();
292  }
293  if( rInf.IsRotated() )
294  rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
295  else if ( bCounterDir )
296  rInf.X( rInf.X() - PrtWidth() );
297  else
298  rInf.X( rInf.X() + PrtWidth() );
299  }
300  if( IsMultiPortion() && static_cast<SwMultiPortion*>(this)->HasTabulator() )
301  rInf.IncSpaceIdx();
302 
303  rInf.SetIdx( rInf.GetIdx() + GetLen() );
304 }
305 
307 {
308  return 0;
309 }
310 
311 bool SwLinePortion::GetExpText( const SwTextSizeInfo &, OUString & ) const
312 {
313  return false;
314 }
315 
317 {
318  rPH.Special( GetLen(), OUString(), GetWhichPor(), Height(), Width() );
319 }
320 
321 void SwLinePortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex& nOffset) const
322 {
323  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwLinePortion"));
324  dumpAsXmlAttributes(pWriter, rText, nOffset);
325  nOffset += GetLen();
326 
327  (void)xmlTextWriterEndElement(pWriter);
328 }
329 
330 void SwLinePortion::dumpAsXmlAttributes(xmlTextWriterPtr pWriter, std::u16string_view rText, TextFrameIndex nOffset) const
331 {
332  (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
333  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("symbol"), BAD_CAST(typeid(*this).name()));
334  (void)xmlTextWriterWriteAttribute(
335  pWriter, BAD_CAST("width"),
336  BAD_CAST(OString::number(Width()).getStr()));
337  (void)xmlTextWriterWriteAttribute(
338  pWriter, BAD_CAST("height"),
339  BAD_CAST(OString::number(Height()).getStr()));
340  (void)xmlTextWriterWriteAttribute(
341  pWriter, BAD_CAST("length"),
342  BAD_CAST(OString::number(static_cast<sal_Int32>(mnLineLength)).getStr()));
343  (void)xmlTextWriterWriteAttribute(
344  pWriter, BAD_CAST("type"),
345  BAD_CAST(sw::PortionTypeToString(GetWhichPor())));
346  OUString aText( rText.substr(sal_Int32(nOffset), sal_Int32(GetLen())) );
347  for (int i = 0; i < 32; ++i)
348  aText = aText.replace(i, '*');
349  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("portion"),
350  BAD_CAST(aText.toUtf8().getStr()));
351 }
352 
353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual bool Format(SwTextFormatInfo &rInf)
Definition: porlin.cxx:238
SwTwips PrtWidth() const
Definition: porlin.hxx:83
void Move(SwTextPaintInfo &rInf)
Definition: porlin.cxx:269
bool InSpaceGrp() const
Definition: porlin.hxx:113
SwFont * GetFont()
Definition: inftxt.hxx:231
virtual tools::Long CalcSpacing(tools::Long nSpaceAdd, const SwTextSizeInfo &rInf) const
Definition: porlin.cxx:306
void Truncate_()
Definition: porlin.cxx:152
const char * PortionTypeToString(PortionType nType)
Definition: xmldump.cxx:33
void CalcTextSize(const SwTextSizeInfo &rInfo)
Definition: porlin.cxx:139
static bool ChkChain(SwLinePortion *pStart)
Definition: porlin.cxx:28
long Long
void dumpAsXmlAttributes(xmlTextWriterPtr writer, std::u16string_view rText, TextFrameIndex nOffset) const
Definition: porlin.cxx:330
The SwPortionHandler interface implements a visitor for the layout engine's text portions.
tools::Long GetSpaceAdd() const
Definition: inftxt.hxx:441
vcl::text::ComplexTextLayoutFlags GetLayoutMode() const
Degree10 GetOrientation(const bool bVertLayout=false, const bool bVertFormatLRBT=false) const
Definition: swfont.cxx:412
virtual SwLinePortion * Compress()
Definition: porlin.cxx:56
bool IsMarginPortion() const
Definition: porlin.hxx:130
virtual void Paint(const SwTextPaintInfo &rInf) const =0
void IncSpaceIdx()
Definition: inftxt.hxx:439
int nCount
#define DIR_BOTTOM2TOP
Definition: inftxt.hxx:55
sal_uInt8 GetDirection() const
Definition: inftxt.hxx:217
bool InFixMargGrp() const
Definition: porlin.hxx:112
SwTwips Y() const
Definition: inftxt.hxx:381
virtual void Special(TextFrameIndex nLength, const OUString &rText, PortionType nType, sal_Int32 nHeight=0, sal_Int32 nWidth=0, const SwFont *pFont=nullptr)=0
special portion.
void IncKanaIdx()
Definition: inftxt.hxx:322
virtual void dumpAsXml(xmlTextWriterPtr pWriter, const OUString &rText, TextFrameIndex &rOffset) const
Definition: porlin.cxx:321
virtual SwLinePortion * Append(SwLinePortion *pPortion)
Definition: porlin.cxx:190
virtual TextFrameIndex GetModelPositionForViewPoint(sal_uInt16 nOfst) const
the parameter is actually SwTwips apparently?
Definition: porlin.cxx:223
virtual sal_uInt16 GetViewWidth(const SwTextSizeInfo &rInf) const
Definition: porlin.cxx:61
#define DIR_LEFT2RIGHT
Definition: inftxt.hxx:54
virtual bool GetExpText(const SwTextSizeInfo &rInf, OUString &rText) const
Definition: porlin.cxx:311
int i
vcl::RenderContext * GetOut()
Definition: inftxt.hxx:224
void SetUnderflow(SwLinePortion *pNew)
Definition: inftxt.hxx:601
bool IsKernPortion() const
Definition: porlin.hxx:138
sal_uInt16 Width() const
Definition: inftxt.hxx:528
virtual void HandlePortion(SwPortionHandler &rPH) const
Definition: porlin.cxx:316
PortionType
Definition: txttypes.hxx:23
TextFrameIndex GetIdx() const
Definition: inftxt.hxx:272
void PrePaint(const SwTextPaintInfo &rInf, const SwLinePortion *pLast) const
Definition: porlin.cxx:77
SwTwips Height() const
Definition: possiz.hxx:49
SwLinePortion * Cut(SwLinePortion *pVictim)
Definition: porlin.cxx:201
TextFrameIndex GetLen() const
Definition: porlin.hxx:76
SwTextFrame * GetTextFrame()
Definition: inftxt.hxx:285
tools::Long SwTwips
Definition: swtypes.hxx:51
SwTwips & GetAscent()
Definition: porlin.hxx:79
void Truncate()
Definition: porlin.hxx:209
SwLinePortion * mpNextPortion
Definition: porlin.hxx:55
bool IsMultiPortion() const
Definition: porlin.hxx:140
SwTwips X() const
Definition: inftxt.hxx:379
virtual ~SwLinePortion()
Definition: porlin.cxx:52
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:51
TextFrameIndex mnLineLength
Definition: porlin.hxx:57
#define DIR_RIGHT2LEFT
Definition: inftxt.hxx:56
void SetLen(const TextFrameIndex nNew)
Definition: inftxt.hxx:275
SwTwips Width() const
Definition: possiz.hxx:51
PortionType GetWhichPor() const
Definition: porlin.hxx:99
SwLinePortion * FindLastPortion()
Definition: porlin.cxx:179
bool OnWin() const
Definition: inftxt.hxx:192
bool IsRightToLeft() const
Definition: frame.hxx:987
virtual SwPosSize GetTextSize(const SwTextSizeInfo &rInfo) const
Definition: porlin.cxx:231
TextFrameIndex GetLen() const
Definition: inftxt.hxx:274
SwLinePortion * FindPrevPortion(const SwLinePortion *pRoot)
Definition: porlin.cxx:210
SwLinePortion * GetLast()
Definition: inftxt.hxx:561
void SetNextPortion(SwLinePortion *pNew)
Definition: porlin.hxx:78
bool IsVertical() const
Definition: frame.hxx:973
struct _xmlTextWriter * xmlTextWriterPtr
virtual void FormatEOL(SwTextFormatInfo &rInf)
Definition: porlin.cxx:266
bool IsRotated() const
Definition: inftxt.hxx:219
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:74
void SetIdx(const TextFrameIndex nNew)
Definition: inftxt.hxx:273
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...
virtual SwLinePortion * Insert(SwLinePortion *pPortion)
Definition: porlin.cxx:169
sal_uInt16 nPos
bool m_bDetectedRangeSegmentation false
SwPosSize(const SwTwips nW=0, const SwTwips nH=0)
Definition: possiz.hxx:30
void SetAscent(const SwTwips nNewAsc)
Definition: porlin.hxx:81
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo