diff options
-rw-r--r-- | lib/libpbmfont.c | 301 | ||||
-rw-r--r-- | lib/pbmfont.h | 10 |
2 files changed, 205 insertions, 106 deletions
diff --git a/lib/libpbmfont.c b/lib/libpbmfont.c index c7b5a355..d79b9262 100644 --- a/lib/libpbmfont.c +++ b/lib/libpbmfont.c @@ -667,9 +667,9 @@ pbm_defaultfont(const char * const name) { unsigned int row; if (strcmp(name, "fixed") != 0) - pm_error( "built-in font name unknown, try 'bdf' or 'fixed'" ); + pm_error( "built-in font name unknown, try 'bdf' or 'fixed'"); - defaultfont = pbm_allocarray( DEFAULTFONT_COLS, DEFAULTFONT_ROWS ); + defaultfont = pbm_allocarray(DEFAULTFONT_COLS, DEFAULTFONT_ROWS); for (row = 0; row < DEFAULTFONT_ROWS; ++row) { unsigned int col; for (col = 0; col < DEFAULTFONT_COLS; col += 32) { @@ -689,104 +689,200 @@ pbm_defaultfont(const char * const name) { } } } - retval = - pbm_dissectfont(defaultfont, DEFAULTFONT_ROWS, DEFAULTFONT_COLS); + pbm_dissectfont((const bit **)defaultfont, + DEFAULTFONT_ROWS, DEFAULTFONT_COLS); } 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(bit ** const font, - int const frows, - int const fcols) { +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 border you see is irrelevant. 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 dissection works by finding the first blank row and column; 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. - ** - ** The difference between cell_height, cell_width and char_height, - ** char_width is that the first is the size of the cell including - ** spacing, while the second is just the actual maximum-size character. - */ - int cell_width, cell_height, char_width, char_height; - int brow, bcol, row, col, d, ch, r, c, i; - struct font* fn; - struct glyph* glyph; + 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; - bit b; - - /* Find first blank row. */ - for ( brow = 0; brow < frows / 6; ++brow ) { - b = font[brow][0]; - for ( col = 1; col < fcols; ++col ) - if ( font[brow][col] != b ) - goto nextrow; - goto gotblankrow; - nextrow: ; - } - pm_error( "couldn't find blank row in font" ); - - gotblankrow: - /* Find first blank col. */ - for ( bcol = 0; bcol < fcols / 8; ++bcol ) { - b = font[0][bcol]; - for ( row = 1; row < frows; ++row ) - if ( font[row][bcol] != b ) - goto nextcol; - goto gotblankcol; - nextcol: ; - } - pm_error( "couldn't find blank col in font" ); - - gotblankcol: - /* Now compute character cell size. */ - d = frows - brow; - cell_height = d / 11; - if ( cell_height * 11 != d ) - pm_error( "problem computing character cell height" ); - d = fcols - bcol; - cell_width = d / 15; - if ( cell_width * 15 != d ) - pm_error( "problem computing character cell width" ); - char_height = brow; - char_width = bcol; + + 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" ); + if (fn == NULL) + pm_error("out of memory allocating font structure"); - fn->maxwidth = char_width; - fn->maxheight = char_height; + fn->maxwidth = charWidth; + fn->maxheight = charHeight; fn->x = fn->y = 0; fn->oldfont = font; @@ -808,8 +904,8 @@ pbm_dissectfont(bit ** const font, pm_error( "out of memory allocating glyph data" ); /* Now fill in the 0,0 coords. */ - row = cell_height * 2; - col = cell_width * 2; + row = cellHeight * 2; + col = cellWidth * 2; for (i = 0; i < firstCodePoint; ++i) fn->glyph[i] = NULL; @@ -817,7 +913,7 @@ pbm_dissectfont(bit ** const font, glyph[ch].width = fn->maxwidth; glyph[ch].height = fn->maxheight; glyph[ch].x = glyph[ch].y = 0; - glyph[ch].xadd = cell_width; + glyph[ch].xadd = cellWidth; for ( r = 0; r < glyph[ch].height; ++r ) for ( c = 0; c < glyph[ch].width; ++c ) @@ -828,10 +924,10 @@ pbm_dissectfont(bit ** const font, fn->glyph[firstCodePoint + ch] = &glyph[ch]; - col += cell_width; - if ( col >= cell_width * 14 ) { - col = cell_width * 2; - row += cell_height; + col += cellWidth; + if ( col >= cellWidth * 14 ) { + col = cellWidth * 2; + row += cellHeight; } } for (i = firstCodePoint + nCharsInFont; i < 256; ++i) @@ -868,18 +964,21 @@ pbm_loadfont(const char * const filename) -struct font* pbm_loadpbmfont(const char * const filename) -{ - FILE* ifp; - bit** font; +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 ); - pm_close( ifp ); - return pbm_dissectfont( font, frows, fcols ); + ifP = pm_openr(filename); + font = pbm_readpbm(ifP, &fcols, &frows); + pm_close(ifP); + return pbm_dissectfont((const bit **)font, frows, fcols); } + + void pbm_dumpfont( fn ) struct font* fn; diff --git a/lib/pbmfont.h b/lib/pbmfont.h index 432aea3c..9fdec0e1 100644 --- a/lib/pbmfont.h +++ b/lib/pbmfont.h @@ -53,17 +53,17 @@ struct font { */ struct glyph * glyph[256]; /* glyph[i] is the glyph for code point i */ - bit** oldfont; + const bit ** oldfont; /* for compatibility with old pbmtext routines */ - /* oldfont is 0 if the font is BDF derived */ + /* oldfont is NULL if the font is BDF derived */ int fcols, frows; }; struct font* pbm_defaultfont(const char* const which); struct font* -pbm_dissectfont(bit ** const font, - int const frows, - int const fcols); +pbm_dissectfont(const bit ** const font, + unsigned int const frows, + unsigned int const fcols); struct font* pbm_loadfont(const char * const filename); struct font* pbm_loadpbmfont(const char * const filename); struct font* pbm_loadbdffont(const char * const filename); |