xref: /OK3568_Linux_fs/external/xserver/mi/miscanfill.h (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
12*4882a593Smuzhiyun in all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15*4882a593Smuzhiyun OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16*4882a593Smuzhiyun MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17*4882a593Smuzhiyun IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*4882a593Smuzhiyun OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*4882a593Smuzhiyun ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*4882a593Smuzhiyun OTHER DEALINGS IN THE SOFTWARE.
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall
23*4882a593Smuzhiyun not be used in advertising or otherwise to promote the sale, use or
24*4882a593Smuzhiyun other dealings in this Software without prior written authorization
25*4882a593Smuzhiyun from The Open Group.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
30*4882a593Smuzhiyun #include <dix-config.h>
31*4882a593Smuzhiyun #endif
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifndef SCANFILLINCLUDED
34*4882a593Smuzhiyun #define SCANFILLINCLUDED
35*4882a593Smuzhiyun /*
36*4882a593Smuzhiyun  *     scanfill.h
37*4882a593Smuzhiyun  *
38*4882a593Smuzhiyun  *     Written by Brian Kelleher; Jan 1985
39*4882a593Smuzhiyun  *
40*4882a593Smuzhiyun  *     This file contains a few macros to help track
41*4882a593Smuzhiyun  *     the edge of a filled object.  The object is assumed
42*4882a593Smuzhiyun  *     to be filled in scanline order, and thus the
43*4882a593Smuzhiyun  *     algorithm used is an extension of Bresenham's line
44*4882a593Smuzhiyun  *     drawing algorithm which assumes that y is always the
45*4882a593Smuzhiyun  *     major axis.
46*4882a593Smuzhiyun  *     Since these pieces of code are the same for any filled shape,
47*4882a593Smuzhiyun  *     it is more convenient to gather the library in one
48*4882a593Smuzhiyun  *     place, but since these pieces of code are also in
49*4882a593Smuzhiyun  *     the inner loops of output primitives, procedure call
50*4882a593Smuzhiyun  *     overhead is out of the question.
51*4882a593Smuzhiyun  *     See the author for a derivation if needed.
52*4882a593Smuzhiyun  */
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /*
55*4882a593Smuzhiyun  *  In scan converting polygons, we want to choose those pixels
56*4882a593Smuzhiyun  *  which are inside the polygon.  Thus, we add .5 to the starting
57*4882a593Smuzhiyun  *  x coordinate for both left and right edges.  Now we choose the
58*4882a593Smuzhiyun  *  first pixel which is inside the pgon for the left edge and the
59*4882a593Smuzhiyun  *  first pixel which is outside the pgon for the right edge.
60*4882a593Smuzhiyun  *  Draw the left pixel, but not the right.
61*4882a593Smuzhiyun  *
62*4882a593Smuzhiyun  *  How to add .5 to the starting x coordinate:
63*4882a593Smuzhiyun  *      If the edge is moving to the right, then subtract dy from the
64*4882a593Smuzhiyun  *  error term from the general form of the algorithm.
65*4882a593Smuzhiyun  *      If the edge is moving to the left, then add dy to the error term.
66*4882a593Smuzhiyun  *
67*4882a593Smuzhiyun  *  The reason for the difference between edges moving to the left
68*4882a593Smuzhiyun  *  and edges moving to the right is simple:  If an edge is moving
69*4882a593Smuzhiyun  *  to the right, then we want the algorithm to flip immediately.
70*4882a593Smuzhiyun  *  If it is moving to the left, then we don't want it to flip until
71*4882a593Smuzhiyun  *  we traverse an entire pixel.
72*4882a593Smuzhiyun  */
73*4882a593Smuzhiyun #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
74*4882a593Smuzhiyun     int dx;      /* local storage */ \
75*4882a593Smuzhiyun \
76*4882a593Smuzhiyun     /* \
77*4882a593Smuzhiyun      *  if the edge is horizontal, then it is ignored \
78*4882a593Smuzhiyun      *  and assumed not to be processed.  Otherwise, do this stuff. \
79*4882a593Smuzhiyun      */ \
80*4882a593Smuzhiyun     if ((dy) != 0) { \
81*4882a593Smuzhiyun         xStart = (x1); \
82*4882a593Smuzhiyun         dx = (x2) - xStart; \
83*4882a593Smuzhiyun         if (dx < 0) { \
84*4882a593Smuzhiyun             m = dx / (dy); \
85*4882a593Smuzhiyun             m1 = m - 1; \
86*4882a593Smuzhiyun             incr1 = -2 * dx + 2 * (dy) * m1; \
87*4882a593Smuzhiyun             incr2 = -2 * dx + 2 * (dy) * m; \
88*4882a593Smuzhiyun             d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
89*4882a593Smuzhiyun         } else { \
90*4882a593Smuzhiyun             m = dx / (dy); \
91*4882a593Smuzhiyun             m1 = m + 1; \
92*4882a593Smuzhiyun             incr1 = 2 * dx - 2 * (dy) * m1; \
93*4882a593Smuzhiyun             incr2 = 2 * dx - 2 * (dy) * m; \
94*4882a593Smuzhiyun             d = -2 * m * (dy) + 2 * dx; \
95*4882a593Smuzhiyun         } \
96*4882a593Smuzhiyun     } \
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
100*4882a593Smuzhiyun     if (m1 > 0) { \
101*4882a593Smuzhiyun         if (d > 0) { \
102*4882a593Smuzhiyun             minval += m1; \
103*4882a593Smuzhiyun             d += incr1; \
104*4882a593Smuzhiyun         } \
105*4882a593Smuzhiyun         else { \
106*4882a593Smuzhiyun             minval += m; \
107*4882a593Smuzhiyun             d += incr2; \
108*4882a593Smuzhiyun         } \
109*4882a593Smuzhiyun     } else {\
110*4882a593Smuzhiyun         if (d >= 0) { \
111*4882a593Smuzhiyun             minval += m1; \
112*4882a593Smuzhiyun             d += incr1; \
113*4882a593Smuzhiyun         } \
114*4882a593Smuzhiyun         else { \
115*4882a593Smuzhiyun             minval += m; \
116*4882a593Smuzhiyun             d += incr2; \
117*4882a593Smuzhiyun         } \
118*4882a593Smuzhiyun     } \
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun /*
122*4882a593Smuzhiyun  *     This structure contains all of the information needed
123*4882a593Smuzhiyun  *     to run the bresenham algorithm.
124*4882a593Smuzhiyun  *     The variables may be hardcoded into the declarations
125*4882a593Smuzhiyun  *     instead of using this structure to make use of
126*4882a593Smuzhiyun  *     register declarations.
127*4882a593Smuzhiyun  */
128*4882a593Smuzhiyun typedef struct {
129*4882a593Smuzhiyun     int minor;                  /* minor axis        */
130*4882a593Smuzhiyun     int d;                      /* decision variable */
131*4882a593Smuzhiyun     int m, m1;                  /* slope and slope+1 */
132*4882a593Smuzhiyun     int incr1, incr2;           /* error increments */
133*4882a593Smuzhiyun } BRESINFO;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
136*4882a593Smuzhiyun 	BRESINITPGON(dmaj, min1, min2, bres.minor, bres.d, \
137*4882a593Smuzhiyun                      bres.m, bres.m1, bres.incr1, bres.incr2)
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun #define BRESINCRPGONSTRUCT(bres) \
140*4882a593Smuzhiyun         BRESINCRPGON(bres.d, bres.minor, bres.m, bres.m1, bres.incr1, bres.incr2)
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun #endif
143