diff options
author | Adam Jackson <ajax@redhat.com> | 2017-10-24 13:54:47 -0400 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2017-10-24 15:14:23 -0400 |
commit | 102696da8737fcb324034f673cd5815f28923311 (patch) | |
tree | 360e49b700b617768f4289c6d9d23da7641791b1 /bdfread.c | |
parent | e12c03d50a634a98e4560c7117a3bec3349561e9 (diff) |
Import libXfont's BDF-to-PCF code
bdftopcf is the only consumer of libXfont 1.x's read/write support, and
we'd like 1.x to go away entirely. Copy in the BDF read and PCF write
support so there's one fewer consumer of 1.x.
Signed-off-by: Adam Jackson <ajax@redhat.com>
Acked-by: Julien Cristau <jcristau@debian.org>
Diffstat (limited to 'bdfread.c')
-rw-r--r-- | bdfread.c | 992 |
1 files changed, 992 insertions, 0 deletions
diff --git a/bdfread.c b/bdfread.c new file mode 100644 index 0000000..f343eed --- /dev/null +++ b/bdfread.c @@ -0,0 +1,992 @@ +/************************************************************************ +Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <ctype.h> +#include <X11/fonts/fntfilst.h> +#include <X11/fonts/fontutil.h> +/* use bitmap structure */ +#include <X11/fonts/bitmap.h> +#include <X11/fonts/bdfint.h> + +#if HAVE_STDINT_H +#include <stdint.h> +#else +# ifndef INT32_MAX +# define INT32_MAX 0x7fffffff +# endif +# ifndef INT16_MAX +# define INT16_MAX 0x7fff +# endif +# ifndef INT16_MIN +# define INT16_MIN (0 - 0x8000) +# endif +#endif + +#define INDICES 256 +#define MAXENCODING 0xFFFF +#define BDFLINELEN 1024 +#define BDFLINESTR "%1023s" /* scanf specifier to read a BDFLINELEN string */ + +static Bool bdfPadToTerminal(FontPtr pFont); +extern int bdfFileLineNum; + +/***====================================================================***/ + +static Bool +bdfReadBitmap(CharInfoPtr pCI, FontFilePtr file, int bit, int byte, + int glyph, int scan, CARD32 *sizes) +{ + int widthBits, + widthBytes, + widthHexChars; + int height, + row; + int i, + inLineLen, + nextByte; + unsigned char *pInBits, + *picture, + *line = NULL; + unsigned char lineBuf[BDFLINELEN]; + + widthBits = GLYPHWIDTHPIXELS(pCI); + height = GLYPHHEIGHTPIXELS(pCI); + + widthBytes = BYTES_PER_ROW(widthBits, glyph); + if (widthBytes * height > 0) { + picture = malloc(widthBytes * height); + if (!picture) { + bdfError("Couldn't allocate picture (%d*%d)\n", widthBytes, height); + goto BAILOUT; + } + } else + picture = NULL; + pCI->bits = (char *) picture; + + if (sizes) { + for (i = 0; i < GLYPHPADOPTIONS; i++) + sizes[i] += BYTES_PER_ROW(widthBits, (1 << i)) * height; + } + nextByte = 0; + widthHexChars = BYTES_PER_ROW(widthBits, 1); + +/* 5/31/89 (ef) -- hack, hack, hack. what *am* I supposed to do with */ +/* 0 width characters? */ + + for (row = 0; row < height; row++) { + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line) + break; + + if (widthBits == 0) { + if ((!line) || (bdfIsPrefix(line, "ENDCHAR"))) + break; + else + continue; + } + pInBits = line; + inLineLen = strlen((char *) pInBits); + + if (inLineLen & 1) { + bdfError("odd number of characters in hex encoding\n"); + line[inLineLen++] = '0'; + line[inLineLen] = '\0'; + } + inLineLen >>= 1; + i = inLineLen; + if (i > widthHexChars) + i = widthHexChars; + for (; i > 0; i--, pInBits += 2) + picture[nextByte++] = bdfHexByte(pInBits); + + /* pad if line is too short */ + if (inLineLen < widthHexChars) { + for (i = widthHexChars - inLineLen; i > 0; i--) + picture[nextByte++] = 0; + } else { + unsigned char mask; + + mask = 0xff << (8 - (widthBits & 0x7)); + if (mask && picture[nextByte - 1] & ~mask) { + picture[nextByte - 1] &= mask; + } + } + + if (widthBytes > widthHexChars) { + i = widthBytes - widthHexChars; + while (i-- > 0) + picture[nextByte++] = 0; + } + } + + if ((line && (!bdfIsPrefix(line, "ENDCHAR"))) || (height == 0)) + line = bdfGetLine(file, lineBuf, BDFLINELEN); + + if ((!line) || (!bdfIsPrefix(line, "ENDCHAR"))) { + bdfError("missing 'ENDCHAR'\n"); + goto BAILOUT; + } + if (nextByte != height * widthBytes) { + bdfError("bytes != rows * bytes_per_row (%d != %d * %d)\n", + nextByte, height, widthBytes); + goto BAILOUT; + } + if (picture != NULL) { + if (bit == LSBFirst) + BitOrderInvert(picture, nextByte); + if (bit != byte) { + if (scan == 2) + TwoByteSwap(picture, nextByte); + else if (scan == 4) + FourByteSwap(picture, nextByte); + } + } + return (TRUE); +BAILOUT: + if (picture) + free(picture); + pCI->bits = NULL; + return (FALSE); +} + +/***====================================================================***/ + +static Bool +bdfSkipBitmap(FontFilePtr file, int height) +{ + unsigned char *line; + int i = 0; + unsigned char lineBuf[BDFLINELEN]; + + do { + line = bdfGetLine(file, lineBuf, BDFLINELEN); + i++; + } while (line && !bdfIsPrefix(line, "ENDCHAR") && i <= height); + + if (i > 1 && line && !bdfIsPrefix(line, "ENDCHAR")) { + bdfError("Error in bitmap, missing 'ENDCHAR'\n"); + return (FALSE); + } + return (TRUE); +} + +/***====================================================================***/ + +static void +bdfFreeFontBits(FontPtr pFont) +{ + BitmapFontPtr bitmapFont; + BitmapExtraPtr bitmapExtra; + int i, nencoding; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra; + free(bitmapFont->ink_metrics); + if(bitmapFont->encoding) { + nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * + (pFont->info.lastRow - pFont->info.firstRow + 1); + for(i=0; i<NUM_SEGMENTS(nencoding); i++) + free(bitmapFont->encoding[i]); + } + free(bitmapFont->encoding); + for (i = 0; i < bitmapFont->num_chars; i++) + free(bitmapFont->metrics[i].bits); + free(bitmapFont->metrics); + if (bitmapExtra) + { + free (bitmapExtra->glyphNames); + free (bitmapExtra->sWidths); + free (bitmapExtra); + } + free(pFont->info.props); + free(bitmapFont); +} + + +static Bool +bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState, + int bit, int byte, int glyph, int scan) +{ + unsigned char *line; + register CharInfoPtr ci; + int i, + ndx, + nchars, + nignored; + unsigned int char_row, char_col; + int numEncodedGlyphs = 0; + CharInfoPtr *bdfEncoding[256]; + BitmapFontPtr bitmapFont; + BitmapExtraPtr bitmapExtra; + CARD32 *bitmapsSizes; + unsigned char lineBuf[BDFLINELEN]; + int nencoding; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra; + + if (bitmapExtra) { + bitmapsSizes = bitmapExtra->bitmapsSizes; + for (i = 0; i < GLYPHPADOPTIONS; i++) + bitmapsSizes[i] = 0; + } else + bitmapsSizes = NULL; + + bzero(bdfEncoding, sizeof(bdfEncoding)); + bitmapFont->metrics = NULL; + ndx = 0; + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + + if ((!line) || (sscanf((char *) line, "CHARS %d", &nchars) != 1)) { + bdfError("bad 'CHARS' in bdf file\n"); + return (FALSE); + } + if (nchars < 1) { + bdfError("invalid number of CHARS in BDF file\n"); + return (FALSE); + } + if (nchars > (signed) (INT32_MAX / sizeof(CharInfoRec))) { + bdfError("Couldn't allocate pCI (%d*%d)\n", nchars, + (int) sizeof(CharInfoRec)); + goto BAILOUT; + } + ci = calloc(nchars, sizeof(CharInfoRec)); + if (!ci) { + bdfError("Couldn't allocate pCI (%d*%d)\n", nchars, + (int) sizeof(CharInfoRec)); + goto BAILOUT; + } + bitmapFont->metrics = ci; + + if (bitmapExtra) { + bitmapExtra->glyphNames = malloc(nchars * sizeof(Atom)); + if (!bitmapExtra->glyphNames) { + bdfError("Couldn't allocate glyphNames (%d*%d)\n", + nchars, (int) sizeof(Atom)); + goto BAILOUT; + } + } + if (bitmapExtra) { + bitmapExtra->sWidths = malloc(nchars * sizeof(int)); + if (!bitmapExtra->sWidths) { + bdfError("Couldn't allocate sWidth (%d *%d)\n", + nchars, (int) sizeof(int)); + return FALSE; + } + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + pFont->info.firstRow = 256; + pFont->info.lastRow = 0; + pFont->info.firstCol = 256; + pFont->info.lastCol = 0; + nignored = 0; + for (ndx = 0; (ndx < nchars) && (line) && (bdfIsPrefix(line, "STARTCHAR"));) { + int t; + int wx; /* x component of width */ + int wy; /* y component of width */ + int bw; /* bounding-box width */ + int bh; /* bounding-box height */ + int bl; /* bounding-box left */ + int bb; /* bounding-box bottom */ + int enc, + enc2; /* encoding */ + unsigned char *p; /* temp pointer into line */ + char charName[100]; + int ignore; + + if (sscanf((char *) line, "STARTCHAR %99s", charName) != 1) { + bdfError("bad character name in BDF file\n"); + goto BAILOUT; /* bottom of function, free and return error */ + } + if (bitmapExtra) + bitmapExtra->glyphNames[ndx] = bdfForceMakeAtom(charName, NULL); + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || (t = sscanf((char *) line, "ENCODING %d %d", &enc, &enc2)) < 1) { + bdfError("bad 'ENCODING' in BDF file\n"); + goto BAILOUT; + } + if (enc < -1 || (t == 2 && enc2 < -1)) { + bdfError("bad ENCODING value"); + goto BAILOUT; + } + if (t == 2 && enc == -1) + enc = enc2; + ignore = 0; + if (enc == -1) { + if (!bitmapExtra) { + nignored++; + ignore = 1; + } + } else if (enc > MAXENCODING) { + bdfError("char '%s' has encoding too large (%d)\n", + charName, enc); + } else { + char_row = (enc >> 8) & 0xFF; + char_col = enc & 0xFF; + if (char_row < pFont->info.firstRow) + pFont->info.firstRow = char_row; + if (char_row > pFont->info.lastRow) + pFont->info.lastRow = char_row; + if (char_col < pFont->info.firstCol) + pFont->info.firstCol = char_col; + if (char_col > pFont->info.lastCol) + pFont->info.lastCol = char_col; + if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) { + bdfEncoding[char_row] = malloc(256 * sizeof(CharInfoPtr)); + if (!bdfEncoding[char_row]) { + bdfError("Couldn't allocate row %d of encoding (%d*%d)\n", + char_row, INDICES, (int) sizeof(CharInfoPtr)); + goto BAILOUT; + } + for (i = 0; i < 256; i++) + bdfEncoding[char_row][i] = (CharInfoPtr) NULL; + } + if (bdfEncoding[char_row] != NULL) { + bdfEncoding[char_row][char_col] = ci; + numEncodedGlyphs++; + } + } + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) { + bdfError("bad 'SWIDTH'\n"); + goto BAILOUT; + } + if (wy != 0) { + bdfError("SWIDTH y value must be zero\n"); + goto BAILOUT; + } + if (bitmapExtra) + bitmapExtra->sWidths[ndx] = wx; + +/* 5/31/89 (ef) -- we should be able to ditch the character and recover */ +/* from all of these. */ + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) { + bdfError("bad 'DWIDTH'\n"); + goto BAILOUT; + } + if (wy != 0) { + bdfError("DWIDTH y value must be zero\n"); + goto BAILOUT; + } + /* xCharInfo metrics are stored as INT16 */ + if ((wx < INT16_MIN) || (wx > INT16_MAX)) { + bdfError("character '%s' has out of range width, %d\n", + charName, wx); + goto BAILOUT; + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) { + bdfError("bad 'BBX'\n"); + goto BAILOUT; + } + if ((bh < 0) || (bw < 0)) { + bdfError("character '%s' has a negative sized bitmap, %dx%d\n", + charName, bw, bh); + goto BAILOUT; + } + /* xCharInfo metrics are read as int, but stored as INT16 */ + if ((bl > INT16_MAX) || (bl < INT16_MIN) || + (bb > INT16_MAX) || (bb < INT16_MIN) || + (bw > (INT16_MAX - bl)) || (bh > (INT16_MAX - bb))) { + bdfError("character '%s' has out of range metrics, %d %d %d %d\n", + charName, bl, (bl+bw), (bh+bb), -bb); + goto BAILOUT; + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) { + for (p = line + strlen("ATTRIBUTES "); + (*p == ' ') || (*p == '\t'); + p++) + /* empty for loop */ ; + ci->metrics.attributes = (bdfHexByte(p) << 8) + bdfHexByte(p + 2); + line = bdfGetLine(file, lineBuf, BDFLINELEN); + } else + ci->metrics.attributes = 0; + + if (!line || !bdfIsPrefix(line, "BITMAP")) { + bdfError("missing 'BITMAP'\n"); + goto BAILOUT; + } + /* collect data for generated properties */ + if ((strlen(charName) == 1)) { + if ((charName[0] >= '0') && (charName[0] <= '9')) { + pState->digitWidths += wx; + pState->digitCount++; + } else if (charName[0] == 'x') { + pState->exHeight = (bh + bb) <= 0 ? bh : bh + bb; + } + } + if (!ignore) { + ci->metrics.leftSideBearing = bl; + ci->metrics.rightSideBearing = bl + bw; + ci->metrics.ascent = bh + bb; + ci->metrics.descent = -bb; + ci->metrics.characterWidth = wx; + ci->bits = NULL; + if (!bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes)) { + bdfError("could not read bitmap for character '%s'\n", charName); + goto BAILOUT; + } + ci++; + ndx++; + } else + bdfSkipBitmap(file, bh); + + line = bdfGetLine(file, lineBuf, BDFLINELEN); /* get STARTCHAR or + * ENDFONT */ + } + + if (ndx + nignored != nchars) { + bdfError("%d too few characters\n", nchars - (ndx + nignored)); + goto BAILOUT; + } + nchars = ndx; + bitmapFont->num_chars = nchars; + if ((line) && (bdfIsPrefix(line, "STARTCHAR"))) { + bdfError("more characters than specified\n"); + goto BAILOUT; + } + if ((!line) || (!bdfIsPrefix(line, "ENDFONT"))) { + bdfError("missing 'ENDFONT'\n"); + goto BAILOUT; + } + if (numEncodedGlyphs == 0) + bdfWarning("No characters with valid encodings\n"); + + nencoding = (pFont->info.lastRow - pFont->info.firstRow + 1) * + (pFont->info.lastCol - pFont->info.firstCol + 1); + bitmapFont->encoding = calloc(NUM_SEGMENTS(nencoding),sizeof(CharInfoPtr*)); + if (!bitmapFont->encoding) { + bdfError("Couldn't allocate ppCI (%d,%d)\n", + NUM_SEGMENTS(nencoding), + (int) sizeof(CharInfoPtr*)); + goto BAILOUT; + } + pFont->info.allExist = TRUE; + i = 0; + for (char_row = pFont->info.firstRow; + char_row <= pFont->info.lastRow; + char_row++) { + if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) { + pFont->info.allExist = FALSE; + i += pFont->info.lastCol - pFont->info.firstCol + 1; + } else { + for (char_col = pFont->info.firstCol; + char_col <= pFont->info.lastCol; + char_col++) { + if (!bdfEncoding[char_row][char_col]) + pFont->info.allExist = FALSE; + else { + if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { + bitmapFont->encoding[SEGMENT_MAJOR(i)]= + calloc(BITMAP_FONT_SEGMENT_SIZE, + sizeof(CharInfoPtr)); + if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) + goto BAILOUT; + } + ACCESSENCODINGL(bitmapFont->encoding,i) = + bdfEncoding[char_row][char_col]; + } + i++; + } + } + } + for (i = 0; i < 256; i++) + if (bdfEncoding[i]) + free(bdfEncoding[i]); + return (TRUE); +BAILOUT: + for (i = 0; i < 256; i++) + if (bdfEncoding[i]) + free(bdfEncoding[i]); + /* bdfFreeFontBits will clean up the rest */ + return (FALSE); +} + +/***====================================================================***/ + +static Bool +bdfReadHeader(FontFilePtr file, bdfFileState *pState) +{ + unsigned char *line; + char namebuf[BDFLINELEN]; + unsigned char lineBuf[BDFLINELEN]; + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || + sscanf((char *) line, "STARTFONT " BDFLINESTR, namebuf) != 1 || + !bdfStrEqual(namebuf, "2.1")) { + bdfError("bad 'STARTFONT'\n"); + return (FALSE); + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); +#if MAXFONTNAMELEN != 1024 +# error "need to adjust sscanf length limit to be MAXFONTNAMELEN - 1" +#endif + if (!line || + sscanf((char *) line, "FONT %1023[^\n]", pState->fontName) != 1) { + bdfError("bad 'FONT'\n"); + return (FALSE); + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || !bdfIsPrefix(line, "SIZE")) { + bdfError("missing 'SIZE'\n"); + return (FALSE); + } + if (sscanf((char *) line, "SIZE %f%d%d", &pState->pointSize, + &pState->resolution_x, &pState->resolution_y) != 3) { + bdfError("bad 'SIZE'\n"); + return (FALSE); + } + if (pState->pointSize < 1 || + pState->resolution_x < 1 || pState->resolution_y < 1) { + bdfError("SIZE values must be > 0\n"); + return (FALSE); + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || !bdfIsPrefix(line, "FONTBOUNDINGBOX")) { + bdfError("missing 'FONTBOUNDINGBOX'\n"); + return (FALSE); + } + return (TRUE); +} + +/***====================================================================***/ + +static Bool +bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState) +{ + int nProps, props_left, + nextProp; + char *stringProps; + FontPropPtr props; + char namebuf[BDFLINELEN], + secondbuf[BDFLINELEN], + thirdbuf[BDFLINELEN]; + unsigned char *line; + unsigned char lineBuf[BDFLINELEN]; + BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) { + bdfError("missing 'STARTPROPERTIES'\n"); + return (FALSE); + } + if ((sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) || + (nProps <= 0) || + (nProps > (signed) ((INT32_MAX / sizeof(FontPropRec)) - BDF_GENPROPS))) { + bdfError("bad 'STARTPROPERTIES'\n"); + return (FALSE); + } + pFont->info.isStringProp = NULL; + pFont->info.props = NULL; + pFont->info.nprops = 0; + + stringProps = malloc((nProps + BDF_GENPROPS) * sizeof(char)); + pFont->info.isStringProp = stringProps; + if (stringProps == NULL) { + bdfError("Couldn't allocate stringProps (%d*%d)\n", + (nProps + BDF_GENPROPS), (int) sizeof(Bool)); + goto BAILOUT; + } + pFont->info.props = props = calloc(nProps + BDF_GENPROPS, + sizeof(FontPropRec)); + if (props == NULL) { + bdfError("Couldn't allocate props (%d*%d)\n", nProps + BDF_GENPROPS, + (int) sizeof(FontPropRec)); + goto BAILOUT; + } + + nextProp = 0; + props_left = nProps; + while (props_left-- > 0) { + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (line == NULL || bdfIsPrefix(line, "ENDPROPERTIES")) { + bdfError("\"STARTPROPERTIES %d\" followed by only %d properties\n", + nProps, nProps - props_left - 1); + goto BAILOUT; + } + while (*line && isspace(*line)) + line++; + + switch (sscanf((char *) line, + BDFLINESTR BDFLINESTR BDFLINESTR, + namebuf, secondbuf, thirdbuf)) { + default: + bdfError("missing '%s' parameter value\n", namebuf); + goto BAILOUT; + + case 2: + /* + * Possibilites include: valid quoted string with no white space + * valid integer value invalid value + */ + if (secondbuf[0] == '"') { + stringProps[nextProp] = TRUE; + props[nextProp].value = + bdfGetPropertyValue((char *)line + strlen(namebuf) + 1); + if (!props[nextProp].value) + goto BAILOUT; + break; + } else if (bdfIsInteger(secondbuf)) { + stringProps[nextProp] = FALSE; + props[nextProp].value = atoi(secondbuf); + break; + } else { + bdfError("invalid '%s' parameter value\n", namebuf); + goto BAILOUT; + } + + case 3: + /* + * Possibilites include: valid quoted string with some white space + * invalid value (reject even if second string is integer) + */ + if (secondbuf[0] == '"') { + stringProps[nextProp] = TRUE; + props[nextProp].value = + bdfGetPropertyValue((char *)line + strlen(namebuf) + 1); + if (!props[nextProp].value) + goto BAILOUT; + break; + } else { + bdfError("invalid '%s' parameter value\n", namebuf); + goto BAILOUT; + } + } + props[nextProp].name = bdfForceMakeAtom(namebuf, NULL); + if (props[nextProp].name == None) { + bdfError("Empty property name.\n"); + goto BAILOUT; + } + if (!bdfSpecialProperty(pFont, &props[nextProp], + stringProps[nextProp], pState)) + nextProp++; + } + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || !bdfIsPrefix(line, "ENDPROPERTIES")) { + bdfError("missing 'ENDPROPERTIES'\n"); + goto BAILOUT; + } + if (!pState->haveFontAscent || !pState->haveFontDescent) { + bdfError("missing 'FONT_ASCENT' or 'FONT_DESCENT' properties\n"); + goto BAILOUT; + } + if (bitmapFont->bitmapExtra) { + bitmapFont->bitmapExtra->info.fontAscent = pFont->info.fontAscent; + bitmapFont->bitmapExtra->info.fontDescent = pFont->info.fontDescent; + } + if (!pState->pointSizeProp) { + props[nextProp].name = bdfForceMakeAtom("POINT_SIZE", NULL); + props[nextProp].value = (INT32) (pState->pointSize * 10.0); + stringProps[nextProp] = FALSE; + pState->pointSizeProp = &props[nextProp]; + nextProp++; + } + if (!pState->fontProp) { + props[nextProp].name = bdfForceMakeAtom("FONT", NULL); + props[nextProp].value = (INT32) bdfForceMakeAtom(pState->fontName, NULL); + stringProps[nextProp] = TRUE; + pState->fontProp = &props[nextProp]; + nextProp++; + } + if (!pState->weightProp) { + props[nextProp].name = bdfForceMakeAtom("WEIGHT", NULL); + props[nextProp].value = -1; /* computed later */ + stringProps[nextProp] = FALSE; + pState->weightProp = &props[nextProp]; + nextProp++; + } + if (!pState->resolutionProp && + pState->resolution_x == pState->resolution_y) { + props[nextProp].name = bdfForceMakeAtom("RESOLUTION", NULL); + props[nextProp].value = (INT32) ((pState->resolution_x * 100.0) / 72.27); + stringProps[nextProp] = FALSE; + pState->resolutionProp = &props[nextProp]; + nextProp++; + } + if (!pState->resolutionXProp) { + props[nextProp].name = bdfForceMakeAtom("RESOLUTION_X", NULL); + props[nextProp].value = (INT32) pState->resolution_x; + stringProps[nextProp] = FALSE; + pState->resolutionProp = &props[nextProp]; + nextProp++; + } + if (!pState->resolutionYProp) { + props[nextProp].name = bdfForceMakeAtom("RESOLUTION_Y", NULL); + props[nextProp].value = (INT32) pState->resolution_y; + stringProps[nextProp] = FALSE; + pState->resolutionProp = &props[nextProp]; + nextProp++; + } + if (!pState->xHeightProp) { + props[nextProp].name = bdfForceMakeAtom("X_HEIGHT", NULL); + props[nextProp].value = -1; /* computed later */ + stringProps[nextProp] = FALSE; + pState->xHeightProp = &props[nextProp]; + nextProp++; + } + if (!pState->quadWidthProp) { + props[nextProp].name = bdfForceMakeAtom("QUAD_WIDTH", NULL); + props[nextProp].value = -1; /* computed later */ + stringProps[nextProp] = FALSE; + pState->quadWidthProp = &props[nextProp]; + nextProp++; + } + pFont->info.nprops = nextProp; + return (TRUE); +BAILOUT: + if (pFont->info.isStringProp) { + free(pFont->info.isStringProp); + pFont->info.isStringProp = NULL; + } + if (pFont->info.props) { + free(pFont->info.props); + pFont->info.props = NULL; + } + while (line && bdfIsPrefix(line, "ENDPROPERTIES")) + line = bdfGetLine(file, lineBuf, BDFLINELEN); + return (FALSE); +} + +/***====================================================================***/ + +static void +bdfUnloadFont(FontPtr pFont) +{ + bdfFreeFontBits (pFont); + DestroyFontRec(pFont); +} + +int +bdfReadFont(FontPtr pFont, FontFilePtr file, + int bit, int byte, int glyph, int scan) +{ + bdfFileState state; + xCharInfo *min, + *max; + BitmapFontPtr bitmapFont; + + pFont->fontPrivate = 0; + + bzero(&state, sizeof(bdfFileState)); + bdfFileLineNum = 0; + + if (!bdfReadHeader(file, &state)) + goto BAILOUT; + + bitmapFont = calloc(1, sizeof(BitmapFontRec)); + if (!bitmapFont) { + bdfError("Couldn't allocate bitmapFontRec (%d)\n", + (int) sizeof(BitmapFontRec)); + goto BAILOUT; + } + + pFont->fontPrivate = (pointer) bitmapFont; + bitmapFont->metrics = 0; + bitmapFont->ink_metrics = 0; + bitmapFont->bitmaps = 0; + bitmapFont->encoding = 0; + bitmapFont->pDefault = NULL; + + bitmapFont->bitmapExtra = calloc(1, sizeof(BitmapExtraRec)); + if (!bitmapFont->bitmapExtra) { + bdfError("Couldn't allocate bitmapExtra (%d)\n", + (int) sizeof(BitmapExtraRec)); + goto BAILOUT; + } + + bitmapFont->bitmapExtra->glyphNames = 0; + bitmapFont->bitmapExtra->sWidths = 0; + + if (!bdfReadProperties(file, pFont, &state)) + goto BAILOUT; + + if (!bdfReadCharacters(file, pFont, &state, bit, byte, glyph, scan)) + goto BAILOUT; + + if (state.haveDefaultCh) { + unsigned int r, c, cols; + + r = pFont->info.defaultCh >> 8; + c = pFont->info.defaultCh & 0xFF; + if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && + pFont->info.firstCol <= c && c <= pFont->info.lastCol) { + cols = pFont->info.lastCol - pFont->info.firstCol + 1; + r = r - pFont->info.firstRow; + c = c - pFont->info.firstCol; + bitmapFont->pDefault = ACCESSENCODING(bitmapFont->encoding, + r * cols + c); + } + } + pFont->bit = bit; + pFont->byte = byte; + pFont->glyph = glyph; + pFont->scan = scan; + pFont->info.anamorphic = FALSE; + pFont->info.cachable = TRUE; + bitmapComputeFontBounds(pFont); + if (FontCouldBeTerminal(&pFont->info)) { + bdfPadToTerminal(pFont); + bitmapComputeFontBounds(pFont); + } + FontComputeInfoAccelerators(&pFont->info); + if (bitmapFont->bitmapExtra) + FontComputeInfoAccelerators(&bitmapFont->bitmapExtra->info); + if (pFont->info.constantMetrics) { + if (!bitmapAddInkMetrics(pFont)) { + bdfError("Failed to add bitmap ink metrics\n"); + goto BAILOUT; + } + } + if (bitmapFont->bitmapExtra) + bitmapFont->bitmapExtra->info.inkMetrics = pFont->info.inkMetrics; + + bitmapComputeFontInkBounds(pFont); +/* ComputeFontAccelerators (pFont); */ + + /* generate properties */ + min = &pFont->info.ink_minbounds; + max = &pFont->info.ink_maxbounds; + if (state.xHeightProp && (state.xHeightProp->value == -1)) + state.xHeightProp->value = state.exHeight ? + state.exHeight : min->ascent; + + if (state.quadWidthProp && (state.quadWidthProp->value == -1)) + state.quadWidthProp->value = state.digitCount ? + (INT32) (state.digitWidths / state.digitCount) : + (min->characterWidth + max->characterWidth) / 2; + + if (state.weightProp && (state.weightProp->value == -1)) + state.weightProp->value = bitmapComputeWeight(pFont); + + pFont->get_glyphs = bitmapGetGlyphs; + pFont->get_metrics = bitmapGetMetrics; + pFont->unload_font = bdfUnloadFont; + pFont->unload_glyphs = NULL; + return Successful; +BAILOUT: + if (pFont->fontPrivate) + bdfFreeFontBits (pFont); + return AllocError; +} + +int +bdfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) +{ + FontRec font; + int ret; + + bzero(&font, sizeof (FontRec)); + + ret = bdfReadFont(&font, file, MSBFirst, LSBFirst, 1, 1); + if (ret == Successful) { + *pFontInfo = font.info; + font.info.props = 0; + font.info.isStringProp = 0; + font.info.nprops = 0; + bdfFreeFontBits (&font); + } + return ret; +} + +static Bool +bdfPadToTerminal(FontPtr pFont) +{ + BitmapFontPtr bitmapFont; + BitmapExtraPtr bitmapExtra; + int i; + int new_size; + CharInfoRec new; + int w, + h; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + + bzero(&new, sizeof(CharInfoRec)); + new.metrics.ascent = pFont->info.fontAscent; + new.metrics.descent = pFont->info.fontDescent; + new.metrics.leftSideBearing = 0; + new.metrics.rightSideBearing = pFont->info.minbounds.characterWidth; + new.metrics.characterWidth = new.metrics.rightSideBearing; + new_size = BYTES_FOR_GLYPH(&new, pFont->glyph); + + for (i = 0; i < bitmapFont->num_chars; i++) { + new.bits = malloc(new_size); + if (!new.bits) { + bdfError("Couldn't allocate bits (%d)\n", new_size); + return FALSE; + } + FontCharReshape(pFont, &bitmapFont->metrics[i], &new); + new.metrics.attributes = bitmapFont->metrics[i].metrics.attributes; + free(bitmapFont->metrics[i].bits); + bitmapFont->metrics[i] = new; + } + bitmapExtra = bitmapFont->bitmapExtra; + if (bitmapExtra) { + w = GLYPHWIDTHPIXELS(&new); + h = GLYPHHEIGHTPIXELS(&new); + for (i = 0; i < GLYPHPADOPTIONS; i++) + bitmapExtra->bitmapsSizes[i] = bitmapFont->num_chars * + (BYTES_PER_ROW(w, 1 << i) * h); + } + return TRUE; +} |