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