diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2018-03-23 01:52:20 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2018-03-23 01:52:20 +0000 |
commit | ed35a4576d1d5e8d7b86ae3fa8e2afea0c1ff67b (patch) | |
tree | b0c2b627855c01c68552abf91e812ddbded78867 /lib | |
parent | a2c68a408cb2b33f09f2cba891c019f84f1f9799 (diff) | |
download | netpbm-mirror-ed35a4576d1d5e8d7b86ae3fa8e2afea0c1ff67b.tar.gz netpbm-mirror-ed35a4576d1d5e8d7b86ae3fa8e2afea0c1ff67b.tar.xz netpbm-mirror-ed35a4576d1d5e8d7b86ae3fa8e2afea0c1ff67b.zip |
Add wide character capability to Pbmtext
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3177 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libpbmfont.c | 211 | ||||
-rw-r--r-- | lib/pbmfont.h | 53 |
2 files changed, 224 insertions, 40 deletions
diff --git a/lib/libpbmfont.c b/lib/libpbmfont.c index 8e854aa6..8f308eda 100644 --- a/lib/libpbmfont.c +++ b/lib/libpbmfont.c @@ -256,7 +256,7 @@ pbm_dissectfont(const bit ** const font, /* Initialize all character positions to "undefined." Those that are defined in the font will be filled in below. */ - for (i = 0; i < 256; i++) + for (i = 0; i < PM_FONT_MAXGLYPH + 1; i++) fn->glyph[i] = NULL; MALLOCARRAY(glyph, nCharsInFont); @@ -294,7 +294,7 @@ pbm_dissectfont(const bit ** const font, row += cellHeight; } } - for (i = firstCodePoint + nCharsInFont; i < 256; ++i) + for (i = firstCodePoint + nCharsInFont; i < PM_FONT_MAXGLYPH + 1; ++i) fn->glyph[i] = NULL; return fn; @@ -377,14 +377,14 @@ pbm_dumpfont(struct font * const fontP, pm_message("Netpbm no longer has the capability to generate " "a font in long hexadecimal data format"); - for (i = 0, ng = 0; i < 256; ++i) { + 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 < 256; ++i) { + for (i = 0; i < PM_FONT_MAXGLYPH + 1; ++i) { struct glyph * const glyphP = fontP->glyph[i]; if (glyphP) { unsigned int j; @@ -409,13 +409,13 @@ pbm_dumpfont(struct font * const fontP, { unsigned int i; - for (i = 0; i < 256; ++i) { + for (i = 0; i < PM_FONT_MAXGLYPH + 1; ++i) { if (fontP->glyph[i]) printf(" _g + %d", ng++); else printf(" NULL"); - if (i != 255) printf(","); + if (i != PM_FONT_MAXGLYPH) printf(","); printf("\n"); } } @@ -738,7 +738,8 @@ skipCharacter(Readline * const readlineP) { static void interpEncoding(const char ** const arg, unsigned int * const codepointP, - bool * const badCodepointP) { + 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 @@ -746,8 +747,9 @@ interpEncoding(const char ** const arg, 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; @@ -763,7 +765,7 @@ interpEncoding(const char ** const arg, gotCodepoint = false; } if (gotCodepoint) { - if (codepoint > 255) + if (codepoint > maxglyph) badCodepoint = true; else badCodepoint = false; @@ -779,17 +781,18 @@ interpEncoding(const char ** const arg, static void readEncoding(Readline * const readlineP, unsigned int * const codepointP, - bool * const badCodepointP) { + bool * const badCodepointP, + PM_WCHAR const maxglyph) { readExpectedStatement(readlineP, "ENCODING"); - interpEncoding(readlineP->arg, codepointP, badCodepointP); + interpEncoding(readlineP->arg, codepointP, badCodepointP, maxglyph); } static void -validateFontLimits(const struct font * const fontP) { +validateFontLimits(const struct font2 * const fontP) { assert(pbm_maxfontheight() > 0 && pbm_maxfontwidth() > 0); @@ -797,22 +800,27 @@ validateFontLimits(const struct font * const fontP) { fontP->maxheight <= 0 || fontP->maxwidth > pbm_maxfontwidth() || fontP->maxheight > pbm_maxfontheight() || - fontP->x < - fontP->maxwidth +1 || - fontP->y < - fontP->maxheight +1 || + -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.\n"); + 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 font * const fontP, +validateGlyphLimits(const struct font2 * const fontP, const struct glyph * const glyphP, const char * const charName) { @@ -842,7 +850,8 @@ validateGlyphLimits(const struct font * const fontP, static void processChars(Readline * const readlineP, - struct font * const fontP) { + 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 @@ -880,7 +889,7 @@ processChars(Readline * const readlineP, pm_error("no memory for font glyph for '%s' character", charName); - readEncoding(readlineP, &codepoint, &badCodepoint); + readEncoding(readlineP, &codepoint, &badCodepoint, maxglyph); if (badCodepoint) skipCharacter(readlineP); @@ -907,7 +916,7 @@ processChars(Readline * const readlineP, readExpectedStatement(readlineP, "ENDCHAR"); - assert(codepoint < 256); /* Ensured by readEncoding() */ + assert(codepoint <= maxglyph); /* Ensured by readEncoding() */ fontP->glyph[codepoint] = glyphP; pm_strfree(charName); @@ -921,8 +930,9 @@ processChars(Readline * const readlineP, static void processBdfFontLine(Readline * const readlineP, - struct font * const fontP, - bool * const endOfFontP) { + struct font2 * const fontP, + bool * const endOfFontP, + PM_WCHAR const maxglyph) { /*---------------------------------------------------------------------------- Process a nonblank line just read from a BDF font file. @@ -964,7 +974,7 @@ processBdfFontLine(Readline * const readlineP, pm_error("Encountered CHARS before FONTBOUNDINGBOX " "in BDF font file"); else - processChars(readlineP, fontP); + processChars(readlineP, fontP, maxglyph); } else { /* ignore */ } @@ -972,36 +982,57 @@ processBdfFontLine(Readline * const readlineP, -struct font * -pbm_loadbdffont(const char * const name) { +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. - FILE * ifP; - Readline readline; - struct font * fontP; - bool endOfFont; + Codepoints up to maxglyph inclusive are valid in the file. - ifP = fopen(name, "rb"); + 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)", - name, errno, strerror(errno)); + filename, errno, strerror(errno)); readline_init(&readline, ifP); - MALLOCVAR(fontP); - if (fontP == NULL) + MALLOCVAR(font2P); + if (font2P == NULL) pm_error("no memory for font"); - fontP->oldfont = 0; - { + 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. */ - unsigned int i; - for (i = 0; i < 256; ++i) - fontP->glyph[i] = NULL; + PM_WCHAR i; + for (i = 0; i <= maxglyph; ++i) + font2P->glyph[i] = NULL; } - fontP->maxwidth = fontP->maxheight = fontP->x = fontP->y = 0; + font2P->maxwidth = font2P->maxheight = font2P->x = font2P->y = 0; readExpectedStatement(&readline, "STARTFONT"); @@ -1013,10 +1044,112 @@ pbm_loadbdffont(const char * const name) { if (eof) pm_error("End of file before ENDFONT statement in BDF font file"); - processBdfFontLine(&readline, fontP, &endOfFont); + 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; +} + + diff --git a/lib/pbmfont.h b/lib/pbmfont.h index 5111a075..ad5d3acf 100644 --- a/lib/pbmfont.h +++ b/lib/pbmfont.h @@ -20,6 +20,23 @@ extern "C" { a 65536 x 65536 glyph occupies 4G pixels. */ +typedef wchar_t PM_WCHAR; + /* Precaution to make adjustments, if necessary, for systems with + unique wchar_t. + */ + +#define PM_FONT_MAXGLYPH 255 + +#define PM_FONT2_MAXGLYPH 65535 + /* Upper limit of codepoint value. + + This is large enough to handle Unicode Plane 0 (Basic Multilingual + Plane: BMP) which defines the great majority of characters used in + modern languages. + + This can be set to a higher value at some cost to efficiency. + As of Unicode v. 11.0.0 planes up to 16 are defined. + */ struct glyph { /* A glyph consists of white borders and the "central glyph" which @@ -60,7 +77,7 @@ struct font { an code point in the range 0..255, this structure describes the glyph for that character. */ - int maxwidth, maxheight; + unsigned int maxwidth, maxheight; int x; /* The minimum value of glyph.font. The left edge of the glyph in the glyph set which advances furthest to the left. */ @@ -76,6 +93,33 @@ struct font { int fcols, frows; }; + +struct font2 { + /* Font structure for expanded character set. Code point is in the + range 0..maxglyph . + */ + int maxwidth, maxheight; + + int x; + /* The minimum value of glyph.font. 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 + this font. Can be negative. + */ + struct glyph ** glyph; + /* glyph[i] is the glyph for code point i */ + + PM_WCHAR maxglyph; + /* max code point for glyphs, including vacant slots */ + + const bit ** oldfont; + /* for compatibility with old pbmtext routines */ + /* oldfont is NULL if the font is BDF derived */ + + unsigned int fcols, frows; +}; + struct font * pbm_defaultfont(const char* const which); @@ -93,6 +137,13 @@ pbm_loadpbmfont(const char * const filename); struct font * pbm_loadbdffont(const char * const filename); +struct font2 * +pbm_loadbdffont2(const char * const filename, + PM_WCHAR const maxglyph); + +struct font2 * +pbm_expandbdffont(const struct font * const font); + void pbm_dumpfont(struct font * const fontP, FILE * const ofP); |