android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / text / porlin.cxx
blob4421f107f27ffd30fa0d9d8780ef02d0ab9a9bae
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/outdev.hxx>
21 #include <SwPortionHandler.hxx>
23 #include "porlin.hxx"
24 #include "inftxt.hxx"
25 #include "pormulti.hxx"
26 #if OSL_DEBUG_LEVEL > 0
28 static bool ChkChain( SwLinePortion *pStart )
30 SwLinePortion *pPor = pStart->GetNextPortion();
31 sal_uInt16 nCount = 0;
32 while( pPor )
34 ++nCount;
35 OSL_ENSURE( nCount < 200 && pPor != pStart,
36 "ChkChain(): lost in chains" );
37 if( nCount >= 200 || pPor == pStart )
39 // the lifesaver
40 pPor = pStart->GetNextPortion();
41 pStart->SetNextPortion(nullptr);
42 pPor->Truncate();
43 pStart->SetNextPortion( pPor );
44 return false;
46 pPor = pPor->GetNextPortion();
48 return true;
50 #endif
52 SwLinePortion::~SwLinePortion()
56 SwLinePortion *SwLinePortion::Compress()
58 return GetLen() || Width() ? this : nullptr;
61 sal_uInt16 SwLinePortion::GetViewWidth( const SwTextSizeInfo & ) const
63 return 0;
66 SwLinePortion::SwLinePortion( ) :
67 mpNextPortion( nullptr ),
68 mnLineLength( 0 ),
69 mnAscent( 0 ),
70 mnHangingBaseline( 0 ),
71 mnWhichPor( PortionType::NONE ),
72 m_bJoinBorderWithPrev(false),
73 m_bJoinBorderWithNext(false)
77 void SwLinePortion::PrePaint( const SwTextPaintInfo& rInf,
78 const SwLinePortion* pLast ) const
80 OSL_ENSURE( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
81 OSL_ENSURE( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");
83 const sal_uInt16 nViewWidth = GetViewWidth( rInf );
85 if( ! nViewWidth )
86 return;
88 const sal_uInt16 nHalfView = nViewWidth / 2;
89 sal_uInt16 nLastWidth = pLast->Width();
91 if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
92 nLastWidth = nLastWidth + o3tl::narrowing<sal_uInt16>(pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf ));
94 sal_uInt16 nPos;
95 SwTextPaintInfo aInf( rInf );
97 const bool bBidiPor = rInf.GetTextFrame()->IsRightToLeft() !=
98 bool( vcl::text::ComplexTextLayoutFlags::BiDiRtl & rInf.GetOut()->GetLayoutMode() );
100 Degree10 nDir = bBidiPor ?
101 1800_deg10 :
102 rInf.GetFont()->GetOrientation( rInf.GetTextFrame()->IsVertical() );
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)
108 switch (nDir.get())
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;
133 SwLinePortion *pThis = const_cast<SwLinePortion*>(this);
134 pThis->Width( nViewWidth );
135 Paint( aInf );
136 pThis->Width(0);
139 void SwLinePortion::CalcTextSize( const SwTextSizeInfo &rInf )
141 if( GetLen() == rInf.GetLen() )
142 *static_cast<SwPosSize*>(this) = GetTextSize( rInf );
143 else
145 SwTextSizeInfo aInf( rInf );
146 aInf.SetLen( GetLen() );
147 *static_cast<SwPosSize*>(this) = GetTextSize( aInf );
151 // all following portions will be deleted
152 void SwLinePortion::Truncate_()
154 SwLinePortion *pPos = mpNextPortion;
157 OSL_ENSURE( pPos != this, "SwLinePortion::Truncate: loop" );
158 SwLinePortion *pLast = pPos;
159 pPos = pPos->GetNextPortion();
160 pLast->SetNextPortion( nullptr );
161 delete pLast;
163 } while( pPos );
165 mpNextPortion = nullptr;
168 // It always will be inserted after us.
169 SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns )
171 pIns->FindLastPortion()->SetNextPortion( mpNextPortion );
172 SetNextPortion( pIns );
173 #if OSL_DEBUG_LEVEL > 0
174 ChkChain( this );
175 #endif
176 return pIns;
179 SwLinePortion *SwLinePortion::FindLastPortion()
181 SwLinePortion *pPos = this;
182 // Find the end and link pLinPortion to the last one...
183 while( pPos->GetNextPortion() )
185 pPos = pPos->GetNextPortion();
187 return pPos;
190 SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns )
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;
201 SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim )
203 SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
204 OSL_ENSURE( pPrev, "SwLinePortion::Cut(): can't cut" );
205 // note: if pVictim is a follow then clearing pPrev's m_bHasFollow here is
206 // tricky because it could be that the HookChar inserted a tab portion
207 // between 2 field portions
208 pPrev->SetNextPortion( pVictim->GetNextPortion() );
209 pVictim->SetNextPortion(nullptr);
210 return pVictim;
213 SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot )
215 OSL_ENSURE( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" );
216 SwLinePortion *pPos = const_cast<SwLinePortion*>(pRoot);
217 while( pPos->GetNextPortion() && pPos->GetNextPortion() != this )
219 pPos = pPos->GetNextPortion();
221 OSL_ENSURE( pPos->GetNextPortion(),
222 "SwLinePortion::FindPrevPortion: blowing in the wind");
223 return pPos;
226 TextFrameIndex SwLinePortion::GetModelPositionForViewPoint(const sal_uInt16 nOfst) const
228 if( nOfst > ( PrtWidth() / 2 ) )
229 return GetLen();
230 else
231 return TextFrameIndex(0);
234 SwPosSize SwLinePortion::GetTextSize( const SwTextSizeInfo & ) const
236 OSL_ENSURE( false, "SwLinePortion::GetTextSize: don't ask me about sizes, "
237 "I'm only a stupid SwLinePortion" );
238 return SwPosSize();
241 bool SwLinePortion::Format( SwTextFormatInfo &rInf )
243 if( rInf.X() > rInf.Width() )
245 Truncate();
246 rInf.SetUnderflow( this );
247 return true;
250 const SwLinePortion *pLast = rInf.GetLast();
251 Height( pLast->Height() );
252 SetAscent( pLast->GetAscent() );
253 const sal_uInt16 nNewWidth = o3tl::narrowing<sal_uInt16>(rInf.X() + PrtWidth());
254 // Only portions with true width can return true
255 // Notes for example never set bFull==true
256 if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
258 Truncate();
259 if( nNewWidth > rInf.Width() )
260 PrtWidth( nNewWidth - rInf.Width() );
261 rInf.GetLast()->FormatEOL( rInf );
262 return true;
264 return false;
267 // Format end of line
269 void SwLinePortion::FormatEOL( SwTextFormatInfo & )
272 void SwLinePortion::Move( SwTextPaintInfo &rInf )
274 bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
275 const bool bFrameDir = rInf.GetTextFrame()->IsRightToLeft();
276 bool bCounterDir = ( ! bFrameDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
277 ( bFrameDir && DIR_LEFT2RIGHT == rInf.GetDirection() );
279 if ( InSpaceGrp() && rInf.GetSpaceAdd() )
281 SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf );
282 if( rInf.IsRotated() )
283 rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
284 else if ( bCounterDir )
285 rInf.X( rInf.X() - nTmp );
286 else
287 rInf.X( rInf.X() + nTmp );
289 else
291 if( InFixMargGrp() && !IsMarginPortion() )
293 rInf.IncSpaceIdx();
294 rInf.IncKanaIdx();
296 if( rInf.IsRotated() )
297 rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
298 else if ( bCounterDir )
299 rInf.X( rInf.X() - PrtWidth() );
300 else
301 rInf.X( rInf.X() + PrtWidth() );
303 if( IsMultiPortion() && static_cast<SwMultiPortion*>(this)->HasTabulator() )
304 rInf.IncSpaceIdx();
306 rInf.SetIdx( rInf.GetIdx() + GetLen() );
309 tools::Long SwLinePortion::CalcSpacing( tools::Long , const SwTextSizeInfo & ) const
311 return 0;
314 bool SwLinePortion::GetExpText( const SwTextSizeInfo &, OUString & ) const
316 return false;
319 void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const
321 rPH.Special( GetLen(), OUString(), GetWhichPor() );
324 void SwLinePortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex& nOffset) const
326 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwLinePortion"));
327 dumpAsXmlAttributes(pWriter, rText, nOffset);
328 nOffset += GetLen();
330 (void)xmlTextWriterEndElement(pWriter);
333 void SwLinePortion::dumpAsXmlAttributes(xmlTextWriterPtr pWriter, std::u16string_view rText, TextFrameIndex nOffset) const
335 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
336 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("symbol"), BAD_CAST(typeid(*this).name()));
337 (void)xmlTextWriterWriteAttribute(
338 pWriter, BAD_CAST("width"),
339 BAD_CAST(OString::number(Width()).getStr()));
340 (void)xmlTextWriterWriteAttribute(
341 pWriter, BAD_CAST("height"),
342 BAD_CAST(OString::number(Height()).getStr()));
343 (void)xmlTextWriterWriteAttribute(
344 pWriter, BAD_CAST("length"),
345 BAD_CAST(OString::number(static_cast<sal_Int32>(mnLineLength)).getStr()));
346 (void)xmlTextWriterWriteAttribute(
347 pWriter, BAD_CAST("type"),
348 BAD_CAST(sw::PortionTypeToString(GetWhichPor())));
349 OUString aText( rText.substr(sal_Int32(nOffset), sal_Int32(GetLen())) );
350 for (int i = 0; i < 32; ++i)
351 aText = aText.replace(i, '*');
352 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("portion"),
353 BAD_CAST(aText.toUtf8().getStr()));
356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */