about summary refs log tree commit diff
path: root/converter
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2019-07-05 00:34:50 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2019-07-05 00:34:50 +0000
commit4308adfd8d6a4523f2a0f45faeae80d472b5b41b (patch)
tree7258c0984fbc4bdcf6b3d53cc1b71be0d195b11f /converter
parent0ef867669db4f32b2fc6b339983b1e81848398df (diff)
downloadnetpbm-mirror-4308adfd8d6a4523f2a0f45faeae80d472b5b41b.tar.gz
netpbm-mirror-4308adfd8d6a4523f2a0f45faeae80d472b5b41b.tar.xz
netpbm-mirror-4308adfd8d6a4523f2a0f45faeae80d472b5b41b.zip
Add -linewidth
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3649 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter')
-rw-r--r--converter/pbm/pbmtolps.c227
1 files changed, 131 insertions, 96 deletions
diff --git a/converter/pbm/pbmtolps.c b/converter/pbm/pbmtolps.c
index dd0342bc..dcc5badd 100644
--- a/converter/pbm/pbmtolps.c
+++ b/converter/pbm/pbmtolps.c
@@ -4,9 +4,13 @@
  * generate a (device dependent) picture which will be imaged
  * much faster.
  *
- * The Postscript path length is constrained to be less that 1000
+ * The Postscript path length is constrained to be at most 1000
  * points so that no limits are overrun on the Apple Laserwriter
- * and (presumably) no other printers.
+ * and (presumably) no other printers.  The typical limit is 1500.
+ * See "4.4 Path Construction" and "Appendix B: Implementation Limits"
+ * in: PostScript Language Reference Manual
+ *     https://www.adobe.com/content/dam/acom/en/devnet/actionscript/
+ *             articles/psrefman.pdf
  *
  * To do:
  *      make sure encapsulated format is correct
@@ -19,125 +23,143 @@
  *      University of British Columbia
  */
 
-#include <string.h>
-#include <stdio.h>
-
+#include "pm_c_util.h"
+#include "mallocvar.h"
 #include "nstring.h"
+#include "shhopt.h"
 #include "pbm.h"
 
 
-static int prev_white = -1;
-static int prev_black = -1;
-static char cmd = '\0';
-static int pointcount = 2;
+static float const MaxDPI = 5000;
+static float const MinDPI = 10;
+static unsigned int const MaxPathPoints = 1000;
+
+
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line, in a form
+       easy for the program to use.
+    */
+    const char * inputFileName;  /* File name of input file */
+    unsigned int inputFileSpec;  /* Input file name specified */
+    float        lineWidth;      /* Line width, if specified */
+    unsigned int lineWidthSpec;  /* Line width specified */
+    float        dpi;            /* Resolution in DPI, if specified */
+    unsigned int dpiSpec;        /* Resolution specified */
+};
+
 
-#ifdef RUN
-static int run = 1;
-#endif
 
-static char
-morepoints(char cmd, int howmany_pbmtolps) {
-    pointcount += 2;
-    if (pointcount > 1000) {
-        pointcount = 2;
-        cmd += 'm' - 'a';
+static void
+parseCommandLine(int                        argc,
+                 const char **        const argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Parse program command line described in Unix standard form by argc
+   and argv.  Return the information in the options as *cmdlineP.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;  /* malloc'ed */
+        /* 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, "linewidth", OPT_FLOAT, &cmdlineP->lineWidth,
+                            &cmdlineP->lineWidthSpec,    0);
+    OPTENT3(0, "dpi",       OPT_FLOAT,  &cmdlineP->dpi,
+                            &cmdlineP->dpiSpec,          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->inputFileName = "-";
+    else {
+        if (argc-1 > 1)
+            pm_error("Program takes zero or one argument (filename).  You "
+                     "specified %d", argc-1);
+        else                      
+            cmdlineP->inputFileName = argv[1];                     
     }
-    return(cmd);
+
+    if (cmdlineP->inputFileName[0] == '-' &&
+        cmdlineP->inputFileName[1] == '\0')
+        cmdlineP->inputFileSpec = FALSE;
+    else 
+        cmdlineP->inputFileSpec = TRUE;
+
+    if (cmdlineP->dpiSpec == FALSE)
+        cmdlineP->dpi = 300;
+
+    free(option_def);
 }
 
 
 
 static void
-addstrip(int const white,
-         int const black) {
-
-    if (cmd) {
-#ifdef RUN
-        if (white == prev_white && black == prev_black)
-            run++;
-        else {
-            if (run == 1)
-#endif
-                printf("%d %d %c ",
-                       prev_black, prev_white, morepoints(cmd, 2));
-#ifdef RUN
-            else
-                                /* of course, we need to give a new command */
-                printf("%d %d %d %c ",
-                       prev_white, prev_black, run,
-                       morepoints(cmd + 'f' - 'a', 2 * run));
-            run = 1;
-        }
-#endif
-    }
+validateLineWidth(float const sc_cols,
+                  float const sc_rows,
+                  float const lineWidth) {
 
-    prev_white = white;
-    prev_black = black;
-    cmd = 'a';
+    if (lineWidth >= sc_cols || lineWidth >= sc_rows)
+        pm_error("Absurdly large -linewidth value (%f)", lineWidth);
 }
 
 
 
 static void
-nextline(void) {
-    /* need to check run, should have an outcommand */
-    if (cmd)
-        printf("%d %d %c\n", prev_black, prev_white, morepoints('c', 3));
-    else
-        printf("%c\n", morepoints('b', 1));
-    cmd = '\0';
+validateDpi(float const dpi) {
+    if (dpi > MaxDPI || dpi < MinDPI)
+        pm_error("Specified DPI value out of range (%f)", dpi);
 }
 
 
 
 int
-main(int argc, char ** argv) {
+main(int argc, const char *argv[]) {
     FILE*   fp;
     bit*    bits;
-    int             row;
-    int             col;
-    int         rows;
-    int             cols;
-    int             format;
-    int             white;
-    int             black;
-    const char*   name;
-    float   dpi = 300.0;
+    int     row;
+    int     col;
+    int     rows;
+    int     cols;
+    int     format;
+    int     white;
+    int     black;
     float   sc_rows;
     float   sc_cols;
-    int             i;
-    const char*   const usage = "[ -dpi n ] [ pbmfile ]";
+    struct CmdlineInfo cmdline;
+    const char* psName;
+    unsigned int pointCnt;
 
+    pm_proginit(&argc, argv);
 
-	pbm_init(&argc, argv);
+    parseCommandLine(argc, argv, &cmdline);
+    
+    if (cmdline.dpi)
+        validateDpi(cmdline.dpi); 
 
-    i = 1;
-    if (i < argc && streq(argv[i], "-dpi")) {
-        if (i == argc - 1)
-            pm_usage(usage);
-        sscanf(argv[i + 1], "%f", &dpi);
-        i += 2;
-    }
+    fp = pm_openr(cmdline.inputFileName);
+    pbm_readpbminit(fp, &cols, &rows, &format);
 
-    if (i < argc - 1)
-        pm_usage(usage);
+    sc_rows = (float) rows / cmdline.dpi * 72.0;
+    sc_cols = (float) cols / cmdline.dpi * 72.0;
+    
+    if (cmdline.lineWidthSpec)
+        validateLineWidth(sc_cols, sc_rows, cmdline.lineWidth); 
 
-    if (i == argc) {
-        name = "noname";
-        fp = stdin;
-    } else {
-        name = argv[i];
-        fp = pm_openr(name);
-    }
-    pbm_readpbminit(fp, &cols, &rows, &format);
     bits = pbm_allocrow(cols);
-
-    sc_rows = (float)rows / dpi * 72.0;
-    sc_cols = (float)cols / dpi * 72.0;
+    psName = cmdline.inputFileSpec ? cmdline.inputFileName : "noname";
 
     puts("%!PS-Adobe-2.0 EPSF-2.0");
     puts("%%Creator: pbmtolps");
-    printf("%%%%Title: %s\n", name);
+    printf("%%%%Title: %s\n", psName);
     printf("%%%%BoundingBox: %d %d %d %d\n",
            (int)(305.5 - sc_cols / 2.0),
            (int)(395.5 - sc_rows / 2.0),
@@ -148,29 +170,42 @@ main(int argc, char ** argv) {
     puts("gsave");
 
     printf("%f %f translate\n", 306.0 - sc_cols / 2.0, 396.0 + sc_rows / 2.0);
-    printf("72 %f div dup neg scale\n", dpi);
+    printf("72 %f div dup neg scale\n", cmdline.dpi);
+    if (cmdline.lineWidthSpec)
+        printf("%f setlinewidth\n", cmdline.lineWidth); 
     puts("/a { 0 rmoveto 0 rlineto } def");
-    puts("/b { 0 row 1 add dup /row exch def moveto } def");
-    puts("/c { a b } def");
-    puts("/m { currentpoint stroke newpath moveto a } def");
-    puts("/n { currentpoint stroke newpath moveto b } def");
-    puts("/o { currentpoint stroke newpath moveto c } def");
-    puts("/row 0 def");
+    puts("/m { currentpoint stroke newpath moveto } def");
     puts("newpath 0 0 moveto");
 
+    pointCnt = 0;
     for (row = 0; row < rows; row++) {
+        bool firstRun = TRUE; /* Initial value */        
+                
         pbm_readpbmrow(fp, bits, cols, format);
-        /* output white-strip+black-strip sequences */
+        /* output white-strip + black-strip sequences */
         for (col = 0; col < cols; ) {
+        
             for (white = 0; col < cols && bits[col] == PBM_WHITE; col++)
                 white++;
             for (black = 0; col < cols && bits[col] == PBM_BLACK; col++)
                 black++;
 
-            if (black != 0)
-                addstrip(white, black);
+            if (black != 0) {
+                if (pointCnt > MaxPathPoints) {
+                     printf("m ");
+		     pointCnt = 0;
+		}
+
+                if (firstRun == TRUE) {
+                    printf ("%d %d moveto %d 0 rlineto\n", white, row, black);
+                    firstRun = FALSE;
+                }
+                else
+                    printf("%d %d a\n", black, white);
+
+                pointCnt += 2;
+            }
         }
-        nextline();
     }
     puts("stroke grestore showpage");
     puts("%%Trailer");