about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-03-27 19:22:22 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-03-27 19:22:22 +0000
commit4c233fcfb54b386fcd96f71deb1e88e10d635825 (patch)
tree8cd7f623d29368a59905ccc108e5151bc28d2e62 /lib
parent3a54a339a59e83834ea18d88cab7104fd9d8b9ca (diff)
downloadnetpbm-mirror-4c233fcfb54b386fcd96f71deb1e88e10d635825.tar.gz
netpbm-mirror-4c233fcfb54b386fcd96f71deb1e88e10d635825.tar.xz
netpbm-mirror-4c233fcfb54b386fcd96f71deb1e88e10d635825.zip
Release 10.50.00 - copied from trunk
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@1162 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib')
-rw-r--r--lib/libpam.c61
-rw-r--r--lib/libpbmfont.c80
-rw-r--r--lib/libpgm1.c2
-rw-r--r--lib/libpnm3.c2
-rw-r--r--lib/libppmd.c214
-rw-r--r--lib/pam.h4
-rw-r--r--lib/pnm.h3
-rw-r--r--lib/ppm.h6
-rw-r--r--lib/util/shhopt.h12
9 files changed, 270 insertions, 114 deletions
diff --git a/lib/libpam.c b/lib/libpam.c
index b890434e..9384e178 100644
--- a/lib/libpam.c
+++ b/lib/libpam.c
@@ -1066,6 +1066,67 @@ pnm_getopacity(const struct pam * const pamP,
 
 
 
+tuple
+pnm_backgroundtuple(struct pam *  const pamP,
+                    tuple      ** const tuples) {
+/*--------------------------------------------------------------------
+  This function was copied from libpnm3.c's pnm_backgroundxel() and
+  modified to use tuples instead of xels.
+----------------------------------------------------------------------*/
+    tuple tuplePtr, bgtuple, ul, ur, ll, lr;
+
+    /* Guess a good background value. */
+    ul = tuples[0][0];
+    ur = tuples[0][pamP->width-1];
+    ll = tuples[pamP->height-1][0];
+    lr = tuples[pamP->height-1][pamP->width-1];
+    bgtuple = NULL;
+
+    /* We first recognize three corners equal.  If not, we look for any
+       two.  If not, we just average all four.
+    */
+    if (pnm_tupleequal(pamP, ul, ur) && pnm_tupleequal(pamP, ur, ll))
+        tuplePtr = ul;
+    else if (pnm_tupleequal(pamP, ul, ur) &&
+             pnm_tupleequal(pamP, ur, lr))
+        tuplePtr = ul;
+    else if (pnm_tupleequal(pamP, ul, ll) &&
+             pnm_tupleequal(pamP, ll, lr))
+        tuplePtr = ul;
+    else if (pnm_tupleequal(pamP, ur, ll) &&
+             pnm_tupleequal(pamP, ll, lr))
+        tuplePtr = ur;
+    else if (pnm_tupleequal(pamP, ul, ur))
+        tuplePtr = ul;
+    else if (pnm_tupleequal(pamP, ul, ll))
+        tuplePtr = ul;
+    else if (pnm_tupleequal(pamP, ul, lr))
+        tuplePtr = ul;
+    else if (pnm_tupleequal(pamP, ur, ll))
+        tuplePtr = ur;
+    else if (pnm_tupleequal(pamP, ur, lr))
+        tuplePtr = ur;
+    else if (pnm_tupleequal(pamP, ll, lr))
+        tuplePtr = ll;
+    else {
+        /* Reimplement libpnm3.c's mean4() but for tuples. */
+        unsigned int plane;
+        bgtuple = pnm_allocpamtuple(pamP);
+        for (plane = 0; plane < pamP->depth; ++plane)
+          bgtuple[plane] = (ul[plane] + ur[plane] + ll[plane] + lr[plane]) / 4;
+    }
+    if (!bgtuple) {
+        unsigned int plane;
+        bgtuple = pnm_allocpamtuple(pamP);
+        for (plane = 0; plane < pamP->depth; ++plane)
+          bgtuple[plane] = tuplePtr[plane];
+    }
+
+    return bgtuple;
+}
+
+
+
 /*=============================================================================
    pm_system() Standard Input feeder and Standard Output accepter functions.   
 =============================================================================*/
diff --git a/lib/libpbmfont.c b/lib/libpbmfont.c
index ff75d0a1..793de6c5 100644
--- a/lib/libpbmfont.c
+++ b/lib/libpbmfont.c
@@ -1275,9 +1275,9 @@ skipCharacter(FILE * const fp) {
 
 
 static void
-validateEncoding(const char **  const arg,
-                 unsigned int * const codepointP,
-                 bool *         const badCodepointP) {
+interpEncoding(const char **  const arg,
+               unsigned int * const codepointP,
+               bool *         const badCodepointP) {
 /*----------------------------------------------------------------------------
    With arg[] being the ENCODING statement from the font, return as
    *codepointP the codepoint that it indicates (code point is the character
@@ -1315,12 +1315,29 @@ validateEncoding(const char **  const arg,
 
 
 
-
 static void
-processCharsLine(FILE *        const fp,
-                 const char ** const arg,
-                 struct font * const fontP) {
+readEncoding(FILE *         const ifP,
+             unsigned int * const codepointP,
+             bool *         const badCodepointP) {
+
+    const char * arg[32];
+
+    expect(ifP, "ENCODING", arg);
+    
+    interpEncoding(arg, codepointP, badCodepointP);
+}
 
+
+
+static void
+processChars(FILE *        const fp,
+             const char ** const arg,
+             struct font * const fontP) {
+/*----------------------------------------------------------------------------
+   Process the CHARS block in a BDF font file, assuming the file is positioned
+   just after the CHARS line and 'arg' is the contents of that CHARS line.
+   Read the rest of the block and apply its contents to *fontP.
+-----------------------------------------------------------------------------*/
     unsigned int const nCharacters = atoi(arg[1]);
 
     unsigned int nCharsDone;
@@ -1354,12 +1371,8 @@ processCharsLine(FILE *        const fp,
                 pm_error("no memory for font glyph for '%s' character",
                          charName);
 
-            {
-                const char * arg[32];
-                expect(fp, "ENCODING", arg);
+            readEncoding(fp, &codepoint, &badCodepoint);
 
-                validateEncoding(arg, &codepoint, &badCodepoint);
-            }
             if (badCodepoint)
                 skipCharacter(fp);
             else {
@@ -1389,7 +1402,7 @@ processCharsLine(FILE *        const fp,
                     const char * arg[32];
                     expect(fp, "ENDCHAR", arg);
                 }
-                assert(codepoint < 256); /* Ensured by validateEncoding() */
+                assert(codepoint < 256); /* Ensured by readEncoding() */
 
                 fontP->glyph[codepoint] = glyphP;
             }
@@ -1401,19 +1414,26 @@ processCharsLine(FILE *        const fp,
 
 
 static void
-processFontLine(FILE *        const fp,
-                const char *  const line,
-                const char ** const arg,
-                struct font * const fontP,
-                bool *        const endOfFontP) {
+processBdfFontLine(FILE *        const fp,
+                   const char *  const line,
+                   const char ** const arg,
+                   struct font * const fontP,
+                   bool *        const endOfFontP) {
+/*----------------------------------------------------------------------------
+   Process a nonblank line just read from a BDF font file.
 
+   This processing may involve reading more lines.
+-----------------------------------------------------------------------------*/
     *endOfFontP = FALSE;  /* initial assumption */
 
+    assert(arg[0] != NULL);  /* Entry condition */
+
     if (streq(arg[0], "COMMENT")) {
         /* ignore */
     } else if (streq(arg[0], "SIZE")) {
         /* ignore */
     } else if (streq(arg[0], "STARTPROPERTIES")) {
+        /* Read off the properties and ignore them all */
         unsigned int const propCount = atoi(arg[1]);
         unsigned int i;
         for (i = 0; i < propCount; ++i) {
@@ -1431,8 +1451,11 @@ processFontLine(FILE *        const fp,
         fontP->y         = atoi(arg[4]);
     } else if (streq(arg[0], "ENDFONT")) {
         *endOfFontP = true;
-    } else if (!strcmp(arg[0], "CHARS"))
-        processCharsLine(fp, arg, fontP);
+    } else if (streq(arg[0], "CHARS")) {
+        processChars(fp, arg, fontP);
+    } else {
+        /* ignore */
+    }
 }
 
 
@@ -1440,18 +1463,17 @@ processFontLine(FILE *        const fp,
 struct font *
 pbm_loadbdffont(const char * const name) {
 
-    FILE * fp;
-    char line[1024];
-    const char * arg[32];
+    FILE * ifP;
     struct font * fontP;
+    const char * wordList[32];
     bool endOfFont;
 
-    fp = fopen(name, "rb");
-    if (!fp)
+    ifP = fopen(name, "rb");
+    if (!ifP)
         pm_error("Unable to open BDF font file name '%s'.  errno=%d (%s)",
                  name, errno, strerror(errno));
 
-    expect(fp, "STARTFONT", arg);
+    expect(ifP, "STARTFONT", wordList);
 
     MALLOCVAR(fontP);
     if (fontP == NULL)
@@ -1471,12 +1493,14 @@ pbm_loadbdffont(const char * const name) {
     endOfFont = FALSE;
 
     while (!endOfFont) {
+        char line[1024];
+        const char * wordList[32];
         int rc;
-        rc = readline(fp, line, arg);
+        rc = readline(ifP, line, wordList);
         if (rc < 0)
             pm_error("End of file before ENDFONT statement in BDF font file");
 
-        processFontLine(fp, line, arg, fontP, &endOfFont);
+        processBdfFontLine(ifP, line, wordList, fontP, &endOfFont);
     }
     return fontP;
 }
diff --git a/lib/libpgm1.c b/lib/libpgm1.c
index 4d93e4be..64a43534 100644
--- a/lib/libpgm1.c
+++ b/lib/libpgm1.c
@@ -189,7 +189,7 @@ readRpgmRow(FILE * const fileP,
         asprintfN(&error, "Unable to allocate memory for row buffer "
                   "for %u columns", cols);
     else {
-        ssize_t rc;
+        size_t rc;
         rc = fread(rowBuffer, 1, bytesPerRow, fileP);
         if (rc == 0)
             asprintfN(&error, "Error reading row.  fread() errno=%d (%s)",
diff --git a/lib/libpnm3.c b/lib/libpnm3.c
index c41a2108..0426ebcb 100644
--- a/lib/libpnm3.c
+++ b/lib/libpnm3.c
@@ -45,7 +45,7 @@ mean4(int const format,
         break;
 
     default:
-        pm_error( "Invalid format passed to pnm_backgroundxel()");
+        pm_error("Invalid format passed to pnm_backgroundxel()");
     }
     return retval;
 }
diff --git a/lib/libppmd.c b/lib/libppmd.c
index 3f824302..deb47c0f 100644
--- a/lib/libppmd.c
+++ b/lib/libppmd.c
@@ -966,14 +966,25 @@ typedef struct
     int edge;
 } coord;
 
-typedef struct fillobj {
+typedef struct fillState {
     int n;
+        /* Number of elements in 'coords' */
     int size;
     int curedge;
     int segstart;
     int ydir;
     int startydir;
     coord * coords;
+} fillState;
+
+typedef struct fillobj {
+
+    /* The only reason we have a struct fillState separate from
+       struct fillobj is that the drawproc interface is defined to
+       have drawing not modify the fillobj, i.e. it passed
+       const fillobj * to the drawing program.
+    */
+    struct fillState * stateP;
 } fillobj;
 
 #define SOME 1000
@@ -984,16 +995,24 @@ struct fillobj *
 ppmd_fill_create(void) {
 
     fillobj * fillObjP;
+    struct fillState * stateP;
 
     MALLOCVAR(fillObjP);
     if (fillObjP == NULL)
         pm_error("out of memory allocating a fillhandle");
-    fillObjP->n = 0;
-    fillObjP->size = SOME;
-    MALLOCARRAY(fillObjP->coords, fillObjP->size);
-    if (fillObjP->coords == NULL)
+
+    MALLOCVAR(stateP);
+    if (stateP == NULL)
+        pm_error("out of memory allocating a fillhandle");
+
+    stateP->n = 0;
+    stateP->size = SOME;
+    MALLOCARRAY(stateP->coords, stateP->size);
+    if (stateP->coords == NULL)
         pm_error("out of memory allocating a fillhandle");
-    fillObjP->curedge = 0;
+    stateP->curedge = 0;
+
+    fillObjP->stateP = stateP;
     
     /* Turn off line clipping. */
     /* UGGH! We must eliminate this global variable */
@@ -1021,14 +1040,95 @@ ppmd_fill_init(void) {
 
 
 void
-ppmd_fill_destroy(struct fillobj * fillObjP) {
+ppmd_fill_destroy(struct fillobj * const fillObjP) {
 
-    free(fillObjP->coords);
+    free(fillObjP->stateP->coords);
+    free(fillObjP->stateP);
     free(fillObjP);
 }
 
 
 
+static void
+addCoord(struct fillState *  const stateP,
+         ppmd_point const point) {
+
+    stateP->coords[stateP->n].point = point;
+    stateP->coords[stateP->n].edge = stateP->curedge;
+
+    ++stateP->n;
+}
+
+
+
+static void
+startNewSegment(struct fillState * const stateP) {
+/*----------------------------------------------------------------------------
+   Close off the segment we're currently building and start a new one.
+-----------------------------------------------------------------------------*/
+    if (stateP->startydir != 0 && stateP->ydir != 0) {
+        /* There's stuff in the current segment.  */
+        if (stateP->startydir == stateP->ydir) {
+            /* Oops, first edge and last edge of current segment are the same.
+               Change all points in the first edge to be in the last.
+            */
+            int const firstEdge = stateP->coords[stateP->segstart].edge;
+            int const lastEdge  = stateP->coords[stateP->n - 1].edge;
+            coord * const segStartCoordP = &stateP->coords[stateP->segstart];
+            coord * const segEndCoordP   = &stateP->coords[stateP->n];
+
+            coord * fcP;
+
+            for (fcP = segStartCoordP;
+                 fcP < segEndCoordP && fcP->edge == firstEdge;
+                 ++fcP)
+                fcP->edge = lastEdge;
+        }
+    }
+    /* And start new segment. */
+    ++stateP->curedge;
+    stateP->segstart  = stateP->n;
+    stateP->ydir      = 0;
+    stateP->startydir = 0;
+}
+
+
+
+static void
+continueSegment(struct fillState * const stateP,
+                int                const dy) {
+/*----------------------------------------------------------------------------
+   'dy' is how much the current point is above the previous one.
+-----------------------------------------------------------------------------*/
+    if (dy != 0) {
+        if (stateP->ydir != 0 && stateP->ydir != dy) {
+            /* Direction changed.  Insert a fake coord, old
+               position but new edge number.
+            */
+            ++stateP->curedge;
+            addCoord(stateP, stateP->coords[stateP->n - 1].point);
+        }
+        stateP->ydir = dy;
+        if (stateP->startydir == 0)
+            stateP->startydir = dy;
+    }
+}
+
+
+
+
+/* ppmd_fill_drawprocp() is a drawproc that turns an outline drawing function
+   into a filled shape function.  This is a somewhat off-label application of
+   a drawproc:  A drawproc is intended just to draw a point.  So e.g. you
+   might draw a circle with a fat brush by calling ppmd_circle with a drawproc
+   that draws a point as a 10-pixel disk.
+
+   But ppmd_fill_drawproc() just draws a point the trivial way: as one pixel.
+   However, it tracks every point that is drawn in a form that a subsequent
+   ppmd_fill() call can use to to fill in the shape drawn, assuming it turns
+   out to be a closed shape.
+*/
+
 void
 ppmd_fill_drawprocp(pixel **     const pixels, 
                     unsigned int const cols, 
@@ -1037,85 +1137,39 @@ ppmd_fill_drawprocp(pixel **     const pixels,
                     ppmd_point   const p,
                     const void * const clientdata) {
 
-    fillobj * fh;
-    coord * cp;
-
-    fh = (fillobj*) clientdata;
+    const fillobj *    const fillObjP = clientdata;
+    struct fillState * const stateP   = fillObjP->stateP;
 
-    /* If these are the same coords we saved last time, don't bother. */
-    if (fh->n > 0) {
-        ppmd_point const lastPoint = fh->coords[fh->n - 1].point;
-        if (pointsEqual(p, lastPoint))
-            return;
-    }
-
-    /* Ok, these are new; make room for two more coords. */
-    if (fh->n + 1 >= fh->size) {
-        fh->size += SOME;
-        REALLOCARRAY(fh->coords, fh->size);
-        if (fh->coords == NULL)
+    /* Make room for two more coords, the max we might add. */
+    if (stateP->n + 2 > stateP->size) {
+        stateP->size += SOME;
+        REALLOCARRAY(stateP->coords, stateP->size);
+        if (stateP->coords == NULL)
             pm_error("out of memory enlarging a fillhandle");
     }
 
-    /* Check for extremum and set the edge number. */
-    if (fh->n == 0) {
+    if (stateP->n == 0) {
         /* Start first segment. */
-        fh->segstart = fh->n;
-        fh->ydir = 0;
-        fh->startydir = 0;
+        stateP->segstart = stateP->n;
+        stateP->ydir = 0;
+        stateP->startydir = 0;
+        addCoord(stateP, p);
     } else {
-        coord * const ocp = &(fh->coords[fh->n - 1]);
-        int dx, dy;
-
-        dx = p.x - ocp->point.x;
-        dy = p.y - ocp->point.y;
-        if (dx < -1 || dx > 1 || dy < -1 || dy > 1) {
-            /* Segment break.  Close off old one. */
-            if (fh->startydir != 0 && fh->ydir != 0)
-                if (fh->startydir == fh->ydir) {
-                    /* Oops, first edge and last edge are the same.
-                       Renumber the first edge in the old segment.
-                    */
-                    const coord * const fcpLast= &(fh->coords[fh->n -1]); 
-                    coord * fcp;
-
-                    int oldedge;
-
-                    fcp = &(fh->coords[fh->segstart]);
-                    oldedge = fcp->edge;
-                    for (; fcp <= fcpLast && fcp->edge == oldedge ; ++fcp)
-                        fcp->edge = ocp->edge;
-                }
-            /* And start new segment. */
-            ++fh->curedge;
-            fh->segstart = fh->n;
-            fh->ydir = 0;
-            fh->startydir = 0;
+        ppmd_point const prevPoint = stateP->coords[stateP->n - 1].point;
+        int const dx = p.x - prevPoint.x;
+        int const dy = p.y - prevPoint.y;
+
+        if (dx == 0 && dy == 0) {
+            /* These are the same coords we had last time; don't bother */
         } else {
-            /* Segment continues. */
-            if (dy != 0) {
-                if (fh->ydir != 0 && fh->ydir != dy) {
-                    /* Direction changed.  Insert a fake coord, old
-                       position but new edge number.
-                    */
-                    ++fh->curedge;
-                    cp = &fh->coords[fh->n];
-                    cp->point = ocp->point;
-                    cp->edge = fh->curedge;
-                    ++fh->n;
-                }
-                fh->ydir = dy;
-                if (fh->startydir == 0)
-                    fh->startydir = dy;
-            }
+            if (abs(dx) > 1 || abs(dy) > 1)
+                startNewSegment(stateP);
+            else
+                continueSegment(stateP, dy);
+
+            addCoord(stateP, p);
         }
     }
-
-    /* Save this coord. */
-    cp = &fh->coords[fh->n];
-    cp->point = p;
-    cp->edge = fh->curedge;
-    ++fh->n;
 }
 
 
@@ -1173,10 +1227,12 @@ ppmd_fill(pixel **         const pixels,
           int              const cols, 
           int              const rows, 
           pixval           const maxval, 
-          struct fillobj * const fh,
+          struct fillobj * const fillObjP,
           ppmd_drawproc          drawProc,
           const void *     const clientdata) {
 
+    struct fillState * const fh = fillObjP->stateP;
+
     int pedge;
     int i, edge, lx, rx, py;
     coord * cp;
diff --git a/lib/pam.h b/lib/pam.h
index c28c5c2c..3d1f8532 100644
--- a/lib/pam.h
+++ b/lib/pam.h
@@ -483,6 +483,10 @@ pnm_YCbCr_to_rgbtuple(const struct pam * const pamP,
     ((tuple)[PAM_RED_PLANE] == (tuple)[PAM_GRN_PLANE] && \
      (tuple)[PAM_RED_PLANE] == (tuple)[PAM_BLU_PLANE])
 
+tuple
+pnm_backgroundtuple(struct pam *  const pamP,
+                    tuple      ** const tuples);
+
 /*----------------------------------------------------------------------------
    These are meant for passing to pm_system() as Standard Input feeder
    and Standard Output accepter.
diff --git a/lib/pnm.h b/lib/pnm.h
index e4bd34a8..de5f1d91 100644
--- a/lib/pnm.h
+++ b/lib/pnm.h
@@ -20,6 +20,9 @@ typedef pixval xelval;
 #define PNM_OVERALLMAXVAL PPM_OVERALLMAXVAL
 #define PNM_MAXMAXVAL PPM_MAXMAXVAL
 #define PNM_GET1(x) PPM_GETB(x)
+#define PNM_GETR(x) PPM_GETR(x)
+#define PNM_GETG(x) PPM_GETG(x)
+#define PNM_GETB(x) PPM_GETB(x)
 #define PNM_ASSIGN1(x,v) PPM_ASSIGN(x,0,0,v)
 #define PNM_ASSIGN(x,r,g,b) PPM_ASSIGN(x,r,g,b)
 #define PNM_EQUAL(x,y) PPM_EQUAL(x,y)
diff --git a/lib/ppm.h b/lib/ppm.h
index 0695295f..57b6c04a 100644
--- a/lib/ppm.h
+++ b/lib/ppm.h
@@ -250,6 +250,12 @@ ppm_hsv_from_color(pixel  const color,
                    pixval const maxval);
 
 static __inline pixval
+ppm_luminosity(pixel const p) {
+
+    return (pixval)(PPM_LUMIN(p) + 0.5);
+}
+
+static __inline pixval
 ppm_colorvalue(pixel const p) {
 /*----------------------------------------------------------------------------
   The color value (V is HSV) as a pixval
diff --git a/lib/util/shhopt.h b/lib/util/shhopt.h
index 2175fc5d..e5e138e1 100644
--- a/lib/util/shhopt.h
+++ b/lib/util/shhopt.h
@@ -1,4 +1,5 @@
-/*=============================================================================
+#if 0
+=============================================================================
 HERE IS AN EXAMPLE OF THE USE OF SHHOPT:
 
 
@@ -6,8 +7,9 @@ HERE IS AN EXAMPLE OF THE USE OF SHHOPT:
 int 
 main ( int argc, char **argv ) {
 
-    // initial values here are just to demonstrate what gets set and
-    // what doesn't by the code below.
+    /* initial values here are just to demonstrate what gets set and
+       what doesn't by the code below.
+    */
     int help_flag = 7;
     unsigned int help_spec =7;
     unsigned int height_spec =7;
@@ -67,8 +69,8 @@ Now run this program with something like
   myprog -v /etc/passwd -name=Bryan --hei=4
 
 
-========================================================================*/
-
+========================================================================
+#endif /* 0 */
 
 #ifndef SHHOPT_H
 #define SHHOPT_H