about summary refs log tree commit diff
path: root/lib/libpbmfont.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpbmfont.c')
-rw-r--r--lib/libpbmfont.c1155
1 files changed, 0 insertions, 1155 deletions
diff --git a/lib/libpbmfont.c b/lib/libpbmfont.c
deleted file mode 100644
index 8f308eda..00000000
--- a/lib/libpbmfont.c
+++ /dev/null
@@ -1,1155 +0,0 @@
-/*
-**
-** Font routines.
-**
-** BDF font code Copyright 1993 by George Phillips.
-**
-** Copyright (C) 1991 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
-**
-** BDF font specs available from:
-** https://partners.adobe.com/public/developer/en/font/5005.BDF_Spec.pdf
-** Glyph Bitmap Distribution Format (BDF) Specification
-** Version 2.2
-** 22 March 1993
-** Adobe Developer Support
-*/
-
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "netpbm/pm_c_util.h"
-#include "netpbm/mallocvar.h"
-#include "netpbm/nstring.h"
-
-#include "pbmfont.h"
-#include "pbm.h"
-
-static unsigned int const firstCodePoint = 32;
-    /* This is the code point of the first character in a pbmfont font.
-       In ASCII, it is a space.
-    */
-
-static unsigned int const nCharsInFont = 96;
-    /* The number of characters in a pbmfont font.  A pbmfont font defines
-       characters at position 32 (ASCII space) through 127, so that's 96.
-    */
-
-
-struct font *
-pbm_defaultfont(const char * const name) {
-/*----------------------------------------------------------------------------
-   Generate the built-in font with name 'name'.
------------------------------------------------------------------------------*/
-    struct font * retval;
-
-    if (streq(name, "bdf"))
-        retval = &pbm_defaultBdffont;
-    else if (streq(name, "fixed"))
-        retval = &pbm_defaultFixedfont;
-    else
-        pm_error( "built-in font name unknown, try 'bdf' or 'fixed'");
-
-    return retval;
-}
-
-
-
-static void
-findFirstBlankRow(const bit **   const font,
-                  unsigned int   const fcols,
-                  unsigned int   const frows,
-                  unsigned int * const browP) {
-
-    unsigned int row;
-    bool foundBlank;
-
-    for (row = 0, foundBlank = false; row < frows / 6 && !foundBlank; ++row) {
-        unsigned int col;
-        bit col0Value = font[row][0];
-        bool rowIsBlank;
-        rowIsBlank = true;  /* initial assumption */
-        for (col = 1; col < fcols; ++col)
-            if (font[row][col] != col0Value)
-                rowIsBlank = false;
-
-        if (rowIsBlank) {
-            foundBlank = true;
-            *browP = row;
-        }
-    }
-
-    if (!foundBlank)
-        pm_error("couldn't find blank pixel row in font");
-}
-
-
-
-static void
-findFirstBlankCol(const bit **   const font,
-                  unsigned int   const fcols,
-                  unsigned int   const frows,
-                  unsigned int * const bcolP) {
-
-    unsigned int col;
-    bool foundBlank;
-
-    for (col = 0, foundBlank = false; col < fcols / 6 && !foundBlank; ++col) {
-        unsigned int row;
-        bit row0Value = font[0][col];
-        bool colIsBlank;
-        colIsBlank = true;  /* initial assumption */
-        for (row = 1; row < frows; ++row)
-            if (font[row][col] != row0Value)
-                colIsBlank = false;
-
-        if (colIsBlank) {
-            foundBlank = true;
-            *bcolP = col;
-        }
-    }
-
-    if (!foundBlank)
-        pm_error("couldn't find blank pixel column in font");
-}
-
-
-
-static void
-computeCharacterSize(const bit **   const font,
-                     unsigned int   const fcols,
-                     unsigned int   const frows,
-                     unsigned int * const cellWidthP,
-                     unsigned int * const cellHeightP,
-                     unsigned int * const charWidthP,
-                     unsigned int * const charHeightP) {
-
-    unsigned int firstBlankRow;
-    unsigned int firstBlankCol;
-    unsigned int heightLast11Rows;
-
-    findFirstBlankRow(font, fcols, frows, &firstBlankRow);
-
-    findFirstBlankCol(font, fcols, frows, &firstBlankCol);
-
-    heightLast11Rows = frows - firstBlankRow;
-
-    if (heightLast11Rows % 11 != 0)
-        pm_error("The rows of characters in the font do not appear to "
-                 "be all the same height.  The last 11 rows are %u pixel "
-                 "rows high (from pixel row %u up to %u), "
-                 "which is not a multiple of 11.",
-                 heightLast11Rows, firstBlankRow, frows);
-    else {
-        unsigned int widthLast15Cols;
-
-        *cellHeightP = heightLast11Rows / 11;
-
-        widthLast15Cols = fcols - firstBlankCol;
-
-        if (widthLast15Cols % 15 != 0)
-            pm_error("The columns of characters in the font do not appear to "
-                     "be all the same width.  "
-                     "The last 15 columns are %u pixel "
-                     "columns wide (from pixel col %u up to %u), "
-                     "which is not a multiple of 15.",
-                     widthLast15Cols, firstBlankCol, fcols);
-        else {
-            *cellWidthP = widthLast15Cols / 15;
-
-            *charWidthP = firstBlankCol;
-            *charHeightP = firstBlankRow;
-        }
-    }
-}
-
-
-
-struct font*
-pbm_dissectfont(const bit ** const font,
-                unsigned int const frows,
-                unsigned int const fcols) {
-    /*
-       This routine expects a font bitmap representing the following text:
-      
-       (0,0)
-          M ",/^_[`jpqy| M
-      
-          /  !"#$%&'()*+ /
-          < ,-./01234567 <
-          > 89:;<=>?@ABC >
-          @ DEFGHIJKLMNO @
-          _ PQRSTUVWXYZ[ _
-          { \]^_`abcdefg {
-          } hijklmnopqrs }
-          ~ tuvwxyz{|}~  ~
-      
-          M ",/^_[`jpqy| M
-      
-       The bitmap must be cropped exactly to the edges.
-      
-       The characters in the border you see are irrelevant except for
-       character size compuations.  The 12 x 8 array in the center is
-       the font.  The top left character there belongs to code point
-       0, and the code points increase in standard reading order, so
-       the bottom right character is code point 127.  You can't define
-       code points < 32 or > 127 with this font format.
-
-       The characters in the top and bottom border rows must include a
-       character with the lowest reach of any in the font (e.g. "y",
-       "_") and one with the highest reach (e.g. '"').  The characters
-       in the left and right border columns must include characters
-       with the rightmost and leftmost reach of any in the font
-       (e.g. "M" for both).
-
-       The border must be separated from the font by one blank text
-       row or text column.
-      
-       The dissection works by finding the first blank row and column;
-       i.e the lower right corner of the "M" in the upper left corner
-       of the matrix.  That gives the height and width of the
-       maximum-sized character, which is not too useful.  But the
-       distance from there to the opposite side is an integral
-       multiple of the cell size, and that's what we need.  Then it's
-       just a matter of filling in all the coordinates.  */
-    
-    unsigned int cellWidth, cellHeight;
-        /* Dimensions in pixels of each cell of the font -- that
-           includes the glyph and the white space above and to the
-           right of it.  Each cell is a tile of the font image.  The
-           top character row and left character row don't count --
-           those cells are smaller because they are missing the white
-           space.
-        */
-    unsigned int charWidth, charHeight;
-        /* Maximum dimensions of glyph itself, inside its cell */
-
-    int row, col, ch, r, c, i;
-    struct font * fn;
-    struct glyph * glyph;
-    char* bmap;
-
-    computeCharacterSize(font, fcols, frows,
-                         &cellWidth, &cellHeight, &charWidth, &charHeight);
-
-    /* Now convert to a general font */
-
-    MALLOCVAR(fn);
-    if (fn == NULL)
-        pm_error("out of memory allocating font structure");
-
-    fn->maxwidth  = charWidth;
-    fn->maxheight = charHeight;
-    fn->x = fn->y = 0;
-
-    fn->oldfont = font;
-    fn->frows = frows;
-    fn->fcols = fcols;
-    
-    /* Initialize all character positions to "undefined."  Those that
-       are defined in the font will be filled in below.
-    */
-    for (i = 0; i < PM_FONT_MAXGLYPH + 1; i++)
-        fn->glyph[i] = NULL;
-
-    MALLOCARRAY(glyph, nCharsInFont);
-    if ( glyph == NULL )
-        pm_error( "out of memory allocating glyphs" );
-    
-    bmap = (char*) malloc( fn->maxwidth * fn->maxheight * nCharsInFont );
-    if ( bmap == (char*) 0)
-        pm_error( "out of memory allocating glyph data" );
-
-    /* Now fill in the 0,0 coords. */
-    row = cellHeight * 2;
-    col = cellWidth * 2;
-    for (i = 0; i < firstCodePoint; ++i)
-        fn->glyph[i] = NULL;
-
-    for ( ch = 0; ch < nCharsInFont; ++ch ) {
-        glyph[ch].width = fn->maxwidth;
-        glyph[ch].height = fn->maxheight;
-        glyph[ch].x = glyph[ch].y = 0;
-        glyph[ch].xadd = cellWidth;
-
-        for ( r = 0; r < glyph[ch].height; ++r )
-            for ( c = 0; c < glyph[ch].width; ++c )
-                bmap[r * glyph[ch].width + c] = font[row + r][col + c];
-    
-        glyph[ch].bmap = bmap;
-        bmap += glyph[ch].width * glyph[ch].height;
-
-        fn->glyph[firstCodePoint + ch] = &glyph[ch];
-
-        col += cellWidth;
-        if ( col >= cellWidth * 14 ) {
-            col = cellWidth * 2;
-            row += cellHeight;
-        }
-    }
-    for (i = firstCodePoint + nCharsInFont; i < PM_FONT_MAXGLYPH + 1; ++i)
-        fn->glyph[i] = NULL;
-    
-    return fn;
-}
-
-
-
-struct font *
-pbm_loadfont(const char * const filename) {
-
-    FILE * fileP;
-    struct font * fontP;
-    char line[10] = "\0\0\0\0\0\0\0\0\0\0";
-        /* Initialize to suppress Valgrind error which is reported when file
-           is empty or very small.
-        */
-
-    fileP = pm_openr(filename);
-    fgets(line, 10, fileP);
-    pm_close(fileP);
-
-    if (line[0] == PBM_MAGIC1 && 
-        (line[1] == PBM_MAGIC2 || line[1] == RPBM_MAGIC2)) {
-        fontP = pbm_loadpbmfont(filename);
-    } else if (!strncmp(line, "STARTFONT", 9)) {
-        fontP = pbm_loadbdffont(filename);
-        if (!fontP)
-            pm_error("could not load BDF font file");
-    } else {
-        pm_error("font file not in a recognized format.  Does not start "
-                 "with the signature of a PBM file or BDF font file");
-        assert(false);
-        fontP = NULL;  /* defeat compiler warning */
-    }
-    return fontP;
-}
-
-
-
-struct font *
-pbm_loadpbmfont(const char * const filename) {
-
-    FILE * ifP;
-    bit ** font;
-    int fcols, frows;
-
-    ifP = pm_openr(filename);
-
-    font = pbm_readpbm(ifP, &fcols, &frows);
-
-    if ((fcols - 1) / 16 >= pbm_maxfontwidth() ||
-       (frows - 1) / 12 >= pbm_maxfontheight())
-        pm_error("Absurdly large PBM font file: %s", filename);
-    else if (fcols < 31 || frows < 23) {
-        /* Need at least one pixel per character, and this is too small to
-           have that.
-        */
-        pm_error("PBM font file '%s' too small to be a font file: %u x %u.  "
-                 "Minimum sensible size is 31 x 23",
-                 filename, fcols, frows);
-    }
-
-    pm_close(ifP);
-
-    return pbm_dissectfont((const bit **)font, frows, fcols);
-}
-
-
-
-void
-pbm_dumpfont(struct font * const fontP,
-             FILE *        const ofP) {
-/*----------------------------------------------------------------------------
-  Dump out font as C source code.
------------------------------------------------------------------------------*/
-    unsigned int i;
-    unsigned int ng;
-
-    if (fontP->oldfont)
-        pm_message("Netpbm no longer has the capability to generate "
-                   "a font in long hexadecimal data format");
-
-    for (i = 0, ng = 0; i < PM_FONT_MAXGLYPH +1; ++i) {
-        if (fontP->glyph[i])
-            ++ng;
-    }
-
-    printf("static struct glyph _g[%d] = {\n", ng);
-
-    for (i = 0; i < PM_FONT_MAXGLYPH + 1; ++i) {
-        struct glyph * const glyphP = fontP->glyph[i];
-        if (glyphP) {
-            unsigned int j;
-            printf(" { %d, %d, %d, %d, %d, \"", glyphP->width, glyphP->height,
-                   glyphP->x, glyphP->y, glyphP->xadd);
-            
-            for (j = 0; j < glyphP->width * glyphP->height; ++j) {
-                if (glyphP->bmap[j])
-                    printf("\\1");
-                else
-                    printf("\\0");
-            }    
-            --ng;
-            printf("\" }%s\n", ng ? "," : "");
-        }
-    }
-    printf("};\n");
-
-    printf("struct font XXX_font = { %d, %d, %d, %d, {\n",
-           fontP->maxwidth, fontP->maxheight, fontP->x, fontP->y);
-
-    {
-        unsigned int i;
-
-        for (i = 0; i < PM_FONT_MAXGLYPH + 1; ++i) {
-            if (fontP->glyph[i])
-                printf(" _g + %d", ng++);
-            else
-                printf(" NULL");
-        
-            if (i != PM_FONT_MAXGLYPH) printf(",");
-            printf("\n");
-        }
-    }
-
-    printf(" }\n};\n");
-}
-
-
-/*----------------------------------------------------------------------------
-  Routines for loading a BDF font file
------------------------------------------------------------------------------*/
-
-
-/* The following are not recognized in individual glyph data; library
-   routines do a pm_error if they see one:
-
-   Vertical writing systems: DWIDTH1, SWIDTH1, VVECTOR, METRICSET,
-   CONTENTVERSION.
-
-   The following is not recognized and is thus ignored at the global level:
-   DWIDTH
-*/
-
-
-#define MAXBDFLINE 1024 
-
-/* Official Adobe document says max length of string is 65535 characters.
-   However the value 1024 is sufficient for practical uses.
-*/
-
-typedef struct {
-/*----------------------------------------------------------------------------
-   This is an object for reading lines of a font file.  It reads and tokenizes
-   them into words.
------------------------------------------------------------------------------*/
-    FILE * ifP;
-
-    char line[MAXBDFLINE+1];
-        /* This is the storage space for the words of the line.  The
-           words go in here, one after another, separated by NULs.
-
-           It also functions as a work area for readline_read().
-        */
-    const char * arg[6];
-        /* These are the words; each entry is a pointer into line[] (above) */
-} Readline;
-
-
-
-static void
-readline_init(Readline * const readlineP,
-              FILE *     const ifP) {
-
-    readlineP->ifP = ifP;
-
-    readlineP->arg[0] = NULL;
-}
-
-
-
-static void
-tokenize(char *         const s,
-         const char **  const words,
-         unsigned int   const wordsSz) {
-/*----------------------------------------------------------------------------
-   Chop up 's' into words by changing space characters to NUL.  Return as
-   'words' an array of pointers to the beginnings of those words in 's'.
-   Terminate the words[] list with a null pointer.
-
-   'wordsSz' is the number of elements of space in 'words'.  If there are more
-   words in 's' than will fit in that space (including the terminating null
-   pointer), ignore the excess on the right.
------------------------------------------------------------------------------*/
-    unsigned int n;  /* Number of words in words[] so far */
-    char * p;
-
-    p = &s[0];
-    n = 0;
-
-    while (*p) {
-        if (ISSPACE(*p))
-            *p++ = '\0';
-        else {
-            words[n++] = p;
-            if (n >= wordsSz - 1)
-                break;
-            while (*p && !ISSPACE(*p))
-                ++p;
-        }
-    }
-    assert(n <= wordsSz - 1);
-    words[n] = NULL;
-}
-
-
-
-static void
-readline_read(Readline * const readlineP,
-              bool *     const eofP) {
-/*----------------------------------------------------------------------------
-   Read a nonblank line from the file.  Make its contents available
-   as readlineP->arg[].
-
-   Return *eofP == true iff there is no nonblank line before EOF or we
-   are unable to read the file.
------------------------------------------------------------------------------*/
-    bool gotLine;
-    bool error;
-
-    for (gotLine = false, error = false; !gotLine && !error; ) {
-        char * rc;
-
-        rc = fgets(readlineP->line, MAXBDFLINE+1, readlineP->ifP);
-        if (rc == NULL)
-            error = true;
-        else {
-            tokenize(readlineP->line,
-                     readlineP->arg, ARRAY_SIZE(readlineP->arg));
-            if (readlineP->arg[0] != NULL)
-                gotLine = true;
-        }
-    }
-    *eofP = error;
-}
-
-
-
-static void
-parseBitmapRow(const char *    const hex,
-               unsigned int    const glyphWidth,
-               unsigned char * const bmap,
-               unsigned int    const origBmapIndex,
-               unsigned int *  const newBmapIndexP,
-               const char **   const errorP) {
-/*----------------------------------------------------------------------------
-   Parse one row of the bitmap for a glyph, from the hexadecimal string
-   for that row in the font file, 'hex'.  The glyph is 'glyphWidth'
-   pixels wide.
-
-   We place our result in 'bmap' at *bmapIndexP and advanced *bmapIndexP.
------------------------------------------------------------------------------*/
-    unsigned int bmapIndex;
-    int i;  /* dot counter */
-    const char * p;
-
-    bmapIndex = origBmapIndex;
-
-    for (i = glyphWidth, p = &hex[0], *errorP = NULL;
-         i > 0 && !*errorP;
-         i -= 4) {
-
-        if (*p == '\0')
-            pm_asprintf(errorP, "Not enough hexadecimal digits for glyph "
-                        "of width %u in '%s'",
-                        glyphWidth, hex);
-        else {
-            char const hdig = *p++;
-            unsigned int hdigValue;
-
-            if (hdig >= '0' && hdig <= '9')
-                hdigValue = hdig - '0';
-            else if (hdig >= 'a' && hdig <= 'f')
-                hdigValue = 10 + (hdig - 'a');
-            else if (hdig >= 'A' && hdig <= 'F')
-                hdigValue = 10 + (hdig - 'A');
-            else 
-                pm_asprintf(errorP,
-                            "Invalid hex digit x%02x (%c) in bitmap data '%s'",
-                            (unsigned int)(unsigned char)hdig, 
-                            isprint(hdig) ? hdig : '.',
-                            hex);
-
-            if (!*errorP) {
-                if (i > 0)
-                    bmap[bmapIndex++] = hdigValue & 0x8 ? 1 : 0;
-                if (i > 1)
-                    bmap[bmapIndex++] = hdigValue & 0x4 ? 1 : 0;
-                if (i > 2)
-                    bmap[bmapIndex++] = hdigValue & 0x2 ? 1 : 0;
-                if (i > 3)
-                    bmap[bmapIndex++] = hdigValue & 0x1 ? 1 : 0;
-            }
-        }
-    }
-    *newBmapIndexP = bmapIndex;
-}
-
-
-
-static void
-readBitmap(Readline *      const readlineP,
-           unsigned int    const glyphWidth,
-           unsigned int    const glyphHeight,
-           const char *    const charName,
-           unsigned char * const bmap) {
-
-    int n;
-    unsigned int bmapIndex;
-
-    bmapIndex = 0;
-           
-    for (n = glyphHeight; n > 0; --n) {
-        bool eof;
-        const char * error;
-
-        readline_read(readlineP, &eof);
-
-        if (eof)
-            pm_error("End of file in bitmap for character '%s' in BDF "
-                     "font file.", charName);
-
-        if (!readlineP->arg[0])
-            pm_error("A line that is supposed to contain bitmap data, "
-                     "in hexadecimal, for character '%s' is empty", charName);
-
-        parseBitmapRow(readlineP->arg[0], glyphWidth, bmap, bmapIndex,
-                       &bmapIndex, &error);
-
-        if (error) {
-            pm_error("Error in line %d of bitmap for character '%s': %s",
-                     n, charName, error);
-            pm_strfree(error);
-        }
-    }
-}
-
-
-
-static void
-createBmap(unsigned int  const glyphWidth,
-           unsigned int  const glyphHeight,
-           Readline *    const readlineP,
-           const char *  const charName,
-           const char ** const bmapP) {
-
-    unsigned char * bmap;
-    bool eof;
-    
-    if (glyphWidth > 0 && UINT_MAX / glyphWidth < glyphHeight)
-        pm_error("Ridiculously large glyph");
-
-    MALLOCARRAY(bmap, glyphWidth * glyphHeight);
-
-    if (!bmap)
-        pm_error("no memory for font glyph byte map");
-
-    readline_read(readlineP, &eof);
-    if (eof)
-        pm_error("End of file encountered reading font glyph byte map from "
-                 "BDF font file.");
-    
-    if (streq(readlineP->arg[0], "ATTRIBUTES")) {
-        /* ATTRIBUTES is defined in Glyph Bitmap Distribution Format (BDF)
-           Specification Version 2.1, but not in Version 2.2. 
-        */
-        bool eof;
-        readline_read(readlineP, &eof);
-        if (eof)
-            pm_error("End of file encountered after ATTRIBUTES in BDF "
-                     "font file.");
-    }                
-    if (!streq(readlineP->arg[0], "BITMAP"))
-        pm_error("'%s' found where BITMAP expected in definition of "
-                 "character '%s' in BDF font file.",
-                 readlineP->arg[0], charName);
-
-    assert(streq(readlineP->arg[0], "BITMAP"));
-
-    readBitmap(readlineP, glyphWidth, glyphHeight, charName, bmap);
-
-    *bmapP = (char *)bmap;
-}
-
-
-
-static void
-readExpectedStatement(Readline *    const readlineP,
-                      const char *  const expected) {
-/*----------------------------------------------------------------------------
-  Have the readline object *readlineP read the next line from the file, but
-  expect it to be a line of type 'expected' (i.e. the verb token at the
-  beginning of the line is that, e.g. "STARTFONT").  If it isn't, fail the
-  program.
------------------------------------------------------------------------------*/
-    bool eof;
-
-    readline_read(readlineP, &eof);
-
-    if (eof)
-        pm_error("EOF in BDF font file where '%s' expected", expected);
-    else if (!streq(readlineP->arg[0], expected))
-        pm_error("Statement of type '%s' where '%s' expected in BDF font file",
-                 readlineP->arg[0], expected);
-}
-
-
-
-static void
-skipCharacter(Readline * const readlineP) {
-/*----------------------------------------------------------------------------
-  In the BDF font file being read by readline object *readlineP, skip through
-  the end of the character we are presently in.
------------------------------------------------------------------------------*/
-    bool endChar;
-                        
-    endChar = FALSE;
-                        
-    while (!endChar) {
-        bool eof;
-        readline_read(readlineP, &eof);
-        if (eof)
-            pm_error("End of file in the middle of a character (before "
-                     "ENDCHAR) in BDF font file.");
-        endChar = streq(readlineP->arg[0], "ENDCHAR");
-    }                        
-}
-
-
-
-static void
-interpEncoding(const char **  const arg,
-               unsigned int * const codepointP,
-               bool *         const badCodepointP,
-               PM_WCHAR       const maxglyph) {
-/*----------------------------------------------------------------------------
-   With arg[] being the ENCODING statement from the font, return as
-   *codepointP the codepoint that it indicates (code point is the character
-   code, e.g. in ASCII, 48 is '0').
-
-   But if the statement doesn't give an acceptable codepoint return
-   *badCodepointP == TRUE.
-
-   'maxglyph' is the maximum codepoint in the font.
------------------------------------------------------------------------------*/
-    bool gotCodepoint;
-    bool badCodepoint;
-    unsigned int codepoint;
-
-    if (atoi(arg[1]) >= 0) {
-        codepoint = atoi(arg[1]);
-        gotCodepoint = true;
-    } else {
-      if (atoi(arg[1]) == -1 && arg[2] != NULL) {
-            codepoint = atoi(arg[2]);
-            gotCodepoint = true;
-        } else
-            gotCodepoint = false;
-    }
-    if (gotCodepoint) {
-        if (codepoint > maxglyph)
-            badCodepoint = true;
-        else
-            badCodepoint = false;
-    } else
-        badCodepoint = true;
-
-    *badCodepointP = badCodepoint;
-    *codepointP    = codepoint;
-}
-
-
-
-static void
-readEncoding(Readline *     const readlineP,
-             unsigned int * const codepointP,
-             bool *         const badCodepointP,
-             PM_WCHAR       const maxglyph) {
-
-    readExpectedStatement(readlineP, "ENCODING");
-    
-    interpEncoding(readlineP->arg, codepointP, badCodepointP, maxglyph);
-}
-
-
-
-static void
-validateFontLimits(const struct font2 * const fontP) {
-
-    assert(pbm_maxfontheight() > 0 && pbm_maxfontwidth() > 0);
-
-    if (fontP->maxwidth  <= 0 ||
-        fontP->maxheight <= 0 ||
-        fontP->maxwidth  > pbm_maxfontwidth()  ||
-        fontP->maxheight > pbm_maxfontheight() ||
-        -fontP->x + 1 > fontP->maxwidth ||
-        -fontP->y + 1 > fontP->maxheight ||
-        fontP->x > fontP->maxwidth  ||
-        fontP->y > fontP->maxheight ||
-        fontP->x + fontP->maxwidth  > pbm_maxfontwidth() || 
-        fontP->y + fontP->maxheight > pbm_maxfontheight()
-        ) {
-
-        pm_error("Global font metric(s) out of bounds."); 
-    }
-
-    if (fontP->maxglyph > PM_FONT2_MAXGLYPH)
-        pm_error("Internal error.  Glyph table too large: %u glyphs; "
-                 "Maximum possible in Netpbm is %u",
-                 fontP->maxglyph, PM_FONT2_MAXGLYPH);
-}
-
-
-
-static void
-validateGlyphLimits(const struct font2 * const fontP,
-                    const struct glyph * const glyphP,
-                    const char *         const charName) {
-
-    /* Some BDF files code space with zero width and height,
-       no bitmap data and just the xadd value.
-       We allow zero width and height, iff both are zero.
-    */
-
-    if (((glyphP->width == 0 || glyphP->height == 0) &&
-         !(glyphP->width == 0 && glyphP->height == 0)) ||
-        glyphP->width  > fontP->maxwidth  ||
-        glyphP->height > fontP->maxheight ||
-        glyphP->x < fontP->x ||
-        glyphP->y < fontP->y ||
-        glyphP->x + (int) glyphP->width  > fontP->x + fontP->maxwidth  ||
-        glyphP->y + (int) glyphP->height > fontP->y + fontP->maxheight ||
-        glyphP->xadd > pbm_maxfontwidth() ||
-        glyphP->xadd + MAX(glyphP->x,0) + (int) glyphP->width >
-        pbm_maxfontwidth()
-        ) {
-
-        pm_error("Font metric(s) for char '%s' out of bounds.\n", charName);
-    }
-}
-
-
-
-static void
-processChars(Readline *     const readlineP,
-             struct font2 * const fontP,
-             PM_WCHAR       const maxglyph ) {
-/*----------------------------------------------------------------------------
-   Process the CHARS block in a BDF font file, assuming the file is positioned
-   just after the CHARS line.  Read the rest of the block and apply its
-   contents to *fontP.
------------------------------------------------------------------------------*/
-    unsigned int const nCharacters = atoi(readlineP->arg[1]);
-
-    unsigned int nCharsDone;
-
-    nCharsDone = 0;
-
-    while (nCharsDone < nCharacters) {
-        bool eof;
-
-        readline_read(readlineP, &eof);
-        if (eof)
-            pm_error("End of file after CHARS reading BDF font file");
-
-        if (streq(readlineP->arg[0], "COMMENT")) {
-            /* ignore */
-        } else if (!streq(readlineP->arg[0], "STARTCHAR"))
-            pm_error("no STARTCHAR after CHARS in BDF font file");
-        else {
-            const char * const charName = pm_strdup(readlineP->arg[1]);
-
-            struct glyph * glyphP;
-            unsigned int codepoint;
-            bool badCodepoint;
-
-            assert(streq(readlineP->arg[0], "STARTCHAR"));
-
-            MALLOCVAR(glyphP);
-
-            if (glyphP == NULL)
-                pm_error("no memory for font glyph for '%s' character",
-                         charName);
-
-            readEncoding(readlineP, &codepoint, &badCodepoint, maxglyph);
-
-            if (badCodepoint)
-                skipCharacter(readlineP);
-            else if (fontP->glyph[codepoint] != NULL)
-                pm_error("Multiple definition of code point %d "
-                         "in font file", (unsigned int) codepoint); 
-            else {
-                readExpectedStatement(readlineP, "SWIDTH");
-                    
-                readExpectedStatement(readlineP, "DWIDTH");
-                glyphP->xadd = atoi(readlineP->arg[1]);
-
-                readExpectedStatement(readlineP, "BBX");
-                glyphP->width  = atoi(readlineP->arg[1]);
-                glyphP->height = atoi(readlineP->arg[2]);
-                glyphP->x      = atoi(readlineP->arg[3]);
-                glyphP->y      = atoi(readlineP->arg[4]);
-
-                validateGlyphLimits(fontP, glyphP, charName);
-
-                createBmap(glyphP->width, glyphP->height, readlineP, charName,
-                           &glyphP->bmap);
-                
-
-                readExpectedStatement(readlineP, "ENDCHAR");
-
-                assert(codepoint <= maxglyph); /* Ensured by readEncoding() */
-
-                fontP->glyph[codepoint] = glyphP;
-                pm_strfree(charName);
-            }
-            ++nCharsDone;
-        }
-    }
-}
-
-
-
-static void
-processBdfFontLine(Readline     * const readlineP,
-                   struct font2 * const fontP,
-                   bool         * const endOfFontP,
-                   PM_WCHAR       const maxglyph) {
-/*----------------------------------------------------------------------------
-   Process a nonblank line just read from a BDF font file.
-
-   This processing may involve reading more lines.
------------------------------------------------------------------------------*/
-    *endOfFontP = FALSE;  /* initial assumption */
-
-    assert(readlineP->arg[0] != NULL);  /* Entry condition */
-
-    if (streq(readlineP->arg[0], "COMMENT")) {
-        /* ignore */
-    } else if (streq(readlineP->arg[0], "SIZE")) {
-        /* ignore */
-    } else if (streq(readlineP->arg[0], "STARTPROPERTIES")) {
-        /* Read off the properties and ignore them all */
-        unsigned int const propCount = atoi(readlineP->arg[1]);
-
-        unsigned int i;
-        for (i = 0; i < propCount; ++i) {
-            bool eof;
-            readline_read(readlineP, &eof);
-            if (eof)
-                pm_error("End of file after STARTPROPERTIES in BDF font file");
-        }
-    } else if (streq(readlineP->arg[0], "FONTBOUNDINGBOX")) {
-        fontP->maxwidth  = atoi(readlineP->arg[1]);
-        fontP->maxheight = atoi(readlineP->arg[2]);
-        fontP->x = atoi(readlineP->arg[3]);
-        fontP->y = atoi(readlineP->arg[4]);
-        validateFontLimits(fontP);
-    } else if (streq(readlineP->arg[0], "ENDPROPERTIES")) {
-      if (fontP->maxwidth ==0)
-      pm_error("Encountered ENDPROPERTIES before FONTBOUNDINGBOX " 
-                   "in BDF font file");
-    } else if (streq(readlineP->arg[0], "ENDFONT")) {
-        *endOfFontP = true;
-    } else if (streq(readlineP->arg[0], "CHARS")) {
-      if (fontP->maxwidth ==0)
-      pm_error("Encountered CHARS before FONTBOUNDINGBOX " 
-                   "in BDF font file");
-      else
-        processChars(readlineP, fontP, maxglyph);
-    } else {
-        /* ignore */
-    }
-}
-
-
-
-struct font2 *
-pbm_loadbdffont2(const char * const filename,
-                 PM_WCHAR     const maxglyph) {
-/*----------------------------------------------------------------------------
-   Read a BDF font file "filename" as a 'font2' structure.  A 'font2'
-   structure is more expressive than a 'font' structure, most notably in that
-   it can handle wide code points and many more glyphs.
-
-   Codepoints up to maxglyph inclusive are valid in the file.
-
-   The returned object is in new malloc'ed storage, in many pieces, and
-   cannot be destroyed.
------------------------------------------------------------------------------*/
-    /* For our return object to be destroyable, we need to supply a destroy
-       function, and it needs to return glyph and raster memory, and
-       struct font needs to manage glyph memory separately from mapping
-       code points to glyphs.
-    */
-    FILE *         ifP;
-    Readline       readline;
-    struct font2 * font2P;
-    bool           endOfFont;
-
-    ifP = fopen(filename, "rb");
-    if (!ifP)
-        pm_error("Unable to open BDF font file name '%s'.  errno=%d (%s)",
-                 filename, errno, strerror(errno));
-
-    readline_init(&readline, ifP);
-
-    MALLOCVAR(font2P);
-    if (font2P == NULL)
-        pm_error("no memory for font");
-
-    MALLOCARRAY(font2P->glyph, maxglyph + 1);
-    if (font2P->glyph == NULL)
-        pm_error("no memory for font glyphs");
-
-    font2P->maxglyph = maxglyph;
-
-    font2P->oldfont = NULL;
-    {
-        /* Initialize all characters to nonexistent; we will fill the ones we
-           find in the bdf file later.
-        */
-        PM_WCHAR i;
-        for (i = 0; i <= maxglyph; ++i)
-            font2P->glyph[i] = NULL;
-    }
-
-    font2P->maxwidth = font2P->maxheight = font2P->x = font2P->y = 0;
-
-    readExpectedStatement(&readline, "STARTFONT");
-
-    endOfFont = FALSE;
-
-    while (!endOfFont) {
-        bool eof;
-        readline_read(&readline, &eof);
-        if (eof)
-            pm_error("End of file before ENDFONT statement in BDF font file");
-
-        processBdfFontLine(&readline, font2P, &endOfFont, maxglyph);
-    }
-    return font2P;
-}
-
-
-
-struct font *
-pbm_loadbdffont(const char * const filename) {
-/*----------------------------------------------------------------------------
-   Read a BDF font file "filename" into a traditional font structure.
-
-   Codepoints up to 255 (PM_FONT_MAXGLYPH) are valid.
-
-   Can handle ASCII, ISO-8859-1, ISO-8859-2, ISO-8859-15, etc.
-
-   The returned object is in new malloc'ed storage, in many pieces, and
-   cannot be destroyed.
------------------------------------------------------------------------------*/
-    /* For our return object to deep copy the glyphs and fonts from
-       the struct font2be destroyable, we need to supply a destroy
-       function, and it needs to return glyph and raster memory, and
-       struct font needs to manage glyph memory separately from mapping
-       code points to glyphs.
-    */
-    struct font  * fontP;
-    struct font2 * font2P;
-    unsigned int   codePoint;
-
-    MALLOCVAR(fontP);
-    if (fontP == NULL)
-        pm_error("no memory for font");
-
-    font2P = pbm_loadbdffont2(filename, PM_FONT_MAXGLYPH);
-
-    fontP->maxwidth  = font2P->maxwidth;
-    fontP->maxheight = font2P->maxheight;
-
-    fontP->x = font2P->x;
-    fontP->y = font2P->y;
-
-    for (codePoint = 0; codePoint < PM_FONT_MAXGLYPH + 1; ++codePoint)
-        fontP->glyph[codePoint] = font2P->glyph[codePoint];
-
-    fontP->oldfont = NULL;
-
-    fontP->fcols = 0;
-    fontP->frows = 0;
-
-    /* Note that *fontP2 is unfreeable.  See pbm_loadbdffont2.  And even if it
-       were, we hooked *fontP into it above, so that would have to turn into a
-       deep copy before we could free *fontP2.
-    */
-
-    return fontP;
-}
-
-
-
-struct font2 *
-pbm_expandbdffont(const struct font * const fontP) {
-/*----------------------------------------------------------------------------
-  Convert a traditional font structure into an expanded font2 structure.
-
-  This function depends upon the fact that *fontP, like any struct font,
-  cannot be destroyed.  The returned object refers to memory that belongs
-  to *fontP.
-
-  The returned object is in new malloc'ed storage, in many pieces, and
-  cannot be destroyed.
------------------------------------------------------------------------------*/
-    /* If we ever make struct font destroyable, this function needs to
-       copy the glyphs and rasters, and struct font and struct font2 need
-       to manage glyph memory separately from mapping code points to the
-       glyphs.
-    */
-    PM_WCHAR const maxglyph = PM_FONT_MAXGLYPH;
-
-    struct font2 * font2P;
-    unsigned int   codePoint;
-
-    MALLOCVAR(font2P);
-    if (font2P == NULL)
-        pm_error("no memory for font");
-
-    MALLOCARRAY(font2P->glyph, maxglyph + 1);
-    if (font2P->glyph == NULL)
-        pm_error("no memory for font glyphs");
-
-    font2P->maxwidth  = fontP->maxwidth;
-    font2P->maxheight = fontP->maxheight;
-
-    font2P->x = fontP->x;
-    font2P->y = fontP->y;
-
-    font2P->maxglyph = maxglyph;
-
-    for (codePoint = 0; codePoint < maxglyph + 1; ++codePoint)
-        font2P->glyph[codePoint] = fontP->glyph[codePoint];
-
-    font2P->oldfont = fontP->oldfont;
-
-    font2P->fcols = fontP->fcols;
-    font2P->frows = fontP->frows;
-
-    return font2P;
-}
-
-