const char * UsageLines [] = {
       "Usage: drawpolygons (width) (height)",
       "Reads corners of polygons in across, down coordinates, from standard input.",
       "Writes a ppm image of specified width and height to standard output.",
       "Each nonblank input line must begin with colors r g b followed",
       "by across,down for each corner (at least 3 corners to have any effect).",
       "The order is front-to-back, meaning a polygon will cover",
       "any polygon given in a later line.",
       "drawpolygon ignores anything after # to end-of-line.",
       "January 4, 2017.  Newest is at gopher -p users/julianbr sdf.org",
       };
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );


struct Polygon {
       int r, g, b;
       struct Corner {
               long int across, down;
               struct Corner * next;
               } * Corners;
       struct Polygon * next;
       };

#include <stdlib.h>
#include <stdio.h>


#define BackgroundR 200
#define BackgroundG 200
#define BackgroundB 200


int ReadPolygon (struct Polygon * * PolygonPtr, int * EndOfInputPtr)
       {
       struct Polygon * Polygon;
       struct Corner * * CornerPtr, * Corners, * Corner;
       int ok, c, IsNegative;
       int r, g, b, across, down, Found, FoundB, FoundDown;

       ok = 1;
       c = getchar ();
       while (c == ' ')
               c = getchar ();
       Found = 0;
       Polygon = NULL;
       if (c != EOF && c != '\n' && c != '#') {
               Found = 1;
               PolygonPtr [0] = malloc (sizeof (PolygonPtr [0] [0] ) );
               Polygon = PolygonPtr [0];
               if (ok && Polygon == NULL) {
                       fprintf (stderr, "***drawpolygons: Not enough memory");
                       ok = 0;
                       }
               }
       IsNegative = 0;
       if (c == '+')
               c = getchar ();
       else if (c == '-') {
               IsNegative = 1;
               c = getchar ();
               }
       r = 0;
       while (c >= '0' && c <= '9') {
               r = 10*r + (c - '0');
               c = getchar ();
               }
       if (IsNegative)
               r = - r;
       while (c == ' ')
               c = getchar ();
       IsNegative = 0;
       if (c == '+')
               c = getchar ();
       else if (c == '-') {
               IsNegative = 1;
               c = getchar ();
               }
       g = 0;
       while (c >= '0' && c <= '9') {
               g = 10*g + (c - '0');
               c = getchar ();
               }
       if (IsNegative)
               g = - g;
       while (c == ' ')
               c = getchar ();
       IsNegative = 0;
       if (c == '+')
               c = getchar ();
       else if (c == '-') {
               IsNegative = 1;
               c = getchar ();
               }
       FoundB = 0;
       b = 0;
       while (c >= '0' && c <= '9') {
               FoundB = 1;
               b = 10*b + (c - '0');
               c = getchar ();
               }
       if (IsNegative)
               b = - b;
       if (ok && Found && !FoundB) {
               fprintf (stderr, "***xyzproject: r g b not found");
               ok = 0;
               }
       Corners = NULL;
       CornerPtr = & Corners;
       while (c == ' ')
               c = getchar ();
       while (c == '+' || c == '-' || (c >= '0' && c <= '9') ) {
               CornerPtr [0] = malloc (sizeof (CornerPtr [0] [0] ) );
               Corner = CornerPtr [0];
               if (ok && CornerPtr [0] == NULL) {
                       fprintf (stderr, "***drawpolygons: Not");
                       fprintf (stderr, " enough memory");
                       ok = 0;
                       }
               IsNegative = 0;
               if (c == '+')
                       c = getchar ();
               else if (c == '-') {
                       IsNegative = 1;
                       c = getchar ();
                       }
               across = 0;
               while (c >= '0' && c <= '9') {
                       across = 10*across + (c - '0');
                       c = getchar ();
                       }
               if (IsNegative)
                       across = - across;
               if (c == ',')
                       c = getchar ();
               IsNegative = 0;
               if (c == '+')
                       c = getchar ();
               else if (c == '-') {
                       IsNegative = 1;
                       c = getchar ();
                       }
               FoundDown = 0;
               down = 0;
               while (c >= '0' && c <= '9') {
                       FoundDown = 1;
                       down = 10*down + (c - '0');
                       c = getchar ();
                       }
               if (IsNegative)
                       down = - down;
               if (c == ',')
                       c = getchar ();
               if (ok && !FoundDown) {
                       fprintf (stderr, "***drawpolygons: Didn't find across,down");
                       ok = 0;
                       }
               while (c == ' ')
                       c = getchar ();
               if (Corner != NULL) {
                       Corner->across = across;
                       Corner->down = down;
                       Corner->next = NULL;
                       CornerPtr = & Corner->next;
                       }
               }
       if (ok && c != EOF && c != '\n' && c != '#') {
               fprintf (stderr, "***drawpolygons: Found improper");
               fprintf (stderr, " '%c'", c);
               ok = 0;
               }
       while (c != EOF && c != '\n')
               c = getchar ();
       if (Polygon != NULL) {
               Polygon->r = r;
               Polygon->g = g;
               Polygon->b = b;
               Polygon->Corners = Corners;
               Polygon->next = NULL;
               }
       PolygonPtr [0] = Polygon;
       if (c != '\n')
               EndOfInputPtr [0] = 1;
       return ok;
       }


int ReadPolygons (struct Polygon * * PolygonsPtr)
       {
       struct Polygon * * PolygonPtr, * Polygon;
       int EndOfInput, LineNum, ok;

       PolygonPtr = PolygonsPtr;
       ok = 1;
       LineNum = 0;
       EndOfInput = 0 ;
       while (!EndOfInput) {
               LineNum++;
               if (!ReadPolygon (& Polygon, & EndOfInput) ) {
                       fprintf (stderr, " in line %d.\n", LineNum);
                       ok = 0;
                       }
               if (Polygon != NULL) {
                       PolygonPtr [0] = Polygon;
                       PolygonPtr = & Polygon->next;
                       }
               }
       return ok;
       }


void DrawPolygons (struct Polygon * Polygons, int width, int height)
       {
       struct Polygon * Polygon;
       struct Corner * Corner;
       long int a1, d1, a2, d2, a, d;
       int i, j, NumCrossings;

       printf ("P6\n");
       printf ("%d %d\n", width, height);
       printf ("255\n");
       for (i = 0; i < height; i++) {
               d = i - height/2;
               for (j = 0; j < width; j++) {
                       a = j - width/2;
                       NumCrossings = 0;
                       Polygon = Polygons;
                       while (Polygon != NULL && NumCrossings == 0) {
                               Corner = Polygon->Corners;
                               while (Corner != NULL) {
                                       a1 = Corner->across;
                                       d1 = Corner->down;
                                       if (Corner->next == NULL) {
                                               a2 = Polygon->Corners->across;
                                               d2 = Polygon->Corners->down;
                                               }
                                       else {
                                               a2 = Corner->next->across;
                                               d2 = Corner->next->down;
                                               }
                                       if (d1 <= d && d < d2 ) {
                                               if ((a - a1)*(d2 - d1) >= (a2 - a1)*(d - d1) )
                                                       NumCrossings++;
                                               }
                                       else if (d1 > d && d >= d2) {
                                               if ((a - a2)*(d1 - d2) >= (a1 - a2)*(d - d2) )
                                                       NumCrossings--;
                                               }
                                       Corner = Corner->next;
                                       }
                               if (NumCrossings != 0) {
                                       putchar (Polygon->r);
                                       putchar (Polygon->g);
                                       putchar (Polygon->b);
                                       }
                               Polygon = Polygon->next;
                               }
                       if (NumCrossings == 0) {
                               putchar (BackgroundR);
                               putchar (BackgroundG);
                               putchar (BackgroundB);
                               }
                       }
               }
       }


void WritePolygons (struct Polygon * Polygons)
       {
       struct Polygon * Polygon;
       struct Corner * Corner;

       Polygon = Polygons;
       while (Polygon != NULL) {
               printf ("%d %d %d", Polygon->r, Polygon->g, Polygon->b);
               Corner = Polygon->Corners;
               while (Corner != NULL) {
                       printf (" %ld,%ld", Corner->across, Corner->down);
                       Corner = Corner->next;
                       }
               printf ("\n");
               Polygon = Polygon->next;
               }
       }


void ClosePolygons (struct Polygon * Polygons)
       {
       struct Polygon * Polygon, * NextPolygon;
       struct Corner * Corner, * NextCorner;

       Polygon = Polygons;
       while (Polygon != NULL) {
               NextPolygon = Polygon->next;
               Corner = Polygon->Corners;
               while (Corner != NULL) {
                       NextCorner = Corner->next;
                       free (Corner);
                       Corner = NextCorner;
                       }
               free (Polygon);
               Polygon = NextPolygon;
               }
       }

int main (int argc, char * argv [] )
       {
       struct Polygon * Polygons;
       int width, height, ok, i;
       char c;

       if (argc < 2) {
               for (i = 0; i < NumUsageLines; i++)
                       printf ("%s\n", UsageLines [i] );
               }
       else if (argc == 3) {
               ok = 1;
               if (sscanf (argv [1], "%d%c", & width, & c) != 1) {
                       fprintf (stderr, "***drawpolygons: expecting");
                       fprintf (stderr, " width, found");
                       fprintf (stderr, " \"%s\".\n", argv [3] );
                       ok = 0;
                       }
               if (sscanf (argv [2], "%d%c", & height, & c) != 1) {
                       fprintf (stderr, "***drawpolygons: expecting");
                       fprintf (stderr, " height, found");
                       fprintf (stderr, " \"%s\".\n", argv [3] );
                       ok = 0;
                       }
               if (ok) {
                       Polygons = NULL;
                       if (ReadPolygons (& Polygons) )
                               DrawPolygons (Polygons, width, height);
                       else
                               WritePolygons (Polygons);
                       ClosePolygons (Polygons);
                       }
               }
       else {
               fprintf (stderr, "Usage: drawpolygons");
               fprintf (stderr, " (width) (height)\n");
               }
       return 0;
       }