ident.c revision 7978d3cd
1/* 2 Copyright (c) 2003 by Juliusz Chroboczek 3 4 Permission is hereby granted, free of charge, to any person obtaining a copy 5 of this software and associated documentation files (the "Software"), to deal 6 in the Software without restriction, including without limitation the rights 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 copies of the Software, and to permit persons to whom the Software is 9 furnished to do so, subject to the following conditions: 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 THE SOFTWARE. 21*/ 22/* Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * 24 * Permission is hereby granted, free of charge, to any person obtaining a 25 * copy of this software and associated documentation files (the 26 * "Software"), to deal in the Software without restriction, including 27 * without limitation the rights to use, copy, modify, merge, publish, 28 * distribute, and/or sell copies of the Software, and to permit persons 29 * to whom the Software is furnished to do so, provided that the above 30 * copyright notice(s) and this permission notice appear in all copies of 31 * the Software and that both the above copyright notice(s) and this 32 * permission notice appear in supporting documentation. 33 * 34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 35 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 36 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 37 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 38 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 39 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 40 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 41 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 42 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 43 * 44 * Except as contained in this notice, the name of a copyright holder 45 * shall not be used in advertising or otherwise to promote the sale, use 46 * or other dealings in this Software without prior written authorization 47 * of the copyright holder. 48 */ 49/* $XFree86: xc/programs/mkfontscale/ident.c,v 1.3tsi Exp $ */ 50 51/* The function identifyBitmap returns -1 if filename is definitively not 52 a font file, 1 if it is a single-face bitmap font with a XLFD name, 53 and 0 if it should be processed normally. identifyBitmap is 54 much faster than parsing the whole font. */ 55 56#include "config.h" 57 58#include <stdlib.h> 59#include <string.h> 60#include "zlib.h" 61#include "ident.h" 62 63#ifdef X_BZIP2_FONT_COMPRESSION 64# include <bzlib.h> 65#endif 66 67#define PCF_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1) 68#define PCF_PROPERTIES (1 << 0) 69 70typedef struct _Prop { 71 unsigned name; 72 int isString; 73 unsigned value; 74} PropRec, *PropPtr; 75 76#ifdef X_BZIP2_FONT_COMPRESSION 77typedef struct { 78 enum { gzFontFile, bz2FontFile } type; 79 union { 80 gzFile gz; 81 BZFILE *bz2; 82 } f; 83 unsigned pos; 84} fontFile; 85 86static inline void * 87fontFileOpen(fontFile *ff, const char *filename) { 88 int n = strlen(filename); 89 90 if (strcmp(filename + n - 4, ".bz2") == 0) { 91 ff->type = bz2FontFile; 92 ff->f.bz2 = BZ2_bzopen(filename, "rb"); 93 ff->pos = 0; 94 return ff->f.bz2; 95 } else { 96 ff->type = gzFontFile; 97 ff->f.gz = gzopen(filename, "rb"); 98 return ff->f.gz; 99 } 100} 101 102static inline int 103fontFileRead(fontFile *ff, void *buf, unsigned len) 104{ 105 if (ff->type == gzFontFile) { 106 return gzread(ff->f.gz, buf, len); 107 } else { 108 int r = BZ2_bzread(ff->f.bz2, buf, len); 109 ff->pos += r; 110 return r; 111 } 112} 113 114static inline int 115fontFileGetc(fontFile *ff) 116{ 117 if (ff->type == gzFontFile) { 118 return gzgetc(ff->f.gz); 119 } else { 120 char buf; 121 if (BZ2_bzread(ff->f.bz2, &buf, 1) != 1) { 122 return -1; 123 } else { 124 ff->pos += 1; 125 return (int) buf; 126 } 127 } 128} 129 130static int 131fontFileSeek(fontFile *ff, z_off_t offset, int whence) 132{ 133 if (ff->type == gzFontFile) { 134 return gzseek(ff->f.gz, offset, whence); 135 } else { 136 /* bzlib has no easy equivalent so we have to fake it, 137 * fortunately, we only have to handle a couple of cases 138 */ 139 int n; 140 char buf[BUFSIZ]; 141 142 switch (whence) { 143 case SEEK_SET: 144 n = offset - ff->pos; 145 break; 146 case SEEK_CUR: 147 n = offset; 148 break; 149 default: 150 return -1; 151 } 152 153 while (n > BUFSIZ) { 154 if (BZ2_bzread(ff->f.bz2, buf, BUFSIZ) != BUFSIZ) 155 return -1; 156 n -= BUFSIZ; 157 } 158 if (BZ2_bzread(ff->f.bz2, buf, n) != n) 159 return -1; 160 ff->pos = offset; 161 return offset; 162 } 163} 164 165 166static inline int 167fontFileClose(fontFile *ff) 168{ 169 if (ff->type == gzFontFile) { 170 return gzclose(ff->f.gz); 171 } else { 172 BZ2_bzclose(ff->f.bz2); 173 return 0; 174 } 175} 176 177#else /* no bzip2, only gzip */ 178typedef gzFile fontFile; 179# define fontFileOpen(ff, filename) (*(ff) = gzopen(filename, "rb")) 180# define fontFileRead(ff, buf, len) gzread(*(ff), buf, len) 181# define fontFileGetc(ff) gzgetc(*(ff)) 182# define fontFileSeek(ff, off, whence) gzseek(*(ff), off, whence) 183# define fontFileClose(ff) gzclose(*(ff)) 184#endif 185 186static int pcfIdentify(fontFile *f, char **name); 187static int bdfIdentify(fontFile *f, char **name); 188 189static int 190getLSB32(fontFile *f) 191{ 192 int rc; 193 unsigned char c[4]; 194 195 rc = fontFileRead(f, c, 4); 196 if(rc != 4) 197 return -1; 198 return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); 199} 200 201static int 202getInt8(fontFile *f, int format) 203{ 204 unsigned char c; 205 int rc; 206 207 rc = fontFileRead(f, &c, 1); 208 if(rc != 1) 209 return -1; 210 return c; 211} 212 213static int 214getInt32(fontFile *f, int format) 215{ 216 int rc; 217 unsigned char c[4]; 218 219 rc = fontFileRead(f, c, 4); 220 if(rc != 4) 221 return -1; 222 223 if(format & (1 << 2)) { 224 return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | (c[3]); 225 } else { 226 return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); 227 } 228} 229 230int 231bitmapIdentify(const char *filename, char **name) 232{ 233 fontFile ff; 234 int magic; 235 236 if (fontFileOpen(&ff, filename) == NULL) 237 return -1; 238 239 magic = getLSB32(&ff); 240 if(magic == PCF_VERSION) 241 return pcfIdentify(&ff, name); 242 else if(magic == ('S' | ('T' << 8) | ('A' << 16) | ('R') << 24)) 243 return bdfIdentify(&ff, name); 244 245 fontFileClose(&ff); 246 return 0; 247} 248 249static int 250pcfIdentify(fontFile *f, char **name) 251{ 252 int prop_position; 253 PropPtr props = NULL; 254 int format, count, nprops, i, string_size, rc; 255 char *strings = NULL, *s; 256 257 count = getLSB32(f); 258 if(count <= 0) 259 goto fail; 260 261 prop_position = -1; 262 for(i = 0; i < count; i++) { 263 int type, offset; 264 type = getLSB32(f); 265 (void) getLSB32(f); 266 (void) getLSB32(f); 267 offset = getLSB32(f); 268 if(type == PCF_PROPERTIES) { 269 prop_position = offset; 270 break; 271 } 272 } 273 if(prop_position < 0) 274 goto fail; 275 276 rc = fontFileSeek(f, prop_position, SEEK_SET); 277 if(rc < 0) 278 goto fail; 279 280 format = getLSB32(f); 281 if((format & 0xFFFFFF00) != 0) 282 goto fail; 283 nprops = getInt32(f, format); 284 if(nprops <= 0 || nprops > 1000) 285 goto fail; 286 props = malloc(nprops * sizeof(PropRec)); 287 if(props == NULL) 288 goto fail; 289 290 for(i = 0; i < nprops; i++) { 291 props[i].name = getInt32(f, format); 292 props[i].isString = getInt8(f, format); 293 props[i].value = getInt32(f, format); 294 } 295 if(nprops & 3) { 296 rc = fontFileSeek(f, 4 - (nprops & 3), SEEK_CUR); 297 if(rc < 0) 298 goto fail; 299 } 300 301 string_size = getInt32(f, format); 302 if(string_size < 0 || string_size > 100000) 303 goto fail; 304 strings = malloc(string_size); 305 if(!strings) 306 goto fail; 307 308 rc = fontFileRead(f, strings, string_size); 309 if(rc != string_size) 310 goto fail; 311 312 for(i = 0; i < nprops; i++) { 313 if(!props[i].isString || 314 props[i].name >= string_size - 4 || 315 props[i].value >= string_size) 316 continue; 317 if(strcmp(strings + props[i].name, "FONT") == 0) 318 break; 319 } 320 321 if(i >= nprops) 322 goto fail; 323 324 s = malloc(strlen(strings + props[i].value) + 1); 325 if(s == NULL) 326 goto fail; 327 strcpy(s, strings + props[i].value); 328 *name = s; 329 free(strings); 330 free(props); 331 fontFileClose(f); 332 return 1; 333 334 fail: 335 if(strings) free(strings); 336 if(props) free(props); 337 fontFileClose(f); 338 return 0; 339} 340 341#define NKEY 20 342 343static char* 344getKeyword(fontFile *f, int *eol) 345{ 346 static char keyword[NKEY + 1]; 347 int c, i; 348 i = 0; 349 while(i < NKEY) { 350 c = fontFileGetc(f); 351 if(c == ' ' || c == '\n') { 352 if(i <= 0) 353 return NULL; 354 if(eol) 355 *eol = (c == '\n'); 356 keyword[i] = '\0'; 357 return keyword; 358 } 359 if(c < 'A' || c > 'Z') 360 return NULL; 361 keyword[i++] = c; 362 } 363 return NULL; 364} 365 366static int 367bdfskip(fontFile *f) 368{ 369 int c; 370 do { 371 c = fontFileGetc(f); 372 } while(c >= 0 && c != '\n'); 373 if(c < 0) 374 return -1; 375 return 1; 376} 377 378static char * 379bdfend(fontFile *f) 380{ 381 int c; 382 char *buf = NULL; 383 int bufsize = 0; 384 int i = 0; 385 386 do { 387 c = fontFileGetc(f); 388 } while (c == ' '); 389 390 while(i < 1000) { 391 if(c < 0 || (c == '\n' && i == 0)) { 392 goto fail; 393 } 394 if(bufsize < i + 1) { 395 char *newbuf; 396 if(bufsize == 0) { 397 bufsize = 20; 398 newbuf = malloc(bufsize); 399 } else { 400 bufsize = 2 * bufsize; 401 newbuf = realloc(buf, bufsize); 402 } 403 if(newbuf == NULL) 404 goto fail; 405 buf = newbuf; 406 } 407 if(c == '\n') { 408 buf[i] = '\0'; 409 return buf; 410 } 411 buf[i++] = c; 412 c = fontFileGetc(f); 413 } 414 415 fail: 416 if(buf) 417 free(buf); 418 return NULL; 419} 420 421static int 422bdfIdentify(fontFile *f, char **name) 423{ 424 char *k; 425 int rc; 426 int eol; 427 /* bitmapIdentify already read "STAR", so we need to check for 428 "TFONT" */ 429 k = getKeyword(f, &eol); 430 if(k == NULL || eol) 431 goto fail; 432 if(strcmp(k, "TFONT") != 0) 433 goto fail; 434 while(1) { 435 if(!eol) { 436 rc = bdfskip(f); 437 if(rc < 0) 438 goto fail; 439 } 440 k = getKeyword(f, &eol); 441 if(k == NULL) 442 goto fail; 443 else if(strcmp(k, "FONT") == 0) { 444 if(eol) 445 goto fail; 446 k = bdfend(f); 447 if(k == NULL) 448 goto fail; 449 *name = k; 450 fontFileClose(f); 451 return 1; 452 } else if(strcmp(k, "CHARS") == 0) 453 goto fail; 454 } 455 fail: 456 fontFileClose(f); 457 return 0; 458} 459