xref: /AOO41X/main/editeng/source/misc/txtrange.cxx (revision 91e36512b89cf5189557d88d061b3b7d17820077)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_editeng.hxx"
26 
27 #include <editeng/txtrange.hxx>
28 #include <math.h>
29 #include <tools/poly.hxx>
30 #include <tools/debug.hxx>
31 #include <basegfx/polygon/b2dpolygon.hxx>
32 #include <basegfx/polygon/b2dpolygontools.hxx>
33 
34 /*************************************************************************
35 |*
36 |*    TextRanger::TextRanger()
37 |*
38 |*    Beschreibung
39 |*    Ersterstellung    20.01.97
40 |*    Letzte Aenderung  20.01.97 AMA
41 |*
42 *************************************************************************/
43 
TextRanger(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::B2DPolyPolygon * pLinePolyPolygon,sal_uInt16 nCacheSz,sal_uInt16 nLft,sal_uInt16 nRght,sal_Bool bSimpl,sal_Bool bInnr,sal_Bool bVert)44 TextRanger::TextRanger( const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DPolyPolygon* pLinePolyPolygon,
45     sal_uInt16 nCacheSz, sal_uInt16 nLft, sal_uInt16 nRght, sal_Bool bSimpl, sal_Bool bInnr,
46     sal_Bool bVert ) :
47     pBound( NULL ),
48     nCacheSize( nCacheSz ),
49     nCacheIdx( 0 ),
50     nRight( nRght ),
51     nLeft( nLft ),
52     nUpper( 0 ),
53     nLower( 0 ),
54     nPointCount( 0 ),
55     bSimple( bSimpl ),
56     bInner( bInnr ),
57     bVertical( bVert )
58 {
59 #ifdef DBG_UTIL
60     bFlag3 = bFlag4 = bFlag5 = bFlag6 = bFlag7 = sal_False;
61 #endif
62     pRangeArr = new Range[ nCacheSize ];
63     pCache = new SvLongsPtr[ nCacheSize ];
64     memset( pRangeArr, 0, nCacheSize * sizeof( Range ) );
65     memset( pCache, 0, nCacheSize * sizeof( SvLongsPtr ) );
66     sal_uInt32 nCount(rPolyPolygon.count());
67     mpPolyPolygon = new PolyPolygon( (sal_uInt16)nCount );
68 
69     for(sal_uInt32 i(0L); i < nCount; i++)
70     {
71         const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(i).getDefaultAdaptiveSubdivision());
72         nPointCount += aCandidate.count();
73         mpPolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
74     }
75 
76     if( pLinePolyPolygon )
77     {
78         nCount = pLinePolyPolygon->count();
79         mpLinePolyPolygon = new PolyPolygon();
80 
81         for(sal_uInt32 i(0L); i < nCount; i++)
82         {
83             const basegfx::B2DPolygon aCandidate(pLinePolyPolygon->getB2DPolygon(i).getDefaultAdaptiveSubdivision());
84             nPointCount += aCandidate.count();
85             mpLinePolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
86         }
87     }
88     else
89         mpLinePolyPolygon = NULL;
90 }
91 
92 /*************************************************************************
93 |*
94 |*    TextRanger::~TextRanger()
95 |*
96 |*    Beschreibung
97 |*    Ersterstellung    20.01.97
98 |*    Letzte Aenderung  20.01.97 AMA
99 |*
100 *************************************************************************/
101 
~TextRanger()102 TextRanger::~TextRanger()
103 {
104     for( sal_uInt16 i = 0; i < nCacheSize; ++i )
105         delete pCache[i];
106     delete[] pCache;
107     delete[] pRangeArr;
108     delete mpPolyPolygon;
109     delete mpLinePolyPolygon;
110     delete pBound;
111 }
112 
113 /*-----------------17.11.00 09:49-------------------
114  * TextRanger::SetVertical(..)
115  * If there's is a change in the writing direction,
116  * the cache has to be cleared.
117  * --------------------------------------------------*/
118 
SetVertical(sal_Bool bNew)119 void TextRanger::SetVertical( sal_Bool bNew )
120 {
121     if( IsVertical() != bNew )
122     {
123         bVertical = bNew;
124         for( sal_uInt16 i = 0; i < nCacheSize; ++i )
125             delete pCache[i];
126         memset( pRangeArr, 0, nCacheSize * sizeof( Range ) );
127         memset( pCache, 0, nCacheSize * sizeof( SvLongsPtr ) );
128     }
129 }
130 
131 /*************************************************************************
132 |*
133 |*    SvxBoundArgs
134 |*
135 |*    Beschreibung
136 |*    Ersterstellung    20.01.97
137 |*    Letzte Aenderung  20.01.97 AMA
138 |*
139 *************************************************************************/
140 
141 class SvxBoundArgs
142 {
143     SvBools aBoolArr;
144     SvLongs *pLongArr;
145     TextRanger *pTextRanger;
146     long nMin;
147     long nMax;
148     long nTop;
149     long nBottom;
150     long nUpDiff;
151     long nLowDiff;
152     long nUpper;
153     long nLower;
154     long nStart;
155     long nEnd;
156     sal_uInt16 nCut;
157     sal_uInt16 nLast;
158     sal_uInt16 nNext;
159     sal_uInt8 nAct;
160     sal_uInt8 nFirst;
161     sal_Bool bClosed : 1;
162     sal_Bool bInner : 1;
163     sal_Bool bMultiple : 1;
164     sal_Bool bConcat : 1;
165     sal_Bool bRotate : 1;
166     void NoteRange( sal_Bool bToggle );
167     long Cut( long nY, const Point& rPt1, const Point& rPt2 );
168     void Add();
169     void _NoteFarPoint( long nPx, long nPyDiff, long nDiff );
NoteFarPoint(long nPx,long nPyDiff,long nDiff)170     void NoteFarPoint( long nPx, long nPyDiff, long nDiff )
171         { if( nDiff ) _NoteFarPoint( nPx, nPyDiff, nDiff ); }
172     long CalcMax( const Point& rPt1, const Point& rPt2, long nRange, long nFar );
173     void CheckCut( const Point& rLst, const Point& rNxt );
A(const Point & rP) const174     inline long A( const Point& rP ) const { return bRotate ? rP.Y() : rP.X(); }
B(const Point & rP) const175     inline long B( const Point& rP ) const { return bRotate ? rP.X() : rP.Y(); }
176 public:
177     SvxBoundArgs( TextRanger* pRanger, SvLongs *pLong, const Range& rRange );
NotePoint(const long nA)178     void NotePoint( const long nA ) { NoteMargin( nA - nStart, nA + nEnd ); }
NoteMargin(const long nL,const long nR)179     void NoteMargin( const long nL, const long nR )
180         { if( nMin > nL ) nMin = nL; if( nMax < nR ) nMax = nR; }
181     sal_uInt16 Area( const Point& rPt );
182     void NoteUpLow( long nA, const sal_uInt8 nArea );
183     void Calc( const PolyPolygon& rPoly );
184     void Concat( const PolyPolygon* pPoly );
185     // inlines
NoteLast()186     void NoteLast() { if( bMultiple ) NoteRange( nAct == nFirst ); }
SetClosed(const sal_Bool bNew)187     void SetClosed( const sal_Bool bNew ){ bClosed = bNew; }
IsClosed() const188     sal_Bool IsClosed() const { return bClosed; }
SetConcat(const sal_Bool bNew)189     void SetConcat( const sal_Bool bNew ){ bConcat = bNew; }
IsConcat() const190     sal_Bool IsConcat() const { return bConcat; }
GetAct() const191     sal_uInt8 GetAct() const { return nAct; }
192 };
193 
SvxBoundArgs(TextRanger * pRanger,SvLongs * pLong,const Range & rRange)194 SvxBoundArgs::SvxBoundArgs( TextRanger* pRanger, SvLongs *pLong,
195     const Range& rRange )
196     : pLongArr( pLong ), pTextRanger( pRanger ),
197     nTop( rRange.Min() ), nBottom( rRange.Max() ),
198     bInner( pRanger->IsInner() ), bMultiple( bInner || !pRanger->IsSimple() ),
199     bConcat( sal_False ), bRotate( pRanger->IsVertical() )
200 {
201     if( bRotate )
202     {
203         nStart = pRanger->GetUpper();
204         nEnd = pRanger->GetLower();
205         nLowDiff = pRanger->GetLeft();
206         nUpDiff = pRanger->GetRight();
207     }
208     else
209     {
210         nStart = pRanger->GetLeft();
211         nEnd = pRanger->GetRight();
212         nLowDiff = pRanger->GetUpper();
213         nUpDiff = pRanger->GetLower();
214     }
215     nUpper = nTop - nUpDiff;
216     nLower = nBottom + nLowDiff;
217     pLongArr->Remove( 0, pLongArr->Count() );
218 }
219 
CalcMax(const Point & rPt1,const Point & rPt2,long nRange,long nFarRange)220 long SvxBoundArgs::CalcMax( const Point& rPt1, const Point& rPt2,
221     long nRange, long nFarRange )
222 {
223     double nDa = Cut( nRange, rPt1, rPt2 ) - Cut( nFarRange, rPt1, rPt2 );
224     double nB;
225     if( nDa < 0 )
226     {
227         nDa = -nDa;
228         nB = nEnd;
229     }
230     else
231         nB = nStart;
232     nB *= nB;
233     nB += nDa * nDa;
234     nB = nRange + nDa * ( nFarRange - nRange ) / sqrt( nB );
235 
236     sal_Bool bNote;
237     if( nB < B(rPt2) )
238         bNote = nB > B(rPt1);
239     else
240         bNote = nB < B(rPt1);
241     if( bNote )
242         return( long( nB ) );
243     return 0;
244 }
245 
CheckCut(const Point & rLst,const Point & rNxt)246 void SvxBoundArgs::CheckCut( const Point& rLst, const Point& rNxt )
247 {
248     if( nCut & 1 )
249         NotePoint( Cut( nBottom, rLst, rNxt ) );
250     if( nCut & 2 )
251         NotePoint( Cut( nTop, rLst, rNxt ) );
252     if( rLst.X() != rNxt.X() && rLst.Y() != rNxt.Y() )
253     {
254         long nYps;
255         if( nLowDiff && ( ( nCut & 1 ) || nLast == 1 || nNext == 1 ) )
256         {
257             nYps = CalcMax( rLst, rNxt, nBottom, nLower );
258             if( nYps )
259                 _NoteFarPoint( Cut( nYps, rLst, rNxt ), nLower-nYps, nLowDiff );
260         }
261         if( nUpDiff && ( ( nCut & 2 ) || nLast == 2 || nNext == 2 ) )
262         {
263             nYps = CalcMax( rLst, rNxt, nTop, nUpper );
264             if( nYps )
265                 _NoteFarPoint( Cut( nYps, rLst, rNxt ), nYps-nUpper, nUpDiff );
266         }
267     }
268 }
269 
_NoteFarPoint(long nPa,long nPbDiff,long nDiff)270 void SvxBoundArgs::_NoteFarPoint( long nPa, long nPbDiff, long nDiff )
271 {
272     long nTmpA;
273     double nQuot = 2 * nDiff - nPbDiff;
274     nQuot *= nPbDiff;
275     nQuot = sqrt( nQuot );
276     nQuot /= nDiff;
277     nTmpA = nPa - long( nStart * nQuot );
278     nPbDiff = nPa + long( nEnd * nQuot );
279     NoteMargin( nTmpA, nPbDiff );
280 }
281 
NoteRange(sal_Bool bToggle)282 void SvxBoundArgs::NoteRange( sal_Bool bToggle )
283 {
284     DBG_ASSERT( nMax >= nMin || bInner, "NoteRange: Min > Max?");
285     if( nMax < nMin )
286         return;
287     if( !bClosed )
288         bToggle = sal_False;
289     sal_uInt16 nIdx = 0;
290     sal_uInt16 nCount = pLongArr->Count();
291     DBG_ASSERT( nCount == 2 * aBoolArr.size(), "NoteRange: Incompatible Sizes" );
292     while( nIdx < nCount && (*pLongArr)[ nIdx ] < nMin )
293         ++nIdx;
294     sal_Bool bOdd = nIdx % 2 ? sal_True : sal_False;
295     // Kein Ueberlappung mit vorhandenen Intervallen?
296     if( nIdx == nCount || ( !bOdd && nMax < (*pLongArr)[ nIdx ] ) )
297     {   // Dann wird ein neues eingefuegt ...
298         pLongArr->Insert( nMin, nIdx );
299         pLongArr->Insert( nMax, nIdx + 1 );
300         aBoolArr.insert( aBoolArr.begin() + nIdx / 2, bToggle );
301     }
302     else
303     {   // ein vorhandes Intervall erweitern ...
304         sal_uInt16 nMaxIdx = nIdx;
305         // Wenn wir auf einer linken Intervallgrenze gelandet sind, muss diese
306         // auf nMin gesenkt werden.
307         if( bOdd )
308             --nIdx;
309         else
310             (*pLongArr)[ nIdx ] = nMin;
311         while( nMaxIdx < nCount && (*pLongArr)[ nMaxIdx ] < nMax )
312             ++nMaxIdx;
313         DBG_ASSERT( nMaxIdx > nIdx || nMin == nMax, "NoteRange: Funny Situation." );
314         if( nMaxIdx )
315             --nMaxIdx;
316         if( nMaxIdx < nIdx )
317             nMaxIdx = nIdx;
318         // Wenn wir auf einer rechten Intervallgrenze landen, muss diese
319         // auf nMax angehoben werden.
320         if( nMaxIdx % 2 )
321             (*pLongArr)[ nMaxIdx-- ] = nMax;
322         // Jetzt werden eventuell noch Intervalle verschmolzen
323         sal_uInt16 nDiff = nMaxIdx - nIdx;
324         nMaxIdx = nIdx / 2; // Ab hier ist nMaxIdx der Index im BoolArray.
325         if( nDiff )
326         {
327             (*pLongArr).Remove( nIdx + 1, nDiff );
328             nDiff /= 2;
329             sal_uInt16 nStop = nMaxIdx + nDiff;
330             for( sal_uInt16 i = nMaxIdx; i < nStop; ++i )
331                 bToggle ^= aBoolArr[ i ];
332             aBoolArr.erase( aBoolArr.begin() + nMaxIdx, aBoolArr.begin() + (nMaxIdx + nDiff) );
333         }
334         DBG_ASSERT( nMaxIdx < aBoolArr.size(), "NoteRange: Too much deleted" );
335         aBoolArr[ nMaxIdx ] ^= bToggle;
336     }
337 }
338 
Calc(const PolyPolygon & rPoly)339 void SvxBoundArgs::Calc( const PolyPolygon& rPoly )
340 {
341     sal_uInt16 nCount;
342     nAct = 0;
343     for( sal_uInt16 i = 0; i < rPoly.Count(); ++i )
344     {
345         const Polygon& rPol = rPoly[ i ];
346         nCount = rPol.GetSize();
347         if( nCount )
348         {
349             const Point& rNull = rPol[ 0 ];
350             SetClosed( IsConcat() || ( rNull == rPol[ nCount - 1 ] ) );
351             nLast = Area( rNull );
352             if( nLast & 12 )
353             {
354                 nFirst = 3;
355                 if( bMultiple )
356                     nAct = 0;
357             }
358             else
359             {
360                 // Der erste Punkt des Polygons liegt innerhalb der Zeile.
361                 if( nLast )
362                 {
363                     if( bMultiple || !nAct )
364                     {
365                         nMin = USHRT_MAX;
366                         nMax = 0;
367                     }
368                     if( nLast & 1 )
369                         NoteFarPoint( A(rNull), nLower - B(rNull), nLowDiff );
370                     else
371                         NoteFarPoint( A(rNull), B(rNull) - nUpper, nUpDiff );
372                 }
373                 else
374                 {
375                     if( bMultiple || !nAct )
376                     {
377                         nMin = A(rNull);
378                         nMax = nMin + nEnd;
379                         nMin -= nStart;
380                     }
381                     else
382                         NotePoint( A(rNull) );
383                 }
384                 nFirst = 0; // In welcher Richtung wird die Zeile verlassen?
385                 nAct = 3;   // Wir sind z.Z. innerhalb der Zeile.
386             }
387             if( nCount > 1 )
388             {
389                 sal_uInt16 nIdx = 1;
390                 while( sal_True )
391                 {
392                     const Point& rLast = rPol[ nIdx - 1 ];
393                     if( nIdx == nCount )
394                         nIdx = 0;
395                     const Point& rNext = rPol[ nIdx ];
396                     nNext = Area( rNext );
397                     nCut = nNext ^ nLast;
398                     sal_uInt16 nOldAct = nAct;
399                     if( nAct )
400                         CheckCut( rLast, rNext );
401                     if( nCut & 4 )
402                     {
403                         NoteUpLow( Cut( nLower, rLast, rNext ), 2 );
404                         if( nAct && nAct != nOldAct )
405                         {
406                             nOldAct = nAct;
407                             CheckCut( rLast, rNext );
408                         }
409                     }
410                     if( nCut & 8 )
411                     {
412                         NoteUpLow( Cut( nUpper, rLast, rNext ), 1 );
413                         if( nAct && nAct != nOldAct )
414                             CheckCut( rLast, rNext );
415                     }
416                     if( !nIdx )
417                     {
418                         if( !( nNext & 12 ) )
419                             NoteLast();
420                         break;
421                     }
422                     if( !( nNext & 12 ) )
423                     {
424                         if( !nNext )
425                             NotePoint( A(rNext) );
426                         else if( nNext & 1 )
427                             NoteFarPoint( A(rNext), nLower-B(rNext), nLowDiff );
428                         else
429                             NoteFarPoint( A(rNext), B(rNext)-nUpper, nUpDiff );
430                     }
431                     nLast = nNext;
432                     if( ++nIdx == nCount && !IsClosed() )
433                     {
434                         if( !( nNext & 12 ) )
435                             NoteLast();
436                         break;
437                     }
438                 }
439             }
440             if( bMultiple && IsConcat() )
441             {
442                 Add();
443                 nAct = 0;
444             }
445         }
446     }
447     if( !bMultiple )
448     {
449         DBG_ASSERT( pLongArr->Count() == 0, "I said: Simple!" );
450         if( nAct )
451         {
452             if( bInner )
453             {
454                 long nTmpMin, nTmpMax;
455                 {
456                     nTmpMin = nMin + 2 * nStart;
457                     nTmpMax = nMax - 2 * nEnd;
458                     if( nTmpMin <= nTmpMax )
459                     {
460                         pLongArr->Insert( nTmpMin, 0 );
461                         pLongArr->Insert( nTmpMax, 1 );
462                     }
463                 }
464             }
465             else
466             {
467                 pLongArr->Insert( nMin, 0 );
468                 pLongArr->Insert( nMax, 1 );
469             }
470         }
471     }
472     else if( !IsConcat() )
473         Add();
474 }
475 
Add()476 void SvxBoundArgs::Add()
477 {
478     sal_uInt16 nLongIdx = 1;
479     size_t nCount = aBoolArr.size();
480     if( nCount && ( !bInner || !pTextRanger->IsSimple() ) )
481     {
482         sal_Bool bDelete = aBoolArr.front();
483         if( bInner )
484             bDelete = !bDelete;
485         for( size_t nBoolIdx = 1; nBoolIdx < nCount; ++nBoolIdx )
486         {
487             if( bDelete )
488             {
489                 sal_uInt16 next = 2;
490                 while( nBoolIdx < nCount && !aBoolArr[ nBoolIdx++ ] &&
491                        (!bInner || nBoolIdx < nCount ) )
492                     next += 2;
493                 pLongArr->Remove( nLongIdx, next );
494                 next /= 2;
495                 nBoolIdx = nBoolIdx - next;
496                 nCount = nCount - next;
497                 aBoolArr.erase( aBoolArr.begin() + nBoolIdx, aBoolArr.begin() + (nBoolIdx + next) );
498                 if( nBoolIdx )
499                     aBoolArr[ nBoolIdx - 1 ] = sal_False;
500 #if OSL_DEBUG_LEVEL > 1
501                 else
502                     ++next;
503 #endif
504             }
505             bDelete = nBoolIdx < nCount && aBoolArr[ nBoolIdx ];
506             nLongIdx += 2;
507             DBG_ASSERT( nLongIdx == 2*nBoolIdx+1, "BoundArgs: Array-Idx Confusion" );
508             DBG_ASSERT( aBoolArr.size()*2 == pLongArr->Count(),
509                         "BoundArgs: Array-Count: Confusion" );
510         }
511     }
512     if( 0 != ( nCount = pLongArr->Count() ) )
513     {
514         if( bInner )
515         {
516             pLongArr->Remove( 0, 1 );
517             pLongArr->Remove( pLongArr->Count() - 1, 1 );
518 
519             // Hier wird die Zeile beim "einfachen" Konturumfluss im Innern
520             // in ein grosses Rechteck zusammengefasst.
521             // Zur Zeit (April 1999) wertet die EditEngine nur das erste Rechteck
522             // aus, falls sie eines Tages in der Lage ist, eine Zeile in mehreren
523             // Teilen auszugeben, kann es sinnvoll sein, die folgenden Zeilen
524             // zu loeschen.
525             if( pTextRanger->IsSimple() && pLongArr->Count() > 2 )
526                 pLongArr->Remove( 1, pLongArr->Count() - 2 );
527 
528         }
529     }
530 }
531 
Concat(const PolyPolygon * pPoly)532 void SvxBoundArgs::Concat( const PolyPolygon* pPoly )
533 {
534     SetConcat( sal_True );
535     DBG_ASSERT( pPoly, "Nothing to do?" );
536     SvLongs *pOld = pLongArr;
537     pLongArr = new SvLongs( 2, 8 );
538     aBoolArr.clear();
539     bInner = sal_False;
540     Calc( *pPoly );
541     sal_uInt16 nCount = pLongArr->Count();
542     sal_uInt16 nIdx = 0;
543     sal_uInt16 i = 0;
544     sal_Bool bSubtract = pTextRanger->IsInner();
545     while( i < nCount )
546     {
547         sal_uInt16 nOldCount = pOld->Count();
548         if( nIdx == nOldCount )
549         {   // Am Ende des alten Arrays angelangt...
550             if( !bSubtract )
551                 pOld->Insert( pLongArr, nIdx, i, USHRT_MAX );
552             break;
553         }
554         long nLeft = (*pLongArr)[ i++ ];
555         long nRight = (*pLongArr)[ i++ ];
556         sal_uInt16 nLeftPos = nIdx + 1;
557         while( nLeftPos < nOldCount && nLeft > (*pOld)[ nLeftPos ] )
558             nLeftPos += 2;
559         if( nLeftPos >= nOldCount )
560         {   // Das aktuelle Intervall gehoert ans Ende des alten Arrays...
561             if( !bSubtract )
562                 pOld->Insert( pLongArr, nOldCount, i - 2, USHRT_MAX );
563             break;
564         }
565         sal_uInt16 nRightPos = nLeftPos - 1;
566         while( nRightPos < nOldCount && nRight >= (*pOld)[ nRightPos ] )
567             nRightPos += 2;
568         if( nRightPos < nLeftPos )
569         {   // Das aktuelle Intervall gehoert zwischen zwei alte Intervalle
570             if( !bSubtract )
571                 pOld->Insert( pLongArr, nRightPos, i - 2, i );
572             nIdx = nRightPos + 2;
573         }
574         else if( bSubtract ) // Subtrahieren ggf. Trennen
575         {
576             long nOld;
577             if( nLeft > ( nOld = (*pOld)[ nLeftPos - 1 ] ) )
578             {   // Jetzt spalten wir den linken Teil ab...
579                 if( nLeft - 1 > nOld )
580                 {
581                     pOld->Insert( nOld, nLeftPos - 1 );
582                     pOld->Insert( nLeft - 1, nLeftPos );
583                     nLeftPos += 2;
584                     nRightPos += 2;
585                 }
586             }
587             if( nRightPos - nLeftPos > 1 )
588                 pOld->Remove( nLeftPos, nRightPos - nLeftPos - 1 );
589             if( ++nRight >= ( nOld = (*pOld)[ nLeftPos ] ) )
590                 pOld->Remove( nLeftPos - 1, 2 );
591             else
592                 (*pOld)[ nLeftPos - 1 ] = nRight;
593         }
594         else // Verschmelzen
595         {
596             if( nLeft < (*pOld)[ nLeftPos - 1 ] )
597                 (*pOld)[ nLeftPos - 1 ] = nLeft;
598             if( nRight > (*pOld)[ nRightPos - 1 ] )
599                 (*pOld)[ nRightPos - 1 ] = nRight;
600             if( nRightPos - nLeftPos > 1 )
601                 pOld->Remove( nLeftPos, nRightPos - nLeftPos - 1 );
602 
603         }
604         nIdx = nLeftPos - 1;
605     }
606     delete pLongArr;
607 }
608 
609 /*************************************************************************
610  * SvxBoundArgs::Area ermittelt den Bereich, in dem sich der Punkt befindet
611  * 0 = innerhalb der Zeile
612  * 1 = unterhalb, aber innerhalb der oberen Randes
613  * 2 = oberhalb, aber innerhalb der unteren Randes
614  * 5 = unterhalb des oberen Randes
615  *10 = oberhalb des unteren Randes
616  *************************************************************************/
617 
Area(const Point & rPt)618 sal_uInt16 SvxBoundArgs::Area( const Point& rPt )
619 {
620     long nB = B( rPt );
621     if( nB >= nBottom )
622     {
623         if( nB >= nLower )
624             return 5;
625         return 1;
626     }
627     if( nB <= nTop )
628     {
629         if( nB <= nUpper )
630             return 10;
631         return 2;
632     }
633     return 0;
634 }
635 
636 /*************************************************************************
637  * lcl_Cut berechnet die X-Koordinate der Strecke (Pt1-Pt2) auf der
638  * Y-Koordinate nY.
639  * Vorausgesetzt wird, dass einer der Punkte oberhalb und der andere
640  * unterhalb der Y-Koordinate liegt.
641  *************************************************************************/
642 
Cut(long nB,const Point & rPt1,const Point & rPt2)643 long SvxBoundArgs::Cut( long nB, const Point& rPt1, const Point& rPt2 )
644 {
645     if( pTextRanger->IsVertical() )
646     {
647         double nQuot = nB - rPt1.X();
648         nQuot /= ( rPt2.X() - rPt1.X() );
649         nQuot *= ( rPt2.Y() - rPt1.Y() );
650         return long( rPt1.Y() + nQuot );
651     }
652     double nQuot = nB - rPt1.Y();
653     nQuot /= ( rPt2.Y() - rPt1.Y() );
654     nQuot *= ( rPt2.X() - rPt1.X() );
655     return long( rPt1.X() + nQuot );
656 }
657 
NoteUpLow(long nA,const sal_uInt8 nArea)658 void SvxBoundArgs::NoteUpLow( long nA, const sal_uInt8 nArea )
659 {
660     if( nAct )
661     {
662         NoteMargin( nA, nA );
663         if( bMultiple )
664         {
665             NoteRange( nArea != nAct );
666             nAct = 0;
667         }
668         if( !nFirst )
669             nFirst = nArea;
670     }
671     else
672     {
673         nAct = nArea;
674         nMin = nA;
675         nMax = nA;
676     }
677 }
678 
GetTextRanges(const Range & rRange)679 SvLongsPtr TextRanger::GetTextRanges( const Range& rRange )
680 {
681     DBG_ASSERT( rRange.Min() || rRange.Max(), "Zero-Range not allowed, Bye Bye" );
682     sal_uInt16 nIndex = 0;
683     while( nIndex < nCacheSize && rRange != pRangeArr[ nIndex ] )
684         ++nIndex;
685     if( nIndex >= nCacheSize )
686     {
687         ++nCacheIdx;
688         nCacheIdx %= nCacheSize;
689         pRangeArr[ nCacheIdx ] = rRange;
690         if( !pCache[ nCacheIdx ] )
691             pCache[ nCacheIdx ] = new SvLongs( 2, 8 );
692         nIndex = nCacheIdx;
693         SvxBoundArgs aArg( this, pCache[ nCacheIdx ], rRange );
694         aArg.Calc( *mpPolyPolygon );
695         if( mpLinePolyPolygon )
696             aArg.Concat( mpLinePolyPolygon );
697     }
698     return pCache[ nIndex ];
699 }
700 
_GetBoundRect()701 const Rectangle& TextRanger::_GetBoundRect()
702 {
703     DBG_ASSERT( 0 == pBound, "Don't call twice." );
704     pBound = new Rectangle( mpPolyPolygon->GetBoundRect() );
705     return *pBound;
706 }
707 
708 
709