xref: /OK3568_Linux_fs/external/xserver/mi/mizerclip.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /***********************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1987, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun                         All Rights Reserved
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
30*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
31*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
32*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
33*4882a593Smuzhiyun supporting documentation, and that the name of Digital not be
34*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
35*4882a593Smuzhiyun software without specific, written prior permission.
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39*4882a593Smuzhiyun DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43*4882a593Smuzhiyun SOFTWARE.
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun ******************************************************************/
46*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
47*4882a593Smuzhiyun #include <dix-config.h>
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #include <X11/X.h>
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #include "misc.h"
53*4882a593Smuzhiyun #include "scrnintstr.h"
54*4882a593Smuzhiyun #include "gcstruct.h"
55*4882a593Smuzhiyun #include "windowstr.h"
56*4882a593Smuzhiyun #include "pixmap.h"
57*4882a593Smuzhiyun #include "mi.h"
58*4882a593Smuzhiyun #include "miline.h"
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun The bresenham error equation used in the mi/mfb/cfb line routines is:
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	e = error
65*4882a593Smuzhiyun 	dx = difference in raw X coordinates
66*4882a593Smuzhiyun 	dy = difference in raw Y coordinates
67*4882a593Smuzhiyun 	M = # of steps in X direction
68*4882a593Smuzhiyun 	N = # of steps in Y direction
69*4882a593Smuzhiyun 	B = 0 to prefer diagonal steps in a given octant,
70*4882a593Smuzhiyun 	    1 to prefer axial steps in a given octant
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	For X major lines:
73*4882a593Smuzhiyun 		e = 2Mdy - 2Ndx - dx - B
74*4882a593Smuzhiyun 		-2dx <= e < 0
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	For Y major lines:
77*4882a593Smuzhiyun 		e = 2Ndx - 2Mdy - dy - B
78*4882a593Smuzhiyun 		-2dy <= e < 0
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun At the start of the line, we have taken 0 X steps and 0 Y steps,
81*4882a593Smuzhiyun so M = 0 and N = 0:
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	X major	e = 2Mdy - 2Ndx - dx - B
84*4882a593Smuzhiyun 		  = -dx - B
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	Y major	e = 2Ndx - 2Mdy - dy - B
87*4882a593Smuzhiyun 		  = -dy - B
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun At the end of the line, we have taken dx X steps and dy Y steps,
90*4882a593Smuzhiyun so M = dx and N = dy:
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	X major	e = 2Mdy - 2Ndx - dx - B
93*4882a593Smuzhiyun 		  = 2dxdy - 2dydx - dx - B
94*4882a593Smuzhiyun 		  = -dx - B
95*4882a593Smuzhiyun 	Y major e = 2Ndx - 2Mdy - dy - B
96*4882a593Smuzhiyun 		  = 2dydx - 2dxdy - dy - B
97*4882a593Smuzhiyun 		  = -dy - B
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun Thus, the error term is the same at the start and end of the line.
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun Let us consider clipping an X coordinate.  There are 4 cases which
102*4882a593Smuzhiyun represent the two independent cases of clipping the start vs. the
103*4882a593Smuzhiyun end of the line and an X major vs. a Y major line.  In any of these
104*4882a593Smuzhiyun cases, we know the number of X steps (M) and we wish to find the
105*4882a593Smuzhiyun number of Y steps (N).  Thus, we will solve our error term equation.
106*4882a593Smuzhiyun If we are clipping the start of the line, we will find the smallest
107*4882a593Smuzhiyun N that satisfies our error term inequality.  If we are clipping the
108*4882a593Smuzhiyun end of the line, we will find the largest number of Y steps that
109*4882a593Smuzhiyun satisfies the inequality.  In that case, since we are representing
110*4882a593Smuzhiyun the Y steps as (dy - N), we will actually want to solve for the
111*4882a593Smuzhiyun smallest N in that equation.
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun Case 1:  X major, starting X coordinate moved by M steps
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 		-2dx <= 2Mdy - 2Ndx - dx - B < 0
116*4882a593Smuzhiyun 	2Ndx <= 2Mdy - dx - B + 2dx	2Ndx > 2Mdy - dx - B
117*4882a593Smuzhiyun 	2Ndx <= 2Mdy + dx - B		N > (2Mdy - dx - B) / 2dx
118*4882a593Smuzhiyun 	N <= (2Mdy + dx - B) / 2dx
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun Since we are trying to find the smallest N that satisfies these
121*4882a593Smuzhiyun equations, we should use the > inequality to find the smallest:
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	N = floor((2Mdy - dx - B) / 2dx) + 1
124*4882a593Smuzhiyun 	  = floor((2Mdy - dx - B + 2dx) / 2dx)
125*4882a593Smuzhiyun 	  = floor((2Mdy + dx - B) / 2dx)
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun Case 1b: X major, ending X coordinate moved to M steps
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun Same derivations as Case 1, but we want the largest N that satisfies
130*4882a593Smuzhiyun the equations, so we use the <= inequality:
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	N = floor((2Mdy + dx - B) / 2dx)
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun Case 2: X major, ending X coordinate moved by M steps
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 		-2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0
137*4882a593Smuzhiyun 		-2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0
138*4882a593Smuzhiyun 		-2dx <= 2Ndx - 2Mdy - dx - B < 0
139*4882a593Smuzhiyun 	2Ndx >= 2Mdy + dx + B - 2dx	2Ndx < 2Mdy + dx + B
140*4882a593Smuzhiyun 	2Ndx >= 2Mdy - dx + B		N < (2Mdy + dx + B) / 2dx
141*4882a593Smuzhiyun 	N >= (2Mdy - dx + B) / 2dx
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun Since we are trying to find the highest number of Y steps that
144*4882a593Smuzhiyun satisfies these equations, we need to find the smallest N, so
145*4882a593Smuzhiyun we should use the >= inequality to find the smallest:
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	N = ceiling((2Mdy - dx + B) / 2dx)
148*4882a593Smuzhiyun 	  = floor((2Mdy - dx + B + 2dx - 1) / 2dx)
149*4882a593Smuzhiyun 	  = floor((2Mdy + dx + B - 1) / 2dx)
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun Case 2b: X major, starting X coordinate moved to M steps from end
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun Same derivations as Case 2, but we want the smallest number of Y
154*4882a593Smuzhiyun steps, so we want the highest N, so we use the < inequality:
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	N = ceiling((2Mdy + dx + B) / 2dx) - 1
157*4882a593Smuzhiyun 	  = floor((2Mdy + dx + B + 2dx - 1) / 2dx) - 1
158*4882a593Smuzhiyun 	  = floor((2Mdy + dx + B + 2dx - 1 - 2dx) / 2dx)
159*4882a593Smuzhiyun 	  = floor((2Mdy + dx + B - 1) / 2dx)
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun Case 3: Y major, starting X coordinate moved by M steps
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 		-2dy <= 2Ndx - 2Mdy - dy - B < 0
164*4882a593Smuzhiyun 	2Ndx >= 2Mdy + dy + B - 2dy	2Ndx < 2Mdy + dy + B
165*4882a593Smuzhiyun 	2Ndx >= 2Mdy - dy + B		N < (2Mdy + dy + B) / 2dx
166*4882a593Smuzhiyun 	N >= (2Mdy - dy + B) / 2dx
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun Since we are trying to find the smallest N that satisfies these
169*4882a593Smuzhiyun equations, we should use the >= inequality to find the smallest:
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	N = ceiling((2Mdy - dy + B) / 2dx)
172*4882a593Smuzhiyun 	  = floor((2Mdy - dy + B + 2dx - 1) / 2dx)
173*4882a593Smuzhiyun 	  = floor((2Mdy - dy + B - 1) / 2dx) + 1
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun Case 3b: Y major, ending X coordinate moved to M steps
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun Same derivations as Case 3, but we want the largest N that satisfies
178*4882a593Smuzhiyun the equations, so we use the < inequality:
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	N = ceiling((2Mdy + dy + B) / 2dx) - 1
181*4882a593Smuzhiyun 	  = floor((2Mdy + dy + B + 2dx - 1) / 2dx) - 1
182*4882a593Smuzhiyun 	  = floor((2Mdy + dy + B + 2dx - 1 - 2dx) / 2dx)
183*4882a593Smuzhiyun 	  = floor((2Mdy + dy + B - 1) / 2dx)
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun Case 4: Y major, ending X coordinate moved by M steps
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 		-2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0
188*4882a593Smuzhiyun 		-2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0
189*4882a593Smuzhiyun 		-2dy <= 2Mdy - 2Ndx - dy - B < 0
190*4882a593Smuzhiyun 	2Ndx <= 2Mdy - dy - B + 2dy	2Ndx > 2Mdy - dy - B
191*4882a593Smuzhiyun 	2Ndx <= 2Mdy + dy - B		N > (2Mdy - dy - B) / 2dx
192*4882a593Smuzhiyun 	N <= (2Mdy + dy - B) / 2dx
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun Since we are trying to find the highest number of Y steps that
195*4882a593Smuzhiyun satisfies these equations, we need to find the smallest N, so
196*4882a593Smuzhiyun we should use the > inequality to find the smallest:
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	N = floor((2Mdy - dy - B) / 2dx) + 1
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun Case 4b: Y major, starting X coordinate moved to M steps from end
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun Same analysis as Case 4, but we want the smallest number of Y steps
203*4882a593Smuzhiyun which means the largest N, so we use the <= inequality:
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	N = floor((2Mdy + dy - B) / 2dx)
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun Now let's try the Y coordinates, we have the same 4 cases.
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun Case 5: X major, starting Y coordinate moved by N steps
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 		-2dx <= 2Mdy - 2Ndx - dx - B < 0
212*4882a593Smuzhiyun 	2Mdy >= 2Ndx + dx + B - 2dx	2Mdy < 2Ndx + dx + B
213*4882a593Smuzhiyun 	2Mdy >= 2Ndx - dx + B		M < (2Ndx + dx + B) / 2dy
214*4882a593Smuzhiyun 	M >= (2Ndx - dx + B) / 2dy
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun Since we are trying to find the smallest M, we use the >= inequality:
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	M = ceiling((2Ndx - dx + B) / 2dy)
219*4882a593Smuzhiyun 	  = floor((2Ndx - dx + B + 2dy - 1) / 2dy)
220*4882a593Smuzhiyun 	  = floor((2Ndx - dx + B - 1) / 2dy) + 1
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun Case 5b: X major, ending Y coordinate moved to N steps
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun Same derivations as Case 5, but we want the largest M that satisfies
225*4882a593Smuzhiyun the equations, so we use the < inequality:
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	M = ceiling((2Ndx + dx + B) / 2dy) - 1
228*4882a593Smuzhiyun 	  = floor((2Ndx + dx + B + 2dy - 1) / 2dy) - 1
229*4882a593Smuzhiyun 	  = floor((2Ndx + dx + B + 2dy - 1 - 2dy) / 2dy)
230*4882a593Smuzhiyun 	  = floor((2Ndx + dx + B - 1) / 2dy)
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun Case 6: X major, ending Y coordinate moved by N steps
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 		-2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0
235*4882a593Smuzhiyun 		-2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0
236*4882a593Smuzhiyun 		-2dx <= 2Ndx - 2Mdy - dx - B < 0
237*4882a593Smuzhiyun 	2Mdy <= 2Ndx - dx - B + 2dx	2Mdy > 2Ndx - dx - B
238*4882a593Smuzhiyun 	2Mdy <= 2Ndx + dx - B		M > (2Ndx - dx - B) / 2dy
239*4882a593Smuzhiyun 	M <= (2Ndx + dx - B) / 2dy
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun Largest # of X steps means smallest M, so use the > inequality:
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	M = floor((2Ndx - dx - B) / 2dy) + 1
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun Case 6b: X major, starting Y coordinate moved to N steps from end
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun Same derivations as Case 6, but we want the smallest # of X steps
248*4882a593Smuzhiyun which means the largest M, so use the <= inequality:
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	M = floor((2Ndx + dx - B) / 2dy)
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun Case 7: Y major, starting Y coordinate moved by N steps
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 		-2dy <= 2Ndx - 2Mdy - dy - B < 0
255*4882a593Smuzhiyun 	2Mdy <= 2Ndx - dy - B + 2dy	2Mdy > 2Ndx - dy - B
256*4882a593Smuzhiyun 	2Mdy <= 2Ndx + dy - B		M > (2Ndx - dy - B) / 2dy
257*4882a593Smuzhiyun 	M <= (2Ndx + dy - B) / 2dy
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun To find the smallest M, use the > inequality:
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	M = floor((2Ndx - dy - B) / 2dy) + 1
262*4882a593Smuzhiyun 	  = floor((2Ndx - dy - B + 2dy) / 2dy)
263*4882a593Smuzhiyun 	  = floor((2Ndx + dy - B) / 2dy)
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun Case 7b: Y major, ending Y coordinate moved to N steps
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun Same derivations as Case 7, but we want the largest M that satisfies
268*4882a593Smuzhiyun the equations, so use the <= inequality:
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	M = floor((2Ndx + dy - B) / 2dy)
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun Case 8: Y major, ending Y coordinate moved by N steps
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 		-2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0
275*4882a593Smuzhiyun 		-2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0
276*4882a593Smuzhiyun 		-2dy <= 2Mdy - 2Ndx - dy - B < 0
277*4882a593Smuzhiyun 	2Mdy >= 2Ndx + dy + B - 2dy	2Mdy < 2Ndx + dy + B
278*4882a593Smuzhiyun 	2Mdy >= 2Ndx - dy + B		M < (2Ndx + dy + B) / 2dy
279*4882a593Smuzhiyun 	M >= (2Ndx - dy + B) / 2dy
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun To find the highest X steps, find the smallest M, use the >= inequality:
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	M = ceiling((2Ndx - dy + B) / 2dy)
284*4882a593Smuzhiyun 	  = floor((2Ndx - dy + B + 2dy - 1) / 2dy)
285*4882a593Smuzhiyun 	  = floor((2Ndx + dy + B - 1) / 2dy)
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun Case 8b: Y major, starting Y coordinate moved to N steps from the end
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun Same derivations as Case 8, but we want to find the smallest # of X
290*4882a593Smuzhiyun steps which means the largest M, so we use the < inequality:
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	M = ceiling((2Ndx + dy + B) / 2dy) - 1
293*4882a593Smuzhiyun 	  = floor((2Ndx + dy + B + 2dy - 1) / 2dy) - 1
294*4882a593Smuzhiyun 	  = floor((2Ndx + dy + B + 2dy - 1 - 2dy) / 2dy)
295*4882a593Smuzhiyun 	  = floor((2Ndx + dy + B - 1) / 2dy)
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun So, our equations are:
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	1:  X major move x1 to x1+M	floor((2Mdy + dx - B) / 2dx)
300*4882a593Smuzhiyun 	1b: X major move x2 to x1+M	floor((2Mdy + dx - B) / 2dx)
301*4882a593Smuzhiyun 	2:  X major move x2 to x2-M	floor((2Mdy + dx + B - 1) / 2dx)
302*4882a593Smuzhiyun 	2b: X major move x1 to x2-M	floor((2Mdy + dx + B - 1) / 2dx)
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	3:  Y major move x1 to x1+M	floor((2Mdy - dy + B - 1) / 2dx) + 1
305*4882a593Smuzhiyun 	3b: Y major move x2 to x1+M	floor((2Mdy + dy + B - 1) / 2dx)
306*4882a593Smuzhiyun 	4:  Y major move x2 to x2-M	floor((2Mdy - dy - B) / 2dx) + 1
307*4882a593Smuzhiyun 	4b: Y major move x1 to x2-M	floor((2Mdy + dy - B) / 2dx)
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	5:  X major move y1 to y1+N	floor((2Ndx - dx + B - 1) / 2dy) + 1
310*4882a593Smuzhiyun 	5b: X major move y2 to y1+N	floor((2Ndx + dx + B - 1) / 2dy)
311*4882a593Smuzhiyun 	6:  X major move y2 to y2-N	floor((2Ndx - dx - B) / 2dy) + 1
312*4882a593Smuzhiyun 	6b: X major move y1 to y2-N	floor((2Ndx + dx - B) / 2dy)
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	7:  Y major move y1 to y1+N	floor((2Ndx + dy - B) / 2dy)
315*4882a593Smuzhiyun 	7b: Y major move y2 to y1+N	floor((2Ndx + dy - B) / 2dy)
316*4882a593Smuzhiyun 	8:  Y major move y2 to y2-N	floor((2Ndx + dy + B - 1) / 2dy)
317*4882a593Smuzhiyun 	8b: Y major move y1 to y2-N	floor((2Ndx + dy + B - 1) / 2dy)
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun We have the following constraints on all of the above terms:
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	0 < M,N <= 2^15		 2^15 can be imposed by miZeroClipLine
322*4882a593Smuzhiyun 	0 <= dx/dy <= 2^16 - 1
323*4882a593Smuzhiyun 	0 <= B <= 1
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun The floor in all of the above equations can be accomplished with a
326*4882a593Smuzhiyun simple C divide operation provided that both numerator and denominator
327*4882a593Smuzhiyun are positive.
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun Since dx,dy >= 0 and since moving an X coordinate implies that dx != 0
330*4882a593Smuzhiyun and moving a Y coordinate implies dy != 0, we know that the denominators
331*4882a593Smuzhiyun are all > 0.
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun For all lines, (-B) and (B-1) are both either 0 or -1, depending on the
334*4882a593Smuzhiyun bias.  Thus, we have to show that the 2MNdxy +/- dxy terms are all >= 1
335*4882a593Smuzhiyun or > 0 to prove that the numerators are positive (or zero).
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun For X Major lines we know that dx > 0 and since 2Mdy is >= 0 due to the
338*4882a593Smuzhiyun constraints, the first four equations all have numerators >= 0.
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun For the second four equations, M > 0, so 2Mdy >= 2dy so (2Mdy - dy) >= dy
341*4882a593Smuzhiyun So (2Mdy - dy) > 0, since they are Y major lines.  Also, (2Mdy + dy) >= 3dy
342*4882a593Smuzhiyun or (2Mdy + dy) > 0.  So all of their numerators are >= 0.
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun For the third set of four equations, N > 0, so 2Ndx >= 2dx so (2Ndx - dx)
345*4882a593Smuzhiyun >= dx > 0.  Similarly (2Ndx + dx) >= 3dx > 0.  So all numerators >= 0.
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun For the fourth set of equations, dy > 0 and 2Ndx >= 0, so all numerators
348*4882a593Smuzhiyun are > 0.
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun To consider overflow, consider the case of 2 * M,N * dx,dy + dx,dy.  This
351*4882a593Smuzhiyun is bounded <= 2 * 2^15 * (2^16 - 1) + (2^16 - 1)
352*4882a593Smuzhiyun 	   <= 2^16 * (2^16 - 1) + (2^16 - 1)
353*4882a593Smuzhiyun 	   <= 2^32 - 2^16 + 2^16 - 1
354*4882a593Smuzhiyun 	   <= 2^32 - 1
355*4882a593Smuzhiyun Since the (-B) and (B-1) terms are all 0 or -1, the maximum value of
356*4882a593Smuzhiyun the numerator is therefore (2^32 - 1), which does not overflow an unsigned
357*4882a593Smuzhiyun 32 bit variable.
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun */
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun /* Bit codes for the terms of the 16 clipping equations defined below. */
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun #define T_2NDX		(1 << 0)
364*4882a593Smuzhiyun #define T_2MDY		(0)     /* implicit term */
365*4882a593Smuzhiyun #define T_DXNOTY	(1 << 1)
366*4882a593Smuzhiyun #define T_DYNOTX	(0)     /* implicit term */
367*4882a593Smuzhiyun #define T_SUBDXORY	(1 << 2)
368*4882a593Smuzhiyun #define T_ADDDX		(T_DXNOTY)      /* composite term */
369*4882a593Smuzhiyun #define T_SUBDX		(T_DXNOTY | T_SUBDXORY) /* composite term */
370*4882a593Smuzhiyun #define T_ADDDY		(T_DYNOTX)      /* composite term */
371*4882a593Smuzhiyun #define T_SUBDY		(T_DYNOTX | T_SUBDXORY) /* composite term */
372*4882a593Smuzhiyun #define T_BIASSUBONE	(1 << 3)
373*4882a593Smuzhiyun #define T_SUBBIAS	(0)     /* implicit term */
374*4882a593Smuzhiyun #define T_DIV2DX	(1 << 4)
375*4882a593Smuzhiyun #define T_DIV2DY	(0)     /* implicit term */
376*4882a593Smuzhiyun #define T_ADDONE	(1 << 5)
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun /* Bit masks defining the 16 equations used in miZeroClipLine. */
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun #define EQN1	(T_2MDY | T_ADDDX | T_SUBBIAS    | T_DIV2DX)
381*4882a593Smuzhiyun #define EQN1B	(T_2MDY | T_ADDDX | T_SUBBIAS    | T_DIV2DX)
382*4882a593Smuzhiyun #define EQN2	(T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX)
383*4882a593Smuzhiyun #define EQN2B	(T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX)
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun #define EQN3	(T_2MDY | T_SUBDY | T_BIASSUBONE | T_DIV2DX | T_ADDONE)
386*4882a593Smuzhiyun #define EQN3B	(T_2MDY | T_ADDDY | T_BIASSUBONE | T_DIV2DX)
387*4882a593Smuzhiyun #define EQN4	(T_2MDY | T_SUBDY | T_SUBBIAS    | T_DIV2DX | T_ADDONE)
388*4882a593Smuzhiyun #define EQN4B	(T_2MDY | T_ADDDY | T_SUBBIAS    | T_DIV2DX)
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun #define EQN5	(T_2NDX | T_SUBDX | T_BIASSUBONE | T_DIV2DY | T_ADDONE)
391*4882a593Smuzhiyun #define EQN5B	(T_2NDX | T_ADDDX | T_BIASSUBONE | T_DIV2DY)
392*4882a593Smuzhiyun #define EQN6	(T_2NDX | T_SUBDX | T_SUBBIAS    | T_DIV2DY | T_ADDONE)
393*4882a593Smuzhiyun #define EQN6B	(T_2NDX | T_ADDDX | T_SUBBIAS    | T_DIV2DY)
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun #define EQN7	(T_2NDX | T_ADDDY | T_SUBBIAS    | T_DIV2DY)
396*4882a593Smuzhiyun #define EQN7B	(T_2NDX | T_ADDDY | T_SUBBIAS    | T_DIV2DY)
397*4882a593Smuzhiyun #define EQN8	(T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY)
398*4882a593Smuzhiyun #define EQN8B	(T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY)
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun /* miZeroClipLine
401*4882a593Smuzhiyun  *
402*4882a593Smuzhiyun  * returns:  1 for partially clipped line
403*4882a593Smuzhiyun  *          -1 for completely clipped line
404*4882a593Smuzhiyun  *
405*4882a593Smuzhiyun  */
406*4882a593Smuzhiyun int
miZeroClipLine(int xmin,int ymin,int xmax,int ymax,int * new_x1,int * new_y1,int * new_x2,int * new_y2,unsigned int adx,unsigned int ady,int * pt1_clipped,int * pt2_clipped,int octant,unsigned int bias,int oc1,int oc2)407*4882a593Smuzhiyun miZeroClipLine(int xmin, int ymin, int xmax, int ymax,
408*4882a593Smuzhiyun                int *new_x1, int *new_y1, int *new_x2, int *new_y2,
409*4882a593Smuzhiyun                unsigned int adx, unsigned int ady,
410*4882a593Smuzhiyun                int *pt1_clipped, int *pt2_clipped,
411*4882a593Smuzhiyun                int octant, unsigned int bias, int oc1, int oc2)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun     int swapped = 0;
414*4882a593Smuzhiyun     int clipDone = 0;
415*4882a593Smuzhiyun     CARD32 utmp = 0;
416*4882a593Smuzhiyun     int clip1, clip2;
417*4882a593Smuzhiyun     int x1, y1, x2, y2;
418*4882a593Smuzhiyun     int x1_orig, y1_orig, x2_orig, y2_orig;
419*4882a593Smuzhiyun     int xmajor;
420*4882a593Smuzhiyun     int negslope = 0, anchorval = 0;
421*4882a593Smuzhiyun     unsigned int eqn = 0;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun     x1 = x1_orig = *new_x1;
424*4882a593Smuzhiyun     y1 = y1_orig = *new_y1;
425*4882a593Smuzhiyun     x2 = x2_orig = *new_x2;
426*4882a593Smuzhiyun     y2 = y2_orig = *new_y2;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun     clip1 = 0;
429*4882a593Smuzhiyun     clip2 = 0;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun     xmajor = IsXMajorOctant(octant);
432*4882a593Smuzhiyun     bias = ((bias >> octant) & 1);
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun     while (1) {
435*4882a593Smuzhiyun         if ((oc1 & oc2) != 0) { /* trivial reject */
436*4882a593Smuzhiyun             clipDone = -1;
437*4882a593Smuzhiyun             clip1 = oc1;
438*4882a593Smuzhiyun             clip2 = oc2;
439*4882a593Smuzhiyun             break;
440*4882a593Smuzhiyun         }
441*4882a593Smuzhiyun         else if ((oc1 | oc2) == 0) {    /* trivial accept */
442*4882a593Smuzhiyun             clipDone = 1;
443*4882a593Smuzhiyun             if (swapped) {
444*4882a593Smuzhiyun                 SWAPINT_PAIR(x1, y1, x2, y2);
445*4882a593Smuzhiyun                 SWAPINT(clip1, clip2);
446*4882a593Smuzhiyun             }
447*4882a593Smuzhiyun             break;
448*4882a593Smuzhiyun         }
449*4882a593Smuzhiyun         else {                  /* have to clip */
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun             /* only clip one point at a time */
452*4882a593Smuzhiyun             if (oc1 == 0) {
453*4882a593Smuzhiyun                 SWAPINT_PAIR(x1, y1, x2, y2);
454*4882a593Smuzhiyun                 SWAPINT_PAIR(x1_orig, y1_orig, x2_orig, y2_orig);
455*4882a593Smuzhiyun                 SWAPINT(oc1, oc2);
456*4882a593Smuzhiyun                 SWAPINT(clip1, clip2);
457*4882a593Smuzhiyun                 swapped = !swapped;
458*4882a593Smuzhiyun             }
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun             clip1 |= oc1;
461*4882a593Smuzhiyun             if (oc1 & OUT_LEFT) {
462*4882a593Smuzhiyun                 negslope = IsYDecreasingOctant(octant);
463*4882a593Smuzhiyun                 utmp = xmin - x1_orig;
464*4882a593Smuzhiyun                 if (utmp <= 32767) {    /* clip based on near endpt */
465*4882a593Smuzhiyun                     if (xmajor)
466*4882a593Smuzhiyun                         eqn = (swapped) ? EQN2 : EQN1;
467*4882a593Smuzhiyun                     else
468*4882a593Smuzhiyun                         eqn = (swapped) ? EQN4 : EQN3;
469*4882a593Smuzhiyun                     anchorval = y1_orig;
470*4882a593Smuzhiyun                 }
471*4882a593Smuzhiyun                 else {          /* clip based on far endpt */
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun                     utmp = x2_orig - xmin;
474*4882a593Smuzhiyun                     if (xmajor)
475*4882a593Smuzhiyun                         eqn = (swapped) ? EQN1B : EQN2B;
476*4882a593Smuzhiyun                     else
477*4882a593Smuzhiyun                         eqn = (swapped) ? EQN3B : EQN4B;
478*4882a593Smuzhiyun                     anchorval = y2_orig;
479*4882a593Smuzhiyun                     negslope = !negslope;
480*4882a593Smuzhiyun                 }
481*4882a593Smuzhiyun                 x1 = xmin;
482*4882a593Smuzhiyun             }
483*4882a593Smuzhiyun             else if (oc1 & OUT_ABOVE) {
484*4882a593Smuzhiyun                 negslope = IsXDecreasingOctant(octant);
485*4882a593Smuzhiyun                 utmp = ymin - y1_orig;
486*4882a593Smuzhiyun                 if (utmp <= 32767) {    /* clip based on near endpt */
487*4882a593Smuzhiyun                     if (xmajor)
488*4882a593Smuzhiyun                         eqn = (swapped) ? EQN6 : EQN5;
489*4882a593Smuzhiyun                     else
490*4882a593Smuzhiyun                         eqn = (swapped) ? EQN8 : EQN7;
491*4882a593Smuzhiyun                     anchorval = x1_orig;
492*4882a593Smuzhiyun                 }
493*4882a593Smuzhiyun                 else {          /* clip based on far endpt */
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun                     utmp = y2_orig - ymin;
496*4882a593Smuzhiyun                     if (xmajor)
497*4882a593Smuzhiyun                         eqn = (swapped) ? EQN5B : EQN6B;
498*4882a593Smuzhiyun                     else
499*4882a593Smuzhiyun                         eqn = (swapped) ? EQN7B : EQN8B;
500*4882a593Smuzhiyun                     anchorval = x2_orig;
501*4882a593Smuzhiyun                     negslope = !negslope;
502*4882a593Smuzhiyun                 }
503*4882a593Smuzhiyun                 y1 = ymin;
504*4882a593Smuzhiyun             }
505*4882a593Smuzhiyun             else if (oc1 & OUT_RIGHT) {
506*4882a593Smuzhiyun                 negslope = IsYDecreasingOctant(octant);
507*4882a593Smuzhiyun                 utmp = x1_orig - xmax;
508*4882a593Smuzhiyun                 if (utmp <= 32767) {    /* clip based on near endpt */
509*4882a593Smuzhiyun                     if (xmajor)
510*4882a593Smuzhiyun                         eqn = (swapped) ? EQN2 : EQN1;
511*4882a593Smuzhiyun                     else
512*4882a593Smuzhiyun                         eqn = (swapped) ? EQN4 : EQN3;
513*4882a593Smuzhiyun                     anchorval = y1_orig;
514*4882a593Smuzhiyun                 }
515*4882a593Smuzhiyun                 else {          /* clip based on far endpt */
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun                     /*
518*4882a593Smuzhiyun                      * Technically since the equations can handle
519*4882a593Smuzhiyun                      * utmp == 32768, this overflow code isn't
520*4882a593Smuzhiyun                      * needed since X11 protocol can't generate
521*4882a593Smuzhiyun                      * a line which goes more than 32768 pixels
522*4882a593Smuzhiyun                      * to the right of a clip rectangle.
523*4882a593Smuzhiyun                      */
524*4882a593Smuzhiyun                     utmp = xmax - x2_orig;
525*4882a593Smuzhiyun                     if (xmajor)
526*4882a593Smuzhiyun                         eqn = (swapped) ? EQN1B : EQN2B;
527*4882a593Smuzhiyun                     else
528*4882a593Smuzhiyun                         eqn = (swapped) ? EQN3B : EQN4B;
529*4882a593Smuzhiyun                     anchorval = y2_orig;
530*4882a593Smuzhiyun                     negslope = !negslope;
531*4882a593Smuzhiyun                 }
532*4882a593Smuzhiyun                 x1 = xmax;
533*4882a593Smuzhiyun             }
534*4882a593Smuzhiyun             else if (oc1 & OUT_BELOW) {
535*4882a593Smuzhiyun                 negslope = IsXDecreasingOctant(octant);
536*4882a593Smuzhiyun                 utmp = y1_orig - ymax;
537*4882a593Smuzhiyun                 if (utmp <= 32767) {    /* clip based on near endpt */
538*4882a593Smuzhiyun                     if (xmajor)
539*4882a593Smuzhiyun                         eqn = (swapped) ? EQN6 : EQN5;
540*4882a593Smuzhiyun                     else
541*4882a593Smuzhiyun                         eqn = (swapped) ? EQN8 : EQN7;
542*4882a593Smuzhiyun                     anchorval = x1_orig;
543*4882a593Smuzhiyun                 }
544*4882a593Smuzhiyun                 else {          /* clip based on far endpt */
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun                     /*
547*4882a593Smuzhiyun                      * Technically since the equations can handle
548*4882a593Smuzhiyun                      * utmp == 32768, this overflow code isn't
549*4882a593Smuzhiyun                      * needed since X11 protocol can't generate
550*4882a593Smuzhiyun                      * a line which goes more than 32768 pixels
551*4882a593Smuzhiyun                      * below the bottom of a clip rectangle.
552*4882a593Smuzhiyun                      */
553*4882a593Smuzhiyun                     utmp = ymax - y2_orig;
554*4882a593Smuzhiyun                     if (xmajor)
555*4882a593Smuzhiyun                         eqn = (swapped) ? EQN5B : EQN6B;
556*4882a593Smuzhiyun                     else
557*4882a593Smuzhiyun                         eqn = (swapped) ? EQN7B : EQN8B;
558*4882a593Smuzhiyun                     anchorval = x2_orig;
559*4882a593Smuzhiyun                     negslope = !negslope;
560*4882a593Smuzhiyun                 }
561*4882a593Smuzhiyun                 y1 = ymax;
562*4882a593Smuzhiyun             }
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun             if (swapped)
565*4882a593Smuzhiyun                 negslope = !negslope;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun             utmp <<= 1;         /* utmp = 2N or 2M */
568*4882a593Smuzhiyun             if (eqn & T_2NDX)
569*4882a593Smuzhiyun                 utmp = (utmp * adx);
570*4882a593Smuzhiyun             else                /* (eqn & T_2MDY) */
571*4882a593Smuzhiyun                 utmp = (utmp * ady);
572*4882a593Smuzhiyun             if (eqn & T_DXNOTY)
573*4882a593Smuzhiyun                 if (eqn & T_SUBDXORY)
574*4882a593Smuzhiyun                     utmp -= adx;
575*4882a593Smuzhiyun                 else
576*4882a593Smuzhiyun                     utmp += adx;
577*4882a593Smuzhiyun             else /* (eqn & T_DYNOTX) */ if (eqn & T_SUBDXORY)
578*4882a593Smuzhiyun                 utmp -= ady;
579*4882a593Smuzhiyun             else
580*4882a593Smuzhiyun                 utmp += ady;
581*4882a593Smuzhiyun             if (eqn & T_BIASSUBONE)
582*4882a593Smuzhiyun                 utmp += bias - 1;
583*4882a593Smuzhiyun             else                /* (eqn & T_SUBBIAS) */
584*4882a593Smuzhiyun                 utmp -= bias;
585*4882a593Smuzhiyun             if (eqn & T_DIV2DX)
586*4882a593Smuzhiyun                 utmp /= (adx << 1);
587*4882a593Smuzhiyun             else                /* (eqn & T_DIV2DY) */
588*4882a593Smuzhiyun                 utmp /= (ady << 1);
589*4882a593Smuzhiyun             if (eqn & T_ADDONE)
590*4882a593Smuzhiyun                 utmp++;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun             if (negslope)
593*4882a593Smuzhiyun                 utmp = -utmp;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun             if (eqn & T_2NDX)   /* We are calculating X steps */
596*4882a593Smuzhiyun                 x1 = anchorval + utmp;
597*4882a593Smuzhiyun             else                /* else, Y steps */
598*4882a593Smuzhiyun                 y1 = anchorval + utmp;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun             oc1 = 0;
601*4882a593Smuzhiyun             MIOUTCODES(oc1, x1, y1, xmin, ymin, xmax, ymax);
602*4882a593Smuzhiyun         }
603*4882a593Smuzhiyun     }
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun     *new_x1 = x1;
606*4882a593Smuzhiyun     *new_y1 = y1;
607*4882a593Smuzhiyun     *new_x2 = x2;
608*4882a593Smuzhiyun     *new_y2 = y2;
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun     *pt1_clipped = clip1;
611*4882a593Smuzhiyun     *pt2_clipped = clip2;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun     return clipDone;
614*4882a593Smuzhiyun }
615