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