ident.c revision ea6ae205
11.1Sthorpej/* 21.1Sthorpej Copyright (c) 2003 by Juliusz Chroboczek 31.1Sthorpej 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/* $XFree86: xc/programs/mkfontscale/ident.c,v 1.3tsi Exp $ */ 23 24/* The function identifyBitmap returns -1 if filename is definitively not 25 a font file, 1 if it is a single-face bitmap font with a XLFD name, 26 and 0 if it should be processed normally. identifyBitmap is 27 much faster than parsing the whole font. */ 28 29#include <stdlib.h> 30#include <string.h> 31#include "zlib.h" 32#include "ident.h" 33 34#define PCF_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1) 35#define PCF_PROPERTIES (1 << 0) 36 37typedef struct _Prop { 38 unsigned name; 39 int isString; 40 unsigned value; 41} PropRec, *PropPtr; 42 43static int pcfIdentify(gzFile f, char **name); 44static int bdfIdentify(gzFile f, char **name); 45 46static int 47getLSB32(gzFile f) 48{ 49 int rc; 50 unsigned char c[4]; 51 52 rc = gzread(f, c, 4); 53 if(rc != 4) 54 return -1; 55 return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); 56} 57 58static int 59getInt8(gzFile f, int format) 60{ 61 unsigned char c; 62 int rc; 63 64 rc = gzread(f, &c, 1); 65 if(rc != 1) 66 return -1; 67 return c; 68} 69 70static int 71getInt32(gzFile f, int format) 72{ 73 int rc; 74 unsigned char c[4]; 75 76 rc = gzread(f, c, 4); 77 if(rc != 4) 78 return -1; 79 80 if(format & (1 << 2)) { 81 return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | (c[3]); 82 } else { 83 return (c[0]) | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); 84 } 85} 86 87static int 88pcfskip(gzFile f, int n) 89{ 90 char buf[32]; 91 int i, rc; 92 while(n > 0) { 93 i = (n > 32 ? 32 : n); 94 rc = gzread(f, buf, i); 95 if(rc != i) 96 return -1; 97 n -= rc; 98 } 99 return 1; 100} 101 102int 103bitmapIdentify(char *filename, char **name) 104{ 105 gzFile f; 106 int magic; 107 108 f = gzopen(filename, "rb"); 109 if(f == NULL) 110 return -1; 111 112 magic = getLSB32(f); 113 if(magic == PCF_VERSION) 114 return pcfIdentify(f, name); 115 else if(magic == ('S' | ('T' << 8) | ('A' << 16) | ('R') << 24)) 116 return bdfIdentify(f, name); 117 118 gzclose(f); 119 return 0; 120} 121 122static int 123pcfIdentify(gzFile f, char **name) 124{ 125 int prop_position; 126 PropPtr props = NULL; 127 int format, count, nprops, i, string_size, rc; 128 char *strings = NULL, *s; 129 130 count = getLSB32(f); 131 if(count <= 0) 132 goto fail; 133 134 prop_position = -1; 135 for(i = 0; i < count; i++) { 136 int type, offset; 137 type = getLSB32(f); 138 (void) getLSB32(f); 139 (void) getLSB32(f); 140 offset = getLSB32(f); 141 if(type == PCF_PROPERTIES) { 142 prop_position = offset; 143 break; 144 } 145 } 146 if(prop_position < 0) 147 goto fail; 148 149 rc = gzseek(f, prop_position, SEEK_SET); 150 if(rc < 0) 151 goto fail; 152 153 format = getLSB32(f); 154 if((format & 0xFFFFFF00) != 0) 155 goto fail; 156 nprops = getInt32(f, format); 157 if(nprops <= 0 || nprops > 1000) 158 goto fail; 159 props = malloc(nprops * sizeof(PropRec)); 160 if(props == NULL) 161 goto fail; 162 163 for(i = 0; i < nprops; i++) { 164 props[i].name = getInt32(f, format); 165 props[i].isString = getInt8(f, format); 166 props[i].value = getInt32(f, format); 167 } 168 if(nprops & 3) { 169 rc = pcfskip(f, 4 - (nprops & 3)); 170 if(rc < 0) 171 goto fail; 172 } 173 174 string_size = getInt32(f, format); 175 if(string_size < 0 || string_size > 100000) 176 goto fail; 177 strings = malloc(string_size); 178 if(!strings) 179 goto fail; 180 181 rc = gzread(f, strings, string_size); 182 if(rc != string_size) 183 goto fail; 184 185 for(i = 0; i < nprops; i++) { 186 if(!props[i].isString || 187 props[i].name >= string_size - 4 || 188 props[i].value >= string_size) 189 continue; 190 if(strcmp(strings + props[i].name, "FONT") == 0) 191 break; 192 } 193 194 if(i >= nprops) 195 goto fail; 196 197 s = malloc(strlen(strings + props[i].value) + 1); 198 if(s == NULL) 199 goto fail; 200 strcpy(s, strings + props[i].value); 201 *name = s; 202 free(strings); 203 free(props); 204 gzclose(f); 205 return 1; 206 207 fail: 208 if(strings) free(strings); 209 if(props) free(props); 210 gzclose(f); 211 return 0; 212} 213 214#define NKEY 20 215 216static char* 217getKeyword(gzFile *f, int *eol) 218{ 219 static char keyword[NKEY + 1]; 220 int c, i; 221 i = 0; 222 while(i < NKEY) { 223 c = gzgetc(f); 224 if(c == ' ' || c == '\n') { 225 if(i <= 0) 226 return NULL; 227 if(eol) 228 *eol = (c == '\n'); 229 keyword[i] = '\0'; 230 return keyword; 231 } 232 if(c < 'A' || c > 'Z') 233 return NULL; 234 keyword[i++] = c; 235 } 236 return NULL; 237} 238 239static int 240bdfskip(gzFile *f) 241{ 242 int c; 243 do { 244 c = gzgetc(f); 245 } while(c >= 0 && c != '\n'); 246 if(c < 0) 247 return -1; 248 return 1; 249} 250 251static char * 252bdfend(gzFile *f) 253{ 254 int c; 255 char *buf = NULL; 256 int bufsize = 0; 257 int i = 0; 258 259 do { 260 c = gzgetc(f); 261 } while (c == ' '); 262 263 while(i < 1000) { 264 if(c < 0 || (c == '\n' && i == 0)) { 265 goto fail; 266 } 267 if(bufsize < i + 1) { 268 char *newbuf; 269 if(bufsize == 0) { 270 bufsize = 20; 271 newbuf = malloc(bufsize); 272 } else { 273 bufsize = 2 * bufsize; 274 newbuf = realloc(buf, bufsize); 275 } 276 if(newbuf == NULL) 277 goto fail; 278 buf = newbuf; 279 } 280 if(c == '\n') { 281 buf[i] = '\0'; 282 return buf; 283 } 284 buf[i++] = c; 285 c = gzgetc(f); 286 } 287 288 fail: 289 if(buf) 290 free(buf); 291 return NULL; 292} 293 294static int 295bdfIdentify(gzFile f, char **name) 296{ 297 char *k; 298 int rc; 299 int eol; 300 /* bitmapIdentify already read "STAR", so we need to check for 301 "TFONT" */ 302 k = getKeyword(f, &eol); 303 if(k == NULL || eol) 304 goto fail; 305 if(strcmp(k, "TFONT") != 0) 306 goto fail; 307 while(1) { 308 if(!eol) { 309 rc = bdfskip(f); 310 if(rc < 0) 311 goto fail; 312 } 313 k = getKeyword(f, &eol); 314 if(k == NULL) 315 goto fail; 316 else if(strcmp(k, "FONT") == 0) { 317 if(eol) 318 goto fail; 319 k = bdfend(f); 320 if(k == NULL) 321 goto fail; 322 *name = k; 323 gzclose(f); 324 return 1; 325 } else if(strcmp(k, "CHARS") == 0) 326 goto fail; 327 } 328 fail: 329 gzclose(f); 330 return 0; 331} 332