19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
39f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file
59f62ea84SAndrew Rist * distributed with this work for additional information
69f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file
79f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at
109f62ea84SAndrew Rist *
119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist *
139f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist * software distributed under the License is distributed on an
159f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist * KIND, either express or implied. See the License for the
179f62ea84SAndrew Rist * specific language governing permissions and limitations
189f62ea84SAndrew Rist * under the License.
199f62ea84SAndrew Rist *
209f62ea84SAndrew Rist *************************************************************/
219f62ea84SAndrew Rist
229f62ea84SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir #include <tools/debug.hxx>
27cdf0e10cSrcweir #include <vcl/salbtype.hxx>
28cdf0e10cSrcweir #include <vcl/regband.hxx>
29cdf0e10cSrcweir
30cdf0e10cSrcweir #include <algorithm>
31cdf0e10cSrcweir
32cdf0e10cSrcweir
33cdf0e10cSrcweir // =======================================================================
34cdf0e10cSrcweir //
35cdf0e10cSrcweir // ImplRegionBand
36cdf0e10cSrcweir //
37cdf0e10cSrcweir // Jedes Band enthaelt die zwischen der enthaltenen Ober- und Untergrenze
38cdf0e10cSrcweir // enthaltenen Rechtecke. Bei den Operationen Union, Intersect, XOr und
39cdf0e10cSrcweir // Exclude werden immer Rechtecke der gleichen Hoehe ausgewerte; die
40cdf0e10cSrcweir // Grenzen der Baender sind immer so zu waehlen, dasz dies moeglich ist.
41cdf0e10cSrcweir //
42cdf0e10cSrcweir // Die Rechtecke in den Baendern werden nach Moeglichkeit zusammengefaszt.
43cdf0e10cSrcweir //
44cdf0e10cSrcweir // Bei der Umwandlung von Polygonen werden alle Punkte des Polygons
45cdf0e10cSrcweir // in die einzelnen Baender eingetragen (sie stehen fuer jedes Band als
46cdf0e10cSrcweir // Punkte in einer Liste). Nach dem Eintragen der Punkte werden diese
47cdf0e10cSrcweir // in Rechtecke umgewandelt und die Liste der Punkte geloescht.
48cdf0e10cSrcweir //
49cdf0e10cSrcweir // -----------------------------------------------------------------------
50cdf0e10cSrcweir
ImplRegionBand(long nTop,long nBottom)51cdf0e10cSrcweir ImplRegionBand::ImplRegionBand( long nTop, long nBottom )
52cdf0e10cSrcweir {
53cdf0e10cSrcweir // save boundaries
54cdf0e10cSrcweir mnYTop = nTop;
55cdf0e10cSrcweir mnYBottom = nBottom;
56cdf0e10cSrcweir
57cdf0e10cSrcweir // initialize lists
58cdf0e10cSrcweir mpNextBand = NULL;
59cdf0e10cSrcweir mpPrevBand = NULL;
60cdf0e10cSrcweir mpFirstSep = NULL;
61cdf0e10cSrcweir mpFirstBandPoint = NULL;
62*e6f63103SArmin Le Grand mbTouched = false;
63cdf0e10cSrcweir }
64cdf0e10cSrcweir
65cdf0e10cSrcweir // -----------------------------------------------------------------------
66cdf0e10cSrcweir
ImplRegionBand(const ImplRegionBand & rRegionBand,const bool bIgnorePoints)67cdf0e10cSrcweir ImplRegionBand::ImplRegionBand(
68cdf0e10cSrcweir const ImplRegionBand& rRegionBand,
69cdf0e10cSrcweir const bool bIgnorePoints)
70cdf0e10cSrcweir {
71cdf0e10cSrcweir // copy boundaries
72cdf0e10cSrcweir mnYTop = rRegionBand.mnYTop;
73cdf0e10cSrcweir mnYBottom = rRegionBand.mnYBottom;
74cdf0e10cSrcweir mbTouched = rRegionBand.mbTouched;
75cdf0e10cSrcweir
76cdf0e10cSrcweir // initialisation
77cdf0e10cSrcweir mpNextBand = NULL;
78cdf0e10cSrcweir mpPrevBand = NULL;
79cdf0e10cSrcweir mpFirstSep = NULL;
80cdf0e10cSrcweir mpFirstBandPoint = NULL;
81cdf0e10cSrcweir
82cdf0e10cSrcweir // copy all elements of the list with separations
83cdf0e10cSrcweir ImplRegionBandSep* pNewSep;
84cdf0e10cSrcweir ImplRegionBandSep* pPrevSep = 0;
85cdf0e10cSrcweir ImplRegionBandSep* pSep = rRegionBand.mpFirstSep;
86cdf0e10cSrcweir while ( pSep )
87cdf0e10cSrcweir {
88cdf0e10cSrcweir // create new and copy data
89cdf0e10cSrcweir pNewSep = new ImplRegionBandSep;
90cdf0e10cSrcweir pNewSep->mnXLeft = pSep->mnXLeft;
91cdf0e10cSrcweir pNewSep->mnXRight = pSep->mnXRight;
92cdf0e10cSrcweir pNewSep->mbRemoved = pSep->mbRemoved;
93cdf0e10cSrcweir pNewSep->mpNextSep = NULL;
94cdf0e10cSrcweir if ( pSep == rRegionBand.mpFirstSep )
95cdf0e10cSrcweir mpFirstSep = pNewSep;
96cdf0e10cSrcweir else
97cdf0e10cSrcweir pPrevSep->mpNextSep = pNewSep;
98cdf0e10cSrcweir
99cdf0e10cSrcweir pPrevSep = pNewSep;
100cdf0e10cSrcweir pSep = pSep->mpNextSep;
101cdf0e10cSrcweir }
102cdf0e10cSrcweir
103cdf0e10cSrcweir if ( ! bIgnorePoints)
104cdf0e10cSrcweir {
105cdf0e10cSrcweir // Copy points.
106cdf0e10cSrcweir ImplRegionBandPoint* pPoint = rRegionBand.mpFirstBandPoint;
107cdf0e10cSrcweir ImplRegionBandPoint* pPrevPointCopy = NULL;
108cdf0e10cSrcweir while (pPoint != NULL)
109cdf0e10cSrcweir {
110cdf0e10cSrcweir ImplRegionBandPoint* pPointCopy = new ImplRegionBandPoint();
111cdf0e10cSrcweir pPointCopy->mnX = pPoint->mnX;
112cdf0e10cSrcweir pPointCopy->mnLineId = pPoint->mnLineId;
113cdf0e10cSrcweir pPointCopy->mbEndPoint = pPoint->mbEndPoint;
114cdf0e10cSrcweir pPointCopy->meLineType = pPoint->meLineType;
115cdf0e10cSrcweir
116cdf0e10cSrcweir if (pPrevPointCopy != NULL)
117cdf0e10cSrcweir pPrevPointCopy->mpNextBandPoint = pPointCopy;
118cdf0e10cSrcweir else
119cdf0e10cSrcweir mpFirstBandPoint = pPointCopy;
120cdf0e10cSrcweir
121cdf0e10cSrcweir pPrevPointCopy = pPointCopy;
122cdf0e10cSrcweir pPoint = pPoint->mpNextBandPoint;
123cdf0e10cSrcweir }
124cdf0e10cSrcweir }
125cdf0e10cSrcweir }
126cdf0e10cSrcweir
127cdf0e10cSrcweir // -----------------------------------------------------------------------
128cdf0e10cSrcweir
~ImplRegionBand()129cdf0e10cSrcweir ImplRegionBand::~ImplRegionBand()
130cdf0e10cSrcweir {
131cdf0e10cSrcweir DBG_ASSERT( mpFirstBandPoint == NULL, "ImplRegionBand::~ImplRegionBand -> pointlist not empty" );
132cdf0e10cSrcweir
133cdf0e10cSrcweir // delete elements of the list
134cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
135cdf0e10cSrcweir while ( pSep )
136cdf0e10cSrcweir {
137cdf0e10cSrcweir ImplRegionBandSep* pTempSep = pSep->mpNextSep;
138cdf0e10cSrcweir delete pSep;
139cdf0e10cSrcweir pSep = pTempSep;
140cdf0e10cSrcweir }
141cdf0e10cSrcweir
142cdf0e10cSrcweir // delete elements of the list
143cdf0e10cSrcweir ImplRegionBandPoint* pPoint = mpFirstBandPoint;
144cdf0e10cSrcweir while ( pPoint )
145cdf0e10cSrcweir {
146cdf0e10cSrcweir ImplRegionBandPoint* pTempPoint = pPoint->mpNextBandPoint;
147cdf0e10cSrcweir delete pPoint;
148cdf0e10cSrcweir pPoint = pTempPoint;
149cdf0e10cSrcweir }
150cdf0e10cSrcweir }
151cdf0e10cSrcweir
152cdf0e10cSrcweir // -----------------------------------------------------------------------
153cdf0e10cSrcweir //
154cdf0e10cSrcweir // generate separations from lines and process union with existing
155cdf0e10cSrcweir // separations
156cdf0e10cSrcweir
ProcessPoints()157cdf0e10cSrcweir void ImplRegionBand::ProcessPoints()
158cdf0e10cSrcweir {
159cdf0e10cSrcweir // check Pointlist
160cdf0e10cSrcweir ImplRegionBandPoint* pRegionBandPoint = mpFirstBandPoint;
161cdf0e10cSrcweir while ( pRegionBandPoint )
162cdf0e10cSrcweir {
163cdf0e10cSrcweir // within list?
164cdf0e10cSrcweir if ( pRegionBandPoint && pRegionBandPoint->mpNextBandPoint )
165cdf0e10cSrcweir {
166cdf0e10cSrcweir // start/stop?
167cdf0e10cSrcweir if ( pRegionBandPoint->mbEndPoint && pRegionBandPoint->mpNextBandPoint->mbEndPoint )
168cdf0e10cSrcweir {
169cdf0e10cSrcweir // same direction? -> remove next point!
170cdf0e10cSrcweir if ( pRegionBandPoint->meLineType == pRegionBandPoint->mpNextBandPoint->meLineType )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir ImplRegionBandPoint* pSaveRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
173cdf0e10cSrcweir pRegionBandPoint->mpNextBandPoint = pRegionBandPoint->mpNextBandPoint->mpNextBandPoint;
174cdf0e10cSrcweir delete pSaveRegionBandPoint;
175cdf0e10cSrcweir }
176cdf0e10cSrcweir }
177cdf0e10cSrcweir }
178cdf0e10cSrcweir
179cdf0e10cSrcweir // continue with next element in the list
180cdf0e10cSrcweir pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
181cdf0e10cSrcweir }
182cdf0e10cSrcweir
183cdf0e10cSrcweir pRegionBandPoint = mpFirstBandPoint;
184cdf0e10cSrcweir while ( pRegionBandPoint && pRegionBandPoint->mpNextBandPoint )
185cdf0e10cSrcweir {
186cdf0e10cSrcweir Union( pRegionBandPoint->mnX, pRegionBandPoint->mpNextBandPoint->mnX );
187cdf0e10cSrcweir
188cdf0e10cSrcweir ImplRegionBandPoint* pNextBandPoint = pRegionBandPoint->mpNextBandPoint->mpNextBandPoint;
189cdf0e10cSrcweir
190cdf0e10cSrcweir // remove allready processed points
191cdf0e10cSrcweir delete pRegionBandPoint->mpNextBandPoint;
192cdf0e10cSrcweir delete pRegionBandPoint;
193cdf0e10cSrcweir
194cdf0e10cSrcweir // continue with next element in the list
195cdf0e10cSrcweir pRegionBandPoint = pNextBandPoint;
196cdf0e10cSrcweir }
197cdf0e10cSrcweir
198cdf0e10cSrcweir // remove last element if necessary
199cdf0e10cSrcweir if ( pRegionBandPoint )
200cdf0e10cSrcweir delete pRegionBandPoint;
201cdf0e10cSrcweir
202cdf0e10cSrcweir // list is now empty
203cdf0e10cSrcweir mpFirstBandPoint = NULL;
204cdf0e10cSrcweir }
205cdf0e10cSrcweir
206cdf0e10cSrcweir // -----------------------------------------------------------------------
207cdf0e10cSrcweir //
208cdf0e10cSrcweir // generate separations from lines and process union with existing
209cdf0e10cSrcweir // separations
210cdf0e10cSrcweir
InsertPoint(long nX,long nLineId,bool bEndPoint,LineType eLineType)211*e6f63103SArmin Le Grand bool ImplRegionBand::InsertPoint( long nX, long nLineId,
212*e6f63103SArmin Le Grand bool bEndPoint, LineType eLineType )
213cdf0e10cSrcweir {
214cdf0e10cSrcweir if ( !mpFirstBandPoint )
215cdf0e10cSrcweir {
216cdf0e10cSrcweir mpFirstBandPoint = new ImplRegionBandPoint;
217cdf0e10cSrcweir mpFirstBandPoint->mnX = nX;
218cdf0e10cSrcweir mpFirstBandPoint->mnLineId = nLineId;
219cdf0e10cSrcweir mpFirstBandPoint->mbEndPoint = bEndPoint;
220cdf0e10cSrcweir mpFirstBandPoint->meLineType = eLineType;
221cdf0e10cSrcweir mpFirstBandPoint->mpNextBandPoint = NULL;
222*e6f63103SArmin Le Grand return true;
223cdf0e10cSrcweir }
224cdf0e10cSrcweir
225cdf0e10cSrcweir // look if line allready touched the band
226cdf0e10cSrcweir ImplRegionBandPoint* pRegionBandPoint = mpFirstBandPoint;
227cdf0e10cSrcweir ImplRegionBandPoint* pLastTestedRegionBandPoint = NULL;
228cdf0e10cSrcweir while( pRegionBandPoint )
229cdf0e10cSrcweir {
230cdf0e10cSrcweir if ( pRegionBandPoint->mnLineId == nLineId )
231cdf0e10cSrcweir {
232cdf0e10cSrcweir if ( bEndPoint )
233cdf0e10cSrcweir {
234cdf0e10cSrcweir if( !pRegionBandPoint->mbEndPoint )
235cdf0e10cSrcweir {
236cdf0e10cSrcweir // remove old band point
237cdf0e10cSrcweir if( !mpFirstBandPoint->mpNextBandPoint )
238cdf0e10cSrcweir {
239cdf0e10cSrcweir // if we've only got one point => replace first point
240cdf0e10cSrcweir pRegionBandPoint->mnX = nX;
241*e6f63103SArmin Le Grand pRegionBandPoint->mbEndPoint = true;
242*e6f63103SArmin Le Grand return true;
243cdf0e10cSrcweir }
244cdf0e10cSrcweir else
245cdf0e10cSrcweir {
246cdf0e10cSrcweir // remove current point
247cdf0e10cSrcweir if( !pLastTestedRegionBandPoint )
248cdf0e10cSrcweir {
249cdf0e10cSrcweir // remove and delete old first point
250cdf0e10cSrcweir ImplRegionBandPoint* pSaveBandPoint = mpFirstBandPoint;
251cdf0e10cSrcweir mpFirstBandPoint = mpFirstBandPoint->mpNextBandPoint;
252cdf0e10cSrcweir delete pSaveBandPoint;
253cdf0e10cSrcweir }
254cdf0e10cSrcweir else
255cdf0e10cSrcweir {
256cdf0e10cSrcweir // remove and delete current band point
257cdf0e10cSrcweir pLastTestedRegionBandPoint->mpNextBandPoint = pRegionBandPoint->mpNextBandPoint;
258cdf0e10cSrcweir delete pRegionBandPoint;
259cdf0e10cSrcweir }
260cdf0e10cSrcweir
261cdf0e10cSrcweir break;
262cdf0e10cSrcweir }
263cdf0e10cSrcweir }
264cdf0e10cSrcweir }
265cdf0e10cSrcweir else
266*e6f63103SArmin Le Grand return false;
267cdf0e10cSrcweir }
268cdf0e10cSrcweir
269cdf0e10cSrcweir // use next element
270cdf0e10cSrcweir pLastTestedRegionBandPoint = pRegionBandPoint;
271cdf0e10cSrcweir pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
272cdf0e10cSrcweir }
273cdf0e10cSrcweir
274cdf0e10cSrcweir // search appropriate position and insert point into the list
275cdf0e10cSrcweir ImplRegionBandPoint* pNewRegionBandPoint;
276cdf0e10cSrcweir
277cdf0e10cSrcweir pRegionBandPoint = mpFirstBandPoint;
278cdf0e10cSrcweir pLastTestedRegionBandPoint = NULL;
279cdf0e10cSrcweir while ( pRegionBandPoint )
280cdf0e10cSrcweir {
281cdf0e10cSrcweir // new point completly left? -> insert as first point
282cdf0e10cSrcweir if ( nX <= pRegionBandPoint->mnX )
283cdf0e10cSrcweir {
284cdf0e10cSrcweir pNewRegionBandPoint = new ImplRegionBandPoint;
285cdf0e10cSrcweir pNewRegionBandPoint->mnX = nX;
286cdf0e10cSrcweir pNewRegionBandPoint->mnLineId = nLineId;
287cdf0e10cSrcweir pNewRegionBandPoint->mbEndPoint = bEndPoint;
288cdf0e10cSrcweir pNewRegionBandPoint->meLineType = eLineType;
289cdf0e10cSrcweir pNewRegionBandPoint->mpNextBandPoint = pRegionBandPoint;
290cdf0e10cSrcweir
291cdf0e10cSrcweir // connections to the new point
292cdf0e10cSrcweir if ( !pLastTestedRegionBandPoint )
293cdf0e10cSrcweir mpFirstBandPoint = pNewRegionBandPoint;
294cdf0e10cSrcweir else
295cdf0e10cSrcweir pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
296cdf0e10cSrcweir
297*e6f63103SArmin Le Grand return true;
298cdf0e10cSrcweir }
299cdf0e10cSrcweir
300cdf0e10cSrcweir // use next element
301cdf0e10cSrcweir pLastTestedRegionBandPoint = pRegionBandPoint;
302cdf0e10cSrcweir pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
303cdf0e10cSrcweir }
304cdf0e10cSrcweir
305cdf0e10cSrcweir // not inserted -> add to the end of the list
306cdf0e10cSrcweir pNewRegionBandPoint = new ImplRegionBandPoint;
307cdf0e10cSrcweir pNewRegionBandPoint->mnX = nX;
308cdf0e10cSrcweir pNewRegionBandPoint->mnLineId = nLineId;
309cdf0e10cSrcweir pNewRegionBandPoint->mbEndPoint = bEndPoint;
310cdf0e10cSrcweir pNewRegionBandPoint->meLineType = eLineType;
311cdf0e10cSrcweir pNewRegionBandPoint->mpNextBandPoint = NULL;
312cdf0e10cSrcweir
313cdf0e10cSrcweir // connections to the new point
314cdf0e10cSrcweir pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
315cdf0e10cSrcweir
316*e6f63103SArmin Le Grand return true;
317cdf0e10cSrcweir }
318cdf0e10cSrcweir
319cdf0e10cSrcweir // -----------------------------------------------------------------------
320cdf0e10cSrcweir
MoveX(long nHorzMove)321cdf0e10cSrcweir void ImplRegionBand::MoveX( long nHorzMove )
322cdf0e10cSrcweir {
323cdf0e10cSrcweir // move all x-separations
324cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
325cdf0e10cSrcweir while ( pSep )
326cdf0e10cSrcweir {
327cdf0e10cSrcweir pSep->mnXLeft += nHorzMove;
328cdf0e10cSrcweir pSep->mnXRight += nHorzMove;
329cdf0e10cSrcweir pSep = pSep->mpNextSep;
330cdf0e10cSrcweir }
331cdf0e10cSrcweir }
332cdf0e10cSrcweir
333cdf0e10cSrcweir // -----------------------------------------------------------------------
334cdf0e10cSrcweir
ScaleX(double fHorzScale)335cdf0e10cSrcweir void ImplRegionBand::ScaleX( double fHorzScale )
336cdf0e10cSrcweir {
337cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
338cdf0e10cSrcweir while ( pSep )
339cdf0e10cSrcweir {
340cdf0e10cSrcweir pSep->mnXLeft = FRound( pSep->mnXLeft * fHorzScale );
341cdf0e10cSrcweir pSep->mnXRight = FRound( pSep->mnXRight * fHorzScale );
342cdf0e10cSrcweir pSep = pSep->mpNextSep;
343cdf0e10cSrcweir }
344cdf0e10cSrcweir }
345cdf0e10cSrcweir
346cdf0e10cSrcweir // -----------------------------------------------------------------------
347cdf0e10cSrcweir //
348cdf0e10cSrcweir // combine overlaping sparations
349cdf0e10cSrcweir
OptimizeBand()350*e6f63103SArmin Le Grand bool ImplRegionBand::OptimizeBand()
351cdf0e10cSrcweir {
352cdf0e10cSrcweir ImplRegionBandSep* pPrevSep = 0;
353cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
354cdf0e10cSrcweir while ( pSep )
355cdf0e10cSrcweir {
356cdf0e10cSrcweir // remove?
357cdf0e10cSrcweir if ( pSep->mbRemoved || (pSep->mnXRight < pSep->mnXLeft) )
358cdf0e10cSrcweir {
359cdf0e10cSrcweir ImplRegionBandSep* pOldSep = pSep;
360cdf0e10cSrcweir if ( pSep == mpFirstSep )
361cdf0e10cSrcweir mpFirstSep = pSep->mpNextSep;
362cdf0e10cSrcweir else
363cdf0e10cSrcweir pPrevSep->mpNextSep = pSep->mpNextSep;
364cdf0e10cSrcweir pSep = pSep->mpNextSep;
365cdf0e10cSrcweir delete pOldSep;
366cdf0e10cSrcweir continue;
367cdf0e10cSrcweir }
368cdf0e10cSrcweir
369cdf0e10cSrcweir // overlaping separations? -> combine!
370cdf0e10cSrcweir if ( pSep->mpNextSep )
371cdf0e10cSrcweir {
372cdf0e10cSrcweir if ( (pSep->mnXRight+1) >= pSep->mpNextSep->mnXLeft )
373cdf0e10cSrcweir {
374cdf0e10cSrcweir if ( pSep->mpNextSep->mnXRight > pSep->mnXRight )
375cdf0e10cSrcweir pSep->mnXRight = pSep->mpNextSep->mnXRight;
376cdf0e10cSrcweir
377cdf0e10cSrcweir ImplRegionBandSep* pOldSep = pSep->mpNextSep;
378cdf0e10cSrcweir pSep->mpNextSep = pOldSep->mpNextSep;
379cdf0e10cSrcweir delete pOldSep;
380cdf0e10cSrcweir continue;
381cdf0e10cSrcweir }
382cdf0e10cSrcweir }
383cdf0e10cSrcweir
384cdf0e10cSrcweir pPrevSep = pSep;
385cdf0e10cSrcweir pSep = pSep->mpNextSep;
386cdf0e10cSrcweir }
387cdf0e10cSrcweir
388*e6f63103SArmin Le Grand return true;
389cdf0e10cSrcweir }
390cdf0e10cSrcweir
391cdf0e10cSrcweir // -----------------------------------------------------------------------
392cdf0e10cSrcweir
Union(long nXLeft,long nXRight)393cdf0e10cSrcweir void ImplRegionBand::Union( long nXLeft, long nXRight )
394cdf0e10cSrcweir {
395cdf0e10cSrcweir DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Union(): nxLeft > nXRight" );
396cdf0e10cSrcweir
397cdf0e10cSrcweir // band empty? -> add element
398cdf0e10cSrcweir if ( !mpFirstSep )
399cdf0e10cSrcweir {
400cdf0e10cSrcweir mpFirstSep = new ImplRegionBandSep;
401cdf0e10cSrcweir mpFirstSep->mnXLeft = nXLeft;
402cdf0e10cSrcweir mpFirstSep->mnXRight = nXRight;
403*e6f63103SArmin Le Grand mpFirstSep->mbRemoved = false;
404cdf0e10cSrcweir mpFirstSep->mpNextSep = NULL;
405cdf0e10cSrcweir return;
406cdf0e10cSrcweir }
407cdf0e10cSrcweir
408cdf0e10cSrcweir // process real union
409cdf0e10cSrcweir ImplRegionBandSep* pNewSep;
410cdf0e10cSrcweir ImplRegionBandSep* pPrevSep = 0;
411cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
412cdf0e10cSrcweir while ( pSep )
413cdf0e10cSrcweir {
414cdf0e10cSrcweir // new separation completely inside? nothing to do!
415cdf0e10cSrcweir if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
416cdf0e10cSrcweir return;
417cdf0e10cSrcweir
418cdf0e10cSrcweir // new separation completly left? -> new separation!
419cdf0e10cSrcweir if ( nXRight < pSep->mnXLeft )
420cdf0e10cSrcweir {
421cdf0e10cSrcweir pNewSep = new ImplRegionBandSep;
422cdf0e10cSrcweir pNewSep->mnXLeft = nXLeft;
423cdf0e10cSrcweir pNewSep->mnXRight = nXRight;
424*e6f63103SArmin Le Grand pNewSep->mbRemoved = false;
425cdf0e10cSrcweir
426cdf0e10cSrcweir pNewSep->mpNextSep = pSep;
427cdf0e10cSrcweir if ( pSep == mpFirstSep )
428cdf0e10cSrcweir mpFirstSep = pNewSep;
429cdf0e10cSrcweir else
430cdf0e10cSrcweir pPrevSep->mpNextSep = pNewSep;
431cdf0e10cSrcweir break;
432cdf0e10cSrcweir }
433cdf0e10cSrcweir
434cdf0e10cSrcweir // new separation overlaping from left? -> extend boundary
435cdf0e10cSrcweir if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
436cdf0e10cSrcweir pSep->mnXLeft = nXLeft;
437cdf0e10cSrcweir
438cdf0e10cSrcweir // new separation overlaping from right? -> extend boundary
439cdf0e10cSrcweir if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
440cdf0e10cSrcweir {
441cdf0e10cSrcweir pSep->mnXRight = nXRight;
442cdf0e10cSrcweir break;
443cdf0e10cSrcweir }
444cdf0e10cSrcweir
445cdf0e10cSrcweir // not inserted, but last element? -> add to the end of the list
446cdf0e10cSrcweir if ( !pSep->mpNextSep && (nXLeft > pSep->mnXRight) )
447cdf0e10cSrcweir {
448cdf0e10cSrcweir pNewSep = new ImplRegionBandSep;
449cdf0e10cSrcweir pNewSep->mnXLeft = nXLeft;
450cdf0e10cSrcweir pNewSep->mnXRight = nXRight;
451*e6f63103SArmin Le Grand pNewSep->mbRemoved = false;
452cdf0e10cSrcweir
453cdf0e10cSrcweir pSep->mpNextSep = pNewSep;
454cdf0e10cSrcweir pNewSep->mpNextSep = NULL;
455cdf0e10cSrcweir break;
456cdf0e10cSrcweir }
457cdf0e10cSrcweir
458cdf0e10cSrcweir pPrevSep = pSep;
459cdf0e10cSrcweir pSep = pSep->mpNextSep;
460cdf0e10cSrcweir }
461cdf0e10cSrcweir
462cdf0e10cSrcweir OptimizeBand();
463cdf0e10cSrcweir }
464cdf0e10cSrcweir
465cdf0e10cSrcweir // -----------------------------------------------------------------------
466cdf0e10cSrcweir
Intersect(long nXLeft,long nXRight)467cdf0e10cSrcweir void ImplRegionBand::Intersect( long nXLeft, long nXRight )
468cdf0e10cSrcweir {
469cdf0e10cSrcweir DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Intersect(): nxLeft > nXRight" );
470cdf0e10cSrcweir
471cdf0e10cSrcweir // band has been touched
472*e6f63103SArmin Le Grand mbTouched = true;
473cdf0e10cSrcweir
474cdf0e10cSrcweir // band empty? -> nothing to do
475cdf0e10cSrcweir if ( !mpFirstSep )
476cdf0e10cSrcweir return;
477cdf0e10cSrcweir
478cdf0e10cSrcweir // process real intersection
479cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
480cdf0e10cSrcweir while ( pSep )
481cdf0e10cSrcweir {
482cdf0e10cSrcweir // new separation completly outside? -> remove separation
483cdf0e10cSrcweir if ( (nXRight < pSep->mnXLeft) || (nXLeft > pSep->mnXRight) )
484cdf0e10cSrcweir // will be removed from the optimizer
485*e6f63103SArmin Le Grand pSep->mbRemoved = true;
486cdf0e10cSrcweir
487cdf0e10cSrcweir // new separation overlaping from left? -> reduce right boundary
488cdf0e10cSrcweir if ( (nXLeft <= pSep->mnXLeft) &&
489cdf0e10cSrcweir (nXRight <= pSep->mnXRight) &&
490cdf0e10cSrcweir (nXRight >= pSep->mnXLeft) )
491cdf0e10cSrcweir pSep->mnXRight = nXRight;
492cdf0e10cSrcweir
493cdf0e10cSrcweir // new separation overlaping from right? -> reduce right boundary
494cdf0e10cSrcweir if ( (nXLeft >= pSep->mnXLeft) &&
495cdf0e10cSrcweir (nXLeft <= pSep->mnXRight) &&
496cdf0e10cSrcweir (nXRight >= pSep->mnXRight) )
497cdf0e10cSrcweir pSep->mnXLeft = nXLeft;
498cdf0e10cSrcweir
499cdf0e10cSrcweir // new separation within the actual one? -> reduce both boundaries
500cdf0e10cSrcweir if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
501cdf0e10cSrcweir {
502cdf0e10cSrcweir pSep->mnXRight = nXRight;
503cdf0e10cSrcweir pSep->mnXLeft = nXLeft;
504cdf0e10cSrcweir }
505cdf0e10cSrcweir
506cdf0e10cSrcweir pSep = pSep->mpNextSep;
507cdf0e10cSrcweir }
508cdf0e10cSrcweir
509cdf0e10cSrcweir OptimizeBand();
510cdf0e10cSrcweir }
511cdf0e10cSrcweir
512cdf0e10cSrcweir // -----------------------------------------------------------------------
513cdf0e10cSrcweir
Exclude(long nXLeft,long nXRight)514cdf0e10cSrcweir void ImplRegionBand::Exclude( long nXLeft, long nXRight )
515cdf0e10cSrcweir {
516cdf0e10cSrcweir DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Exclude(): nxLeft > nXRight" );
517cdf0e10cSrcweir
518cdf0e10cSrcweir // band has been touched
519*e6f63103SArmin Le Grand mbTouched = true;
520cdf0e10cSrcweir
521cdf0e10cSrcweir // band empty? -> nothing to do
522cdf0e10cSrcweir if ( !mpFirstSep )
523cdf0e10cSrcweir return;
524cdf0e10cSrcweir
525cdf0e10cSrcweir // process real exclusion
526cdf0e10cSrcweir ImplRegionBandSep* pNewSep;
527cdf0e10cSrcweir ImplRegionBandSep* pPrevSep = 0;
528cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
529cdf0e10cSrcweir while ( pSep )
530cdf0e10cSrcweir {
531*e6f63103SArmin Le Grand bool bSepProcessed = false;
532cdf0e10cSrcweir
533cdf0e10cSrcweir // new separation completely overlapping? -> remove separation
534cdf0e10cSrcweir if ( (nXLeft <= pSep->mnXLeft) && (nXRight >= pSep->mnXRight) )
535cdf0e10cSrcweir {
536cdf0e10cSrcweir // will be removed from the optimizer
537*e6f63103SArmin Le Grand pSep->mbRemoved = true;
538*e6f63103SArmin Le Grand bSepProcessed = true;
539cdf0e10cSrcweir }
540cdf0e10cSrcweir
541cdf0e10cSrcweir // new separation overlaping from left? -> reduce boundary
542cdf0e10cSrcweir if ( !bSepProcessed )
543cdf0e10cSrcweir {
544cdf0e10cSrcweir if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
545cdf0e10cSrcweir {
546cdf0e10cSrcweir pSep->mnXLeft = nXRight+1;
547*e6f63103SArmin Le Grand bSepProcessed = true;
548cdf0e10cSrcweir }
549cdf0e10cSrcweir }
550cdf0e10cSrcweir
551cdf0e10cSrcweir // new separation overlaping from right? -> reduce boundary
552cdf0e10cSrcweir if ( !bSepProcessed )
553cdf0e10cSrcweir {
554cdf0e10cSrcweir if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
555cdf0e10cSrcweir {
556cdf0e10cSrcweir pSep->mnXRight = nXLeft-1;
557*e6f63103SArmin Le Grand bSepProcessed = true;
558cdf0e10cSrcweir }
559cdf0e10cSrcweir }
560cdf0e10cSrcweir
561cdf0e10cSrcweir // new separation within the actual one? -> reduce boundary
562cdf0e10cSrcweir // and add new entry for reminder
563cdf0e10cSrcweir if ( !bSepProcessed )
564cdf0e10cSrcweir {
565cdf0e10cSrcweir if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
566cdf0e10cSrcweir {
567cdf0e10cSrcweir pNewSep = new ImplRegionBandSep;
568cdf0e10cSrcweir pNewSep->mnXLeft = pSep->mnXLeft;
569cdf0e10cSrcweir pNewSep->mnXRight = nXLeft-1;
570*e6f63103SArmin Le Grand pNewSep->mbRemoved = false;
571cdf0e10cSrcweir
572cdf0e10cSrcweir pSep->mnXLeft = nXRight+1;
573cdf0e10cSrcweir
574cdf0e10cSrcweir // connections from the new separation
575cdf0e10cSrcweir pNewSep->mpNextSep = pSep;
576cdf0e10cSrcweir
577cdf0e10cSrcweir // connections to the new separation
578cdf0e10cSrcweir if ( pSep == mpFirstSep )
579cdf0e10cSrcweir mpFirstSep = pNewSep;
580cdf0e10cSrcweir else
581cdf0e10cSrcweir pPrevSep->mpNextSep = pNewSep;
582cdf0e10cSrcweir }
583cdf0e10cSrcweir }
584cdf0e10cSrcweir
585cdf0e10cSrcweir pPrevSep = pSep;
586cdf0e10cSrcweir pSep = pSep->mpNextSep;
587cdf0e10cSrcweir }
588cdf0e10cSrcweir
589cdf0e10cSrcweir OptimizeBand();
590cdf0e10cSrcweir }
591cdf0e10cSrcweir
592cdf0e10cSrcweir // -----------------------------------------------------------------------
593cdf0e10cSrcweir
XOr(long nXLeft,long nXRight)594cdf0e10cSrcweir void ImplRegionBand::XOr( long nXLeft, long nXRight )
595cdf0e10cSrcweir {
596cdf0e10cSrcweir DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::XOr(): nxLeft > nXRight" );
597cdf0e10cSrcweir
598cdf0e10cSrcweir // #i46602# Reworked rectangle Xor
599cdf0e10cSrcweir //
600cdf0e10cSrcweir // In general, we can distinguish 11 cases of intersection
601cdf0e10cSrcweir // (details below). The old implementation explicitely handled 7
602cdf0e10cSrcweir // cases (numbered in the order of appearance, use CVS to get your
603cdf0e10cSrcweir // hands on the old version), therefore, I've sticked to that
604cdf0e10cSrcweir // order, and added four more cases. The code below references
605cdf0e10cSrcweir // those numbers via #1, #2, etc.
606cdf0e10cSrcweir //
607cdf0e10cSrcweir // Num Mnem newX:oldX newY:oldY Description Result Can quit?
608cdf0e10cSrcweir //
609cdf0e10cSrcweir // #1 Empty band - - The band is empty, thus, simply add new bandSep just add Yes
610cdf0e10cSrcweir //
611cdf0e10cSrcweir // #2 apart - - The rectangles are disjunct, add new one as is just add Yes
612cdf0e10cSrcweir //
613cdf0e10cSrcweir // #3 atop == == The rectangles are _exactly_ the same, remove existing just remove Yes
614cdf0e10cSrcweir //
615cdf0e10cSrcweir // #4 around < > The new rectangle extends the old to both sides intersect No
616cdf0e10cSrcweir //
617cdf0e10cSrcweir // #5 left < < The new rectangle is left of the old (but intersects) intersect Yes
618cdf0e10cSrcweir //
619cdf0e10cSrcweir // #5b left-atop < == The new is left of the old, and coincides on the right intersect Yes
620cdf0e10cSrcweir //
621cdf0e10cSrcweir // #6 right > > The new is right of the old (but intersects) intersect No
622cdf0e10cSrcweir //
623cdf0e10cSrcweir // #6b right-atop == > The new is right of the old, and coincides on the left intersect No
624cdf0e10cSrcweir //
625cdf0e10cSrcweir // #7 inside > < The new is fully inside the old intersect Yes
626cdf0e10cSrcweir //
627cdf0e10cSrcweir // #8 inside-right > == The new is fully inside the old, coincides on the right intersect Yes
628cdf0e10cSrcweir //
629cdf0e10cSrcweir // #9 inside-left == < The new is fully inside the old, coincides on the left intersect Yes
630cdf0e10cSrcweir //
631cdf0e10cSrcweir //
632cdf0e10cSrcweir // Then, to correctly perform XOr, the segment that's switched off
633cdf0e10cSrcweir // (i.e. the overlapping part of the old and the new segment) must
634cdf0e10cSrcweir // be extended by one pixel value at each border:
635cdf0e10cSrcweir // 1 1
636cdf0e10cSrcweir // 0 4 0 4
637cdf0e10cSrcweir // 111100000001111
638cdf0e10cSrcweir //
639cdf0e10cSrcweir // Clearly, the leading band sep now goes from 0 to 3, and the
640cdf0e10cSrcweir // trailing band sep from 11 to 14. This mimicks the xor look of a
641cdf0e10cSrcweir // bitmap operation.
642cdf0e10cSrcweir //
643cdf0e10cSrcweir
644cdf0e10cSrcweir // band empty? -> add element
645cdf0e10cSrcweir if ( !mpFirstSep )
646cdf0e10cSrcweir {
647cdf0e10cSrcweir mpFirstSep = new ImplRegionBandSep;
648cdf0e10cSrcweir mpFirstSep->mnXLeft = nXLeft;
649cdf0e10cSrcweir mpFirstSep->mnXRight = nXRight;
650*e6f63103SArmin Le Grand mpFirstSep->mbRemoved = false;
651cdf0e10cSrcweir mpFirstSep->mpNextSep = NULL;
652cdf0e10cSrcweir return;
653cdf0e10cSrcweir }
654cdf0e10cSrcweir
655cdf0e10cSrcweir // process real xor
656cdf0e10cSrcweir ImplRegionBandSep* pNewSep;
657cdf0e10cSrcweir ImplRegionBandSep* pPrevSep = 0;
658cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
659cdf0e10cSrcweir
660cdf0e10cSrcweir while ( pSep )
661cdf0e10cSrcweir {
662cdf0e10cSrcweir long nOldLeft( pSep->mnXLeft );
663cdf0e10cSrcweir long nOldRight( pSep->mnXRight );
664cdf0e10cSrcweir
665cdf0e10cSrcweir // did the current segment actually touch the new rect? If
666cdf0e10cSrcweir // not, skip all comparisons, go on, loop and try to find
667cdf0e10cSrcweir // intersecting bandSep
668cdf0e10cSrcweir if( nXLeft <= nOldRight )
669cdf0e10cSrcweir {
670cdf0e10cSrcweir if( nXRight < nOldLeft )
671cdf0e10cSrcweir {
672cdf0e10cSrcweir // #2
673cdf0e10cSrcweir
674cdf0e10cSrcweir // add _before_ current bandSep
675cdf0e10cSrcweir pNewSep = new ImplRegionBandSep;
676cdf0e10cSrcweir pNewSep->mnXLeft = nXLeft;
677cdf0e10cSrcweir pNewSep->mnXRight = nXRight;
678cdf0e10cSrcweir pNewSep->mpNextSep = pSep;
679*e6f63103SArmin Le Grand pNewSep->mbRemoved = false;
680cdf0e10cSrcweir
681cdf0e10cSrcweir // connections from the new separation
682cdf0e10cSrcweir pNewSep->mpNextSep = pSep;
683cdf0e10cSrcweir
684cdf0e10cSrcweir // connections to the new separation
685cdf0e10cSrcweir if ( pSep == mpFirstSep )
686cdf0e10cSrcweir mpFirstSep = pNewSep;
687cdf0e10cSrcweir else
688cdf0e10cSrcweir pPrevSep->mpNextSep = pNewSep;
689cdf0e10cSrcweir pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
690cdf0e10cSrcweir break;
691cdf0e10cSrcweir }
692cdf0e10cSrcweir else if( nXLeft == nOldLeft && nXRight == nOldRight )
693cdf0e10cSrcweir {
694cdf0e10cSrcweir // #3
695*e6f63103SArmin Le Grand pSep->mbRemoved = true;
696cdf0e10cSrcweir pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
697cdf0e10cSrcweir break;
698cdf0e10cSrcweir }
699cdf0e10cSrcweir else if( nXLeft != nOldLeft && nXRight == nOldRight )
700cdf0e10cSrcweir {
701cdf0e10cSrcweir // # 5b, 8
702cdf0e10cSrcweir if( nXLeft < nOldLeft )
703cdf0e10cSrcweir {
704cdf0e10cSrcweir nXRight = nOldLeft; // 5b
705cdf0e10cSrcweir }
706cdf0e10cSrcweir else
707cdf0e10cSrcweir {
708cdf0e10cSrcweir nXRight = nXLeft; // 8
709cdf0e10cSrcweir nXLeft = nOldLeft;
710cdf0e10cSrcweir }
711cdf0e10cSrcweir
712cdf0e10cSrcweir pSep->mnXLeft = nXLeft;
713cdf0e10cSrcweir pSep->mnXRight = nXRight-1;
714cdf0e10cSrcweir
715cdf0e10cSrcweir pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
716cdf0e10cSrcweir break;
717cdf0e10cSrcweir }
718cdf0e10cSrcweir else if( nXLeft == nOldLeft && nXRight != nOldRight )
719cdf0e10cSrcweir {
720cdf0e10cSrcweir // # 6b, 9
721cdf0e10cSrcweir
722cdf0e10cSrcweir if( nXRight > nOldRight )
723cdf0e10cSrcweir {
724cdf0e10cSrcweir nXLeft = nOldRight+1; // 6b
725cdf0e10cSrcweir
726cdf0e10cSrcweir // cannot break here, simply mark segment as removed,
727cdf0e10cSrcweir // and go on with adapted nXLeft/nXRight
728*e6f63103SArmin Le Grand pSep->mbRemoved = true;
729cdf0e10cSrcweir }
730cdf0e10cSrcweir else
731cdf0e10cSrcweir {
732cdf0e10cSrcweir pSep->mnXLeft = nXRight+1; // 9
733cdf0e10cSrcweir
734cdf0e10cSrcweir pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
735cdf0e10cSrcweir break;
736cdf0e10cSrcweir }
737cdf0e10cSrcweir }
738cdf0e10cSrcweir else // if( nXLeft != nOldLeft && nXRight != nOldRight ) follows automatically
739cdf0e10cSrcweir {
740cdf0e10cSrcweir // #4,5,6,7
741cdf0e10cSrcweir DBG_ASSERT( nXLeft != nOldLeft && nXRight != nOldRight,
742cdf0e10cSrcweir "ImplRegionBand::XOr(): Case 4,5,6,7 expected all coordinates to be not equal!" );
743cdf0e10cSrcweir
744cdf0e10cSrcweir // The plain-jane check would look like this:
745cdf0e10cSrcweir //
746cdf0e10cSrcweir // if( nXLeft < nOldLeft )
747cdf0e10cSrcweir // {
748cdf0e10cSrcweir // // #4,5
749cdf0e10cSrcweir // if( nXRight > nOldRight )
750cdf0e10cSrcweir // {
751cdf0e10cSrcweir // // #4
752cdf0e10cSrcweir // }
753cdf0e10cSrcweir // else
754cdf0e10cSrcweir // {
755cdf0e10cSrcweir // // #5 done!
756cdf0e10cSrcweir // }
757cdf0e10cSrcweir // }
758cdf0e10cSrcweir // else
759cdf0e10cSrcweir // {
760cdf0e10cSrcweir // // #6,7
761cdf0e10cSrcweir // if( nXRight > nOldRight )
762cdf0e10cSrcweir // {
763cdf0e10cSrcweir // // #6
764cdf0e10cSrcweir // }
765cdf0e10cSrcweir // else
766cdf0e10cSrcweir // {
767cdf0e10cSrcweir // // #7 done!
768cdf0e10cSrcweir // }
769cdf0e10cSrcweir // }
770cdf0e10cSrcweir //
771cdf0e10cSrcweir // but since we generally don't have to care whether
772cdf0e10cSrcweir // it's 4 or 6 (only that we must not stop processing
773cdf0e10cSrcweir // here), condensed that in such a way that only the
774cdf0e10cSrcweir // coordinates get shuffled into correct ordering.
775cdf0e10cSrcweir
776cdf0e10cSrcweir if( nXLeft < nOldLeft )
777cdf0e10cSrcweir ::std::swap( nOldLeft, nXLeft );
778cdf0e10cSrcweir
779cdf0e10cSrcweir bool bDone( false );
780cdf0e10cSrcweir
781cdf0e10cSrcweir if( nXRight < nOldRight )
782cdf0e10cSrcweir {
783cdf0e10cSrcweir ::std::swap( nOldRight, nXRight );
784cdf0e10cSrcweir bDone = true;
785cdf0e10cSrcweir }
786cdf0e10cSrcweir
787cdf0e10cSrcweir // now, nOldLeft<nXLeft<=nOldRight<nXRight always
788cdf0e10cSrcweir // holds. Note that we need the nXLeft<=nOldRight here, as
789cdf0e10cSrcweir // the intersection part might be only one pixel (original
790cdf0e10cSrcweir // nXLeft==nXRight)
791cdf0e10cSrcweir DBG_ASSERT( nOldLeft<nXLeft && nXLeft<=nOldRight && nOldRight<nXRight,
792cdf0e10cSrcweir "ImplRegionBand::XOr(): Case 4,5,6,7 expected coordinates to be ordered now!" );
793cdf0e10cSrcweir
794cdf0e10cSrcweir pSep->mnXLeft = nOldLeft;
795cdf0e10cSrcweir pSep->mnXRight = nXLeft-1;
796cdf0e10cSrcweir
797cdf0e10cSrcweir nXLeft = nOldRight+1;
798cdf0e10cSrcweir // nxRight is already setup correctly
799cdf0e10cSrcweir
800cdf0e10cSrcweir if( bDone )
801cdf0e10cSrcweir {
802cdf0e10cSrcweir // add behind current bandSep
803cdf0e10cSrcweir pNewSep = new ImplRegionBandSep;
804cdf0e10cSrcweir
805cdf0e10cSrcweir pNewSep->mnXLeft = nXLeft;
806cdf0e10cSrcweir pNewSep->mnXRight = nXRight;
807cdf0e10cSrcweir pNewSep->mpNextSep = pSep->mpNextSep;
808*e6f63103SArmin Le Grand pNewSep->mbRemoved = false;
809cdf0e10cSrcweir
810cdf0e10cSrcweir // connections from the new separation
811cdf0e10cSrcweir pSep->mpNextSep = pNewSep;
812cdf0e10cSrcweir
813cdf0e10cSrcweir pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
814cdf0e10cSrcweir break;
815cdf0e10cSrcweir }
816cdf0e10cSrcweir }
817cdf0e10cSrcweir }
818cdf0e10cSrcweir
819cdf0e10cSrcweir pPrevSep = pSep;
820cdf0e10cSrcweir pSep = pSep->mpNextSep;
821cdf0e10cSrcweir }
822cdf0e10cSrcweir
823cdf0e10cSrcweir // new separation completely right of existing bandSeps ?
824cdf0e10cSrcweir if( pPrevSep && nXLeft >= pPrevSep->mnXRight )
825cdf0e10cSrcweir {
826cdf0e10cSrcweir pNewSep = new ImplRegionBandSep;
827cdf0e10cSrcweir pNewSep->mnXLeft = nXLeft;
828cdf0e10cSrcweir pNewSep->mnXRight = nXRight;
829cdf0e10cSrcweir pNewSep->mpNextSep = NULL;
830*e6f63103SArmin Le Grand pNewSep->mbRemoved = false;
831cdf0e10cSrcweir
832cdf0e10cSrcweir // connections from the new separation
833cdf0e10cSrcweir pPrevSep->mpNextSep = pNewSep;
834cdf0e10cSrcweir }
835cdf0e10cSrcweir
836cdf0e10cSrcweir OptimizeBand();
837cdf0e10cSrcweir }
838cdf0e10cSrcweir
839cdf0e10cSrcweir // -----------------------------------------------------------------------
840cdf0e10cSrcweir
IsInside(long nX)841*e6f63103SArmin Le Grand bool ImplRegionBand::IsInside( long nX )
842cdf0e10cSrcweir {
843cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
844cdf0e10cSrcweir while ( pSep )
845cdf0e10cSrcweir {
846cdf0e10cSrcweir if ( (pSep->mnXLeft <= nX) && (pSep->mnXRight >= nX) )
847*e6f63103SArmin Le Grand return true;
848cdf0e10cSrcweir
849cdf0e10cSrcweir pSep = pSep->mpNextSep;
850cdf0e10cSrcweir }
851cdf0e10cSrcweir
852*e6f63103SArmin Le Grand return false;
853cdf0e10cSrcweir }
854cdf0e10cSrcweir
855cdf0e10cSrcweir // -----------------------------------------------------------------------
856cdf0e10cSrcweir
IsOver(long nLeft,long nRight)857*e6f63103SArmin Le Grand bool ImplRegionBand::IsOver( long nLeft, long nRight )
858cdf0e10cSrcweir {
859cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
860cdf0e10cSrcweir while ( pSep )
861cdf0e10cSrcweir {
862cdf0e10cSrcweir if ( (pSep->mnXLeft < nRight) && (pSep->mnXRight > nLeft) )
863*e6f63103SArmin Le Grand return true;
864cdf0e10cSrcweir
865cdf0e10cSrcweir pSep = pSep->mpNextSep;
866cdf0e10cSrcweir }
867cdf0e10cSrcweir
868*e6f63103SArmin Le Grand return false;
869cdf0e10cSrcweir }
870cdf0e10cSrcweir
871cdf0e10cSrcweir // -----------------------------------------------------------------------
872cdf0e10cSrcweir
IsInside(long nLeft,long nRight)873*e6f63103SArmin Le Grand bool ImplRegionBand::IsInside( long nLeft, long nRight )
874cdf0e10cSrcweir {
875cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
876cdf0e10cSrcweir while ( pSep )
877cdf0e10cSrcweir {
878cdf0e10cSrcweir if ( (pSep->mnXLeft >= nLeft) && (nRight <= pSep->mnXRight) )
879*e6f63103SArmin Le Grand return true;
880cdf0e10cSrcweir
881cdf0e10cSrcweir pSep = pSep->mpNextSep;
882cdf0e10cSrcweir }
883cdf0e10cSrcweir
884*e6f63103SArmin Le Grand return false;
885cdf0e10cSrcweir }
886cdf0e10cSrcweir
887cdf0e10cSrcweir // -----------------------------------------------------------------------
888cdf0e10cSrcweir
GetXLeftBoundary() const889cdf0e10cSrcweir long ImplRegionBand::GetXLeftBoundary() const
890cdf0e10cSrcweir {
891cdf0e10cSrcweir DBG_ASSERT( mpFirstSep != NULL, "ImplRegionBand::XLeftBoundary -> no separation in band!" );
892cdf0e10cSrcweir
893cdf0e10cSrcweir return mpFirstSep->mnXLeft;
894cdf0e10cSrcweir }
895cdf0e10cSrcweir
896cdf0e10cSrcweir // -----------------------------------------------------------------------
897cdf0e10cSrcweir
GetXRightBoundary() const898cdf0e10cSrcweir long ImplRegionBand::GetXRightBoundary() const
899cdf0e10cSrcweir {
900cdf0e10cSrcweir DBG_ASSERT( mpFirstSep != NULL, "ImplRegionBand::XRightBoundary -> no separation in band!" );
901cdf0e10cSrcweir
902cdf0e10cSrcweir // search last separation
903cdf0e10cSrcweir ImplRegionBandSep* pSep = mpFirstSep;
904cdf0e10cSrcweir while ( pSep->mpNextSep )
905cdf0e10cSrcweir pSep = pSep->mpNextSep;
906cdf0e10cSrcweir return pSep->mnXRight;
907cdf0e10cSrcweir }
908cdf0e10cSrcweir
909cdf0e10cSrcweir // -----------------------------------------------------------------------
910cdf0e10cSrcweir
operator ==(const ImplRegionBand & rRegionBand) const911*e6f63103SArmin Le Grand bool ImplRegionBand::operator==( const ImplRegionBand& rRegionBand ) const
912cdf0e10cSrcweir {
913cdf0e10cSrcweir ImplRegionBandSep* pOwnRectBandSep = mpFirstSep;
914cdf0e10cSrcweir ImplRegionBandSep* pSecondRectBandSep = rRegionBand.mpFirstSep;
915cdf0e10cSrcweir while ( pOwnRectBandSep && pSecondRectBandSep )
916cdf0e10cSrcweir {
917cdf0e10cSrcweir // get boundaries of current rectangle
918cdf0e10cSrcweir long nOwnXLeft = pOwnRectBandSep->mnXLeft;
919cdf0e10cSrcweir long nSecondXLeft = pSecondRectBandSep->mnXLeft;
920cdf0e10cSrcweir if ( nOwnXLeft != nSecondXLeft )
921*e6f63103SArmin Le Grand return false;
922cdf0e10cSrcweir
923cdf0e10cSrcweir long nOwnXRight = pOwnRectBandSep->mnXRight;
924cdf0e10cSrcweir long nSecondXRight = pSecondRectBandSep->mnXRight;
925cdf0e10cSrcweir if ( nOwnXRight != nSecondXRight )
926*e6f63103SArmin Le Grand return false;
927cdf0e10cSrcweir
928cdf0e10cSrcweir // get next separation from current band
929cdf0e10cSrcweir pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
930cdf0e10cSrcweir
931cdf0e10cSrcweir // get next separation from current band
932cdf0e10cSrcweir pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
933cdf0e10cSrcweir }
934cdf0e10cSrcweir
935cdf0e10cSrcweir // differnt number of separations?
936cdf0e10cSrcweir if ( pOwnRectBandSep || pSecondRectBandSep )
937*e6f63103SArmin Le Grand return false;
938cdf0e10cSrcweir
939*e6f63103SArmin Le Grand return true;
940cdf0e10cSrcweir }
941cdf0e10cSrcweir
942cdf0e10cSrcweir // -----------------------------------------------------------------------
943cdf0e10cSrcweir
SplitBand(const sal_Int32 nY)944cdf0e10cSrcweir ImplRegionBand* ImplRegionBand::SplitBand (const sal_Int32 nY)
945cdf0e10cSrcweir {
946cdf0e10cSrcweir OSL_ASSERT(nY>mnYTop);
947cdf0e10cSrcweir OSL_ASSERT(nY<=mnYBottom);
948cdf0e10cSrcweir
949cdf0e10cSrcweir // Create a copy of the given band (we tell the constructor to copy the points together
950cdf0e10cSrcweir // with the seps.)
951cdf0e10cSrcweir ImplRegionBand* pLowerBand = new ImplRegionBand(*this, false);
952cdf0e10cSrcweir
953cdf0e10cSrcweir // Adapt vertical coordinates.
954cdf0e10cSrcweir mnYBottom = nY-1;
955cdf0e10cSrcweir pLowerBand->mnYTop = nY;
956cdf0e10cSrcweir
957cdf0e10cSrcweir // Insert new band into list of bands.
958cdf0e10cSrcweir pLowerBand->mpNextBand = mpNextBand;
959cdf0e10cSrcweir mpNextBand = pLowerBand;
960cdf0e10cSrcweir pLowerBand->mpPrevBand = this;
961cdf0e10cSrcweir if (pLowerBand->mpNextBand != NULL)
962cdf0e10cSrcweir pLowerBand->mpNextBand->mpPrevBand = pLowerBand;
963cdf0e10cSrcweir
964cdf0e10cSrcweir return pLowerBand;
965cdf0e10cSrcweir }
966