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