ident.c revision 45a6f659
1ea6ae205Smrg/* 2ea6ae205Smrg Copyright (c) 2003 by Juliusz Chroboczek 3ea6ae205Smrg 4ea6ae205Smrg Permission is hereby granted, free of charge, to any person obtaining a copy 5ea6ae205Smrg of this software and associated documentation files (the "Software"), to deal 6ea6ae205Smrg in the Software without restriction, including without limitation the rights 7ea6ae205Smrg to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8ea6ae205Smrg copies of the Software, and to permit persons to whom the Software is 9ea6ae205Smrg furnished to do so, subject to the following conditions: 10ea6ae205Smrg 11ea6ae205Smrg The above copyright notice and this permission notice shall be included in 12ea6ae205Smrg all copies or substantial portions of the Software. 13ea6ae205Smrg 14ea6ae205Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15ea6ae205Smrg IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16ea6ae205Smrg FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17ea6ae205Smrg AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18ea6ae205Smrg LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19ea6ae205Smrg OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20ea6ae205Smrg THE SOFTWARE. 21ea6ae205Smrg*/ 227978d3cdSmrg/* Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237978d3cdSmrg * 247978d3cdSmrg * Permission is hereby granted, free of charge, to any person obtaining a 257978d3cdSmrg * copy of this software and associated documentation files (the 267978d3cdSmrg * "Software"), to deal in the Software without restriction, including 277978d3cdSmrg * without limitation the rights to use, copy, modify, merge, publish, 287978d3cdSmrg * distribute, and/or sell copies of the Software, and to permit persons 297978d3cdSmrg * to whom the Software is furnished to do so, provided that the above 307978d3cdSmrg * copyright notice(s) and this permission notice appear in all copies of 317978d3cdSmrg * the Software and that both the above copyright notice(s) and this 327978d3cdSmrg * permission notice appear in supporting documentation. 337978d3cdSmrg * 347978d3cdSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 357978d3cdSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 367978d3cdSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 377978d3cdSmrg * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 387978d3cdSmrg * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 397978d3cdSmrg * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 407978d3cdSmrg * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 417978d3cdSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 427978d3cdSmrg * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 437978d3cdSmrg * 447978d3cdSmrg * Except as contained in this notice, the name of a copyright holder 457978d3cdSmrg * shall not be used in advertising or otherwise to promote the sale, use 467978d3cdSmrg * or other dealings in this Software without prior written authorization 477978d3cdSmrg * of the copyright holder. 487978d3cdSmrg */ 49ea6ae205Smrg/* $XFree86: xc/programs/mkfontscale/ident.c,v 1.3tsi Exp $ */ 50ea6ae205Smrg 51ea6ae205Smrg/* The function identifyBitmap returns -1 if filename is definitively not 52ea6ae205Smrg a font file, 1 if it is a single-face bitmap font with a XLFD name, 53ea6ae205Smrg and 0 if it should be processed normally. identifyBitmap is 54ea6ae205Smrg much faster than parsing the whole font. */ 55ea6ae205Smrg 5645a6f659Smrg#ifdef HAVE_CONFIG_H 577978d3cdSmrg#include "config.h" 5845a6f659Smrg#endif 597978d3cdSmrg 60ea6ae205Smrg#include <stdlib.h> 61ea6ae205Smrg#include <string.h> 62ea6ae205Smrg#include "zlib.h" 63ea6ae205Smrg#include "ident.h" 64ea6ae205Smrg 657978d3cdSmrg#ifdef X_BZIP2_FONT_COMPRESSION 667978d3cdSmrg# include <bzlib.h> 677978d3cdSmrg#endif 687978d3cdSmrg 69ea6ae205Smrg#define PCF_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1) 70ea6ae205Smrg#define PCF_PROPERTIES (1 << 0) 71ea6ae205Smrg 72ea6ae205Smrgtypedef struct _Prop { 73ea6ae205Smrg unsigned name; 74ea6ae205Smrg int isString; 75ea6ae205Smrg unsigned value; 76ea6ae205Smrg} PropRec, *PropPtr; 77ea6ae205Smrg 787978d3cdSmrg#ifdef X_BZIP2_FONT_COMPRESSION 797978d3cdSmrgtypedef struct { 807978d3cdSmrg enum { gzFontFile, bz2FontFile } type; 817978d3cdSmrg union { 827978d3cdSmrg gzFile gz; 837978d3cdSmrg BZFILE *bz2; 847978d3cdSmrg } f; 857978d3cdSmrg unsigned pos; 867978d3cdSmrg} fontFile; 877978d3cdSmrg 887978d3cdSmrgstatic inline void * 897978d3cdSmrgfontFileOpen(fontFile *ff, const char *filename) { 907978d3cdSmrg int n = strlen(filename); 917978d3cdSmrg 927978d3cdSmrg if (strcmp(filename + n - 4, ".bz2") == 0) { 937978d3cdSmrg ff->type = bz2FontFile; 947978d3cdSmrg ff->f.bz2 = BZ2_bzopen(filename, "rb"); 957978d3cdSmrg ff->pos = 0; 967978d3cdSmrg return ff->f.bz2; 977978d3cdSmrg } else { 987978d3cdSmrg ff->type = gzFontFile; 997978d3cdSmrg ff->f.gz = gzopen(filename, "rb"); 1007978d3cdSmrg return ff->f.gz; 1017978d3cdSmrg } 1027978d3cdSmrg} 1037978d3cdSmrg 1047978d3cdSmrgstatic inline int 1057978d3cdSmrgfontFileRead(fontFile *ff, void *buf, unsigned len) 1067978d3cdSmrg{ 1077978d3cdSmrg if (ff->type == gzFontFile) { 1087978d3cdSmrg return gzread(ff->f.gz, buf, len); 1097978d3cdSmrg } else { 1107978d3cdSmrg int r = BZ2_bzread(ff->f.bz2, buf, len); 1117978d3cdSmrg ff->pos += r; 1127978d3cdSmrg return r; 1137978d3cdSmrg } 1147978d3cdSmrg} 1157978d3cdSmrg 1167978d3cdSmrgstatic inline int 1177978d3cdSmrgfontFileGetc(fontFile *ff) 1187978d3cdSmrg{ 1197978d3cdSmrg if (ff->type == gzFontFile) { 1207978d3cdSmrg return gzgetc(ff->f.gz); 1217978d3cdSmrg } else { 1227978d3cdSmrg char buf; 1237978d3cdSmrg if (BZ2_bzread(ff->f.bz2, &buf, 1) != 1) { 1247978d3cdSmrg return -1; 1257978d3cdSmrg } else { 1267978d3cdSmrg ff->pos += 1; 1277978d3cdSmrg return (int) buf; 1287978d3cdSmrg } 1297978d3cdSmrg } 1307978d3cdSmrg} 1317978d3cdSmrg 1327978d3cdSmrgstatic int 1337978d3cdSmrgfontFileSeek(fontFile *ff, z_off_t offset, int whence) 1347978d3cdSmrg{ 1357978d3cdSmrg if (ff->type == gzFontFile) { 1367978d3cdSmrg return gzseek(ff->f.gz, offset, whence); 1377978d3cdSmrg } else { 1387978d3cdSmrg /* bzlib has no easy equivalent so we have to fake it, 1397978d3cdSmrg * fortunately, we only have to handle a couple of cases 1407978d3cdSmrg */ 1417978d3cdSmrg int n; 1427978d3cdSmrg char buf[BUFSIZ]; 1437978d3cdSmrg 1447978d3cdSmrg switch (whence) { 1457978d3cdSmrg case SEEK_SET: 1467978d3cdSmrg n = offset - ff->pos; 1477978d3cdSmrg break; 1487978d3cdSmrg case SEEK_CUR: 1497978d3cdSmrg n = offset; 1507978d3cdSmrg break; 1517978d3cdSmrg default: 1527978d3cdSmrg return -1; 1537978d3cdSmrg } 1547978d3cdSmrg 1557978d3cdSmrg while (n > BUFSIZ) { 1567978d3cdSmrg if (BZ2_bzread(ff->f.bz2, buf, BUFSIZ) != BUFSIZ) 1577978d3cdSmrg return -1; 1587978d3cdSmrg n -= BUFSIZ; 1597978d3cdSmrg } 1607978d3cdSmrg if (BZ2_bzread(ff->f.bz2, buf, n) != n) 1617978d3cdSmrg return -1; 1627978d3cdSmrg ff->pos = offset; 1637978d3cdSmrg return offset; 1647978d3cdSmrg } 1657978d3cdSmrg} 1667978d3cdSmrg 1677978d3cdSmrg 1687978d3cdSmrgstatic inline int 1697978d3cdSmrgfontFileClose(fontFile *ff) 1707978d3cdSmrg{ 1717978d3cdSmrg if (ff->type == gzFontFile) { 1727978d3cdSmrg return gzclose(ff->f.gz); 1737978d3cdSmrg } else { 1747978d3cdSmrg BZ2_bzclose(ff->f.bz2); 1757978d3cdSmrg return 0; 1767978d3cdSmrg } 1777978d3cdSmrg} 1787978d3cdSmrg 1797978d3cdSmrg#else /* no bzip2, only gzip */ 1807978d3cdSmrgtypedef gzFile fontFile; 1817978d3cdSmrg# define fontFileOpen(ff, filename) (*(ff) = gzopen(filename, "rb")) 1827978d3cdSmrg# define fontFileRead(ff, buf, len) gzread(*(ff), buf, len) 1837978d3cdSmrg# define fontFileGetc(ff) gzgetc(*(ff)) 1847978d3cdSmrg# define fontFileSeek(ff, off, whence) gzseek(*(ff), off, whence) 1857978d3cdSmrg# define fontFileClose(ff) gzclose(*(ff)) 1867978d3cdSmrg#endif 1877978d3cdSmrg 1887978d3cdSmrgstatic int pcfIdentify(fontFile *f, char **name); 1897978d3cdSmrgstatic int bdfIdentify(fontFile *f, char **name); 190ea6ae205Smrg 191ea6ae205Smrgstatic int 1927978d3cdSmrggetLSB32(fontFile *f) 193ea6ae205Smrg{ 194ea6ae205Smrg int rc; 195ea6ae205Smrg unsigned char c[4]; 196ea6ae205Smrg 1977978d3cdSmrg rc = fontFileRead(f, c, 4); 198ea6ae205Smrg if(rc != 4) 199ea6ae205Smrg return -1; 200ea6ae205Smrg return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); 201ea6ae205Smrg} 202ea6ae205Smrg 203ea6ae205Smrgstatic int 2047978d3cdSmrggetInt8(fontFile *f, int format) 205ea6ae205Smrg{ 206ea6ae205Smrg unsigned char c; 207ea6ae205Smrg int rc; 208ea6ae205Smrg 2097978d3cdSmrg rc = fontFileRead(f, &c, 1); 210ea6ae205Smrg if(rc != 1) 211ea6ae205Smrg return -1; 212ea6ae205Smrg return c; 213ea6ae205Smrg} 214ea6ae205Smrg 215ea6ae205Smrgstatic int 2167978d3cdSmrggetInt32(fontFile *f, int format) 217ea6ae205Smrg{ 218ea6ae205Smrg int rc; 219ea6ae205Smrg unsigned char c[4]; 220ea6ae205Smrg 2217978d3cdSmrg rc = fontFileRead(f, c, 4); 222ea6ae205Smrg if(rc != 4) 223ea6ae205Smrg return -1; 224ea6ae205Smrg 225ea6ae205Smrg if(format & (1 << 2)) { 226ea6ae205Smrg return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | (c[3]); 227ea6ae205Smrg } else { 228ea6ae205Smrg return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); 229ea6ae205Smrg } 230ea6ae205Smrg} 231ea6ae205Smrg 232ea6ae205Smrgint 2337978d3cdSmrgbitmapIdentify(const char *filename, char **name) 234ea6ae205Smrg{ 2357978d3cdSmrg fontFile ff; 236ea6ae205Smrg int magic; 237ea6ae205Smrg 2387978d3cdSmrg if (fontFileOpen(&ff, filename) == NULL) 2397978d3cdSmrg return -1; 240ea6ae205Smrg 2417978d3cdSmrg magic = getLSB32(&ff); 242ea6ae205Smrg if(magic == PCF_VERSION) 2437978d3cdSmrg return pcfIdentify(&ff, name); 244ea6ae205Smrg else if(magic == ('S' | ('T' << 8) | ('A' << 16) | ('R') << 24)) 2457978d3cdSmrg return bdfIdentify(&ff, name); 246ea6ae205Smrg 2477978d3cdSmrg fontFileClose(&ff); 248ea6ae205Smrg return 0; 249ea6ae205Smrg} 250ea6ae205Smrg 251ea6ae205Smrgstatic int 2527978d3cdSmrgpcfIdentify(fontFile *f, char **name) 253ea6ae205Smrg{ 254ea6ae205Smrg int prop_position; 255ea6ae205Smrg PropPtr props = NULL; 256ea6ae205Smrg int format, count, nprops, i, string_size, rc; 257ea6ae205Smrg char *strings = NULL, *s; 258ea6ae205Smrg 259ea6ae205Smrg count = getLSB32(f); 260ea6ae205Smrg if(count <= 0) 261ea6ae205Smrg goto fail; 262ea6ae205Smrg 263ea6ae205Smrg prop_position = -1; 264ea6ae205Smrg for(i = 0; i < count; i++) { 265ea6ae205Smrg int type, offset; 266ea6ae205Smrg type = getLSB32(f); 267ea6ae205Smrg (void) getLSB32(f); 268ea6ae205Smrg (void) getLSB32(f); 269ea6ae205Smrg offset = getLSB32(f); 270ea6ae205Smrg if(type == PCF_PROPERTIES) { 271ea6ae205Smrg prop_position = offset; 272ea6ae205Smrg break; 273ea6ae205Smrg } 274ea6ae205Smrg } 275ea6ae205Smrg if(prop_position < 0) 276ea6ae205Smrg goto fail; 277ea6ae205Smrg 2787978d3cdSmrg rc = fontFileSeek(f, prop_position, SEEK_SET); 279ea6ae205Smrg if(rc < 0) 280ea6ae205Smrg goto fail; 281ea6ae205Smrg 282ea6ae205Smrg format = getLSB32(f); 283ea6ae205Smrg if((format & 0xFFFFFF00) != 0) 284ea6ae205Smrg goto fail; 285ea6ae205Smrg nprops = getInt32(f, format); 286ea6ae205Smrg if(nprops <= 0 || nprops > 1000) 287ea6ae205Smrg goto fail; 288ea6ae205Smrg props = malloc(nprops * sizeof(PropRec)); 289ea6ae205Smrg if(props == NULL) 290ea6ae205Smrg goto fail; 291ea6ae205Smrg 292ea6ae205Smrg for(i = 0; i < nprops; i++) { 293ea6ae205Smrg props[i].name = getInt32(f, format); 294ea6ae205Smrg props[i].isString = getInt8(f, format); 295ea6ae205Smrg props[i].value = getInt32(f, format); 296ea6ae205Smrg } 297ea6ae205Smrg if(nprops & 3) { 2987978d3cdSmrg rc = fontFileSeek(f, 4 - (nprops & 3), SEEK_CUR); 299ea6ae205Smrg if(rc < 0) 300ea6ae205Smrg goto fail; 301ea6ae205Smrg } 302ea6ae205Smrg 303ea6ae205Smrg string_size = getInt32(f, format); 304ea6ae205Smrg if(string_size < 0 || string_size > 100000) 305ea6ae205Smrg goto fail; 306ea6ae205Smrg strings = malloc(string_size); 307ea6ae205Smrg if(!strings) 308ea6ae205Smrg goto fail; 309ea6ae205Smrg 3107978d3cdSmrg rc = fontFileRead(f, strings, string_size); 311ea6ae205Smrg if(rc != string_size) 312ea6ae205Smrg goto fail; 313ea6ae205Smrg 314ea6ae205Smrg for(i = 0; i < nprops; i++) { 315ea6ae205Smrg if(!props[i].isString || 316ea6ae205Smrg props[i].name >= string_size - 4 || 317ea6ae205Smrg props[i].value >= string_size) 318ea6ae205Smrg continue; 319ea6ae205Smrg if(strcmp(strings + props[i].name, "FONT") == 0) 320ea6ae205Smrg break; 321ea6ae205Smrg } 322ea6ae205Smrg 323ea6ae205Smrg if(i >= nprops) 324ea6ae205Smrg goto fail; 325ea6ae205Smrg 326ea6ae205Smrg s = malloc(strlen(strings + props[i].value) + 1); 327ea6ae205Smrg if(s == NULL) 328ea6ae205Smrg goto fail; 329ea6ae205Smrg strcpy(s, strings + props[i].value); 330ea6ae205Smrg *name = s; 331ea6ae205Smrg free(strings); 332ea6ae205Smrg free(props); 3337978d3cdSmrg fontFileClose(f); 334ea6ae205Smrg return 1; 335ea6ae205Smrg 336ea6ae205Smrg fail: 337ea6ae205Smrg if(strings) free(strings); 338ea6ae205Smrg if(props) free(props); 3397978d3cdSmrg fontFileClose(f); 340ea6ae205Smrg return 0; 341ea6ae205Smrg} 342ea6ae205Smrg 343ea6ae205Smrg#define NKEY 20 344ea6ae205Smrg 345ea6ae205Smrgstatic char* 3467978d3cdSmrggetKeyword(fontFile *f, int *eol) 347ea6ae205Smrg{ 348ea6ae205Smrg static char keyword[NKEY + 1]; 349ea6ae205Smrg int c, i; 350ea6ae205Smrg i = 0; 351ea6ae205Smrg while(i < NKEY) { 3527978d3cdSmrg c = fontFileGetc(f); 353ea6ae205Smrg if(c == ' ' || c == '\n') { 354ea6ae205Smrg if(i <= 0) 355ea6ae205Smrg return NULL; 356ea6ae205Smrg if(eol) 357ea6ae205Smrg *eol = (c == '\n'); 358ea6ae205Smrg keyword[i] = '\0'; 359ea6ae205Smrg return keyword; 360ea6ae205Smrg } 361ea6ae205Smrg if(c < 'A' || c > 'Z') 362ea6ae205Smrg return NULL; 363ea6ae205Smrg keyword[i++] = c; 364ea6ae205Smrg } 365ea6ae205Smrg return NULL; 366ea6ae205Smrg} 367ea6ae205Smrg 368ea6ae205Smrgstatic int 3697978d3cdSmrgbdfskip(fontFile *f) 370ea6ae205Smrg{ 371ea6ae205Smrg int c; 372ea6ae205Smrg do { 3737978d3cdSmrg c = fontFileGetc(f); 374ea6ae205Smrg } while(c >= 0 && c != '\n'); 375ea6ae205Smrg if(c < 0) 376ea6ae205Smrg return -1; 377ea6ae205Smrg return 1; 378ea6ae205Smrg} 379ea6ae205Smrg 380ea6ae205Smrgstatic char * 3817978d3cdSmrgbdfend(fontFile *f) 382ea6ae205Smrg{ 383ea6ae205Smrg int c; 384ea6ae205Smrg char *buf = NULL; 385ea6ae205Smrg int bufsize = 0; 386ea6ae205Smrg int i = 0; 387ea6ae205Smrg 388ea6ae205Smrg do { 3897978d3cdSmrg c = fontFileGetc(f); 390ea6ae205Smrg } while (c == ' '); 391ea6ae205Smrg 392ea6ae205Smrg while(i < 1000) { 393ea6ae205Smrg if(c < 0 || (c == '\n' && i == 0)) { 394ea6ae205Smrg goto fail; 395ea6ae205Smrg } 396ea6ae205Smrg if(bufsize < i + 1) { 397ea6ae205Smrg char *newbuf; 398ea6ae205Smrg if(bufsize == 0) { 399ea6ae205Smrg bufsize = 20; 400ea6ae205Smrg newbuf = malloc(bufsize); 401ea6ae205Smrg } else { 402ea6ae205Smrg bufsize = 2 * bufsize; 403ea6ae205Smrg newbuf = realloc(buf, bufsize); 404ea6ae205Smrg } 405ea6ae205Smrg if(newbuf == NULL) 406ea6ae205Smrg goto fail; 407ea6ae205Smrg buf = newbuf; 408ea6ae205Smrg } 409ea6ae205Smrg if(c == '\n') { 410ea6ae205Smrg buf[i] = '\0'; 411ea6ae205Smrg return buf; 412ea6ae205Smrg } 413ea6ae205Smrg buf[i++] = c; 4147978d3cdSmrg c = fontFileGetc(f); 415ea6ae205Smrg } 416ea6ae205Smrg 417ea6ae205Smrg fail: 418ea6ae205Smrg if(buf) 419ea6ae205Smrg free(buf); 420ea6ae205Smrg return NULL; 421ea6ae205Smrg} 422ea6ae205Smrg 423ea6ae205Smrgstatic int 4247978d3cdSmrgbdfIdentify(fontFile *f, char **name) 425ea6ae205Smrg{ 426ea6ae205Smrg char *k; 427ea6ae205Smrg int rc; 428ea6ae205Smrg int eol; 429ea6ae205Smrg /* bitmapIdentify already read "STAR", so we need to check for 430ea6ae205Smrg "TFONT" */ 431ea6ae205Smrg k = getKeyword(f, &eol); 432ea6ae205Smrg if(k == NULL || eol) 433ea6ae205Smrg goto fail; 434ea6ae205Smrg if(strcmp(k, "TFONT") != 0) 435ea6ae205Smrg goto fail; 436ea6ae205Smrg while(1) { 437ea6ae205Smrg if(!eol) { 438ea6ae205Smrg rc = bdfskip(f); 439ea6ae205Smrg if(rc < 0) 440ea6ae205Smrg goto fail; 441ea6ae205Smrg } 442ea6ae205Smrg k = getKeyword(f, &eol); 443ea6ae205Smrg if(k == NULL) 444ea6ae205Smrg goto fail; 445ea6ae205Smrg else if(strcmp(k, "FONT") == 0) { 446ea6ae205Smrg if(eol) 447ea6ae205Smrg goto fail; 448ea6ae205Smrg k = bdfend(f); 449ea6ae205Smrg if(k == NULL) 450ea6ae205Smrg goto fail; 451ea6ae205Smrg *name = k; 4527978d3cdSmrg fontFileClose(f); 453ea6ae205Smrg return 1; 454ea6ae205Smrg } else if(strcmp(k, "CHARS") == 0) 455ea6ae205Smrg goto fail; 456ea6ae205Smrg } 457ea6ae205Smrg fail: 4587978d3cdSmrg fontFileClose(f); 459ea6ae205Smrg return 0; 460ea6ae205Smrg} 461