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