]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mi/mifpolycon.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / mi / mifpolycon.c
1 /***********************************************************
2
3 Copyright (c) 1987  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25
26
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29                         All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its 
32 documentation for any purpose and without fee is hereby granted, 
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in 
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.  
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 ******************************************************************/
48 /* $XConsortium: mifpolycon.c,v 5.4 94/04/17 20:27:36 rws Exp $ */
49 #include <math.h>
50 #include "X.h"
51 #include "gcstruct.h"
52 #include "windowstr.h"
53 #include "pixmapstr.h"
54 #include "mifpoly.h"
55
56 static int GetFPolyYBounds();
57
58 #ifdef ICEILTEMPDECL
59 ICEILTEMPDECL
60 #endif
61
62 /*
63  *      Written by Todd Newman; April. 1987.
64  *
65  *      Fill a convex polygon.  If the given polygon
66  *      is not convex, then the result is undefined.
67  *      The algorithm is to order the edges from smallest
68  *      y to largest by partitioning the array into a left
69  *      edge list and a right edge list.  The algorithm used
70  *      to traverse each edge is digital differencing analyzer
71  *      line algorithm with y as the major axis. There's some funny linear
72  *      interpolation involved because of the subpixel postioning.
73  */
74 void
75 miFillSppPoly(dst, pgc, count, ptsIn, xTrans, yTrans, xFtrans, yFtrans)
76     DrawablePtr         dst;
77     GCPtr               pgc;
78     int                 count;          /* number of points */
79     SppPointPtr         ptsIn;          /* the points */
80     int                 xTrans, yTrans; /* Translate each point by this */
81     double              xFtrans, yFtrans;       /* translate before conversion
82                                                    by this amount.  This provides
83                                                    a mechanism to match rounding
84                                                    errors with any shape that must
85                                                    meet the polygon exactly.
86                                                  */
87 {
88     double              xl, xr,         /* x vals of left and right edges */
89                         ml,             /* left edge slope */
90                         mr,             /* right edge slope */
91                         dy,             /* delta y */
92                         i;              /* loop counter */
93     int                 y,              /* current scanline */
94                         j,
95                         imin,           /* index of vertex with smallest y */
96                         ymin,           /* y-extents of polygon */
97                         ymax,
98                         *width,
99                         *FirstWidth,    /* output buffer */
100                         *Marked;        /* set if this vertex has been used */
101     register int        left, right,    /* indices to first endpoints */
102                         nextleft,
103                         nextright;      /* indices to second endpoints */
104     DDXPointPtr         ptsOut,
105                         FirstPoint;     /* output buffer */
106
107     if (pgc->miTranslate)
108     {
109         xTrans += dst->x;
110         yTrans += dst->y;
111     }
112
113     imin = GetFPolyYBounds(ptsIn, count, yFtrans, &ymin, &ymax);
114
115     y = ymax - ymin + 1;
116     if ((count < 3) || (y <= 0))
117         return;
118     ptsOut = FirstPoint = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * y);
119     width = FirstWidth = (int *) ALLOCATE_LOCAL(sizeof(int) * y);
120     Marked = (int *) ALLOCATE_LOCAL(sizeof(int) * count);
121
122     if(!ptsOut || !width || !Marked)
123     {
124         if (Marked) DEALLOCATE_LOCAL(Marked);
125         if (width) DEALLOCATE_LOCAL(width);
126         if (ptsOut) DEALLOCATE_LOCAL(ptsOut);
127         return;
128     }
129
130     for(j = 0; j < count; j++)
131         Marked[j] = 0;
132     nextleft = nextright = imin;
133     Marked[imin] = -1;
134     y = ICEIL(ptsIn[nextleft].y + yFtrans);
135
136     /*
137      *  loop through all edges of the polygon
138      */
139     do
140     {
141         /* add a left edge if we need to */
142         if ((y > (ptsIn[nextleft].y + yFtrans) ||
143              ISEQUAL(y, ptsIn[nextleft].y + yFtrans)) &&
144              Marked[nextleft] != 1)
145         {
146             Marked[nextleft]++;
147             left = nextleft++;
148
149             /* find the next edge, considering the end conditions */
150             if (nextleft >= count)
151                 nextleft = 0;
152
153             /* now compute the starting point and slope */
154             dy = ptsIn[nextleft].y - ptsIn[left].y;
155             if (dy != 0.0)
156             { 
157                 ml = (ptsIn[nextleft].x - ptsIn[left].x) / dy;
158                 dy = y - (ptsIn[left].y + yFtrans);
159                 xl = (ptsIn[left].x + xFtrans) + ml * max(dy, 0); 
160             }
161         }
162
163         /* add a right edge if we need to */
164         if ((y > ptsIn[nextright].y + yFtrans) ||
165              ISEQUAL(y, ptsIn[nextright].y + yFtrans)
166              && Marked[nextright] != 1)
167         {
168             Marked[nextright]++;
169             right = nextright--;
170
171             /* find the next edge, considering the end conditions */
172             if (nextright < 0)
173                 nextright = count - 1;
174
175             /* now compute the starting point and slope */
176             dy = ptsIn[nextright].y - ptsIn[right].y;
177             if (dy != 0.0) 
178             { 
179                 mr = (ptsIn[nextright].x - ptsIn[right].x) / dy;
180                 dy = y - (ptsIn[right].y + yFtrans); 
181                 xr = (ptsIn[right].x + xFtrans) + mr * max(dy, 0);
182             }
183         }
184
185
186         /*
187          *  generate scans to fill while we still have
188          *  a right edge as well as a left edge.
189          */
190         i = (min(ptsIn[nextleft].y, ptsIn[nextright].y) + yFtrans) - y;
191
192         if (i < EPSILON)
193         {
194             if(Marked[nextleft] && Marked[nextright])
195             {
196                 /* Arrgh, we're trapped! (no more points) 
197                  * Out, we've got to get out of here before this decadence saps
198                  * our will completely! */
199                 break;
200             }
201             continue;
202         }
203         else
204         {
205                 j = (int) i;
206                 if(!j)
207                     j++;
208         }
209         while (j > 0) 
210         {
211             int cxl, cxr;
212
213             ptsOut->y = (y) + yTrans;
214
215             cxl = ICEIL(xl);
216             cxr = ICEIL(xr);
217             /* reverse the edges if necessary */
218             if (xl < xr) 
219             {
220                 *(width++) = cxr - cxl;
221                 (ptsOut++)->x = cxl + xTrans;
222             }
223             else 
224             {
225                 *(width++) = cxl - cxr;
226                 (ptsOut++)->x = cxr + xTrans;
227             }
228             y++;
229
230             /* increment down the edges */
231             xl += ml;
232             xr += mr;
233             j--;
234         }
235     }  while (y <= ymax);
236
237     /* Finally, fill the spans we've collected */
238     (*pgc->ops->FillSpans)(dst, pgc, 
239                       ptsOut-FirstPoint, FirstPoint, FirstWidth, 1);
240     DEALLOCATE_LOCAL(Marked);
241     DEALLOCATE_LOCAL(FirstWidth);
242     DEALLOCATE_LOCAL(FirstPoint);
243 }
244
245 \f
246 /* Find the index of the point with the smallest y.also return the
247  * smallest and largest y */
248 static
249 int
250 GetFPolyYBounds(pts, n, yFtrans, by, ty)
251     register SppPointPtr        pts;
252     int                         n;
253     double                      yFtrans;
254     int                         *by, *ty;
255 {
256     register SppPointPtr        ptMin;
257     double                      ymin, ymax;
258     SppPointPtr                 ptsStart = pts;
259
260     ptMin = pts;
261     ymin = ymax = (pts++)->y;
262
263     while (--n > 0) {
264         if (pts->y < ymin)
265         {
266             ptMin = pts;
267             ymin = pts->y;
268         }
269         if(pts->y > ymax)
270             ymax = pts->y;
271
272         pts++;
273     }
274
275     *by = ICEIL(ymin + yFtrans);
276     *ty = ICEIL(ymax + yFtrans - 1);
277     return(ptMin-ptsStart);
278 }