ReactOS  r73918
polytest.cpp
Go to the documentation of this file.
1 // this is a little 'sandbox' application I put together that duplicates
2 // the 'guts' of the Polygon algorithm. It allows for quick turn-around
3 // in testing the algorithm to see what effect your changes have.
4 //
5 // Royce3
6 
7 // the stuff immediately following is support so that the sandbox code
8 // is nearly identical to the real thing.
9 // search for the _tagFILL_EDGE struct to find the beginning of the
10 // real stuff.
11 
12 #include <memory.h>
13 #include <malloc.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <conio.h>
17 #include <assert.h>
18 
19 #define FASTCALL
20 #define INT int
21 #define CLIPOBJ int
22 #define SURFOBJ int
23 #define PBRUSHOBJ int
24 #define MIX char
25 #define BOOL bool
26 #define TRUE true
27 #define FALSE false
28 #define CONST const
29 #define MmCopyFromCaller memmove
30 #define ALTERNATE 0
31 #define WINDING 1
32 
33 #define ASSERT assert
34 
35 typedef struct W
36 {
38 } W;
39 
40 typedef struct DC
41 {
43  W w;
44 } DC, *PDC;
45 
46 typedef struct tagPOINT
47 {
48  long x, y;
49 } POINT, *PPOINT, *LPPOINT;
50 
51 typedef struct RECTL
52 {
53  long left, top, right, bottom;
54 } RECTL, *PRECTL;
55 
56 #define EngFreeMem free
57 
58 #define FL_ZERO_MEMORY 1
59 
60 #define DPRINT1 printf("%i:",__LINE__);printf
61 inline void DPRINT(...){}
62 
63 #define SCREENX 25
64 #define SCREENY 15
66 
67 #define EDGE_CHAR '*'
68 #define FILL_CHAR 'o'
69 
70 void* EngAllocMem ( int zero, unsigned long size, int tag=0 )
71 {
72  void* p = malloc ( size );
73  if ( zero )
74  memset ( p, 0, size );
75  return p;
76 }
77 
78 template <class T>
79 inline T MIN ( T a, T b )
80 {
81  return a < b ? a : b;
82 }
83 
84 template <class T>
85 inline T MAX ( T a, T b )
86 {
87  return a > b ? a : b;
88 }
89 
90 template <class T>
91 inline T abs ( T t )
92 {
93  return t < 0 ? -t : t;
94 }
95 
96 void putpixel ( int x, int y, char c )
97 {
98  ASSERT( x >= 0 && x < SCREENX && y >= 0 && y < SCREENY );
99  if ( screen[y][x] == c )
100  return;
101  if ( screen[y][x] == ' ' )
102  screen[y][x] = c;
103  else
104  screen[y][x] = '#';
105 }
106 
108  SURFOBJ*,
109  CLIPOBJ,
110  PBRUSHOBJ,
111  int x1, int y1, int x2, int y2,
112  RECTL*,
113  MIX mix )
114 {
115  int dx = x2 - x1;
116  int dy = y2 - y1;
117  int absdx = abs(dx);
118  int absdy = abs(dy);
119  int EMax = MAX(absdx,absdy);
120  int E = EMax/2;
121  int xinc = dx < 0 ? -1 : 1,
122  yinc = dy < 0 ? -1 : 1;
123  if ( !dy )
124  {
125  while ( x1 != x2 )
126  {
127  putpixel ( x1, y1, mix );
128  x1 += xinc;
129  }
130  return;
131  }
132  if ( !dx )
133  {
134  while ( y1 != y2 )
135  {
136  putpixel ( x1, y1, mix );
137  y1 += yinc;
138  }
139  return;
140  }
141  for ( int i = 0; i < EMax; i++ )
142  {
143  putpixel ( x1, y1, mix );
144  if ( absdy > absdx )
145  {
146  y1 += yinc;
147  E += absdx;
148  if ( E >= EMax )
149  {
150  E -= absdy;
151  x1 += xinc;
152  }
153  }
154  else
155  {
156  x1 += xinc;
157  E += absdy;
158  if ( E >= EMax )
159  {
160  E -= absdx;
161  y1 += yinc;
162  }
163  }
164  }
165 }
166 
167 #define FILL_EDGE_ALLOC_TAG 0x45465044
168 
169 /*
170 ** This struct is used for book keeping during polygon filling routines.
171 */
172 typedef struct _tagFILL_EDGE
173 {
174  /*Basic line information*/
175  int FromX;
176  int FromY;
177  int ToX;
178  int ToY;
179  int dx;
180  int dy;
181  int absdx, absdy;
182  int x, y;
183  int xmajor;
184 
185  /*Active Edge List information*/
186  int XIntercept[2];
187  int Error;
188  int ErrorMax;
190 
191  /* The next edge in the active Edge List*/
193 } FILL_EDGE;
194 
195 typedef struct _FILL_EDGE_LIST
196 {
197  int Count;
200 
201 #if 0
202 static
203 void
205 {
206  FILL_EDGE* pThis = list;
207  if (0 == list)
208  {
209  DPRINT1("List is NULL\n");
210  return;
211  }
212 
213  while(0 != pThis)
214  {
215  //DPRINT1("EDGE: (%d, %d) to (%d, %d)\n", pThis->FromX, pThis->FromY, pThis->ToX, pThis->ToY);
216  DPRINT1("EDGE: [%d,%d]\n", pThis->XIntercept[0], pThis->XIntercept[1] );
217  pThis = pThis->pNext;
218  }
219 }
220 #else
221 #define DEBUG_PRINT_ACTIVE_EDGELIST(x)
222 #endif
223 
224 /*
225 ** Hide memory clean up.
226 */
227 static
228 void
229 FASTCALL
231 {
232  int i;
233  if ( list )
234  {
235  if ( list->Edges )
236  {
237  for ( i = 0; i < list->Count; i++ )
238  {
239  if ( list->Edges[i] )
240  EngFreeMem ( list->Edges[i] );
241  }
242  EngFreeMem ( list->Edges );
243  }
244  EngFreeMem ( list );
245  }
246 }
247 
248 /*
249 ** This makes and initiaizes an Edge struct for a line between two points.
250 */
251 static
252 FILL_EDGE*
253 FASTCALL
255 {
257 
258  if (0 == rc)
259  return NULL;
260 
261  //DPRINT1("Making Edge: (%d, %d) to (%d, %d)\n", From.x, From.y, To.x, To.y);
262  //Now Fill the struct.
263  if ( To.y < From.y )
264  {
265  rc->FromX = To.x;
266  rc->FromY = To.y;
267  rc->ToX = From.x;
268  rc->ToY = From.y;
269  rc->YDirection = -1;
270 
271  // lines that go up get walked backwards, so need to be offset
272  // by -1 in order to make the walk identically on a pixel-level
273  rc->Error = -1;
274  }
275  else
276  {
277  rc->FromX = From.x;
278  rc->FromY = From.y;
279  rc->ToX = To.x;
280  rc->ToY = To.y;
281  rc->YDirection = 1;
282 
283  rc->Error = 0;
284  }
285 
286  rc->x = rc->FromX;
287  rc->y = rc->FromY;
288  rc->dx = rc->ToX - rc->FromX;
289  rc->dy = rc->ToY - rc->FromY;
290  rc->absdx = abs(rc->dx);
291  rc->absdy = abs(rc->dy);
292 
293  rc->xmajor = rc->absdx > rc->absdy;
294 
295  rc->ErrorMax = MAX(rc->absdx,rc->absdy);
296 
297  rc->Error += rc->ErrorMax / 2;
298 
299  rc->XDirection = (rc->dx < 0)?(-1):(1);
300 
301  rc->pNext = 0;
302 
303  DPRINT("MakeEdge (%i,%i)->(%i,%i) d=(%i,%i) dir=(%i,%i) err=%i max=%i\n",
304  From.x, From.y, To.x, To.y, rc->dx, rc->dy, rc->XDirection, rc->YDirection, rc->Error, rc->ErrorMax );
305 
306  return rc;
307 }
308 /*
309 ** My Edge comparison routine.
310 ** This is for scan converting polygon fill.
311 ** First sort by MinY, then Minx, then slope.
312 **
313 ** This comparison will help us determine which
314 ** lines will become active first when scanning from
315 ** top (min y) to bottom (max y).
316 **
317 ** Return Value Meaning
318 ** Negative integer element1 < element2
319 ** Zero element1 = element2
320 ** Positive integer element1 > element2
321 */
322 static
323 INT
324 FASTCALL
326 {
327  int e1 = Edge1->XIntercept[0] + Edge1->XIntercept[1];
328  int e2 = Edge2->XIntercept[0] + Edge2->XIntercept[1];
329 
330  return e1 - e2;
331 }
332 
333 
334 /*
335 ** Insert an edge into a list keeping the list in order.
336 */
337 static
338 void
339 FASTCALL
341 {
342  FILL_EDGE *pPrev, *pThis;
343  //DPRINT1("In POLYGONFILL_ActiveListInsert()\n");
344  ASSERT ( activehead && NewEdge );
345  if ( !*activehead )
346  {
347  NewEdge->pNext = NULL;
348  *activehead = NewEdge;
349  return;
350  }
351  /*
352  ** First lets check to see if we have a new smallest value.
353  */
354  if (FILL_EDGE_Compare(NewEdge, *activehead) <= 0)
355  {
356  NewEdge->pNext = *activehead;
357  *activehead = NewEdge;
358  return;
359  }
360  /*
361  ** Ok, now scan to the next spot to put this item.
362  */
363  pThis = *activehead;
364  pPrev = NULL;
365  while ( pThis && FILL_EDGE_Compare(pThis, NewEdge) < 0 )
366  {
367  pPrev = pThis;
368  pThis = pThis->pNext;
369  }
370 
371  ASSERT(pPrev);
372  NewEdge->pNext = pPrev->pNext;
373  pPrev->pNext = NewEdge;
374  //DEBUG_PRINT_ACTIVE_EDGELIST(*activehead);
375 }
376 
377 /*
378 ** Create a list of edges for a list of points.
379 */
380 static
382 FASTCALL
383 POLYGONFILL_MakeEdgeList(PPOINT Points, int Count)
384 {
385  int CurPt = 0;
386  FILL_EDGE_LIST* list = 0;
387  FILL_EDGE* e = 0;
388 
389  if ( 0 == Points || 2 > Count )
390  return 0;
391 
393  if ( 0 == list )
394  goto fail;
395  list->Count = 0;
397  if ( !list->Edges )
398  goto fail;
399  memset ( list->Edges, 0, Count * sizeof(FILL_EDGE*) );
400 
401  for ( CurPt = 1; CurPt < Count; ++CurPt )
402  {
403  e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[CurPt] );
404  if ( !e )
405  goto fail;
406  // if a straight horizontal line - who cares?
407  if ( !e->absdy )
408  EngFreeMem ( e );
409  else
410  list->Edges[list->Count++] = e;
411  }
412  e = POLYGONFILL_MakeEdge ( Points[CurPt-1], Points[0] );
413  if ( !e )
414  goto fail;
415  if ( !e->absdy )
416  EngFreeMem ( e );
417  else
418  list->Edges[list->Count++] = e;
419  return list;
420 
421 fail:
422  DPRINT1("Out Of MEMORY!!\n");
424  return 0;
425 }
426 
427 
428 /*
429 ** This slow routine uses the data stored in the edge list to
430 ** calculate the x intercepts for each line in the edge list
431 ** for scanline Scanline.
432 **TODO: Get rid of this floating point arithmetic
433 */
434 static
435 void
436 FASTCALL
438 {
439  if ( 0 == pEdge->dy )
440  return;
441 
442  ASSERT ( pEdge->FromY <= Scanline && pEdge->ToY > Scanline );
443 
444  if ( pEdge->xmajor )
445  {
446  int steps;
447 
448  ASSERT ( pEdge->y == Scanline );
449 
450  // now shoot to end of scanline collision
451  steps = (pEdge->ErrorMax-pEdge->Error-1)/pEdge->absdy;
452  if ( steps )
453  {
454  // record first collision with scanline
455  int x1 = pEdge->x;
456  pEdge->x += steps * pEdge->XDirection;
457  pEdge->Error += steps * pEdge->absdy;
458  ASSERT ( pEdge->Error < pEdge->ErrorMax );
459  pEdge->XIntercept[0] = MIN(x1,pEdge->x);
460  pEdge->XIntercept[1] = MAX(x1,pEdge->x);
461  }
462  else
463  {
464  pEdge->XIntercept[0] = pEdge->x;
465  pEdge->XIntercept[1] = pEdge->x;
466  }
467 
468  // we should require exactly 1 step to step onto next scanline...
469  ASSERT ( (pEdge->ErrorMax-pEdge->Error-1) / pEdge->absdy == 0 );
470  pEdge->x += pEdge->XDirection;
471  pEdge->Error += pEdge->absdy;
472  ASSERT ( pEdge->Error >= pEdge->ErrorMax );
473 
474  // now step onto next scanline...
475  pEdge->Error -= pEdge->absdx;
476  pEdge->y++;
477  }
478  else // then this is a y-major line
479  {
480  pEdge->XIntercept[0] = pEdge->x;
481  pEdge->XIntercept[1] = pEdge->x;
482 
483  pEdge->Error += pEdge->absdx;
484  pEdge->y++;
485 
486  if ( pEdge->Error >= pEdge->ErrorMax )
487  {
488  pEdge->Error -= pEdge->ErrorMax;
489  pEdge->x += pEdge->XDirection;
490  ASSERT ( pEdge->Error < pEdge->ErrorMax );
491  }
492  }
493 
494  DPRINT("Line (%d, %d) to (%d, %d) intersects scanline %d at (%d,%d)\n",
495  pEdge->FromX, pEdge->FromY, pEdge->ToX, pEdge->ToY, Scanline, pEdge->XIntercept[0], pEdge->XIntercept[1] );
496 }
497 
498 /*
499 ** This method updates the Active edge collection for the scanline Scanline.
500 */
501 static
502 void
503 POLYGONFILL_BuildActiveList ( int Scanline, FILL_EDGE_LIST* list, FILL_EDGE** ActiveHead )
504 {
505  int i;
506 
507  ASSERT ( list && ActiveHead );
508  *ActiveHead = 0;
509  for ( i = 0; i < list->Count; i++ )
510  {
511  FILL_EDGE* pEdge = list->Edges[i];
512  ASSERT(pEdge);
513  if ( pEdge->FromY <= Scanline && pEdge->ToY > Scanline )
514  {
515  POLYGONFILL_UpdateScanline ( pEdge, Scanline );
516  POLYGONFILL_ActiveListInsert ( ActiveHead, pEdge );
517  }
518  }
519 }
520 
521 /*
522 ** This method fills the portion of the polygon that intersects with the scanline
523 ** Scanline.
524 */
525 static
526 void
528  PDC dc,
529  int ScanLine,
530  FILL_EDGE* ActiveHead,
531  SURFOBJ *SurfObj,
532  PBRUSHOBJ BrushObj,
533  MIX RopMode )
534 {
535  FILL_EDGE *pLeft, *pRight;
536 
537  if ( !ActiveHead )
538  return;
539 
540  pLeft = ActiveHead;
541  pRight = pLeft->pNext;
542  ASSERT(pRight);
543 
544  while ( NULL != pRight )
545  {
546  int x1 = pLeft->XIntercept[0];
547  int x2 = pRight->XIntercept[1];
548  if ( x2 > x1 )
549  {
550  RECTL BoundRect;
551  BoundRect.top = ScanLine;
552  BoundRect.bottom = ScanLine + 1;
553  BoundRect.left = x1;
554  BoundRect.right = x2;
555 
556  DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
557  IntEngLineTo( SurfObj,
558  dc->CombinedClip,
559  BrushObj,
560  x1,
561  ScanLine,
562  x2,
563  ScanLine,
564  &BoundRect, // Bounding rectangle
565  RopMode); // MIX
566  }
567  pLeft = pRight->pNext;
568  pRight = pLeft ? pLeft->pNext : NULL;
569  }
570 }
571 
572 static
573 void
575  PDC dc,
576  int ScanLine,
577  FILL_EDGE* ActiveHead,
578  SURFOBJ *SurfObj,
579  PBRUSHOBJ BrushObj,
580  MIX RopMode )
581 {
582  FILL_EDGE *pLeft, *pRight;
583  int x1, x2, winding = 0;
584  RECTL BoundRect;
585 
586  if ( !ActiveHead )
587  return;
588 
589  BoundRect.top = ScanLine;
590  BoundRect.bottom = ScanLine + 1;
591 
592  pLeft = ActiveHead;
593  winding = pLeft->YDirection;
594  pRight = pLeft->pNext;
595  ASSERT(pRight);
596 
597  // setup first line...
598  x1 = pLeft->XIntercept[0];
599  x2 = pRight->XIntercept[1];
600 
601  pLeft = pRight;
602  pRight = pLeft->pNext;
603  winding += pLeft->YDirection;
604 
605  while ( NULL != pRight )
606  {
607  int newx1 = pLeft->XIntercept[0];
608  int newx2 = pRight->XIntercept[1];
609  if ( winding )
610  {
611  // check and see if this new line touches the previous...
612  if ( (newx1 >= x1 && newx1 <= x2)
613  || (newx2 >= x1 && newx2 <= x2)
614  || (x1 >= newx1 && x1 <= newx2)
615  || (x2 >= newx2 && x2 <= newx2)
616  )
617  {
618  // yup, just tack it on to our existing line
619  x1 = MIN(x1,newx1);
620  x2 = MAX(x2,newx2);
621  }
622  else
623  {
624  // nope - render the old line..
625  BoundRect.left = x1;
626  BoundRect.right = x2;
627 
628  DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
629  IntEngLineTo( SurfObj,
630  dc->CombinedClip,
631  BrushObj,
632  x1,
633  ScanLine,
634  x2,
635  ScanLine,
636  &BoundRect, // Bounding rectangle
637  RopMode); // MIX
638 
639  x1 = newx1;
640  x2 = newx2;
641  }
642  }
643  pLeft = pRight;
644  pRight = pLeft->pNext;
645  winding += pLeft->YDirection;
646  }
647  // there will always be a line left-over, render it now...
648  BoundRect.left = x1;
649  BoundRect.right = x2;
650 
651  DPRINT("Fill Line (%d, %d) to (%d, %d)\n",x1, ScanLine, x2, ScanLine);
652  IntEngLineTo( SurfObj,
653  dc->CombinedClip,
654  BrushObj,
655  x1,
656  ScanLine,
657  x2,
658  ScanLine,
659  &BoundRect, // Bounding rectangle
660  RopMode); // MIX
661 }
662 
663 //When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and
664 //even-numbered polygon sides on each scan line. That is, GDI fills the area between the
665 //first and second side, between the third and fourth side, and so on.
666 
667 //WINDING Selects winding mode (fills any region with a nonzero winding value).
668 //When the fill mode is WINDING, GDI fills any region that has a nonzero winding value.
669 //This value is defined as the number of times a pen used to draw the polygon would go around the region.
670 //The direction of each edge of the polygon is important.
671 
672 BOOL
674  PDC dc,
675  SURFOBJ *SurfObj,
676  PBRUSHOBJ BrushObj,
677  MIX RopMode,
678  CONST PPOINT Points,
679  int Count,
680  RECTL BoundRect )
681 {
682  FILL_EDGE_LIST *list = 0;
683  FILL_EDGE *ActiveHead = 0;
684  int ScanLine;
685 
686  void
687  (*FillScanLine)(
688  PDC dc,
689  int ScanLine,
690  FILL_EDGE* ActiveHead,
691  SURFOBJ *SurfObj,
692  PBRUSHOBJ BrushObj,
693  MIX RopMode );
694 
695  DPRINT("FillPolygon\n");
696 
697  /* Create Edge List. */
698  list = POLYGONFILL_MakeEdgeList(Points, Count);
699  /* DEBUG_PRINT_EDGELIST(list); */
700  if (NULL == list)
701  return FALSE;
702 
703  if ( WINDING == dc->w.polyFillMode )
704  FillScanLine = POLYGONFILL_FillScanLineWinding;
705  else /* default */
706  FillScanLine = POLYGONFILL_FillScanLineAlternate;
707 
708  /* For each Scanline from BoundRect.bottom to BoundRect.top,
709  * determine line segments to draw
710  */
711  for ( ScanLine = BoundRect.top; ScanLine < BoundRect.bottom; ++ScanLine )
712  {
713  POLYGONFILL_BuildActiveList(ScanLine, list, &ActiveHead);
714  //DEBUG_PRINT_ACTIVE_EDGELIST(ActiveHead);
715  FillScanLine ( dc, ScanLine, ActiveHead, SurfObj, BrushObj, RopMode );
716  }
717 
718  /* Free Edge List. If any are left. */
720 
721  return TRUE;
722 }
723 
724 
725 
726 
727 
728 // this is highly hacked from W32kPolygon...
729 BOOL
730 Polygon ( CONST PPOINT UnsafePoints, int Count, int polyFillMode )
731 {
732  BOOL ret;
733  RECTL DestRect;
734  int CurrentPoint;
735  PPOINT Points;
736  SURFOBJ* SurfObj = 0;
737  DC dc;
738  PBRUSHOBJ OutBrushObj = 0;
739 
740  dc.CombinedClip = 0;
741  dc.w.polyFillMode = polyFillMode;
742 
743  DPRINT1("In W32kPolygon()\n");
744 
745  if ( NULL == UnsafePoints || Count < 2)
746  {
747  DPRINT1("ERROR_INVALID_PARAMETER\n");
748  return FALSE;
749  }
750 
751  /* Copy points from userspace to kernelspace */
752  Points = (PPOINT)EngAllocMem(0, Count * sizeof(POINT));
753  if (NULL == Points)
754  {
755  DPRINT1("ERROR_NOT_ENOUGH_MEMORY\n");
756  return FALSE;
757  }
758  MmCopyFromCaller(Points, UnsafePoints, Count * sizeof(POINT));
759  if ( memcmp ( Points, UnsafePoints, Count * sizeof(POINT) ) )
760  {
761  free(Points);
762  return FALSE;
763  }
764 
765  DestRect.left = Points[0].x;
766  DestRect.right = Points[0].x;
767  DestRect.top = Points[0].y;
768  DestRect.bottom = Points[0].y;
769 
770  for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint)
771  {
772  DestRect.left = MIN(DestRect.left, Points[CurrentPoint].x);
773  DestRect.right = MAX(DestRect.right, Points[CurrentPoint].x);
774  DestRect.top = MIN(DestRect.top, Points[CurrentPoint].y);
775  DestRect.bottom = MAX(DestRect.bottom, Points[CurrentPoint].y);
776  }
777 
778  // Draw the Polygon Edges with the current pen
779  for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint)
780  {
781  POINT To, From; //, Next;
782 
783  /* Let CurrentPoint be i
784  * if i+1 > Count, Draw a line from Points[i] to Points[0]
785  * Draw a line from Points[i] to Points[i+1]
786  */
787  From = Points[CurrentPoint];
788  if ( CurrentPoint + 1 >= Count)
789  {
790  To = Points[0];
791  }
792  else
793  {
794  To = Points[CurrentPoint + 1];
795  }
796 
797  DPRINT1("Polygon Making line from (%ld,%ld) to (%ld,%ld)\n", From.x, From.y, To.x, To.y );
798  IntEngLineTo(SurfObj,
799  dc.CombinedClip,
800  OutBrushObj,
801  From.x,
802  From.y,
803  To.x,
804  To.y,
805  &DestRect,
806  EDGE_CHAR); /* MIX */
807  }
808  /* determine the fill mode to fill the polygon. */
809  ret = FillPolygon(&dc, SurfObj, OutBrushObj, FILL_CHAR, Points, Count, DestRect );
810  free(Points);
811 
812  return ret;
813 }
814 
815 
816 int main()
817 {
818  memset ( screen, ' ', sizeof(screen) );
819  POINT pts[] =
820  {
821 #if 0
822  { 0, 0 },
823  { 12, 4 },
824  { 4, 8 },
825 #elif 0
826  { 3, 0 },
827  { 0, 3 },
828  { 3, 6 },
829 #elif 0
830  { 1, 1 },
831  { 3, 1 },
832  { 3, 3 },
833  { 1, 3 }
834 #elif 0
835  { 0, 0 },
836  { 4, 0 },
837  { 4, 4 },
838  { 8, 4 },
839  { 8, 8 },
840  { 4, 8 },
841  { 4, 4 },
842  { 0, 4 },
843 #else
844  { 4, 12 },
845  { 12, 0 },
846  { 18, 12 },
847  { 4, 4 },
848  { 20, 4 }
849 #endif
850  };
851  const int pts_count = sizeof(pts)/sizeof(pts[0]);
852 
853  // use ALTERNATE or WINDING for 3rd param
854  Polygon ( pts, pts_count, ALTERNATE );
855 
856  // print out our "screen"
857  for ( int y = 0; y < SCREENY; y++ )
858  {
859  for ( int x = 0; x < SCREENX; x++ )
860  {
861  printf("%c", screen[y][x] );
862  }
863  printf("\n");
864  }
865  DPRINT1("Done!\n");
866  (void)_getch();
867 }
868 /* EOF */
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3706
struct DC * PDC
int polyFillMode
Definition: polytest.cpp:37
FILL_EDGE ** Edges
Definition: polytest.cpp:198
#define ALTERNATE
Definition: polytest.cpp:30
struct tagPOINT * LPPOINT
static void FASTCALL POLYGONFILL_ActiveListInsert(FILL_EDGE **activehead, FILL_EDGE *NewEdge)
Definition: polytest.cpp:340
T abs(T t)
Definition: polytest.cpp:91
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ULONG MIX
Definition: winddi.h:129
long y
Definition: polytest.cpp:48
struct RECTL * PRECTL
BOOL Polygon(CONST PPOINT UnsafePoints, int Count, int polyFillMode)
Definition: polytest.cpp:730
long x
Definition: polytest.cpp:48
#define EngFreeMem
Definition: polytest.cpp:56
#define free
Definition: debug_ros.c:5
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
long bottom
Definition: polytest.cpp:53
GLdouble GLdouble t
Definition: gl.h:2047
Definition: ecma_167.h:138
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define MmCopyFromCaller
Definition: polytest.cpp:29
HDC dc
Definition: cylfrac.c:34
#define FILL_CHAR
Definition: polytest.cpp:68
#define SCREENY
Definition: polytest.cpp:64
struct tagPOINT * PPOINT
int XIntercept[2]
Definition: polytest.cpp:186
#define EDGE_CHAR
Definition: polytest.cpp:67
int32_t INT
Definition: typedefs.h:57
#define T
Definition: mbstring.h:31
BOOL FillPolygon(PDC dc, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect)
Definition: polytest.cpp:673
T MIN(T a, T b)
Definition: polytest.cpp:79
long right
Definition: polytest.cpp:53
#define DPRINT1
Definition: polytest.cpp:60
GLenum GLclampf GLint i
Definition: glfuncs.h:14
static FILL_EDGE_LIST *FASTCALL POLYGONFILL_MakeEdgeList(PPOINT Points, int Count)
Definition: polytest.cpp:383
#define e
Definition: ke_i.h:82
Definition: polytest.cpp:35
#define NULL
Definition: mystdio.h:57
long top
Definition: polytest.cpp:53
#define ASSERT
Definition: polytest.cpp:33
static void POLYGONFILL_FillScanLineWinding(PDC dc, int ScanLine, FILL_EDGE *ActiveHead, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode)
Definition: polytest.cpp:574
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:47
struct _tagFILL_EDGE FILL_EDGE
static DWORD DWORD DWORD DWORD * steps
Definition: cursoricon.c:1508
void DPRINT(...)
Definition: polytest.cpp:61
#define FALSE
Definition: polytest.cpp:27
long left
Definition: polytest.cpp:53
#define b
Definition: ke_i.h:79
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
Definition: polytest.cpp:40
unsigned int BOOL
Definition: ntddk_ex.h:94
if(!(yy_init))
Definition: macro.lex.yy.c:704
static void FASTCALL POLYGONFILL_DestroyEdgeList(FILL_EDGE_LIST *list)
Definition: polytest.cpp:230
CLIPOBJ CombinedClip
Definition: polytest.cpp:42
struct DC DC
const GLubyte * c
Definition: glext.h:8905
#define TRUE
Definition: polytest.cpp:26
static void FASTCALL POLYGONFILL_UpdateScanline(FILL_EDGE *pEdge, int Scanline)
Definition: polytest.cpp:437
struct W W
void IntEngLineTo(SURFOBJ *, CLIPOBJ, PBRUSHOBJ, int x1, int y1, int x2, int y2, RECTL *, MIX mix)
Definition: polytest.cpp:107
void * EngAllocMem(int zero, unsigned long size, int tag=0)
Definition: polytest.cpp:70
int ret
static double zero
Definition: j0_y0.c:96
#define FL_ZERO_MEMORY
Definition: polytest.cpp:58
#define FILL_EDGE_ALLOC_TAG
Definition: polytest.cpp:167
#define CONST
Definition: polytest.cpp:28
struct _FILL_EDGE_LIST FILL_EDGE_LIST
static FILL_EDGE *FASTCALL POLYGONFILL_MakeEdge(POINT From, POINT To)
Definition: polytest.cpp:254
Definition: _list.h:228
#define PBRUSHOBJ
Definition: polytest.cpp:23
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3706
T MAX(T a, T b)
Definition: polytest.cpp:85
char screen[SCREENY][SCREENX]
Definition: polytest.cpp:65
static void POLYGONFILL_FillScanLineAlternate(PDC dc, int ScanLine, FILL_EDGE *ActiveHead, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode)
Definition: polytest.cpp:527
#define FASTCALL
Definition: polytest.cpp:19
static const WCHAR E[]
Definition: oid.c:1070
struct _tagFILL_EDGE * pNext
Definition: polytest.cpp:192
INT INT dy
Definition: msvc.h:65
static INT FASTCALL FILL_EDGE_Compare(FILL_EDGE *Edge1, FILL_EDGE *Edge2)
Definition: polytest.cpp:325
int main()
Definition: polytest.cpp:816
GLsizeiptr size
Definition: glext.h:5919
_In_ PATHOBJ _In_ CLIPOBJ _In_ BRUSHOBJ _In_ POINTL _In_ MIX mix
Definition: winddi.h:3591
#define DEBUG_PRINT_ACTIVE_EDGELIST(x)
Definition: polytest.cpp:221
#define SCREENX
Definition: polytest.cpp:63
#define WINDING
Definition: polytest.cpp:31
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
void putpixel(int x, int y, char c)
Definition: polytest.cpp:96
static void POLYGONFILL_BuildActiveList(int Scanline, FILL_EDGE_LIST *list, FILL_EDGE **ActiveHead)
Definition: polytest.cpp:503
W w
Definition: polytest.cpp:43
#define c
Definition: ke_i.h:80
#define list
Definition: rosglue.h:35
#define malloc
Definition: debug_ros.c:4
struct RECTL RECTL
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
int _getch()
Definition: getch.c:16
struct tagPOINT POINT
INT INT y
Definition: msvc.h:62
#define memset(x, y, z)
Definition: compat.h:39
#define printf
Definition: config.h:213
INT x
Definition: msvc.h:62
INT dx
Definition: msvc.h:65