From 780486818286799c8cce5f4e3ad3a312773e6f16 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Thu, 28 May 2020 21:04:14 +0000 Subject: From a BDF font file, load only the characters that are needed instead of the full font git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3811 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- lib/libpbmfont0.c | 83 ++++++--- lib/libpbmfont1.c | 2 +- lib/libpbmfont2.c | 515 +++++++++++++++++++++++++++++++++++++++++------------ lib/pbmfont.h | 93 ++++++++-- lib/pbmfontdata2.c | 2 +- 5 files changed, 535 insertions(+), 160 deletions(-) (limited to 'lib') diff --git a/lib/libpbmfont0.c b/lib/libpbmfont0.c index 503c7ee7..a8027a38 100644 --- a/lib/libpbmfont0.c +++ b/lib/libpbmfont0.c @@ -27,7 +27,6 @@ #include "pbmfont.h" #include "pbmfontdata.h" - struct font * pbm_defaultfont(const char * const name) { /*---------------------------------------------------------------------------- @@ -77,11 +76,12 @@ pbm_defaultfont2(const char * const requestedFontName) { static void -selectFontType(const char * const filename, - PM_WCHAR const maxmaxglyph, - unsigned int const isWide, - struct font ** const fontPP, - struct font2 ** const font2PP) { +selectFontType(const char * const filename, + PM_WCHAR const maxmaxglyph, + unsigned int const isWide, + struct font ** const fontPP, + struct font2 ** const font2PP, + const struct pm_selector * const selectorP) { FILE * fileP; struct font * fontP = NULL; /* initial value */ @@ -106,7 +106,7 @@ selectFontType(const char * const filename, } else if (!strncmp(line, "STARTFONT", 9)) { if (isWide == TRUE) - font2P = pbm_loadbdffont2(filename, maxmaxglyph); + font2P = pbm_loadbdffont2select(filename, maxmaxglyph, selectorP); else fontP = pbm_loadbdffont(filename); if (fontP == NULL && font2P == NULL) @@ -128,25 +128,49 @@ selectFontType(const char * const filename, struct font * -pbm_loadfont(const char * const filename) { - +pbm_loadfont(const char * const filename) { +/*---------------------------------------------------------------------------- + Load font file named 'filename'. + Font file may be either a PBM sheet or BDF. + Supports 8 bit codepoints. +-----------------------------------------------------------------------------*/ struct font * fontP; struct font2 * font2P; - selectFontType(filename, PM_FONT_MAXGLYPH, FALSE, &fontP, &font2P); + selectFontType(filename, PM_FONT_MAXGLYPH, FALSE, &fontP, &font2P, NULL); return fontP; } struct font2 * -pbm_loadfont2(const char * const filename, - PM_WCHAR const maxmaxglyph) { +pbm_loadfont2(const char * const filename, + PM_WCHAR const maxmaxglyph) { +/*---------------------------------------------------------------------------- + Load font file named 'filename'. + Font file may be either a PBM sheet or BDF. + Supports codepoints above 256. +-----------------------------------------------------------------------------*/ + struct font * fontP; + struct font2 * font2P; + selectFontType(filename, maxmaxglyph, TRUE, &fontP, &font2P, NULL); + return font2P; +} + + +struct font2 * +pbm_loadfont2select(const char * const filename, + PM_WCHAR const maxmaxglyph, + const struct pm_selector * const selectorP) { +/*---------------------------------------------------------------------------- + Same as pbm_loadfont2(), but load only glyphs indicated by *selectorP +-----------------------------------------------------------------------------*/ struct font * fontP; struct font2 * font2P; - selectFontType(filename, maxmaxglyph, TRUE, &fontP, &font2P); + selectFontType(filename, maxmaxglyph, TRUE, &fontP, &font2P, selectorP); + return font2P; } @@ -173,7 +197,7 @@ pbm_createbdffont2_base(struct font2 ** const font2PP, /* Caller should overwrite following fields as necessary */ font2P->oldfont = NULL; font2P->fcols = font2P->frows = 0; - font2P->selector = NULL; + font2P->selectorP = NULL; font2P->default_char = 0; font2P->default_char_defined = FALSE; font2P->total_chars = font2P->chars = 0; @@ -187,23 +211,32 @@ pbm_createbdffont2_base(struct font2 ** const font2PP, static void -destroyGlyphData(struct glyph ** const glyph, - PM_WCHAR const maxglyph) { +destroyGlyphData(struct glyph ** const glyph, + PM_WCHAR const maxglyph, + const struct pm_selector * const selectorP) { /*---------------------------------------------------------------------------- Free glyph objects and bitmap objects. This does not work when an object is "shared" through multiple pointers referencing an identical address and thus pointing to a common glyph or bitmap object. + + If 'selectorP' is NULL, free all glyph and bitmap objects in the range + 0 ... maxglyph. If not, free only the objects which the selector + indicates as present. -----------------------------------------------------------------------------*/ + PM_WCHAR const min = (selectorP != NULL) ? selectorP->min : 0; + PM_WCHAR const max = + (selectorP != NULL) ? MIN(selectorP->max, maxglyph) : maxglyph; + PM_WCHAR i; - for(i = 0; i <= maxglyph; ++i) { - if (glyph[i]!=NULL) { + for (i = min; i <= max; ++i) { + if (pm_selector_is_marked(selectorP, i) && glyph[i]) { free((void *) (glyph[i]->bmap)); free(glyph[i]); - } + } } } @@ -214,11 +247,10 @@ pbm_destroybdffont2_base(struct font2 * const font2P) { Free font2 structure, but not the glyph data ---------------------------------------------------------------------------- */ - free(font2P->selector); - pm_strfree(font2P->name); pm_strfree(font2P->charset_string); free(font2P->glyph); + pm_selector_destroy(font2P->selectorP); if (font2P->oldfont !=NULL) pbm_freearray(font2P->oldfont, font2P->frows); @@ -239,8 +271,8 @@ pbm_destroybdffont2(struct font2 * const font2P) { ---------------------------------------------------------------------------- */ if (font2P->load_fn != FIXED_DATA) { - destroyGlyphData(font2P->glyph, font2P->maxglyph); - pbm_destroybdffont2_base(font2P); + destroyGlyphData(font2P->glyph, font2P->maxglyph, font2P->selectorP); + pbm_destroybdffont2_base(font2P); } } @@ -254,7 +286,7 @@ pbm_destroybdffont(struct font * const fontP) { For freeing a structure created by pbm_loadbdffont() or pbm_loadpbmfont(). ---------------------------------------------------------------------------- */ - destroyGlyphData(fontP->glyph, PM_FONT_MAXGLYPH); + destroyGlyphData(fontP->glyph, PM_FONT_MAXGLYPH, NULL); if (fontP->oldfont !=NULL) pbm_freearray(fontP->oldfont, fontP->frows); @@ -326,8 +358,7 @@ pbm_expandbdffont(const struct font * const fontP) { font2P->bit_format = PBM_FORMAT; font2P->total_chars = font2P->chars = nCharacters; font2P->load_fn = CONVERTED_TYPE1_FONT; - /* Caller should be overwrite the above to a more descriptive - value */ + /* Caller should overwrite the above to a more descriptive value */ return font2P; } diff --git a/lib/libpbmfont1.c b/lib/libpbmfont1.c index 4189f150..fe014150 100644 --- a/lib/libpbmfont1.c +++ b/lib/libpbmfont1.c @@ -47,7 +47,7 @@ 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 + 32, 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. diff --git a/lib/libpbmfont2.c b/lib/libpbmfont2.c index b4cf4c2a..1560b407 100644 --- a/lib/libpbmfont2.c +++ b/lib/libpbmfont2.c @@ -32,6 +32,208 @@ #include "pbmfont.h" #include "pbm.h" +/*---------------------------------------------------------------------------- + Font selector routines + + The selector is a device consisting of a bitmap, min value, max value and + count. It is used here to specify necessary fonts and record what entries + are valid in the glyph array. + + This device may be used for other purposes. In that case the code should + be put into an independent source file in the lib/util subdirectory. +-----------------------------------------------------------------------------*/ + +static void +allocRecord(struct pm_selector * const selectorP, + unsigned int const max) { + + unsigned int const size = (max + 8) / 8; + + MALLOCARRAY(selectorP->localRecord, size); + + if (!selectorP->localRecord) + pm_error("Failed to allocate %u bytes of memory for font selector " + "bitmap", size); + + selectorP->record = selectorP->localRecord; +} + + + +void +pm_selector_create(unsigned int const max, + struct pm_selector ** const selectorPP) { + + struct pm_selector * selectorP; + + MALLOCVAR_NOFAIL(selectorP); + + allocRecord(selectorP, max); + + { + unsigned int byteIndex; + for (byteIndex = 0; byteIndex <= max/8; ++byteIndex) + selectorP->localRecord[byteIndex]= 0x00; + } + + selectorP->maxmax = selectorP->min = max; + selectorP->max = 0; + selectorP->count = 0; + + *selectorPP = selectorP; +} + + + +void +pm_selector_create_fixed(const unsigned char * const record, + unsigned int const min, + unsigned int const max, + unsigned int const count, + struct pm_selector ** const selectorPP) { + + struct pm_selector * selectorP; + + MALLOCVAR_NOFAIL(selectorP); + + selectorP->localRecord = NULL; + selectorP->record = record; + selectorP->min = min; + selectorP->max = max; + selectorP->maxmax = max; + selectorP->count = count; + + *selectorPP = selectorP; +} + + + +void +pm_selector_destroy(struct pm_selector * const selectorP) { + + if (selectorP->localRecord) + free(selectorP->localRecord); + + free(selectorP); +} + + + +void +pm_selector_copy(unsigned int const max, + const struct pm_selector * const srcSelectorP, + struct pm_selector ** const destSelectorPP) { + + /* Create a new selector and copy into it the content of another */ + + struct pm_selector * destSelectorP; + + if (max < srcSelectorP->max) + pm_error("internal error: attempt to copy a selector as " + "another with a smaller max value %u -> %u", + srcSelectorP->max, max); + + MALLOCVAR_NOFAIL(destSelectorP); + + destSelectorP->maxmax = max; + destSelectorP->max = srcSelectorP->max; + destSelectorP->min = srcSelectorP->min; + destSelectorP->count = srcSelectorP->count; + + allocRecord(destSelectorP, max); + + { + unsigned int const minByteIndex = srcSelectorP->min / 8; + unsigned int const maxByteIndex = srcSelectorP->max / 8; + unsigned int const maxmaxByteIndex = max / 8; + + unsigned int byteIndex; + + for (byteIndex = 0 ; byteIndex < minByteIndex; ++byteIndex) + destSelectorP->localRecord[byteIndex] = 0x00; + for (byteIndex = maxByteIndex + 1 ; byteIndex <= maxmaxByteIndex; + ++byteIndex) + destSelectorP->localRecord[byteIndex] = 0x00; + for (byteIndex = minByteIndex; byteIndex <= maxByteIndex; ++byteIndex) + destSelectorP->localRecord[byteIndex] = + srcSelectorP->record[byteIndex]; + } + + *destSelectorPP = destSelectorP; +} + + + +void +pm_selector_mark(struct pm_selector * const selectorP, + unsigned int const index) { +/*---------------------------------------------------------------------------- + Mark index 'index'. +-----------------------------------------------------------------------------*/ + unsigned int byteIndex = index / 8; + unsigned int bitIndex = index % 8; + unsigned char mask = (0x01 <<7) >> bitIndex; + + /* set bit on to indicate presence of this index */ + + if (!selectorP->localRecord) + pm_error("INTERNAL ERROR: attempt to mark in a fixed pm_selector"); + + if ((selectorP->localRecord[byteIndex] & mask) == 0x00) { + /* if bit is not already set */ + + selectorP->localRecord[byteIndex] |= mask; + ++selectorP->count; /* increment count */ + + /* reset min and max */ + if (selectorP->min > index) + selectorP->min = index; + if (selectorP->max < index) + selectorP->max = index; + } +} + +/* There is no function for erasing a marked bit */ + + +int /* boolean */ +pm_selector_is_marked(const struct pm_selector * const selectorP, + unsigned int const index) { +/*---------------------------------------------------------------------------- + Index 'index' is marked. +-----------------------------------------------------------------------------*/ + bool retval; + + if (selectorP) { + unsigned int const byteIndex = index / 8; + unsigned int const bitIndex = index % 8; + unsigned char const mask = (0x01 <<7) >> bitIndex; + + if ( index < selectorP->min || index > selectorP->max) + retval = false; + else if ((selectorP->record[byteIndex] & mask) != 0x00) + retval = true; + else + retval = false; + } else { + /* All entries are set to "exist" */ + retval = true; + } + return retval ? 1 : 0; +} + + + +unsigned int +pm_selector_marked_ct(const struct pm_selector * const selectorP) { +/*---------------------------------------------------------------------------- + Number of indices that are marked. +-----------------------------------------------------------------------------*/ + return selectorP->count; +} + + + /*---------------------------------------------------------------------------- Routines for loading a BDF font file -----------------------------------------------------------------------------*/ @@ -354,21 +556,23 @@ readExpectedStatement(Readline * const readlineP, 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 currently in. + In the BDF font file being read by readline object *readlineP, skip + through to the end of the data for the character we are presently in. + + At entry the stream must be positioned at the end of the ENCODING line. -----------------------------------------------------------------------------*/ - bool endChar; - endChar = FALSE; + char * rc; + do { + rc = fgets(readlineP->line, MAXBDFLINE+1, readlineP->ifP); + readlineP->line[7] = '\0'; + + } while (rc != NULL && !streq(readlineP->line, "ENDCHAR")); + + if (rc == NULL) + pm_error("End of file in the middle of a character (before " + "ENDCHAR) in BDF font file."); - 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"); - } } @@ -421,7 +625,7 @@ interpEncoding(const char ** const arg, 'maxmaxglyph' is the maximum codepoint in the font. -----------------------------------------------------------------------------*/ - bool gotCodepoint; + bool gotCodepoint = false; /* initial value */ bool badCodepoint; unsigned int codepoint; @@ -429,12 +633,15 @@ interpEncoding(const char ** const arg, codepoint = wordToInt(arg[1]); gotCodepoint = true; } else { - if (wordToInt(arg[1]) == -1 && arg[2] != NULL) { - codepoint = wordToInt(arg[2]); - gotCodepoint = true; - } else - gotCodepoint = false; + if (wordToInt(arg[1]) == -1 && arg[2] != NULL) { + int const codepoint0 = wordToInt(arg[2]); + if (codepoint0 >= 0) { + codepoint = codepoint0; + gotCodepoint = true; + } + } } + if (gotCodepoint) { if (codepoint > maxmaxglyph) badCodepoint = true; @@ -538,112 +745,147 @@ validateGlyphLimits(const struct font2 * const font2P, static void -processChars(Readline * const readlineP, - struct font2 * const font2P) { -/*---------------------------------------------------------------------------- - 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 *font2P. ------------------------------------------------------------------------------*/ - unsigned int const nCharacters = wordToInt(readlineP->arg[1]); - - unsigned int nCharsDone; - unsigned int nCharsValid; - - for (nCharsDone = 0, nCharsValid = 0; - nCharsDone < nCharacters; ) { - +readStartchar(Readline * const readlineP, + const char ** charNameP) { + + const char * charName; 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")) { + while (streq(readlineP->arg[0], "COMMENT")) { + readline_read(readlineP, &eof); + if (eof) + pm_error("End of file after CHARS reading BDF font file"); /* ignore */ - } else if (!streq(readlineP->arg[0], "STARTCHAR")) + } + + if (!streq(readlineP->arg[0], "STARTCHAR")) pm_error("%s detected where \'STARTCHAR\' expected " "in BDF font file", readlineP->arg[0] ); - else { - const char * charName; - - struct glyph * glyphP; - unsigned int codepoint; - bool badCodepoint; - - if (readlineP->wordCt < 2) - pm_error("Wrong number of arguments in STARTCHAR line " - "in BDF font file"); + else if (readlineP->wordCt < 2) + pm_error("Wrong number of arguments in STARTCHAR line " + "in BDF font file"); /* Character name may contain spaces: there may be more than three words in the line. */ + else charName = pm_strdup(readlineP->arg[1]); - assert(streq(readlineP->arg[0], "STARTCHAR")); + *charNameP = charName; +} - MALLOCVAR(glyphP); - if (glyphP == NULL) - pm_error("no memory for font glyph for '%s' character", - charName); - readEncoding(readlineP, &codepoint, &badCodepoint, - font2P->maxmaxglyph); +static void +readGlyph(Readline * const readlineP, + const char * const charName, + const struct font2 * const font2P, + struct glyph ** const glyphPP) { - if (badCodepoint) - skipCharacter(readlineP); - else { - if (codepoint < font2P->maxglyph) { - if (font2P->glyph[codepoint] != NULL) - pm_error("Multiple definition of code point %u " - "in BDF font file", (unsigned int) codepoint); - else - pm_message("Reverse order detected in BDF file. " - "Code point %u defined after %u", - (unsigned int) codepoint, - (unsigned int) font2P->maxglyph); - } else { - /* Initialize all characters in the gap to nonexistent */ - unsigned int i; - unsigned int const oldMaxglyph = font2P->maxglyph; - unsigned int const newMaxglyph = codepoint; + struct glyph * glyphP; + MALLOCVAR(glyphP); + if (glyphP == NULL) + pm_error("no memory for font glyph for '%s' character", + charName); - for (i = oldMaxglyph + 1; i < newMaxglyph; ++i) - font2P->glyph[i] = NULL; + readExpectedStatement(readlineP, "SWIDTH", 3); - font2P->maxglyph = newMaxglyph; - } + readExpectedStatement(readlineP, "DWIDTH", 3); + glyphP->xadd = wordToInt(readlineP->arg[1]); - readExpectedStatement(readlineP, "SWIDTH", 3); + readExpectedStatement(readlineP, "BBX", 5); + glyphP->width = wordToInt(readlineP->arg[1]); + glyphP->height = wordToInt(readlineP->arg[2]); + glyphP->x = wordToInt(readlineP->arg[3]); + glyphP->y = wordToInt(readlineP->arg[4]); - readExpectedStatement(readlineP, "DWIDTH", 3); - glyphP->xadd = wordToInt(readlineP->arg[1]); + validateGlyphLimits(font2P, glyphP, charName); - readExpectedStatement(readlineP, "BBX", 5); - glyphP->width = wordToInt(readlineP->arg[1]); - glyphP->height = wordToInt(readlineP->arg[2]); - glyphP->x = wordToInt(readlineP->arg[3]); - glyphP->y = wordToInt(readlineP->arg[4]); + createBmap(glyphP->width, glyphP->height, readlineP, charName, + &glyphP->bmap); - validateGlyphLimits(font2P, glyphP, charName); + *glyphPP = glyphP; +} + + + +static void +processChars(Readline * const readlineP, + struct font2 * const font2P) { +/*---------------------------------------------------------------------------- + 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 *font2P. +-----------------------------------------------------------------------------*/ + unsigned int const nCharacters = wordToInt(readlineP->arg[1]); + unsigned int const nCharsWanted = (font2P->selectorP != NULL) ? + font2P->selectorP->count : nCharacters; + + unsigned int nCharsEncountered; + unsigned int nCharsLoaded; + + for (nCharsEncountered = 0, nCharsLoaded = 0; + nCharsEncountered < nCharacters && nCharsLoaded < nCharsWanted; + ++nCharsEncountered ) { + + const char * charName; + unsigned int codepoint; + bool badCodepoint; + + readStartchar(readlineP, &charName); + + readEncoding(readlineP, &codepoint, &badCodepoint, + font2P->maxmaxglyph); + + if ( badCodepoint ) { + skipCharacter(readlineP); + pm_strfree (charName); + } + else if (!pm_selector_is_marked(font2P->selectorP, codepoint) ) { + skipCharacter(readlineP); + pm_strfree (charName); + font2P->maxglyph = codepoint; + } + else { + if (codepoint < font2P->maxglyph) { + if (font2P->glyph[codepoint] != NULL ) + pm_error("Multiple definition of code point %u " + "in BDF font file", (unsigned int) codepoint); + else + pm_message("Reverse order detected in BDF file. " + "Code point %u defined after %u", + (unsigned int) codepoint, + (unsigned int) font2P->maxglyph); + } - createBmap(glyphP->width, glyphP->height, readlineP, charName, - &glyphP->bmap); + { + struct glyph * glyphP; - readExpectedStatement(readlineP, "ENDCHAR", 1); + readGlyph(readlineP, charName, font2P, &glyphP); + readExpectedStatement(readlineP, "ENDCHAR", 1); - assert(codepoint <= font2P->maxmaxglyph); - /* Ensured by readEncoding() */ + assert(codepoint <= font2P->maxmaxglyph); + /* Ensured by readEncoding() */ - font2P->glyph[codepoint] = glyphP; - pm_strfree(charName); + font2P->glyph[codepoint] = glyphP; + pm_strfree(charName); - ++nCharsValid; + font2P->maxglyph = codepoint; + ++nCharsLoaded; } - ++nCharsDone; } } - font2P->chars = nCharsValid; + + /* Note that BDF file may have reached end before the largest entry + in selector was checked. */ + /* + if (font2P->selectorP->max > font2P->maxglyph) + font2P->maxglyph = font2P->selectorP->max; + */ + font2P->chars = nCharsLoaded; font2P->total_chars = nCharacters; } @@ -717,12 +959,8 @@ loadCharsetString(const char * const registry, } - - static unsigned int const maxTokenLen = 60; - - static void doCharsetRegistry(Readline * const readlineP, bool * const gotRegistryP, @@ -904,6 +1142,9 @@ processBdfFontLine(Readline * const readlineP, else { validateWordCount(readlineP, 2); /* CHARS n */ processChars(readlineP, font2P); + if (font2P->selectorP != NULL && + font2P->selectorP->count == font2P->chars) + *endOfFontP = true; } } else { /* ignore */ @@ -913,9 +1154,39 @@ processBdfFontLine(Readline * const readlineP, +static void +initializeGlyphArray(struct font2 * const font2P, + unsigned int const maxmaxglyph) { +/*---------------------------------------------------------------------------- + Initialize glyph array based on entries in selector. + Note that only valid codepoints are set to NULL. + Entries for unused glyphs are left untouched. +-----------------------------------------------------------------------------*/ + const struct pm_selector * const selectorP = font2P->selectorP; + unsigned int const min = (selectorP == NULL) ? 0 : selectorP->min; + unsigned int const max = + (selectorP == NULL) ? font2P->maxglyph : selectorP->max; + + unsigned int codepoint; + + for (codepoint = min; codepoint <= max ; ++codepoint) + if (pm_selector_is_marked(selectorP, codepoint) == true) + font2P->glyph[codepoint] = NULL; + + font2P->glyph[L' '] = NULL; + /* Clear the slot for space character. + It may not be defined in the font, but the program may try + to use space as a substitute char + */ + +} + + + struct font2 * -pbm_loadbdffont2(const char * const filename, - PM_WCHAR const maxmaxglyph) { +pbm_loadbdffont2select(const char * const filename, + PM_WCHAR const maxmaxglyph, + const struct pm_selector * const selectorP) { /*---------------------------------------------------------------------------- Read a BDF font file "filename" as a 'font2' structure. A 'font2' structure is more expressive than a 'font' structure, most notably in that @@ -943,8 +1214,14 @@ pbm_loadbdffont2(const char * const filename, font2P->maxglyph = 0; /* Initial value. Increases as new characters are loaded */ - font2P->glyph[0] = NULL; - /* Initial value. Overwrite later if codepoint 0 is defined. */ + + if (font2P->selectorP == NULL) { + PM_WCHAR i; + + for(i = 0; i <= maxmaxglyph; ++i) + font2P->glyph[i] = NULL; + /* Initial value. Overwrite later if codepoint i is defined. */ + } font2P->maxmaxglyph = maxmaxglyph; @@ -955,6 +1232,9 @@ pbm_loadbdffont2(const char * const filename, font2P->chars = font2P->total_chars = 0; font2P->default_char = 0; font2P->default_char_defined = FALSE; + font2P->selectorP = (struct pm_selector * const) selectorP; + + initializeGlyphArray(font2P, maxmaxglyph); readExpectedStatement(&readline, "STARTFONT", 2); @@ -970,9 +1250,13 @@ pbm_loadbdffont2(const char * const filename, } fclose(ifP); - if(font2P->chars == 0) + if(font2P->total_chars == 0) pm_error("No glyphs found in BDF font file " "in codepoint range 0 - %u", (unsigned int) maxmaxglyph); + if(font2P->chars == 0) + pm_error("Not any requested glyphs found in BDF font file " + "in codepoint range 0 - %u", (unsigned int) maxmaxglyph); + REALLOCARRAY(font2P->glyph, font2P->maxglyph + 1); @@ -986,8 +1270,21 @@ pbm_loadbdffont2(const char * const filename, } +struct font2 * +pbm_loadbdffont2(const char * const filename, + PM_WCHAR const maxmaxglyph) { + + return (pbm_loadbdffont2select(filename, maxmaxglyph, NULL)); + + return(0); +} + + + + static struct font * font2ToFont(const struct font2 * const font2P) { + struct font * fontP; unsigned int codePoint; @@ -1001,18 +1298,10 @@ font2ToFont(const struct font2 * const font2P) { fontP->x = font2P->x; fontP->y = font2P->y; - for (codePoint = 0; codePoint <= font2P->maxglyph; ++codePoint) - fontP->glyph[codePoint] = font2P->glyph[codePoint]; - - /* font2P->maxglyph is typically 255 (PM_FONT_MAXGLYPH) or larger. - But in some rare cases it is smaller. - If an ASCII-only font is read, it will be 126 or 127. - - Set remaining codepoints up to PM_FONT_MAXGLYPH, if any, to NULL - */ - - for ( ; codePoint <= PM_FONT_MAXGLYPH; ++codePoint) - fontP->glyph[codePoint] = NULL; + for (codePoint = 0; codePoint <= PM_FONT_MAXGLYPH; ++codePoint) + fontP->glyph[codePoint] = + pm_selector_is_marked(font2P->selectorP, codePoint) ? + font2P->glyph[codePoint] : NULL; /* Give values to legacy fields */ fontP->oldfont = font2P->oldfont; diff --git a/lib/pbmfont.h b/lib/pbmfont.h index c8b3934b..6adbe814 100644 --- a/lib/pbmfont.h +++ b/lib/pbmfont.h @@ -115,12 +115,12 @@ struct glyph { struct font { /* This describes a combination of font and character set. Given - an code point in the range 0..255, this structure describes the + a code point in the range 0..255, this structure describes the glyph for that character. */ unsigned int maxwidth, maxheight; int x; - /* The minimum value of glyph.font. The left edge of the glyph + /* The minimum value of glyph.x . The left edge of the glyph in the glyph set which advances furthest to the left. */ int y; /* Amount of white space that should be added between lines of @@ -137,10 +137,29 @@ struct font { }; + +struct pm_selector { + unsigned int min; /* smallest index requested */ + unsigned int max; /* largest index requested */ + unsigned int maxmax; /* largest index possible */ + unsigned int count; /* number bits set to 1 in 'record' */ + const unsigned char * record; + /* Bit array 0: absent 1: existent size calculated from maxmax + This is for reading only; not updating. + Might be 'localRecord'; might be fixed object elsewhere. + */ + unsigned char * localRecord; + /* Updateable record optionally pointed to by 'record'. + Null if none. Malloc'ed storage we own otherwise. + */ +}; + + + struct font2 { /* Font structure for expanded character set. - Code points in the range 0...maxmaxglyph are loaded. - Loaded code point is in the range 0..maxglyph . + Code points in the range 0...maxmaxglyph may be loaded. + Actually loaded code point is in the range 0..maxglyph . */ /* 'size' and 'len' are necessary in order to provide forward and @@ -159,7 +178,7 @@ struct font2 { int maxwidth, maxheight; int x; - /* The minimum value of glyph.font. The left edge of the glyph in + /* The minimum value of glyph.x . The left edge of the glyph in the glyph set which advances furthest to the left. */ int y; @@ -177,14 +196,12 @@ struct font2 { */ PM_WCHAR maxglyph; - /* max code point for glyphs, including vacant slots max value of - above i + /* max code point for glyphs, including vacant slots + max value of above i */ - void * selector; - /* Reserved - - Bit array or structure indicating which code points to load. + struct pm_selector * selectorP; + /* Structure with bit array indicating which code points to load. When NULL, all available code points up to maxmaxglyph, inclusive are loaded. @@ -206,14 +223,15 @@ struct font2 { */ unsigned int bit_format; - /* PBM_FORMAT: glyph data: 1 byte per pixel (like P1, but not ASCII) - RPBM_FORMAT: glyph data: 1 bit per pixel + /* PBM_FORMAT: glyph data: 1 byte per pixel (like P1, but not ASCII) + RPBM_FORMAT: glyph data: 1 bit per pixel Currently only PBM_FORMAT is possible */ unsigned int total_chars; - /* Number of glyphs defined in font file, as stated in the CHARS line - of the BDF file PBM sheet font. Always 96 + /* Number of glyphs defined in font file. + BDF file: as stated in the CHARS line. + PBM sheet font: always 96. */ unsigned int chars; @@ -237,7 +255,7 @@ struct font2 { PM_WCHAR default_char; /* Code index of what to show when there is no glyph for a requested - code Available in many BDF fonts between STARPROPERTIES - + code. Available in many BDF fonts between STARPROPERTIES - ENDPROPERTIES. Set to value read from BDF font file. @@ -306,6 +324,11 @@ struct font2 * pbm_loadfont2(const char * const filename, PM_WCHAR const maxmaxglyph); +struct font2 * +pbm_loadfont2select(const char * const filename, + PM_WCHAR const maxmaxglyph, + const struct pm_selector * const selectorP); + struct font * pbm_loadpbmfont(const char * const filename); @@ -320,9 +343,9 @@ pbm_loadbdffont2(const char * const filename, PM_WCHAR const maxmaxglyph); struct font2 * -pbm_loadbdffont2_select(const char * const filename, - PM_WCHAR const maxmaxglyph, - const void * const selector); +pbm_loadbdffont2select(const char * const filename, + PM_WCHAR const maxmaxglyph, + const struct pm_selector * const selectorP); void pbm_createbdffont2_base(struct font2 ** const font2P, @@ -344,6 +367,38 @@ void pbm_dumpfont(struct font * const fontP, FILE * const ofP); +/* selector functions */ + +void +pm_selector_create(unsigned int const max, + struct pm_selector ** const selectorPP); + +void +pm_selector_create_fixed(const unsigned char * const record, + unsigned int const min, + unsigned int const max, + unsigned int const count, + struct pm_selector ** const selectorPP); + +void +pm_selector_destroy(struct pm_selector * const selectorP); + +void +pm_selector_copy(unsigned int const max, + const struct pm_selector * const srcSelectorP, + struct pm_selector ** const destSelectorPP); + +void +pm_selector_mark(struct pm_selector * const selectorP, + unsigned int const index); + +int /* boolean */ +pm_selector_is_marked(const struct pm_selector * const selectorP, + unsigned int const index); + +unsigned int +pm_selector_marked_ct(const struct pm_selector * const selectorP); + #ifdef __cplusplus } #endif diff --git a/lib/pbmfontdata2.c b/lib/pbmfontdata2.c index 11dd84e6..63dd36be 100644 --- a/lib/pbmfontdata2.c +++ b/lib/pbmfontdata2.c @@ -452,7 +452,7 @@ struct font2 const pbm_defaultBdffont2 = { 255, NULL, 255, /* maxglyph, selector, maxmaxglyph */ NULL, 0, 0, /* oldfont, fcols, frows */ PBM_FORMAT, /* bit_format */ - 190, 190, /* total_chars, chars */ + 191, 191, /* total_chars, chars */ FIXED_DATA, /* load_fn */ 32, 1, /* default_char, default_char_defined */ (char *) "builtin bdf", /* name */ -- cgit 1.4.1