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