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 36 : 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 36 : bVertical( bVert )
45 : {
46 36 : sal_uInt32 nCount(rPolyPolygon.count());
47 36 : mpPolyPolygon = new tools::PolyPolygon( (sal_uInt16)nCount );
48 :
49 72 : for(sal_uInt32 i(0L); i < nCount; i++)
50 : {
51 36 : const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(i).getDefaultAdaptiveSubdivision());
52 36 : nPointCount += aCandidate.count();
53 36 : mpPolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
54 36 : }
55 :
56 36 : if( pLinePolyPolygon )
57 : {
58 18 : nCount = pLinePolyPolygon->count();
59 18 : mpLinePolyPolygon = new tools::PolyPolygon();
60 :
61 18 : for(sal_uInt32 i(0L); i < nCount; i++)
62 : {
63 0 : const basegfx::B2DPolygon aCandidate(pLinePolyPolygon->getB2DPolygon(i).getDefaultAdaptiveSubdivision());
64 0 : nPointCount += aCandidate.count();
65 0 : mpLinePolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
66 0 : }
67 : }
68 : else
69 18 : mpLinePolyPolygon = NULL;
70 36 : }
71 :
72 :
73 72 : TextRanger::~TextRanger()
74 : {
75 36 : mRangeCache.clear();
76 36 : delete mpPolyPolygon;
77 36 : delete mpLinePolyPolygon;
78 36 : delete pBound;
79 36 : }
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 252 : 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 0 : void NoteFarPoint( long nPx, long nPyDiff, long nDiff )
126 0 : { 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 180 : inline long A( const Point& rP ) const { return bRotate ? rP.Y() : rP.X(); }
130 1806 : 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 978 : void NotePoint( const long nA ) { NoteMargin( nA - nStart, nA + nEnd ); }
134 1434 : void NoteMargin( const long nL, const long nR )
135 1434 : { 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 30 : void NoteLast() { if( bMultiple ) NoteRange( nAct == nFirst ); }
142 252 : void SetClosed( const bool bNew ){ bClosed = bNew; }
143 252 : bool IsClosed() const { return bClosed; }
144 198 : void SetConcat( const bool bNew ){ bConcat = bNew; }
145 846 : bool IsConcat() const { return bConcat; }
146 : };
147 :
148 252 : SvxBoundArgs::SvxBoundArgs( TextRanger* pRanger, LongDqPtr pLong,
149 : const Range& rRange )
150 : : pLongArr(pLong)
151 : , pTextRanger(pRanger)
152 : , nMin(0)
153 : , nMax(0)
154 252 : , nTop(rRange.Min())
155 252 : , nBottom(rRange.Max())
156 : , nCut(0)
157 : , nLast(0)
158 : , nNext(0)
159 : , nAct(0)
160 : , nFirst(0)
161 : , bClosed(false)
162 252 : , bInner(pRanger->IsInner())
163 252 : , bMultiple(bInner || !pRanger->IsSimple())
164 : , bConcat(false)
165 1260 : , bRotate(pRanger->IsVertical())
166 : {
167 252 : 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 252 : nStart = pRanger->GetLeft();
177 252 : nEnd = pRanger->GetRight();
178 252 : nLowDiff = pRanger->GetUpper();
179 252 : nUpDiff = pRanger->GetLower();
180 : }
181 252 : nUpper = nTop - nUpDiff;
182 252 : nLower = nBottom + nLowDiff;
183 252 : pLongArr->clear();
184 252 : }
185 :
186 0 : long SvxBoundArgs::CalcMax( const Point& rPt1, const Point& rPt2,
187 : long nRange, long nFarRange )
188 : {
189 0 : double nDa = Cut( nRange, rPt1, rPt2 ) - Cut( nFarRange, rPt1, rPt2 );
190 : double nB;
191 0 : if( nDa < 0 )
192 : {
193 0 : nDa = -nDa;
194 0 : nB = nEnd;
195 : }
196 : else
197 0 : nB = nStart;
198 0 : nB *= nB;
199 0 : nB += nDa * nDa;
200 0 : nB = nRange + nDa * ( nFarRange - nRange ) / sqrt( nB );
201 :
202 : bool bNote;
203 0 : if( nB < B(rPt2) )
204 0 : bNote = nB > B(rPt1);
205 : else
206 0 : bNote = nB < B(rPt1);
207 0 : if( bNote )
208 0 : return( long( nB ) );
209 0 : return 0;
210 : }
211 :
212 858 : void SvxBoundArgs::CheckCut( const Point& rLst, const Point& rNxt )
213 : {
214 858 : if( nCut & 1 )
215 432 : NotePoint( Cut( nBottom, rLst, rNxt ) );
216 858 : if( nCut & 2 )
217 396 : NotePoint( Cut( nTop, rLst, rNxt ) );
218 858 : if( rLst.X() != rNxt.X() && rLst.Y() != rNxt.Y() )
219 : {
220 : long nYps;
221 780 : if( nLowDiff && ( ( nCut & 1 ) || nLast == 1 || nNext == 1 ) )
222 : {
223 0 : nYps = CalcMax( rLst, rNxt, nBottom, nLower );
224 0 : if( nYps )
225 0 : _NoteFarPoint( Cut( nYps, rLst, rNxt ), nLower-nYps, nLowDiff );
226 : }
227 780 : if( nUpDiff && ( ( nCut & 2 ) || nLast == 2 || nNext == 2 ) )
228 : {
229 0 : nYps = CalcMax( rLst, rNxt, nTop, nUpper );
230 0 : if( nYps )
231 0 : _NoteFarPoint( Cut( nYps, rLst, rNxt ), nYps-nUpper, nUpDiff );
232 : }
233 : }
234 858 : }
235 :
236 0 : void SvxBoundArgs::_NoteFarPoint( long nPa, long nPbDiff, long nDiff )
237 : {
238 : long nTmpA;
239 0 : double nQuot = 2 * nDiff - nPbDiff;
240 0 : nQuot *= nPbDiff;
241 0 : nQuot = sqrt( nQuot );
242 0 : nQuot /= nDiff;
243 0 : nTmpA = nPa - long( nStart * nQuot );
244 0 : nPbDiff = nPa + long( nEnd * nQuot );
245 0 : NoteMargin( nTmpA, nPbDiff );
246 0 : }
247 :
248 360 : void SvxBoundArgs::NoteRange( bool bToggle )
249 : {
250 : DBG_ASSERT( nMax >= nMin || bInner, "NoteRange: Min > Max?");
251 360 : if( nMax < nMin )
252 360 : return;
253 360 : if( !bClosed )
254 0 : bToggle = false;
255 360 : sal_uInt16 nIdx = 0;
256 360 : sal_uInt16 nCount = pLongArr->size();
257 : DBG_ASSERT( nCount == 2 * aBoolArr.size(), "NoteRange: Incompatible Sizes" );
258 834 : while( nIdx < nCount && (*pLongArr)[ nIdx ] < nMin )
259 114 : ++nIdx;
260 360 : bool bOdd = (nIdx % 2) ? sal_True : sal_False;
261 : // No overlap with existing intervals?
262 360 : if( nIdx == nCount || ( !bOdd && nMax < (*pLongArr)[ nIdx ] ) )
263 : { // Then a new one is inserted ...
264 312 : pLongArr->insert( pLongArr->begin() + nIdx, nMin );
265 312 : pLongArr->insert( pLongArr->begin() + nIdx + 1, nMax );
266 312 : aBoolArr.insert( aBoolArr.begin() + (nIdx/2), bToggle );
267 : }
268 : else
269 : { // expand an existing interval ...
270 48 : sal_uInt16 nMaxIdx = nIdx;
271 : // If we end up on a left interval boundary, it must be reduced to nMin.
272 48 : if( bOdd )
273 18 : --nIdx;
274 : else
275 30 : (*pLongArr)[ nIdx ] = nMin;
276 156 : while( nMaxIdx < nCount && (*pLongArr)[ nMaxIdx ] < nMax )
277 60 : ++nMaxIdx;
278 : DBG_ASSERT( nMaxIdx > nIdx || nMin == nMax, "NoteRange: Funny Situation." );
279 48 : if( nMaxIdx )
280 48 : --nMaxIdx;
281 48 : if( nMaxIdx < nIdx )
282 0 : nMaxIdx = nIdx;
283 : // If we end up on a right interval boundary, it must be raised to nMax.
284 48 : if( nMaxIdx % 2 )
285 30 : (*pLongArr)[ nMaxIdx-- ] = nMax;
286 : // Possible merge of intervals.
287 48 : sal_uInt16 nDiff = nMaxIdx - nIdx;
288 48 : nMaxIdx = nIdx / 2; // From here on is nMaxIdx the Index in BoolArray.
289 48 : if( nDiff )
290 : {
291 0 : pLongArr->erase( pLongArr->begin() + nIdx + 1, pLongArr->begin() + nIdx + 1 + nDiff );
292 0 : nDiff /= 2;
293 0 : sal_uInt16 nStop = nMaxIdx + nDiff;
294 0 : for( sal_uInt16 i = nMaxIdx; i < nStop; ++i )
295 0 : bToggle ^= aBoolArr[ i ];
296 0 : aBoolArr.erase( aBoolArr.begin() + nMaxIdx, aBoolArr.begin() + (nMaxIdx + nDiff) );
297 : }
298 : DBG_ASSERT( nMaxIdx < aBoolArr.size(), "NoteRange: Too much deleted" );
299 48 : aBoolArr[ nMaxIdx ] = aBoolArr[ nMaxIdx ] != bToggle;
300 : }
301 : }
302 :
303 450 : void SvxBoundArgs::Calc( const tools::PolyPolygon& rPoly )
304 : {
305 : sal_uInt16 nCount;
306 450 : nAct = 0;
307 702 : for( sal_uInt16 i = 0; i < rPoly.Count(); ++i )
308 : {
309 252 : const Polygon& rPol = rPoly[ i ];
310 252 : nCount = rPol.GetSize();
311 252 : if( nCount )
312 : {
313 252 : const Point& rNull = rPol[ 0 ];
314 252 : SetClosed( IsConcat() || ( rNull == rPol[ nCount - 1 ] ) );
315 252 : nLast = Area( rNull );
316 252 : if( nLast & 12 )
317 : {
318 222 : nFirst = 3;
319 222 : if( bMultiple )
320 180 : nAct = 0;
321 : }
322 : else
323 : {
324 : // The first point of the polygon is within the line.
325 30 : if( nLast )
326 : {
327 0 : if( bMultiple || !nAct )
328 : {
329 0 : nMin = USHRT_MAX;
330 0 : nMax = 0;
331 : }
332 0 : if( nLast & 1 )
333 0 : NoteFarPoint( A(rNull), nLower - B(rNull), nLowDiff );
334 : else
335 0 : NoteFarPoint( A(rNull), B(rNull) - nUpper, nUpDiff );
336 : }
337 : else
338 : {
339 30 : if( bMultiple || !nAct )
340 : {
341 30 : nMin = A(rNull);
342 30 : nMax = nMin + nEnd;
343 30 : nMin -= nStart;
344 : }
345 : else
346 0 : NotePoint( A(rNull) );
347 : }
348 30 : nFirst = 0; // leaving the line in which direction?
349 30 : nAct = 3; // we are within the line at the moment.
350 : }
351 252 : if( nCount > 1 )
352 : {
353 252 : sal_uInt16 nIdx = 1;
354 : while( true )
355 : {
356 1554 : const Point& rLast = rPol[ nIdx - 1 ];
357 1554 : if( nIdx == nCount )
358 252 : nIdx = 0;
359 1554 : const Point& rNext = rPol[ nIdx ];
360 1554 : nNext = Area( rNext );
361 1554 : nCut = nNext ^ nLast;
362 1554 : sal_uInt16 nOldAct = nAct;
363 1554 : if( nAct )
364 486 : CheckCut( rLast, rNext );
365 1554 : if( nCut & 4 )
366 : {
367 432 : NoteUpLow( Cut( nLower, rLast, rNext ), 2 );
368 432 : if( nAct && nAct != nOldAct )
369 : {
370 318 : nOldAct = nAct;
371 318 : CheckCut( rLast, rNext );
372 : }
373 : }
374 1554 : if( nCut & 8 )
375 : {
376 396 : NoteUpLow( Cut( nUpper, rLast, rNext ), 1 );
377 396 : if( nAct && nAct != nOldAct )
378 54 : CheckCut( rLast, rNext );
379 : }
380 1554 : if( !nIdx )
381 : {
382 252 : if( !( nNext & 12 ) )
383 30 : NoteLast();
384 252 : break;
385 : }
386 1302 : if( !( nNext & 12 ) )
387 : {
388 150 : if( !nNext )
389 150 : NotePoint( A(rNext) );
390 0 : else if( nNext & 1 )
391 0 : NoteFarPoint( A(rNext), nLower-B(rNext), nLowDiff );
392 : else
393 0 : NoteFarPoint( A(rNext), B(rNext)-nUpper, nUpDiff );
394 : }
395 1302 : nLast = nNext;
396 1302 : if( ++nIdx == nCount && !IsClosed() )
397 : {
398 0 : if( !( nNext & 12 ) )
399 0 : NoteLast();
400 0 : break;
401 : }
402 1302 : }
403 : }
404 252 : if( bMultiple && IsConcat() )
405 : {
406 0 : Add();
407 0 : nAct = 0;
408 : }
409 : }
410 : }
411 450 : if( !bMultiple )
412 : {
413 : DBG_ASSERT( pLongArr->empty(), "I said: Simple!" );
414 54 : if( nAct )
415 : {
416 42 : 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 42 : pLongArr->push_front(nMax);
429 42 : pLongArr->push_front(nMin);
430 : }
431 : }
432 : }
433 396 : else if( !IsConcat() )
434 198 : Add();
435 450 : }
436 :
437 198 : void SvxBoundArgs::Add()
438 : {
439 198 : size_t nCount = aBoolArr.size();
440 198 : if( nCount && ( !bInner || !pTextRanger->IsSimple() ) )
441 : {
442 198 : bool bDelete = aBoolArr.front();
443 198 : if( bInner )
444 0 : bDelete = !bDelete;
445 198 : sal_uInt16 nLongIdx = 1;
446 312 : for( size_t nBoolIdx = 1; nBoolIdx < nCount; ++nBoolIdx )
447 : {
448 114 : if( bDelete )
449 : {
450 114 : sal_uInt16 next = 2;
451 228 : while( nBoolIdx < nCount && !aBoolArr[ nBoolIdx++ ] &&
452 0 : (!bInner || nBoolIdx < nCount ) )
453 0 : next += 2;
454 114 : pLongArr->erase( pLongArr->begin() + nLongIdx, pLongArr->begin() + nLongIdx + next );
455 114 : next /= 2;
456 114 : nBoolIdx = nBoolIdx - next;
457 114 : nCount = nCount - next;
458 114 : aBoolArr.erase( aBoolArr.begin() + nBoolIdx, aBoolArr.begin() + (nBoolIdx + next) );
459 114 : if( nBoolIdx )
460 114 : aBoolArr[ nBoolIdx - 1 ] = false;
461 : #if OSL_DEBUG_LEVEL > 1
462 : else
463 : ++next;
464 : #endif
465 : }
466 114 : bDelete = nBoolIdx < nCount && aBoolArr[ nBoolIdx ];
467 114 : 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 198 : if( !pLongArr->empty() )
474 : {
475 198 : 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 198 : }
490 :
491 198 : void SvxBoundArgs::Concat( const tools::PolyPolygon* pPoly )
492 : {
493 198 : SetConcat( true );
494 : DBG_ASSERT( pPoly, "Nothing to do?" );
495 198 : LongDqPtr pOld = pLongArr;
496 198 : pLongArr = new std::deque<long>();
497 198 : aBoolArr.clear();
498 198 : bInner = false;
499 198 : Calc( *pPoly ); // Note that this updates pLongArr, which is why we swapped it out earlier.
500 198 : sal_uInt16 nCount = pLongArr->size();
501 198 : sal_uInt16 nIdx = 0;
502 198 : sal_uInt16 i = 0;
503 198 : bool bSubtract = pTextRanger->IsInner();
504 396 : while( i < nCount )
505 : {
506 0 : sal_uLong nOldCount = pOld->size();
507 0 : 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 0 : long nLeft = (*pLongArr)[ i++ ];
514 0 : long nRight = (*pLongArr)[ i++ ];
515 0 : sal_uInt16 nLeftPos = nIdx + 1;
516 0 : while( nLeftPos < nOldCount && nLeft > (*pOld)[ nLeftPos ] )
517 0 : nLeftPos += 2;
518 0 : 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 0 : sal_uInt16 nRightPos = nLeftPos - 1;
525 0 : while( nRightPos < nOldCount && nRight >= (*pOld)[ nRightPos ] )
526 0 : nRightPos += 2;
527 0 : 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 0 : else if( bSubtract ) // Subtract, if necessary separate
533 : {
534 : long nOld;
535 0 : if( nLeft > ( nOld = (*pOld)[ nLeftPos - 1 ] ) )
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 >= ( nOld = (*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 0 : if( nLeft < (*pOld)[ nLeftPos - 1 ] )
555 0 : (*pOld)[ nLeftPos - 1 ] = nLeft;
556 0 : if( nRight > (*pOld)[ nRightPos - 1 ] )
557 0 : (*pOld)[ nRightPos - 1 ] = nRight;
558 0 : if( nRightPos - nLeftPos > 1 )
559 0 : pOld->erase( pOld->begin() + nLeftPos, pOld->begin() + nRightPos - 1 );
560 :
561 : }
562 0 : nIdx = nLeftPos - 1;
563 : }
564 198 : delete pLongArr;
565 198 : }
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 1806 : sal_uInt16 SvxBoundArgs::Area( const Point& rPt )
577 : {
578 1806 : long nB = B( rPt );
579 1806 : if( nB >= nBottom )
580 : {
581 924 : if( nB >= nLower )
582 924 : return 5;
583 0 : return 1;
584 : }
585 882 : if( nB <= nTop )
586 : {
587 672 : if( nB <= nUpper )
588 672 : return 10;
589 0 : return 2;
590 : }
591 210 : 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 1656 : long SvxBoundArgs::Cut( long nB, const Point& rPt1, const Point& rPt2 )
602 : {
603 1656 : 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 1656 : double nQuot = nB - rPt1.Y();
611 1656 : nQuot /= ( rPt2.Y() - rPt1.Y() );
612 1656 : nQuot *= ( rPt2.X() - rPt1.X() );
613 1656 : return long( rPt1.X() + nQuot );
614 : }
615 :
616 828 : void SvxBoundArgs::NoteUpLow( long nA, const sal_uInt8 nArea )
617 : {
618 828 : if( nAct )
619 : {
620 456 : NoteMargin( nA, nA );
621 456 : if( bMultiple )
622 : {
623 342 : NoteRange( nArea != nAct );
624 342 : nAct = 0;
625 : }
626 456 : if( !nFirst )
627 30 : nFirst = nArea;
628 : }
629 : else
630 : {
631 372 : nAct = nArea;
632 372 : nMin = nA;
633 372 : nMax = nA;
634 : }
635 828 : }
636 :
637 1062 : 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 6966 : for (std::deque<RangeCache>::iterator it = mRangeCache.begin(); it != mRangeCache.end(); ++it)
642 : {
643 6714 : if (it->range == rRange)
644 810 : return &(it->results);
645 : }
646 : //Calculate a new result
647 252 : RangeCache rngCache(rRange);
648 504 : SvxBoundArgs aArg( this, &(rngCache.results), rRange );
649 252 : aArg.Calc( *mpPolyPolygon );
650 252 : if( mpLinePolyPolygon )
651 198 : aArg.Concat( mpLinePolyPolygon );
652 : //Add new result to the cache
653 252 : mRangeCache.push_back(rngCache);
654 252 : if (mRangeCache.size() > nCacheSize)
655 0 : mRangeCache.pop_front();
656 504 : 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: */
|