about summary refs log tree commit diff
path: root/generator/pbmpage.c
diff options
context:
space:
mode:
Diffstat (limited to 'generator/pbmpage.c')
-rw-r--r--generator/pbmpage.c392
1 files changed, 255 insertions, 137 deletions
diff --git a/generator/pbmpage.c b/generator/pbmpage.c
index a2f47bcc..96dca876 100644
--- a/generator/pbmpage.c
+++ b/generator/pbmpage.c
@@ -1,6 +1,6 @@
-/***************************************************************************
+/*=============================================================================
                                 pbmpage
-
+===============================================================================
   This program produces a printed page test pattern in PBM format.
 
   This was adapted from Tim Norman's 'pbmtpg' program, part of his
@@ -10,7 +10,7 @@
 
   For copyright and licensing information, see the pbmtoppa program,
   which was also derived from the same package.
-****************************************************************************/
+=============================================================================*/
 
 #include <stdlib.h>
 #include <string.h>
@@ -18,73 +18,139 @@
 #include <stdio.h>
 
 #include "pm_c_util.h"
+#include "mallocvar.h"
+#include "shhopt.h"
+#include "nstring.h"
 #include "pbm.h"
 
+enum Pattern {PAT_GRID, PAT_VERTICAL, PAT_DIAGONAL};
+
 /* US is 8.5 in by 11 in */
 
-#define USWIDTH  (5100)
-#define USHEIGHT (6600)
+static unsigned int const usWidth  = 5100;
+static unsigned int const usHeight = 6600;
 
 /* A4 is 210 mm by 297 mm == 8.27 in by 11.69 in */
 
-#define A4WIDTH  (4960)
-#define A4HEIGHT (7016)
+static unsigned int const a4Width  = 4960;
+static unsigned int const a4Height = 7016;
 
 
-struct bitmap {
-    unsigned int Width;      /* width and height in 600ths of an inch */
-    unsigned int Height;
-    bit ** bitmap;
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    enum Pattern pattern;
+    unsigned int a4;
 };
 
-static struct bitmap bitmap;
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that the file spec array we return is stored in the storage that
+   was passed to us as the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;
+        /* Instructions to OptParseOptions3 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENTRY */
+    OPTENT3(0, "a4",         OPT_FLAG, NULL, &cmdlineP->a4,       0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+    /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (argc-1 < 1)
+        cmdlineP->pattern = PAT_GRID;
+    else {
+        if (argc-1 > 1)
+            pm_error("Too many arguments (%u).  The only possible argument "
+                     "is the pattern number", argc-1);
+        if (streq(argv[1], "1"))
+            cmdlineP->pattern = PAT_GRID;
+        else if (streq(argv[1], "2"))
+            cmdlineP->pattern = PAT_VERTICAL;
+        else if (streq(argv[1], "3"))
+            cmdlineP->pattern = PAT_DIAGONAL;
+        else
+            pm_error("Invalid test pattern name '%s'.  "
+                     "We recognize only '1', '2', and '3'", argv[1]);
+    }
+    free(option_def);
+}
+
+
+
+struct Bitmap {
+    /* width and height in 600ths of an inch */
+    unsigned int width;
+    unsigned int height;
+
+    unsigned char ** bitmap;
+};
 
 
 
 static void
-setpixel(unsigned int const x,
-         unsigned int const y,
-         unsigned int const c) {
+setpixel(struct Bitmap * const bitmapP,
+         unsigned int    const x,
+         unsigned int    const y,
+         bit             const c) {
 
     char const bitmask = 128 >> (x % 8);
 
-    if (x < 0 || x >= bitmap.Width)
-        return;
-    if (y < 0 || y >= bitmap.Height)
-        return;
-
-    if (c)
-        bitmap.bitmap[y][x/8] |= bitmask;
-    else
-        bitmap.bitmap[y][x/8] &= ~bitmask;
+    if (x < 0 || x >= bitmapP->width) {
+        /* Off the edge of the canvas */
+    } else if (y < 0 || y >= bitmapP->height) {
+        /* Off the edge of the canvas */
+    } else {
+        if (c == PBM_BLACK)
+            bitmapP->bitmap[y][x/8] |= bitmask;
+        else
+            bitmapP->bitmap[y][x/8] &= ~bitmask;
+    }
 }
 
 
 
-static void 
-setplus(unsigned int const x,
-        unsigned int const y,
-        unsigned int const s) {
+static void
+setplus(struct Bitmap * const bitmapP,
+        unsigned int    const x,
+        unsigned int    const y,
+        unsigned int    const s) {
 /*----------------------------------------------------------------------------
-   Draw a black plus sign centered at (x,y) with arms 's' pixels long.  
+   Draw a black plus sign centered at (x,y) with arms 's' pixels long.
    Leave the exact center of the plus white.
 -----------------------------------------------------------------------------*/
     unsigned int i;
 
     for (i = 0; i < s; ++i) {
-        setpixel(x+i, y,   1);
-        setpixel(x-i, y,   1);
-        setpixel(x,   y+i, 1);
-        setpixel(x,   y-i, 1);
+        setpixel(bitmapP, x + i, y,     PBM_BLACK);
+        setpixel(bitmapP, x - i, y,     PBM_BLACK);
+        setpixel(bitmapP, x ,    y + i, PBM_BLACK);
+        setpixel(bitmapP, x ,    y - i, PBM_BLACK);
     }
 }
 
 
 
-static void 
-setblock(unsigned int const x,
-         unsigned int const y,
-         unsigned int const s) {
+static void
+setblock(struct Bitmap * const bitmapP,
+         unsigned int    const x,
+         unsigned int    const y,
+         unsigned int    const s) {
 
     unsigned int i;
 
@@ -92,16 +158,17 @@ setblock(unsigned int const x,
         unsigned int j;
 
         for (j = 0; j < s; ++j)
-            setpixel(x+i, y+j, 1);
+            setpixel(bitmapP, x + i, y + j, PBM_BLACK);
     }
 }
 
 
 
-static void 
-setchar(unsigned int const x,
-        unsigned int const y,
-        char         const c) {
+static void
+setchar(struct Bitmap * const bitmapP,
+        unsigned int    const x,
+        unsigned int    const y,
+        char            const c) {
 
     static char const charmap[10][5]= { { 0x3e, 0x41, 0x41, 0x41, 0x3e },
                                         { 0x00, 0x42, 0x7f, 0x40, 0x00 },
@@ -113,7 +180,7 @@ setchar(unsigned int const x,
                                         { 0x01, 0x01, 0x61, 0x19, 0x07 },
                                         { 0x36, 0x49, 0x49, 0x49, 0x36 },
                                         { 0x26, 0x49, 0x49, 0x49, 0x3e } };
-    
+
     if (c <= '9' && c >= '0') {
         unsigned int xo;
 
@@ -122,7 +189,7 @@ setchar(unsigned int const x,
 
             for (yo = 0; yo < 8; ++yo) {
                 if ((charmap[c-'0'][xo] >> yo) & 0x01)
-                    setblock(x + xo*3, y + yo*3, 3);
+                    setblock(bitmapP, x + xo*3, y + yo*3, 3);
             }
         }
     }
@@ -130,23 +197,25 @@ setchar(unsigned int const x,
 
 
 
-static void 
-setstring(unsigned int const x,
-          unsigned int const y,
-          const char * const s) {
+static void
+setstring(struct Bitmap * const bitmapP,
+          unsigned int    const x,
+          unsigned int    const y,
+          const char *    const s) {
 
     const char * p;
     unsigned int xo;
 
     for (xo = 0, p = s; *p; xo += 21, ++p)
-        setchar(x + xo, y, *p);
+        setchar(bitmapP, x + xo, y, *p);
 }
 
 
 
-static void 
-setCG(unsigned int const x,
-      unsigned int const y) {
+static void
+setCG(struct Bitmap * const bitmapP,
+      unsigned int    const x,
+      unsigned int    const y) {
 
     unsigned int xo;
 
@@ -155,16 +224,16 @@ setCG(unsigned int const x,
 
         unsigned int zo;
 
-        setpixel(x + xo, y + yo, 1);
-        setpixel(x+yo,   y + xo, 1);
-        setpixel(x-1-xo, y-1-yo, 1);
-        setpixel(x-1-yo, y-1-xo, 1);
-        setpixel(x+xo,   y-1-yo, 1);
-        setpixel(x-1-xo, y+yo,   1);
+        setpixel(bitmapP, x + xo    , y + yo    , PBM_BLACK);
+        setpixel(bitmapP, x + yo    , y + xo    , PBM_BLACK);
+        setpixel(bitmapP, x - 1 - xo, y - 1 - yo, PBM_BLACK);
+        setpixel(bitmapP, x - 1 - yo, y - 1 - xo, PBM_BLACK);
+        setpixel(bitmapP, x + xo    , y - 1 - yo, PBM_BLACK);
+        setpixel(bitmapP, x - 1 - xo, y + yo    , PBM_BLACK);
 
-        for(zo = 0; zo < yo; ++zo) {
-            setpixel(x + xo, y-1-zo, 1);
-            setpixel(x-1-xo, y+zo,   1);
+        for (zo = 0; zo < yo; ++zo) {
+            setpixel(bitmapP, x + xo    , y - 1 - zo, PBM_BLACK);
+            setpixel(bitmapP, x - 1 - xo, y + zo    , PBM_BLACK);
         }
     }
 }
@@ -173,129 +242,178 @@ setCG(unsigned int const x,
 
 static void
 outputPbm(FILE *        const ofP,
-          struct bitmap const bitmap) {
+          struct Bitmap const bitmap) {
 /*----------------------------------------------------------------------------
   Create a pbm file containing the image from the global variable bitmap[].
 -----------------------------------------------------------------------------*/
     int const forceplain = 0;
 
     unsigned int row;
-    
-    pbm_writepbminit(ofP, bitmap.Width, bitmap.Height, forceplain);
-    
-    for (row = 0; row < bitmap.Height; ++row) {
+
+    pbm_writepbminit(ofP, bitmap.width, bitmap.height, forceplain);
+
+    for (row = 0; row < bitmap.height; ++row) {
         pbm_writepbmrow_packed(ofP, bitmap.bitmap[row],
-                               bitmap.Width, forceplain); 
+                               bitmap.width, forceplain);
     }
 }
 
 
 
 static void
-framePerimeter(unsigned int const Width, 
-               unsigned int const Height) {
+framePerimeter(struct Bitmap * const bitmapP) {
 
     unsigned int x, y;
 
     /* Top edge */
-    for (x = 0; x < Width; ++x)
-        setpixel(x, 0, 1);
+    for (x = 0; x < bitmapP->width; ++x)
+        setpixel(bitmapP, x, 0, PBM_BLACK);
 
     /* Bottom edge */
-    for (x = 0; x < Width; ++x)
-        setpixel(x, Height-1, 1);
+    for (x = 0; x < bitmapP->width; ++x)
+        setpixel(bitmapP, x, bitmapP->height - 1, PBM_BLACK);
 
     /* Left edge */
-    for (y = 0; y < Height; ++y)
-        setpixel(0, y, 1);
+    for (y = 0; y < bitmapP->height; ++y)
+        setpixel(bitmapP, 0, y, PBM_BLACK);
 
     /* Right edge */
-    for (y = 0; y < Height; ++y)
-        setpixel(Width-1, y, 1);
+    for (y = 0; y < bitmapP->height; ++y)
+        setpixel(bitmapP, bitmapP->width - 1, y, PBM_BLACK);
 }
 
 
 
-int 
-main(int argc, const char** argv) {
+static void
+makeWhite(struct Bitmap * const bitmapP) {
 
-    int TP;
-    unsigned int x, y;
-    char buf[128];
-    /* width and height in 600ths of an inch */
-    unsigned int Width;
-    unsigned int Height;
+    unsigned int y;
 
-    pm_proginit(&argc, argv);
-
-    if (argc > 1 && strcmp(argv[1], "-a4") == 0) {
-        Width  = A4WIDTH;
-        Height = A4HEIGHT;
-        --argc;
-        ++argv;
-    } else {
-        Width  = USWIDTH;
-        Height = USHEIGHT;
+    for (y = 0; y < bitmapP->height; ++y) {
+        unsigned int x;
+        for (x = 0; x < pbm_packed_bytes(bitmapP->width); ++x)
+            bitmapP->bitmap[y][x] = 0x00;  /* 8 white pixels */
     }
+}
 
-    if (argc > 1)
-        TP = atoi(argv[1]);
-    else
-        TP = 1;
 
-    bitmap.Width  = Width;
-    bitmap.Height = Height;
-    bitmap.bitmap = pbm_allocarray_packed(Width, bitmap.Height);
 
-    for (y = 0; y < bitmap.Height; ++y) {
-        unsigned int x;
-        for (x = 0; x < pbm_packed_bytes(bitmap.Width); ++x) 
-            bitmap.bitmap[y][x] = 0x00; 
-    }
+static void
+drawGrid(struct Bitmap * const bitmapP) {
 
-    switch (TP) {
-    case 1:
-        framePerimeter(Width, Height);
-        for (x = 0; x < Width; x += 100) {
+    char buf[128];
+
+    framePerimeter(bitmapP);
+    {
+        unsigned int x;
+        for (x = 0; x < bitmapP->width; x += 100) {
             unsigned int y;
-            for(y = 0; y < Height; y += 100)
-                setplus(x, y, 4);
+            for (y = 0; y < bitmapP->height; y += 100)
+                setplus(bitmapP, x, y, 4);
         }
-        for(x = 0; x < Width; x += 100) {
-            sprintf(buf,"%d", x);
-            setstring(x + 3, (Height/200) * 100 + 3, buf);
+    }
+    {
+        unsigned int x;
+        for (x = 0; x < bitmapP->width; x += 100) {
+            sprintf(buf,"%u", x);
+            setstring(bitmapP, x + 3, (bitmapP->height/200) * 100 + 3, buf);
         }
-        for (y = 0; y < Height; y += 100) {
-            sprintf(buf, "%d", y);
-            setstring((Width/200) * 100 + 3, y + 3, buf);
+    }
+    {
+        unsigned int y;
+        for (y = 0; y < bitmapP->height; y += 100) {
+            sprintf(buf, "%u", y);
+            setstring(bitmapP, (bitmapP->width/200) * 100 + 3, y + 3, buf);
         }
-        for (x = 0; x < Width; x += 10)
-            for (y = 0; y < Height; y += 100)
-                setplus(x, y, ((x%100) == 50) ? 2 : 1);
-        for (x = 0; x < Width; x += 100) {
+    }
+    {
+        unsigned int x;
+        for (x = 0; x < bitmapP->width; x += 10) {
             unsigned int y;
-            for (y = 0; y < Height; y += 10)
-                setplus(x, y, ((y%100) == 50) ? 2 : 1);
+            for (y = 0; y < bitmapP->height; y += 100)
+                setplus(bitmapP, x, y, ((x%100) == 50) ? 2 : 1);
         }
-        setCG(Width/2, Height/2);
+    }
+    {
+        unsigned int x;
+        for (x = 0; x < bitmapP->width; x += 100) {
+            unsigned int y;
+            for (y = 0; y < bitmapP->height; y += 10)
+                setplus(bitmapP, x, y, ((y%100) == 50) ? 2 : 1);
+        }
+    }
+    setCG(bitmapP, bitmapP->width/2, bitmapP->height/2);
+}
+
+
+
+static void
+drawVertical(struct Bitmap * const bitmapP) {
+
+    unsigned int y;
+
+    for (y = 0; y < 300; ++y)
+        setpixel(bitmapP, bitmapP->width/2, bitmapP->height/2 - y, PBM_BLACK);
+}
+
+
+
+static void
+drawDiagonal(struct Bitmap * const bitmapP) {
+
+    unsigned int y;
+
+    for (y = 0; y < 300; ++y) {
+        setpixel(bitmapP, y, y, PBM_BLACK);
+        setpixel(bitmapP, bitmapP->width - 1 - y, bitmapP->height - 1 - y,
+                 PBM_BLACK);
+    }
+}
+
+
+
+int
+main(int argc, const char** argv) {
+
+    struct CmdlineInfo cmdline;
+    /* width and height in 600ths of an inch */
+    unsigned int width;
+    unsigned int height;
+    struct Bitmap bitmap;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    if (cmdline.a4) {
+        width  = a4Width;
+        height = a4Height;
+    } else {
+        width  = usWidth;
+        height = usHeight;
+    }
+
+    bitmap.width  = width;
+    bitmap.height = height;
+    bitmap.bitmap = pbm_allocarray_packed(width, height);
+
+    makeWhite(&bitmap);
+
+    switch (cmdline.pattern) {
+    case PAT_GRID:
+        drawGrid(&bitmap);
         break;
-    case 2:
-        for (y = 0; y < 300; ++y)
-            setpixel(Width/2, Height/2-y, 1);
+    case PAT_VERTICAL:
+        drawVertical(&bitmap);
         break;
-    case 3:
-        for (y = 0; y < 300; ++y) {
-            setpixel(y, y, 1);
-            setpixel(Width-1-y, Height-1-y, 1);
-        }
+    case PAT_DIAGONAL:
+        drawDiagonal(&bitmap);
         break;
-    default:
-        pm_error("unknown test pattern (%d)", TP);
     }
 
     outputPbm(stdout, bitmap);
 
-    pbm_freearray(bitmap.bitmap, Height);
+    pbm_freearray(bitmap.bitmap, height);
 
     pm_close(stdout);