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
28static 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
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{
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
311bool SwLinePortion::GetExpText( const SwTextSizeInfo &, OUString & ) const
312{
313 return false;
314}
315
317{
318 rPH.Special( GetLen(), OUString(), GetWhichPor() );
319}
320
321void 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
330void 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"),
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: */
struct _xmlTextWriter * xmlTextWriterPtr
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...
vcl::text::ComplexTextLayoutFlags GetLayoutMode() const
Degree10 GetOrientation(const bool bVertLayout=false, const bool bVertFormatLRBT=false) const
Definition: swfont.cxx:412
bool IsRightToLeft() const
Definition: frame.hxx:987
bool IsVertical() const
Definition: frame.hxx:973
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:52
TextFrameIndex mnLineLength
Definition: porlin.hxx:57
void dumpAsXmlAttributes(xmlTextWriterPtr writer, std::u16string_view rText, TextFrameIndex nOffset) const
Definition: porlin.cxx:330
virtual void FormatEOL(SwTextFormatInfo &rInf)
Definition: porlin.cxx:266
SwLinePortion * mpNextPortion
Definition: porlin.hxx:55
void Truncate_()
Definition: porlin.cxx:152
bool IsMarginPortion() const
Definition: porlin.hxx:133
virtual TextFrameIndex GetModelPositionForViewPoint(sal_uInt16 nOfst) const
the parameter is actually SwTwips apparently?
Definition: porlin.cxx:223
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:75
void SetAscent(const SwTwips nNewAsc)
Definition: porlin.hxx:82
PortionType GetWhichPor() const
Definition: porlin.hxx:102
void SetNextPortion(SwLinePortion *pNew)
Definition: porlin.hxx:79
virtual void Paint(const SwTextPaintInfo &rInf) const =0
SwLinePortion * Cut(SwLinePortion *pVictim)
Definition: porlin.cxx:201
virtual SwLinePortion * Append(SwLinePortion *pPortion)
Definition: porlin.cxx:190
TextFrameIndex GetLen() const
Definition: porlin.hxx:77
void Move(SwTextPaintInfo &rInf)
Definition: porlin.cxx:269
SwLinePortion * FindLastPortion()
Definition: porlin.cxx:179
bool IsKernPortion() const
Definition: porlin.hxx:141
void Truncate()
Definition: porlin.hxx:214
virtual bool GetExpText(const SwTextSizeInfo &rInf, OUString &rText) const
Definition: porlin.cxx:311
virtual ~SwLinePortion()
Definition: porlin.cxx:52
virtual sal_uInt16 GetViewWidth(const SwTextSizeInfo &rInf) const
Definition: porlin.cxx:61
virtual SwLinePortion * Compress()
Definition: porlin.cxx:56
SwTwips & GetAscent()
Definition: porlin.hxx:80
bool InSpaceGrp() const
Definition: porlin.hxx:116
virtual tools::Long CalcSpacing(tools::Long nSpaceAdd, const SwTextSizeInfo &rInf) const
Definition: porlin.cxx:306
void CalcTextSize(const SwTextSizeInfo &rInfo)
Definition: porlin.cxx:139
SwLinePortion * FindPrevPortion(const SwLinePortion *pRoot)
Definition: porlin.cxx:210
virtual void dumpAsXml(xmlTextWriterPtr pWriter, const OUString &rText, TextFrameIndex &rOffset) const
Definition: porlin.cxx:321
virtual void HandlePortion(SwPortionHandler &rPH) const
Definition: porlin.cxx:316
bool IsMultiPortion() const
Definition: porlin.hxx:143
virtual SwPosSize GetTextSize(const SwTextSizeInfo &rInfo) const
Definition: porlin.cxx:231
SwTwips PrtWidth() const
Definition: porlin.hxx:84
virtual bool Format(SwTextFormatInfo &rInf)
Definition: porlin.cxx:238
bool InFixMargGrp() const
Definition: porlin.hxx:115
void PrePaint(const SwTextPaintInfo &rInf, const SwLinePortion *pLast) const
Definition: porlin.cxx:77
virtual SwLinePortion * Insert(SwLinePortion *pPortion)
Definition: porlin.cxx:169
The SwPortionHandler interface implements a visitor for the layout engine's text portions.
virtual void Special(TextFrameIndex nLength, const OUString &rText, PortionType nType)=0
special portion.
SwTwips Width() const
Definition: possiz.hxx:51
SwPosSize(const SwTwips nW=0, const SwTwips nH=0)
Definition: possiz.hxx:30
SwTwips Height() const
Definition: possiz.hxx:49
SwLinePortion * GetLast()
Definition: inftxt.hxx:564
sal_uInt16 Width() const
Definition: inftxt.hxx:531
void SetUnderflow(SwLinePortion *pNew)
Definition: inftxt.hxx:604
SwTwips X() const
Definition: inftxt.hxx:382
void IncSpaceIdx()
Definition: inftxt.hxx:442
tools::Long GetSpaceAdd() const
Definition: inftxt.hxx:444
SwTwips Y() const
Definition: inftxt.hxx:384
SwTextFrame * GetTextFrame()
Definition: inftxt.hxx:288
vcl::RenderContext * GetOut()
Definition: inftxt.hxx:225
sal_uInt8 GetDirection() const
Definition: inftxt.hxx:218
void SetLen(const TextFrameIndex nNew)
Definition: inftxt.hxx:276
SwFont * GetFont()
Definition: inftxt.hxx:232
bool OnWin() const
Definition: inftxt.hxx:193
void SetIdx(const TextFrameIndex nNew)
Definition: inftxt.hxx:274
bool IsRotated() const
Definition: inftxt.hxx:220
void IncKanaIdx()
Definition: inftxt.hxx:325
TextFrameIndex GetLen() const
Definition: inftxt.hxx:275
TextFrameIndex GetIdx() const
Definition: inftxt.hxx:273
int nCount
#define DIR_BOTTOM2TOP
Definition: inftxt.hxx:55
#define DIR_LEFT2RIGHT
Definition: inftxt.hxx:54
#define DIR_RIGHT2LEFT
Definition: inftxt.hxx:56
sal_uInt16 nPos
int i
const char * PortionTypeToString(PortionType nType)
Definition: xmldump.cxx:33
long Long
static bool ChkChain(SwLinePortion *pStart)
Definition: porlin.cxx:28
UNDERLYING_TYPE get() const
tools::Long SwTwips
Definition: swtypes.hxx:51
PortionType
Definition: txttypes.hxx:24