Line data Source code
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 "portxt.hxx"
26 : #include "pormulti.hxx"
27 : #include "porglue.hxx"
28 : #include "blink.hxx"
29 : #if OSL_DEBUG_LEVEL > 0
30 :
31 : bool ChkChain( SwLinePortion *pStart )
32 : {
33 : SwLinePortion *pPor = pStart->GetPortion();
34 : sal_uInt16 nCount = 0;
35 : while( pPor )
36 : {
37 : ++nCount;
38 : OSL_ENSURE( nCount < 200 && pPor != pStart,
39 : "ChkChain(): lost in chains" );
40 : if( nCount >= 200 || pPor == pStart )
41 : {
42 : // der Lebensretter
43 : pPor = pStart->GetPortion();
44 : pStart->SetPortion(0);
45 : pPor->Truncate();
46 : pStart->SetPortion( pPor );
47 : return false;
48 : }
49 : pPor = pPor->GetPortion();
50 : }
51 : return true;
52 : }
53 : #endif
54 :
55 149414 : SwLinePortion::~SwLinePortion()
56 : {
57 149414 : if( pBlink )
58 347 : pBlink->Delete( this );
59 149414 : }
60 :
61 69893 : SwLinePortion *SwLinePortion::Compress()
62 : {
63 69893 : return GetLen() || Width() ? this : 0;
64 : }
65 :
66 4161 : sal_uInt16 SwLinePortion::GetViewWidth( const SwTextSizeInfo & ) const
67 : {
68 4161 : return 0;
69 : }
70 :
71 148844 : SwLinePortion::SwLinePortion( ) :
72 : pPortion( NULL ),
73 : nLineLength( 0 ),
74 : nAscent( 0 ),
75 : nWhichPor( POR_LIN ),
76 : m_bJoinBorderWithPrev(false),
77 148844 : m_bJoinBorderWithNext(false)
78 : {
79 148844 : }
80 :
81 6082 : void SwLinePortion::PrePaint( const SwTextPaintInfo& rInf,
82 : const SwLinePortion* pLast ) const
83 : {
84 : OSL_ENSURE( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
85 : OSL_ENSURE( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");
86 :
87 6082 : const sal_uInt16 nViewWidth = GetViewWidth( rInf );
88 :
89 6082 : if( ! nViewWidth )
90 11446 : return;
91 :
92 718 : const sal_uInt16 nHalfView = nViewWidth / 2;
93 718 : sal_uInt16 nLastWidth = pLast->Width();
94 :
95 718 : if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
96 0 : nLastWidth = nLastWidth + (sal_uInt16)pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf );
97 :
98 : sal_uInt16 nPos;
99 718 : SwTextPaintInfo aInf( rInf );
100 :
101 1436 : const bool bBidiPor = rInf.GetTextFrm()->IsRightToLeft() !=
102 1436 : bool( TEXT_LAYOUT_BIDI_RTL & rInf.GetOut()->GetLayoutMode() );
103 :
104 : sal_uInt16 nDir = bBidiPor ?
105 : 1800 :
106 718 : rInf.GetFont()->GetOrientation( rInf.GetTextFrm()->IsVertical() );
107 :
108 718 : switch ( nDir )
109 : {
110 : case 0 :
111 718 : nPos = sal_uInt16( rInf.X() );
112 718 : if( nLastWidth > nHalfView )
113 578 : nPos += nLastWidth - nHalfView;
114 718 : aInf.X( nPos );
115 718 : break;
116 : case 900 :
117 0 : nPos = sal_uInt16( rInf.Y() );
118 0 : if( nLastWidth > nHalfView )
119 0 : nPos -= nLastWidth + nHalfView;
120 0 : aInf.Y( nPos );
121 0 : break;
122 : case 1800 :
123 0 : nPos = sal_uInt16( rInf.X() );
124 0 : if( nLastWidth > nHalfView )
125 0 : nPos -= nLastWidth + nHalfView;
126 0 : aInf.X( nPos );
127 0 : break;
128 : case 2700 :
129 0 : nPos = sal_uInt16( rInf.Y() );
130 0 : if( nLastWidth > nHalfView )
131 0 : nPos += nLastWidth - nHalfView;
132 0 : aInf.Y( nPos );
133 0 : break;
134 : }
135 :
136 718 : SwLinePortion *pThis = const_cast<SwLinePortion*>(this);
137 718 : pThis->Width( nViewWidth );
138 718 : Paint( aInf );
139 718 : pThis->Width(0);
140 : }
141 :
142 1626 : void SwLinePortion::CalcTextSize( const SwTextSizeInfo &rInf )
143 : {
144 1626 : if( GetLen() == rInf.GetLen() )
145 1626 : *static_cast<SwPosSize*>(this) = GetTextSize( rInf );
146 : else
147 : {
148 0 : SwTextSizeInfo aInf( rInf );
149 0 : aInf.SetLen( GetLen() );
150 0 : *static_cast<SwPosSize*>(this) = GetTextSize( aInf );
151 : }
152 1626 : }
153 :
154 : // Es werden alle nachfolgenden Portions geloescht.
155 26251 : void SwLinePortion::_Truncate()
156 : {
157 26251 : SwLinePortion *pPos = pPortion;
158 81577 : do
159 : { OSL_ENSURE( pPos != this, "SwLinePortion::Truncate: loop" );
160 81577 : SwLinePortion *pLast = pPos;
161 81577 : pPos = pPos->GetPortion();
162 81577 : pLast->SetPortion( 0 );
163 81577 : delete pLast;
164 :
165 : } while( pPos );
166 :
167 26251 : pPortion = 0;
168 26251 : }
169 :
170 : // Es wird immer hinter uns eingefuegt.
171 61165 : SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns )
172 : {
173 61165 : pIns->FindLastPortion()->SetPortion( pPortion );
174 61165 : SetPortion( pIns );
175 : #if OSL_DEBUG_LEVEL > 0
176 : ChkChain( this );
177 : #endif
178 61165 : return pIns;
179 : }
180 :
181 64013 : SwLinePortion *SwLinePortion::FindLastPortion()
182 : {
183 64013 : SwLinePortion *pPos = this;
184 : // An das Ende wandern und pLinPortion an den letzten haengen ...
185 132260 : while( pPos->GetPortion() )
186 : {
187 4234 : pPos = pPos->GetPortion();
188 : }
189 64013 : return pPos;
190 : }
191 :
192 1426 : SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns )
193 : {
194 1426 : SwLinePortion *pPos = FindLastPortion();
195 1426 : pPos->SetPortion( pIns );
196 1426 : pIns->SetPortion( 0 );
197 : #if OSL_DEBUG_LEVEL > 0
198 : ChkChain( this );
199 : #endif
200 1426 : return pIns;
201 : }
202 :
203 8300 : SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim )
204 : {
205 8300 : SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
206 : OSL_ENSURE( pPrev, "SwLinePortion::Cut(): can't cut" );
207 8300 : pPrev->SetPortion( pVictim->GetPortion() );
208 8300 : pVictim->SetPortion(0);
209 8300 : return pVictim;
210 : }
211 :
212 8665 : SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot )
213 : {
214 : OSL_ENSURE( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" );
215 8665 : SwLinePortion *pPos = const_cast<SwLinePortion*>(pRoot);
216 17884 : while( pPos->GetPortion() && pPos->GetPortion() != this )
217 : {
218 554 : pPos = pPos->GetPortion();
219 : }
220 : OSL_ENSURE( pPos->GetPortion(),
221 : "SwLinePortion::FindPrevPortion: blowing in the wind");
222 8665 : return pPos;
223 : }
224 :
225 29 : sal_Int32 SwLinePortion::GetCrsrOfst( const sal_uInt16 nOfst ) const
226 : {
227 29 : if( nOfst > ( PrtWidth() / 2 ) )
228 26 : return GetLen();
229 : else
230 3 : return 0;
231 : }
232 :
233 0 : SwPosSize SwLinePortion::GetTextSize( const SwTextSizeInfo & ) const
234 : {
235 : OSL_ENSURE( false, "SwLinePortion::GetTextSize: don't ask me about sizes, "
236 : "I'm only a stupid SwLinePortion" );
237 0 : return SwPosSize();
238 : }
239 :
240 489 : bool SwLinePortion::Format( SwTextFormatInfo &rInf )
241 : {
242 489 : if( rInf.X() > rInf.Width() )
243 : {
244 0 : Truncate();
245 0 : rInf.SetUnderflow( this );
246 0 : return true;
247 : }
248 :
249 489 : const SwLinePortion *pLast = rInf.GetLast();
250 489 : Height( pLast->Height() );
251 489 : SetAscent( pLast->GetAscent() );
252 489 : const sal_uInt16 nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth());
253 : // Nur Portions mit echter Breite koennen ein true zurueckliefern
254 : // Notizen beispielsweise setzen niemals bFull==true
255 489 : if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
256 : {
257 0 : Truncate();
258 0 : if( nNewWidth > rInf.Width() )
259 0 : PrtWidth( nNewWidth - rInf.Width() );
260 0 : rInf.GetLast()->FormatEOL( rInf );
261 0 : return true;
262 : }
263 489 : return false;
264 : }
265 :
266 : // Format end of line
267 :
268 116 : void SwLinePortion::FormatEOL( SwTextFormatInfo & )
269 116 : { }
270 :
271 261904 : void SwLinePortion::Move( SwTextPaintInfo &rInf )
272 : {
273 261904 : bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
274 261904 : const bool bFrmDir = rInf.GetTextFrm()->IsRightToLeft();
275 261913 : bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
276 262093 : ( bFrmDir && DIR_LEFT2RIGHT == rInf.GetDirection() );
277 :
278 261904 : if ( InSpaceGrp() && rInf.GetSpaceAdd() )
279 : {
280 1224 : SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf );
281 1224 : if( rInf.IsRotated() )
282 0 : rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
283 1224 : else if ( bCounterDir )
284 0 : rInf.X( rInf.X() - nTmp );
285 : else
286 1224 : rInf.X( rInf.X() + nTmp );
287 : }
288 : else
289 : {
290 260680 : if( InFixMargGrp() && !IsMarginPortion() )
291 : {
292 30974 : rInf.IncSpaceIdx();
293 30974 : rInf.IncKanaIdx();
294 : }
295 260680 : if( rInf.IsRotated() )
296 1 : rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
297 260679 : else if ( bCounterDir )
298 9 : rInf.X( rInf.X() - PrtWidth() );
299 : else
300 260670 : rInf.X( rInf.X() + PrtWidth() );
301 : }
302 261904 : if( IsMultiPortion() && static_cast<SwMultiPortion*>(this)->HasTabulator() )
303 0 : rInf.IncSpaceIdx();
304 :
305 261904 : rInf.SetIdx( rInf.GetIdx() + GetLen() );
306 261904 : }
307 :
308 0 : long SwLinePortion::CalcSpacing( long , const SwTextSizeInfo & ) const
309 : {
310 0 : return 0;
311 : }
312 :
313 0 : bool SwLinePortion::GetExpText( const SwTextSizeInfo &, OUString & ) const
314 : {
315 0 : return false;
316 : }
317 :
318 57 : void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const
319 : {
320 57 : rPH.Special( GetLen(), OUString(), GetWhichPor(), Height(), Width() );
321 234 : }
322 :
323 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|