diff options
Diffstat (limited to 'mkfontscale/ident.c')
-rw-r--r-- | mkfontscale/ident.c | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/mkfontscale/ident.c b/mkfontscale/ident.c new file mode 100644 index 000000000..544583398 --- /dev/null +++ b/mkfontscale/ident.c @@ -0,0 +1,458 @@ +/* + Copyright (c) 2003 by Juliusz Chroboczek + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + 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 + AUTHORS OR COPYRIGHT HOLDERS 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. +*/ +/* Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * 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 + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. + * + * Except as contained in this notice, the name of a copyright holder + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * of the copyright holder. + */ +/* $XFree86: xc/programs/mkfontscale/ident.c,v 1.3tsi Exp $ */ + +/* The function identifyBitmap returns -1 if filename is definitively not + a font file, 1 if it is a single-face bitmap font with a XLFD name, + and 0 if it should be processed normally. identifyBitmap is + much faster than parsing the whole font. */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> +#include "zlib.h" +#include "ident.h" + +#ifdef X_BZIP2_FONT_COMPRESSION +# include <bzlib.h> +#endif + +#define PCF_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1) +#define PCF_PROPERTIES (1 << 0) + +typedef struct _Prop { + unsigned name; + int isString; + unsigned value; +} PropRec, *PropPtr; + +#ifdef X_BZIP2_FONT_COMPRESSION +typedef struct { + enum { gzFontFile, bz2FontFile } type; + union { + gzFile gz; + BZFILE *bz2; + } f; + unsigned pos; +} fontFile; + +static inline void * +fontFileOpen(fontFile *ff, const char *filename) { + int n = strlen(filename); + + if (strcmp(filename + n - 4, ".bz2") == 0) { + ff->type = bz2FontFile; + ff->f.bz2 = BZ2_bzopen(filename, "rb"); + ff->pos = 0; + return ff->f.bz2; + } else { + ff->type = gzFontFile; + ff->f.gz = gzopen(filename, "rb"); + return ff->f.gz; + } +} + +static inline int +fontFileRead(fontFile *ff, void *buf, unsigned len) +{ + if (ff->type == gzFontFile) { + return gzread(ff->f.gz, buf, len); + } else { + int r = BZ2_bzread(ff->f.bz2, buf, len); + ff->pos += r; + return r; + } +} + +static inline int +fontFileGetc(fontFile *ff) +{ + if (ff->type == gzFontFile) { + return gzgetc(ff->f.gz); + } else { + char buf; + if (BZ2_bzread(ff->f.bz2, &buf, 1) != 1) { + return -1; + } else { + ff->pos += 1; + return (int) buf; + } + } +} + +static int +fontFileSeek(fontFile *ff, z_off_t offset, int whence) +{ + if (ff->type == gzFontFile) { + return gzseek(ff->f.gz, offset, whence); + } else { + /* bzlib has no easy equivalent so we have to fake it, + * fortunately, we only have to handle a couple of cases + */ + int n; + char buf[BUFSIZ]; + + switch (whence) { + case SEEK_SET: + n = offset - ff->pos; + break; + case SEEK_CUR: + n = offset; + break; + default: + return -1; + } + + while (n > BUFSIZ) { + if (BZ2_bzread(ff->f.bz2, buf, BUFSIZ) != BUFSIZ) + return -1; + n -= BUFSIZ; + } + if (BZ2_bzread(ff->f.bz2, buf, n) != n) + return -1; + ff->pos = offset; + return offset; + } +} + + +static inline int +fontFileClose(fontFile *ff) +{ + if (ff->type == gzFontFile) { + return gzclose(ff->f.gz); + } else { + BZ2_bzclose(ff->f.bz2); + return 0; + } +} + +#else /* no bzip2, only gzip */ +typedef gzFile fontFile; +# define fontFileOpen(ff, filename) (*(ff) = gzopen(filename, "rb")) +# define fontFileRead(ff, buf, len) gzread(*(ff), buf, len) +# define fontFileGetc(ff) gzgetc(*(ff)) +# define fontFileSeek(ff, off, whence) gzseek(*(ff), off, whence) +# define fontFileClose(ff) gzclose(*(ff)) +#endif + +static int pcfIdentify(fontFile *f, char **name); +static int bdfIdentify(fontFile *f, char **name); + +static int +getLSB32(fontFile *f) +{ + int rc; + unsigned char c[4]; + + rc = fontFileRead(f, c, 4); + if(rc != 4) + return -1; + return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); +} + +static int +getInt8(fontFile *f, int format) +{ + unsigned char c; + int rc; + + rc = fontFileRead(f, &c, 1); + if(rc != 1) + return -1; + return c; +} + +static int +getInt32(fontFile *f, int format) +{ + int rc; + unsigned char c[4]; + + rc = fontFileRead(f, c, 4); + if(rc != 4) + return -1; + + if(format & (1 << 2)) { + return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | (c[3]); + } else { + return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); + } +} + +int +bitmapIdentify(const char *filename, char **name) +{ + fontFile ff; + int magic; + + if (fontFileOpen(&ff, filename) == NULL) + return -1; + + magic = getLSB32(&ff); + if(magic == PCF_VERSION) + return pcfIdentify(&ff, name); + else if(magic == ('S' | ('T' << 8) | ('A' << 16) | ('R') << 24)) + return bdfIdentify(&ff, name); + + fontFileClose(&ff); + return 0; +} + +static int +pcfIdentify(fontFile *f, char **name) +{ + int prop_position; + PropPtr props = NULL; + int format, count, nprops, i, string_size, rc; + char *strings = NULL, *s; + + count = getLSB32(f); + if(count <= 0) + goto fail; + + prop_position = -1; + for(i = 0; i < count; i++) { + int type, offset; + type = getLSB32(f); + (void) getLSB32(f); + (void) getLSB32(f); + offset = getLSB32(f); + if(type == PCF_PROPERTIES) { + prop_position = offset; + break; + } + } + if(prop_position < 0) + goto fail; + + rc = fontFileSeek(f, prop_position, SEEK_SET); + if(rc < 0) + goto fail; + + format = getLSB32(f); + if((format & 0xFFFFFF00) != 0) + goto fail; + nprops = getInt32(f, format); + if(nprops <= 0 || nprops > 1000) + goto fail; + props = malloc(nprops * sizeof(PropRec)); + if(props == NULL) + goto fail; + + for(i = 0; i < nprops; i++) { + props[i].name = getInt32(f, format); + props[i].isString = getInt8(f, format); + props[i].value = getInt32(f, format); + } + if(nprops & 3) { + rc = fontFileSeek(f, 4 - (nprops & 3), SEEK_CUR); + if(rc < 0) + goto fail; + } + + string_size = getInt32(f, format); + if(string_size < 0 || string_size > 100000) + goto fail; + strings = malloc(string_size); + if(!strings) + goto fail; + + rc = fontFileRead(f, strings, string_size); + if(rc != string_size) + goto fail; + + for(i = 0; i < nprops; i++) { + if(!props[i].isString || + props[i].name >= string_size - 4 || + props[i].value >= string_size) + continue; + if(strcmp(strings + props[i].name, "FONT") == 0) + break; + } + + if(i >= nprops) + goto fail; + + s = malloc(strlen(strings + props[i].value) + 1); + if(s == NULL) + goto fail; + strcpy(s, strings + props[i].value); + *name = s; + free(strings); + free(props); + fontFileClose(f); + return 1; + + fail: + if(strings) free(strings); + if(props) free(props); + fontFileClose(f); + return 0; +} + +#define NKEY 20 + +static char* +getKeyword(fontFile *f, int *eol) +{ + static char keyword[NKEY + 1]; + int c, i; + i = 0; + while(i < NKEY) { + c = fontFileGetc(f); + if(c == ' ' || c == '\n') { + if(i <= 0) + return NULL; + if(eol) + *eol = (c == '\n'); + keyword[i] = '\0'; + return keyword; + } + if(c < 'A' || c > 'Z') + return NULL; + keyword[i++] = c; + } + return NULL; +} + +static int +bdfskip(fontFile *f) +{ + int c; + do { + c = fontFileGetc(f); + } while(c >= 0 && c != '\n'); + if(c < 0) + return -1; + return 1; +} + +static char * +bdfend(fontFile *f) +{ + int c; + char *buf = NULL; + int bufsize = 0; + int i = 0; + + do { + c = fontFileGetc(f); + } while (c == ' '); + + while(i < 1000) { + if(c < 0 || (c == '\n' && i == 0)) { + goto fail; + } + if(bufsize < i + 1) { + char *newbuf; + if(bufsize == 0) { + bufsize = 20; + newbuf = malloc(bufsize); + } else { + bufsize = 2 * bufsize; + newbuf = realloc(buf, bufsize); + } + if(newbuf == NULL) + goto fail; + buf = newbuf; + } + if(c == '\n') { + buf[i] = '\0'; + return buf; + } + buf[i++] = c; + c = fontFileGetc(f); + } + + fail: + if(buf) + free(buf); + return NULL; +} + +static int +bdfIdentify(fontFile *f, char **name) +{ + char *k; + int rc; + int eol; + /* bitmapIdentify already read "STAR", so we need to check for + "TFONT" */ + k = getKeyword(f, &eol); + if(k == NULL || eol) + goto fail; + if(strcmp(k, "TFONT") != 0) + goto fail; + while(1) { + if(!eol) { + rc = bdfskip(f); + if(rc < 0) + goto fail; + } + k = getKeyword(f, &eol); + if(k == NULL) + goto fail; + else if(strcmp(k, "FONT") == 0) { + if(eol) + goto fail; + k = bdfend(f); + if(k == NULL) + goto fail; + *name = k; + fontFileClose(f); + return 1; + } else if(strcmp(k, "CHARS") == 0) + goto fail; + } + fail: + fontFileClose(f); + return 0; +} |