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 :
21 : #include <editeng/txtrange.hxx>
22 : #include <math.h>
23 : #include <tools/poly.hxx>
24 : #include <tools/debug.hxx>
25 : #include <basegfx/polygon/b2dpolygon.hxx>
26 : #include <basegfx/polygon/b2dpolygontools.hxx>
27 :
28 : #include <vector>
29 :
30 5 : TextRanger::TextRanger( const basegfx::B2DPolyPolygon& rPolyPolygon,
31 : const basegfx::B2DPolyPolygon* pLinePolyPolygon,
32 : sal_uInt16 nCacheSz, sal_uInt16 nLft, sal_uInt16 nRght,
33 : sal_Bool bSimpl, sal_Bool bInnr, sal_Bool bVert ) :
34 : pBound( NULL ),
35 : nCacheSize( nCacheSz ),
36 : nRight( nRght ),
37 : nLeft( nLft ),
38 : nUpper( 0 ),
39 : nLower( 0 ),
40 : nPointCount( 0 ),
41 : bSimple( bSimpl ),
42 : bInner( bInnr ),
43 5 : bVertical( bVert )
44 : {
45 : #ifdef DBG_UTIL
46 : bFlag3 = bFlag4 = bFlag5 = bFlag6 = bFlag7 = sal_False;
47 : #endif
48 5 : sal_uInt32 nCount(rPolyPolygon.count());
49 5 : mpPolyPolygon = new PolyPolygon( (sal_uInt16)nCount );
50 :
51 10 : for(sal_uInt32 i(0L); i < nCount; i++)
52 : {
53 5 : const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(i).getDefaultAdaptiveSubdivision());
54 5 : nPointCount += aCandidate.count();
55 5 : mpPolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
56 5 : }
57 :
58 5 : if( pLinePolyPolygon )
59 : {
60 0 : nCount = pLinePolyPolygon->count();
61 0 : mpLinePolyPolygon = new PolyPolygon();
62 :
63 0 : for(sal_uInt32 i(0L); i < nCount; i++)
64 : {
65 0 : const basegfx::B2DPolygon aCandidate(pLinePolyPolygon->getB2DPolygon(i).getDefaultAdaptiveSubdivision());
66 0 : nPointCount += aCandidate.count();
67 0 : mpLinePolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
68 0 : }
69 : }
70 : else
71 5 : mpLinePolyPolygon = NULL;
72 5 : }
73 :
74 :
75 10 : TextRanger::~TextRanger()
76 : {
77 5 : mRangeCache.clear();
78 5 : delete mpPolyPolygon;
79 5 : delete mpLinePolyPolygon;
80 5 : delete pBound;
81 5 : }
82 :
83 : /* TextRanger::SetVertical(..)
84 : If there's is a change in the writing direction,
85 : the cache has to be cleared.
86 : */
87 0 : void TextRanger::SetVertical( sal_Bool bNew )
88 : {
89 0 : if( IsVertical() != bNew )
90 : {
91 0 : bVertical = bNew;
92 0 : mRangeCache.clear();
93 : }
94 0 : }
95 :
96 : //! SvxBoundArgs is used to perform temporary calculations on a range array.
97 : //! Temporary instances are created in TextRanger::GetTextRanges()
98 5 : class SvxBoundArgs
99 : {
100 : std::vector<bool> aBoolArr;
101 : LongDqPtr pLongArr;
102 : TextRanger *pTextRanger;
103 : long nMin;
104 : long nMax;
105 : long nTop;
106 : long nBottom;
107 : long nUpDiff;
108 : long nLowDiff;
109 : long nUpper;
110 : long nLower;
111 : long nStart;
112 : long nEnd;
113 : sal_uInt16 nCut;
114 : sal_uInt16 nLast;
115 : sal_uInt16 nNext;
116 : sal_uInt8 nAct;
117 : sal_uInt8 nFirst;
118 : sal_Bool bClosed : 1;
119 : sal_Bool bInner : 1;
120 : sal_Bool bMultiple : 1;
121 : sal_Bool bConcat : 1;
122 : sal_Bool bRotate : 1;
123 : void NoteRange( bool bToggle );
124 : long Cut( long nY, const Point& rPt1, const Point& rPt2 );
125 : void Add();
126 : void _NoteFarPoint( long nPx, long nPyDiff, long nDiff );
127 0 : void NoteFarPoint( long nPx, long nPyDiff, long nDiff )
128 0 : { if( nDiff ) _NoteFarPoint( nPx, nPyDiff, nDiff ); }
129 : long CalcMax( const Point& rPt1, const Point& rPt2, long nRange, long nFar );
130 : void CheckCut( const Point& rLst, const Point& rNxt );
131 0 : inline long A( const Point& rP ) const { return bRotate ? rP.Y() : rP.X(); }
132 30 : inline long B( const Point& rP ) const { return bRotate ? rP.X() : rP.Y(); }
133 : public:
134 : SvxBoundArgs( TextRanger* pRanger, LongDqPtr pLong, const Range& rRange );
135 20 : void NotePoint( const long nA ) { NoteMargin( nA - nStart, nA + nEnd ); }
136 35 : void NoteMargin( const long nL, const long nR )
137 35 : { if( nMin > nL ) nMin = nL; if( nMax < nR ) nMax = nR; }
138 : sal_uInt16 Area( const Point& rPt );
139 : void NoteUpLow( long nA, const sal_uInt8 nArea );
140 : void Calc( const PolyPolygon& rPoly );
141 : void Concat( const PolyPolygon* pPoly );
142 : // inlines
143 0 : void NoteLast() { if( bMultiple ) NoteRange( nAct == nFirst ); }
144 5 : void SetClosed( const sal_Bool bNew ){ bClosed = bNew; }
145 5 : sal_Bool IsClosed() const { return bClosed; }
146 0 : void SetConcat( const sal_Bool bNew ){ bConcat = bNew; }
147 5 : sal_Bool IsConcat() const { return bConcat; }
148 : sal_uInt8 GetAct() const { return nAct; }
149 : };
150 :
151 5 : SvxBoundArgs::SvxBoundArgs( TextRanger* pRanger, LongDqPtr pLong,
152 : const Range& rRange )
153 : : pLongArr( pLong ), pTextRanger( pRanger ),
154 10 : nTop( rRange.Min() ), nBottom( rRange.Max() ),
155 10 : bInner( pRanger->IsInner() ), bMultiple( bInner || !pRanger->IsSimple() ),
156 25 : bConcat( sal_False ), bRotate( pRanger->IsVertical() )
157 : {
158 5 : if( bRotate )
159 : {
160 0 : nStart = pRanger->GetUpper();
161 0 : nEnd = pRanger->GetLower();
162 0 : nLowDiff = pRanger->GetLeft();
163 0 : nUpDiff = pRanger->GetRight();
164 : }
165 : else
166 : {
167 5 : nStart = pRanger->GetLeft();
168 5 : nEnd = pRanger->GetRight();
169 5 : nLowDiff = pRanger->GetUpper();
170 5 : nUpDiff = pRanger->GetLower();
171 : }
172 5 : nUpper = nTop - nUpDiff;
173 5 : nLower = nBottom + nLowDiff;
174 5 : pLongArr->clear();
175 5 : }
176 :
177 0 : long SvxBoundArgs::CalcMax( const Point& rPt1, const Point& rPt2,
178 : long nRange, long nFarRange )
179 : {
180 0 : double nDa = Cut( nRange, rPt1, rPt2 ) - Cut( nFarRange, rPt1, rPt2 );
181 : double nB;
182 0 : if( nDa < 0 )
183 : {
184 0 : nDa = -nDa;
185 0 : nB = nEnd;
186 : }
187 : else
188 0 : nB = nStart;
189 0 : nB *= nB;
190 0 : nB += nDa * nDa;
191 0 : nB = nRange + nDa * ( nFarRange - nRange ) / sqrt( nB );
192 :
193 : sal_Bool bNote;
194 0 : if( nB < B(rPt2) )
195 0 : bNote = nB > B(rPt1);
196 : else
197 0 : bNote = nB < B(rPt1);
198 0 : if( bNote )
199 0 : return( long( nB ) );
200 0 : return 0;
201 : }
202 :
203 20 : void SvxBoundArgs::CheckCut( const Point& rLst, const Point& rNxt )
204 : {
205 20 : if( nCut & 1 )
206 10 : NotePoint( Cut( nBottom, rLst, rNxt ) );
207 20 : if( nCut & 2 )
208 10 : NotePoint( Cut( nTop, rLst, rNxt ) );
209 20 : if( rLst.X() != rNxt.X() && rLst.Y() != rNxt.Y() )
210 : {
211 : long nYps;
212 0 : if( nLowDiff && ( ( nCut & 1 ) || nLast == 1 || nNext == 1 ) )
213 : {
214 0 : nYps = CalcMax( rLst, rNxt, nBottom, nLower );
215 0 : if( nYps )
216 0 : _NoteFarPoint( Cut( nYps, rLst, rNxt ), nLower-nYps, nLowDiff );
217 : }
218 0 : if( nUpDiff && ( ( nCut & 2 ) || nLast == 2 || nNext == 2 ) )
219 : {
220 0 : nYps = CalcMax( rLst, rNxt, nTop, nUpper );
221 0 : if( nYps )
222 0 : _NoteFarPoint( Cut( nYps, rLst, rNxt ), nYps-nUpper, nUpDiff );
223 : }
224 : }
225 20 : }
226 :
227 0 : void SvxBoundArgs::_NoteFarPoint( long nPa, long nPbDiff, long nDiff )
228 : {
229 : long nTmpA;
230 0 : double nQuot = 2 * nDiff - nPbDiff;
231 0 : nQuot *= nPbDiff;
232 0 : nQuot = sqrt( nQuot );
233 0 : nQuot /= nDiff;
234 0 : nTmpA = nPa - long( nStart * nQuot );
235 0 : nPbDiff = nPa + long( nEnd * nQuot );
236 0 : NoteMargin( nTmpA, nPbDiff );
237 0 : }
238 :
239 0 : void SvxBoundArgs::NoteRange( bool bToggle )
240 : {
241 : DBG_ASSERT( nMax >= nMin || bInner, "NoteRange: Min > Max?");
242 0 : if( nMax < nMin )
243 0 : return;
244 0 : if( !bClosed )
245 0 : bToggle = sal_False;
246 0 : sal_uInt16 nIdx = 0;
247 0 : sal_uInt16 nCount = pLongArr->size();
248 : DBG_ASSERT( nCount == 2 * aBoolArr.size(), "NoteRange: Incompatible Sizes" );
249 0 : while( nIdx < nCount && (*pLongArr)[ nIdx ] < nMin )
250 0 : ++nIdx;
251 0 : sal_Bool bOdd = (nIdx % 2) ? sal_True : sal_False;
252 : // No overlap with existing intervals?
253 0 : if( nIdx == nCount || ( !bOdd && nMax < (*pLongArr)[ nIdx ] ) )
254 : { // Then a new one is inserted ...
255 0 : pLongArr->insert( pLongArr->begin() + nIdx, nMin );
256 0 : pLongArr->insert( pLongArr->begin() + nIdx + 1, nMax );
257 0 : aBoolArr.insert( aBoolArr.begin() + (nIdx/2), bToggle );
258 : }
259 : else
260 : { // expand an existing interval ...
261 0 : sal_uInt16 nMaxIdx = nIdx;
262 : // If we end up on a left interval boundary, it must be reduced to nMin.
263 0 : if( bOdd )
264 0 : --nIdx;
265 : else
266 0 : (*pLongArr)[ nIdx ] = nMin;
267 0 : while( nMaxIdx < nCount && (*pLongArr)[ nMaxIdx ] < nMax )
268 0 : ++nMaxIdx;
269 : DBG_ASSERT( nMaxIdx > nIdx || nMin == nMax, "NoteRange: Funny Situation." );
270 0 : if( nMaxIdx )
271 0 : --nMaxIdx;
272 0 : if( nMaxIdx < nIdx )
273 0 : nMaxIdx = nIdx;
274 : // If we end up on a right interval boundary, it must be raised to nMax.
275 0 : if( nMaxIdx % 2 )
276 0 : (*pLongArr)[ nMaxIdx-- ] = nMax;
277 : // Possible merge of intervals.
278 0 : sal_uInt16 nDiff = nMaxIdx - nIdx;
279 0 : nMaxIdx = nIdx / 2; // From here on is nMaxIdx the Index in BoolArray.
280 0 : if( nDiff )
281 : {
282 0 : pLongArr->erase( pLongArr->begin() + nIdx + 1, pLongArr->begin() + nIdx + 1 + nDiff );
283 0 : nDiff /= 2;
284 0 : sal_uInt16 nStop = nMaxIdx + nDiff;
285 0 : for( sal_uInt16 i = nMaxIdx; i < nStop; ++i )
286 0 : bToggle ^= aBoolArr[ i ];
287 0 : aBoolArr.erase( aBoolArr.begin() + nMaxIdx, aBoolArr.begin() + (nMaxIdx + nDiff) );
288 : }
289 : DBG_ASSERT( nMaxIdx < aBoolArr.size(), "NoteRange: Too much deleted" );
290 0 : aBoolArr[ nMaxIdx ] = aBoolArr[ nMaxIdx ] ^ bToggle;
291 : }
292 : }
293 :
294 5 : void SvxBoundArgs::Calc( const PolyPolygon& rPoly )
295 : {
296 : sal_uInt16 nCount;
297 5 : nAct = 0;
298 10 : for( sal_uInt16 i = 0; i < rPoly.Count(); ++i )
299 : {
300 5 : const Polygon& rPol = rPoly[ i ];
301 5 : nCount = rPol.GetSize();
302 5 : if( nCount )
303 : {
304 5 : const Point& rNull = rPol[ 0 ];
305 5 : SetClosed( IsConcat() || ( rNull == rPol[ nCount - 1 ] ) );
306 5 : nLast = Area( rNull );
307 5 : if( nLast & 12 )
308 : {
309 5 : nFirst = 3;
310 5 : if( bMultiple )
311 0 : nAct = 0;
312 : }
313 : else
314 : {
315 : // The first point of the polygon is within the line.
316 0 : if( nLast )
317 : {
318 0 : if( bMultiple || !nAct )
319 : {
320 0 : nMin = USHRT_MAX;
321 0 : nMax = 0;
322 : }
323 0 : if( nLast & 1 )
324 0 : NoteFarPoint( A(rNull), nLower - B(rNull), nLowDiff );
325 : else
326 0 : NoteFarPoint( A(rNull), B(rNull) - nUpper, nUpDiff );
327 : }
328 : else
329 : {
330 0 : if( bMultiple || !nAct )
331 : {
332 0 : nMin = A(rNull);
333 0 : nMax = nMin + nEnd;
334 0 : nMin -= nStart;
335 : }
336 : else
337 0 : NotePoint( A(rNull) );
338 : }
339 0 : nFirst = 0; // leaving the line in which direction?
340 0 : nAct = 3; // we are within the line at the moment.
341 : }
342 5 : if( nCount > 1 )
343 : {
344 5 : sal_uInt16 nIdx = 1;
345 : while( true )
346 : {
347 25 : const Point& rLast = rPol[ nIdx - 1 ];
348 25 : if( nIdx == nCount )
349 5 : nIdx = 0;
350 25 : const Point& rNext = rPol[ nIdx ];
351 25 : nNext = Area( rNext );
352 25 : nCut = nNext ^ nLast;
353 25 : sal_uInt16 nOldAct = nAct;
354 25 : if( nAct )
355 15 : CheckCut( rLast, rNext );
356 25 : if( nCut & 4 )
357 : {
358 10 : NoteUpLow( Cut( nLower, rLast, rNext ), 2 );
359 10 : if( nAct && nAct != nOldAct )
360 : {
361 5 : nOldAct = nAct;
362 5 : CheckCut( rLast, rNext );
363 : }
364 : }
365 25 : if( nCut & 8 )
366 : {
367 10 : NoteUpLow( Cut( nUpper, rLast, rNext ), 1 );
368 10 : if( nAct && nAct != nOldAct )
369 0 : CheckCut( rLast, rNext );
370 : }
371 25 : if( !nIdx )
372 : {
373 5 : if( !( nNext & 12 ) )
374 0 : NoteLast();
375 5 : break;
376 : }
377 20 : if( !( nNext & 12 ) )
378 : {
379 0 : if( !nNext )
380 0 : NotePoint( A(rNext) );
381 0 : else if( nNext & 1 )
382 0 : NoteFarPoint( A(rNext), nLower-B(rNext), nLowDiff );
383 : else
384 0 : NoteFarPoint( A(rNext), B(rNext)-nUpper, nUpDiff );
385 : }
386 20 : nLast = nNext;
387 20 : if( ++nIdx == nCount && !IsClosed() )
388 : {
389 0 : if( !( nNext & 12 ) )
390 0 : NoteLast();
391 0 : break;
392 : }
393 20 : }
394 : }
395 5 : if( bMultiple && IsConcat() )
396 : {
397 0 : Add();
398 0 : nAct = 0;
399 : }
400 : }
401 : }
402 5 : if( !bMultiple )
403 : {
404 : DBG_ASSERT( pLongArr->empty(), "I said: Simple!" );
405 5 : if( nAct )
406 : {
407 5 : if( bInner )
408 : {
409 0 : long nTmpMin = nMin + 2 * nStart;
410 0 : long nTmpMax = nMax - 2 * nEnd;
411 0 : if( nTmpMin <= nTmpMax )
412 : {
413 0 : pLongArr->push_front(nTmpMax);
414 0 : pLongArr->push_front(nTmpMin);
415 : }
416 : }
417 : else
418 : {
419 5 : pLongArr->push_front(nMax);
420 5 : pLongArr->push_front(nMin);
421 : }
422 : }
423 : }
424 0 : else if( !IsConcat() )
425 0 : Add();
426 5 : }
427 :
428 0 : void SvxBoundArgs::Add()
429 : {
430 0 : size_t nCount = aBoolArr.size();
431 0 : if( nCount && ( !bInner || !pTextRanger->IsSimple() ) )
432 : {
433 0 : sal_Bool bDelete = aBoolArr.front();
434 0 : if( bInner )
435 0 : bDelete = !bDelete;
436 0 : sal_uInt16 nLongIdx = 1;
437 0 : for( size_t nBoolIdx = 1; nBoolIdx < nCount; ++nBoolIdx )
438 : {
439 0 : if( bDelete )
440 : {
441 0 : sal_uInt16 next = 2;
442 0 : while( nBoolIdx < nCount && !aBoolArr[ nBoolIdx++ ] &&
443 0 : (!bInner || nBoolIdx < nCount ) )
444 0 : next += 2;
445 0 : pLongArr->erase( pLongArr->begin() + nLongIdx, pLongArr->begin() + nLongIdx + next );
446 0 : next /= 2;
447 0 : nBoolIdx = nBoolIdx - next;
448 0 : nCount = nCount - next;
449 0 : aBoolArr.erase( aBoolArr.begin() + nBoolIdx, aBoolArr.begin() + (nBoolIdx + next) );
450 0 : if( nBoolIdx )
451 0 : aBoolArr[ nBoolIdx - 1 ] = sal_False;
452 : #if OSL_DEBUG_LEVEL > 1
453 : else
454 : ++next;
455 : #endif
456 : }
457 0 : bDelete = nBoolIdx < nCount && aBoolArr[ nBoolIdx ];
458 0 : nLongIdx += 2;
459 : DBG_ASSERT( nLongIdx == 2*nBoolIdx+1, "BoundArgs: Array-Idx Confusion" );
460 : DBG_ASSERT( aBoolArr.size()*2 == pLongArr->size(),
461 : "BoundArgs: Array-Count: Confusion" );
462 : }
463 : }
464 0 : if( !pLongArr->empty() )
465 : {
466 0 : if( bInner )
467 : {
468 0 : pLongArr->pop_front();
469 0 : pLongArr->pop_back();
470 :
471 : // Here the line is held inside a large rectangle for "simple"
472 : // contour wrap. Currently (April 1999) the EditEngine evaluates
473 : // only the first rectangle. If it one day is able to output a line
474 : // in several parts, it may be advisable to delete the following lines.
475 0 : if( pTextRanger->IsSimple() && pLongArr->size() > 2 )
476 0 : pLongArr->erase( pLongArr->begin() + 1, pLongArr->end() - 1 );
477 :
478 : }
479 : }
480 0 : }
481 :
482 0 : void SvxBoundArgs::Concat( const PolyPolygon* pPoly )
483 : {
484 0 : SetConcat( sal_True );
485 : DBG_ASSERT( pPoly, "Nothing to do?" );
486 0 : LongDqPtr pOld = pLongArr;
487 0 : pLongArr = new std::deque<long>();
488 0 : aBoolArr.clear();
489 0 : bInner = sal_False;
490 0 : Calc( *pPoly ); // Note that this updates pLongArr, which is why we swapped it out earlier.
491 0 : sal_uInt16 nCount = pLongArr->size();
492 0 : sal_uInt16 nIdx = 0;
493 0 : sal_uInt16 i = 0;
494 0 : sal_Bool bSubtract = pTextRanger->IsInner();
495 0 : while( i < nCount )
496 : {
497 0 : sal_uLong nOldCount = pOld->size();
498 0 : if( nIdx == nOldCount )
499 : { // Reached the end of the old Array...
500 0 : if( !bSubtract )
501 0 : pOld->insert( pOld->begin() + nIdx, pLongArr->begin() + i, pLongArr->end() );
502 0 : break;
503 : }
504 0 : long nLeft = (*pLongArr)[ i++ ];
505 0 : long nRight = (*pLongArr)[ i++ ];
506 0 : sal_uInt16 nLeftPos = nIdx + 1;
507 0 : while( nLeftPos < nOldCount && nLeft > (*pOld)[ nLeftPos ] )
508 0 : nLeftPos += 2;
509 0 : if( nLeftPos >= nOldCount )
510 : { // The current interval belongs to the end of the old array ...
511 0 : if( !bSubtract )
512 0 : pOld->insert( pOld->begin() + nOldCount, pLongArr->begin() + i - 2, pLongArr->end() );
513 0 : break;
514 : }
515 0 : sal_uInt16 nRightPos = nLeftPos - 1;
516 0 : while( nRightPos < nOldCount && nRight >= (*pOld)[ nRightPos ] )
517 0 : nRightPos += 2;
518 0 : if( nRightPos < nLeftPos )
519 : { // The current interval belongs between two old intervals
520 0 : if( !bSubtract )
521 0 : pOld->insert( pOld->begin() + nRightPos, pLongArr->begin() + i - 2, pLongArr->begin() + i );
522 0 : nIdx = nRightPos + 2;
523 : }
524 0 : else if( bSubtract ) // Subtract, if necessary separate
525 : {
526 : long nOld;
527 0 : if( nLeft > ( nOld = (*pOld)[ nLeftPos - 1 ] ) )
528 : { // Now we split the left part...
529 0 : if( nLeft - 1 > nOld )
530 : {
531 0 : pOld->insert( pOld->begin() + nLeftPos - 1, nOld );
532 0 : pOld->insert( pOld->begin() + nLeftPos, nLeft - 1 );
533 0 : nLeftPos += 2;
534 0 : nRightPos += 2;
535 : }
536 : }
537 0 : if( nRightPos - nLeftPos > 1 )
538 0 : pOld->erase( pOld->begin() + nLeftPos, pOld->begin() + nRightPos - 1 );
539 0 : if( ++nRight >= ( nOld = (*pOld)[ nLeftPos ] ) )
540 0 : pOld->erase( pOld->begin() + nLeftPos - 1, pOld->begin() + nLeftPos + 1 );
541 : else
542 0 : (*pOld)[ nLeftPos - 1 ] = nRight;
543 : }
544 : else // Merge
545 : {
546 0 : if( nLeft < (*pOld)[ nLeftPos - 1 ] )
547 0 : (*pOld)[ nLeftPos - 1 ] = nLeft;
548 0 : if( nRight > (*pOld)[ nRightPos - 1 ] )
549 0 : (*pOld)[ nRightPos - 1 ] = nRight;
550 0 : if( nRightPos - nLeftPos > 1 )
551 0 : pOld->erase( pOld->begin() + nLeftPos, pOld->begin() + nRightPos - 1 );
552 :
553 : }
554 0 : nIdx = nLeftPos - 1;
555 : }
556 0 : delete pLongArr;
557 0 : }
558 :
559 : /*************************************************************************
560 : * SvxBoundArgs::Area returns the area in which the point is located.
561 : * 0 = within the line
562 : * 1 = below, but within the upper edge
563 : * 2 = above, but within the lower edge
564 : * 5 = below the upper edge
565 : *10 = above the lower edge
566 : *************************************************************************/
567 :
568 30 : sal_uInt16 SvxBoundArgs::Area( const Point& rPt )
569 : {
570 30 : long nB = B( rPt );
571 30 : if( nB >= nBottom )
572 : {
573 10 : if( nB >= nLower )
574 10 : return 5;
575 0 : return 1;
576 : }
577 20 : if( nB <= nTop )
578 : {
579 20 : if( nB <= nUpper )
580 20 : return 10;
581 0 : return 2;
582 : }
583 0 : return 0;
584 : }
585 :
586 : /*************************************************************************
587 : * lcl_Cut calculates the X-Coordinate of the distance (Pt1-Pt2) at the
588 : * Y-Coordinate nY.
589 : * It is assumed that the one of the points are located above and the other
590 : * one below the Y-Coordinate.
591 : *************************************************************************/
592 :
593 40 : long SvxBoundArgs::Cut( long nB, const Point& rPt1, const Point& rPt2 )
594 : {
595 40 : if( pTextRanger->IsVertical() )
596 : {
597 0 : double nQuot = nB - rPt1.X();
598 0 : nQuot /= ( rPt2.X() - rPt1.X() );
599 0 : nQuot *= ( rPt2.Y() - rPt1.Y() );
600 0 : return long( rPt1.Y() + nQuot );
601 : }
602 40 : double nQuot = nB - rPt1.Y();
603 40 : nQuot /= ( rPt2.Y() - rPt1.Y() );
604 40 : nQuot *= ( rPt2.X() - rPt1.X() );
605 40 : return long( rPt1.X() + nQuot );
606 : }
607 :
608 20 : void SvxBoundArgs::NoteUpLow( long nA, const sal_uInt8 nArea )
609 : {
610 20 : if( nAct )
611 : {
612 15 : NoteMargin( nA, nA );
613 15 : if( bMultiple )
614 : {
615 0 : NoteRange( nArea != nAct );
616 0 : nAct = 0;
617 : }
618 15 : if( !nFirst )
619 0 : nFirst = nArea;
620 : }
621 : else
622 : {
623 5 : nAct = nArea;
624 5 : nMin = nA;
625 5 : nMax = nA;
626 : }
627 20 : }
628 :
629 15 : LongDqPtr TextRanger::GetTextRanges( const Range& rRange )
630 : {
631 : DBG_ASSERT( rRange.Min() || rRange.Max(), "Zero-Range not allowed, Bye Bye" );
632 : //Can we find the result we need in the cache?
633 15 : for (std::deque<RangeCache>::iterator it = mRangeCache.begin(); it != mRangeCache.end(); ++it)
634 : {
635 10 : if (it->range == rRange)
636 10 : return &(it->results);
637 : }
638 : //Calculate a new result
639 5 : RangeCache rngCache(rRange);
640 10 : SvxBoundArgs aArg( this, &(rngCache.results), rRange );
641 5 : aArg.Calc( *mpPolyPolygon );
642 5 : if( mpLinePolyPolygon )
643 0 : aArg.Concat( mpLinePolyPolygon );
644 : //Add new result to the cache
645 5 : mRangeCache.push_back(rngCache);
646 5 : if (mRangeCache.size() > nCacheSize)
647 0 : mRangeCache.pop_front();
648 10 : return &(mRangeCache.back().results);
649 : }
650 :
651 0 : const Rectangle& TextRanger::_GetBoundRect()
652 : {
653 : DBG_ASSERT( 0 == pBound, "Don't call twice." );
654 0 : pBound = new Rectangle( mpPolyPolygon->GetBoundRect() );
655 0 : return *pBound;
656 : }
657 :
658 :
659 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|