pcfread.c revision fd60135f
1a96d7823Smrg/* 2a96d7823Smrg 3a96d7823SmrgCopyright 1990, 1998 The Open Group 4a96d7823Smrg 5a96d7823SmrgPermission to use, copy, modify, distribute, and sell this software and its 6a96d7823Smrgdocumentation for any purpose is hereby granted without fee, provided that 7a96d7823Smrgthe above copyright notice appear in all copies and that both that 8a96d7823Smrgcopyright notice and this permission notice appear in supporting 9a96d7823Smrgdocumentation. 10a96d7823Smrg 11a96d7823SmrgThe above copyright notice and this permission notice shall be included 12a96d7823Smrgin all copies or substantial portions of the Software. 13a96d7823Smrg 14a96d7823SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15a96d7823SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16a96d7823SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17a96d7823SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18a96d7823SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19a96d7823SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20a96d7823SmrgOTHER DEALINGS IN THE SOFTWARE. 21a96d7823Smrg 22a96d7823SmrgExcept as contained in this notice, the name of The Open Group shall 23a96d7823Smrgnot be used in advertising or otherwise to promote the sale, use or 24a96d7823Smrgother dealings in this Software without prior written authorization 25a96d7823Smrgfrom The Open Group. 26a96d7823Smrg 27a96d7823Smrg*/ 28a96d7823Smrg 29a96d7823Smrg/* 30a96d7823Smrg * Author: Keith Packard, MIT X Consortium 31a96d7823Smrg */ 32a96d7823Smrg 33a96d7823Smrg#ifdef HAVE_CONFIG_H 34a96d7823Smrg#include <config.h> 35a96d7823Smrg#endif 36a96d7823Smrg#include "libxfontint.h" 37a96d7823Smrg 38a96d7823Smrg#include <X11/fonts/fntfilst.h> 39a96d7823Smrg#include <X11/fonts/bitmap.h> 40a96d7823Smrg#include <X11/fonts/pcf.h> 41a96d7823Smrg 42a96d7823Smrg#ifndef MAX 43a96d7823Smrg#define MAX(a,b) (((a)>(b)) ? a : b) 44a96d7823Smrg#endif 45a96d7823Smrg 46a96d7823Smrg#include <stdarg.h> 47a96d7823Smrg#include <stdint.h> 48fd60135fSmrg#include <string.h> 49a96d7823Smrg 50a96d7823Smrgvoid 51a96d7823SmrgpcfError(const char* message, ...) 52a96d7823Smrg{ 53a96d7823Smrg va_list args; 54a96d7823Smrg 55a96d7823Smrg va_start(args, message); 56a96d7823Smrg 57a96d7823Smrg fprintf(stderr, "PCF Error: "); 58a96d7823Smrg vfprintf(stderr, message, args); 59a96d7823Smrg va_end(args); 60a96d7823Smrg} 61a96d7823Smrg 62a96d7823Smrg/* Read PCF font files */ 63a96d7823Smrg 64a96d7823Smrgstatic void pcfUnloadFont ( FontPtr pFont ); 65a96d7823Smrgstatic int position; 66a96d7823Smrg 67a96d7823Smrg 68a96d7823Smrg#define IS_EOF(file) ((file)->eof == BUFFILEEOF) 69a96d7823Smrg 70a96d7823Smrg#define FONT_FILE_GETC_ERR(f) (tmp = FontFileGetc(f), BAIL_ON_EOF) 71a96d7823Smrg 72a96d7823Smrgstatic int 73a96d7823SmrgpcfGetLSB32(FontFilePtr file) 74a96d7823Smrg{ 75a96d7823Smrg int c; 76a96d7823Smrg 77a96d7823Smrg c = FontFileGetc(file); 78a96d7823Smrg c |= FontFileGetc(file) << 8; 79a96d7823Smrg c |= FontFileGetc(file) << 16; 80a96d7823Smrg c |= FontFileGetc(file) << 24; 81a96d7823Smrg position += 4; 82a96d7823Smrg return c; 83a96d7823Smrg} 84a96d7823Smrg 85a96d7823Smrgstatic int 86a96d7823SmrgpcfGetINT32(FontFilePtr file, CARD32 format) 87a96d7823Smrg{ 88a96d7823Smrg int c; 89a96d7823Smrg 90a96d7823Smrg if (PCF_BYTE_ORDER(format) == MSBFirst) { 91a96d7823Smrg c = FontFileGetc(file) << 24; 92a96d7823Smrg c |= FontFileGetc(file) << 16; 93a96d7823Smrg c |= FontFileGetc(file) << 8; 94a96d7823Smrg c |= FontFileGetc(file); 95a96d7823Smrg } else { 96a96d7823Smrg c = FontFileGetc(file); 97a96d7823Smrg c |= FontFileGetc(file) << 8; 98a96d7823Smrg c |= FontFileGetc(file) << 16; 99a96d7823Smrg c |= FontFileGetc(file) << 24; 100a96d7823Smrg } 101a96d7823Smrg position += 4; 102a96d7823Smrg return c; 103a96d7823Smrg} 104a96d7823Smrg 105a96d7823Smrgstatic int 106a96d7823SmrgpcfGetINT16(FontFilePtr file, CARD32 format) 107a96d7823Smrg{ 108a96d7823Smrg int c; 109a96d7823Smrg 110a96d7823Smrg if (PCF_BYTE_ORDER(format) == MSBFirst) { 111a96d7823Smrg c = FontFileGetc(file) << 8; 112a96d7823Smrg c |= FontFileGetc(file); 113a96d7823Smrg } else { 114a96d7823Smrg c = FontFileGetc(file); 115a96d7823Smrg c |= FontFileGetc(file) << 8; 116a96d7823Smrg } 117a96d7823Smrg position += 2; 118a96d7823Smrg return c; 119a96d7823Smrg} 120a96d7823Smrg 121a96d7823Smrg#define pcfGetINT8(file, format) (position++, FontFileGetc(file)) 122a96d7823Smrg 123a96d7823Smrgstatic PCFTablePtr 124a96d7823SmrgpcfReadTOC(FontFilePtr file, int *countp) 125a96d7823Smrg{ 126a96d7823Smrg CARD32 version; 127a96d7823Smrg PCFTablePtr tables; 128a96d7823Smrg int count; 129a96d7823Smrg int i; 130a96d7823Smrg 131a96d7823Smrg position = 0; 132a96d7823Smrg version = pcfGetLSB32(file); 133a96d7823Smrg if (version != PCF_FILE_VERSION) 134a96d7823Smrg return (PCFTablePtr) NULL; 135a96d7823Smrg count = pcfGetLSB32(file); 136a96d7823Smrg if (IS_EOF(file)) return (PCFTablePtr) NULL; 137a96d7823Smrg if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) { 138a96d7823Smrg pcfError("pcfReadTOC(): invalid file format\n"); 139a96d7823Smrg return NULL; 140a96d7823Smrg } 141a96d7823Smrg tables = malloc(count * sizeof(PCFTableRec)); 142a96d7823Smrg if (!tables) { 143a96d7823Smrg pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n", 144a96d7823Smrg count, (int) sizeof(PCFTableRec)); 145a96d7823Smrg return (PCFTablePtr) NULL; 146a96d7823Smrg } 147a96d7823Smrg for (i = 0; i < count; i++) { 148a96d7823Smrg tables[i].type = pcfGetLSB32(file); 149a96d7823Smrg tables[i].format = pcfGetLSB32(file); 150a96d7823Smrg tables[i].size = pcfGetLSB32(file); 151a96d7823Smrg tables[i].offset = pcfGetLSB32(file); 152a96d7823Smrg if (IS_EOF(file)) goto Bail; 153a96d7823Smrg } 154a96d7823Smrg 155a96d7823Smrg *countp = count; 156a96d7823Smrg return tables; 157a96d7823Smrg 158a96d7823Smrg Bail: 159a96d7823Smrg free(tables); 160a96d7823Smrg return (PCFTablePtr) NULL; 161a96d7823Smrg} 162a96d7823Smrg 163a96d7823Smrg/* 164a96d7823Smrg * PCF supports two formats for metrics, both the regular 165a96d7823Smrg * jumbo size, and 'lite' metrics, which are useful 166a96d7823Smrg * for most fonts which have even vaguely reasonable 167a96d7823Smrg * metrics 168a96d7823Smrg */ 169a96d7823Smrg 170a96d7823Smrgstatic Bool 171a96d7823SmrgpcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) 172a96d7823Smrg{ 173a96d7823Smrg metric->leftSideBearing = pcfGetINT16(file, format); 174a96d7823Smrg metric->rightSideBearing = pcfGetINT16(file, format); 175a96d7823Smrg metric->characterWidth = pcfGetINT16(file, format); 176a96d7823Smrg metric->ascent = pcfGetINT16(file, format); 177a96d7823Smrg metric->descent = pcfGetINT16(file, format); 178a96d7823Smrg metric->attributes = pcfGetINT16(file, format); 179a96d7823Smrg if (IS_EOF(file)) return FALSE; 180a96d7823Smrg 181a96d7823Smrg return TRUE; 182a96d7823Smrg} 183a96d7823Smrg 184a96d7823Smrgstatic Bool 185a96d7823SmrgpcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) 186a96d7823Smrg{ 187a96d7823Smrg metric->leftSideBearing = pcfGetINT8(file, format) - 0x80; 188a96d7823Smrg metric->rightSideBearing = pcfGetINT8(file, format) - 0x80; 189a96d7823Smrg metric->characterWidth = pcfGetINT8(file, format) - 0x80; 190a96d7823Smrg metric->ascent = pcfGetINT8(file, format) - 0x80; 191a96d7823Smrg metric->descent = pcfGetINT8(file, format) - 0x80; 192a96d7823Smrg metric->attributes = 0; 193a96d7823Smrg if (IS_EOF(file)) return FALSE; 194a96d7823Smrg 195a96d7823Smrg return TRUE; 196a96d7823Smrg} 197a96d7823Smrg 198a96d7823Smrg/* 199a96d7823Smrg * Position the file to the begining of the specified table 200a96d7823Smrg * in the font file 201a96d7823Smrg */ 202a96d7823Smrgstatic Bool 203a96d7823SmrgpcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables, 204a96d7823Smrg CARD32 type, CARD32 *formatp, CARD32 *sizep) 205a96d7823Smrg{ 206a96d7823Smrg int i; 207a96d7823Smrg 208a96d7823Smrg for (i = 0; i < ntables; i++) 209a96d7823Smrg if (tables[i].type == type) { 210a96d7823Smrg if (position > tables[i].offset) 211a96d7823Smrg return FALSE; 212a96d7823Smrg if (!FontFileSkip(file, tables[i].offset - position)) 213a96d7823Smrg return FALSE; 214a96d7823Smrg position = tables[i].offset; 215a96d7823Smrg *sizep = tables[i].size; 216a96d7823Smrg *formatp = tables[i].format; 217a96d7823Smrg return TRUE; 218a96d7823Smrg } 219a96d7823Smrg return FALSE; 220a96d7823Smrg} 221a96d7823Smrg 222a96d7823Smrgstatic Bool 223a96d7823SmrgpcfHasType (PCFTablePtr tables, int ntables, CARD32 type) 224a96d7823Smrg{ 225a96d7823Smrg int i; 226a96d7823Smrg 227a96d7823Smrg for (i = 0; i < ntables; i++) 228a96d7823Smrg if (tables[i].type == type) 229a96d7823Smrg return TRUE; 230a96d7823Smrg return FALSE; 231a96d7823Smrg} 232a96d7823Smrg 233a96d7823Smrg/* 234a96d7823Smrg * pcfGetProperties 235a96d7823Smrg * 236a96d7823Smrg * Reads the font properties from the font file, filling in the FontInfo rec 237a96d7823Smrg * supplied. Used by by both ReadFont and ReadFontInfo routines. 238a96d7823Smrg */ 239a96d7823Smrg 240a96d7823Smrgstatic Bool 241a96d7823SmrgpcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file, 242a96d7823Smrg PCFTablePtr tables, int ntables) 243a96d7823Smrg{ 244a96d7823Smrg FontPropPtr props = 0; 245a96d7823Smrg int nprops; 246a96d7823Smrg char *isStringProp = 0; 247a96d7823Smrg CARD32 format; 248a96d7823Smrg int i; 249a96d7823Smrg CARD32 size; 250a96d7823Smrg int string_size; 251a96d7823Smrg char *strings; 252a96d7823Smrg 253a96d7823Smrg /* font properties */ 254a96d7823Smrg 255a96d7823Smrg if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size)) 256a96d7823Smrg goto Bail; 257a96d7823Smrg format = pcfGetLSB32(file); 258a96d7823Smrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 259a96d7823Smrg goto Bail; 260a96d7823Smrg nprops = pcfGetINT32(file, format); 261a96d7823Smrg if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) { 262a96d7823Smrg pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops); 263a96d7823Smrg goto Bail; 264a96d7823Smrg } 265a96d7823Smrg if (IS_EOF(file)) goto Bail; 266a96d7823Smrg props = malloc(nprops * sizeof(FontPropRec)); 267a96d7823Smrg if (!props) { 268a96d7823Smrg pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n", 269a96d7823Smrg nprops, (int) sizeof(FontPropRec)); 270a96d7823Smrg goto Bail; 271a96d7823Smrg } 272a96d7823Smrg isStringProp = malloc(nprops * sizeof(char)); 273a96d7823Smrg if (!isStringProp) { 274a96d7823Smrg pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n", 275a96d7823Smrg nprops, (int) sizeof(char)); 276a96d7823Smrg goto Bail; 277a96d7823Smrg } 278a96d7823Smrg for (i = 0; i < nprops; i++) { 279a96d7823Smrg props[i].name = pcfGetINT32(file, format); 280a96d7823Smrg isStringProp[i] = pcfGetINT8(file, format); 281a96d7823Smrg props[i].value = pcfGetINT32(file, format); 282a96d7823Smrg if (props[i].name < 0 283a96d7823Smrg || (isStringProp[i] != 0 && isStringProp[i] != 1) 284a96d7823Smrg || (isStringProp[i] && props[i].value < 0)) { 285a96d7823Smrg pcfError("pcfGetProperties(): invalid file format %ld %d %ld\n", 286a96d7823Smrg props[i].name, isStringProp[i], props[i].value); 287a96d7823Smrg goto Bail; 288a96d7823Smrg } 289a96d7823Smrg if (IS_EOF(file)) goto Bail; 290a96d7823Smrg } 291a96d7823Smrg /* pad the property array */ 292a96d7823Smrg /* 293a96d7823Smrg * clever here - nprops is the same as the number of odd-units read, as 294a96d7823Smrg * only isStringProp are odd length 295a96d7823Smrg */ 296a96d7823Smrg if (nprops & 3) 297a96d7823Smrg { 298a96d7823Smrg i = 4 - (nprops & 3); 299a96d7823Smrg (void)FontFileSkip(file, i); 300a96d7823Smrg position += i; 301a96d7823Smrg } 302a96d7823Smrg if (IS_EOF(file)) goto Bail; 303a96d7823Smrg string_size = pcfGetINT32(file, format); 304a96d7823Smrg if (string_size < 0) goto Bail; 305a96d7823Smrg if (IS_EOF(file)) goto Bail; 306a96d7823Smrg strings = malloc(string_size); 307a96d7823Smrg if (!strings) { 308a96d7823Smrg pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size); 309a96d7823Smrg goto Bail; 310a96d7823Smrg } 311a96d7823Smrg FontFileRead(file, strings, string_size); 312a96d7823Smrg if (IS_EOF(file)) goto Bail; 313a96d7823Smrg position += string_size; 314a96d7823Smrg for (i = 0; i < nprops; i++) { 315fd60135fSmrg if (props[i].name >= string_size) { 316fd60135fSmrg pcfError("pcfGetProperties(): String starts out of bounds (%ld/%d)\n", props[i].name, string_size); 317fd60135fSmrg goto Bail; 318fd60135fSmrg } 319a96d7823Smrg props[i].name = MakeAtom(strings + props[i].name, 320fd60135fSmrg strnlen(strings + props[i].name, string_size - props[i].name), TRUE); 321a96d7823Smrg if (isStringProp[i]) { 322fd60135fSmrg if (props[i].value >= string_size) { 323fd60135fSmrg pcfError("pcfGetProperties(): String starts out of bounds (%ld/%d)\n", props[i].value, string_size); 324fd60135fSmrg goto Bail; 325fd60135fSmrg } 326a96d7823Smrg props[i].value = MakeAtom(strings + props[i].value, 327fd60135fSmrg strnlen(strings + props[i].value, string_size - props[i].value), TRUE); 328a96d7823Smrg } 329a96d7823Smrg } 330a96d7823Smrg free(strings); 331a96d7823Smrg pFontInfo->isStringProp = isStringProp; 332a96d7823Smrg pFontInfo->props = props; 333a96d7823Smrg pFontInfo->nprops = nprops; 334a96d7823Smrg return TRUE; 335a96d7823SmrgBail: 336a96d7823Smrg free(isStringProp); 337a96d7823Smrg free(props); 338a96d7823Smrg return FALSE; 339a96d7823Smrg} 340a96d7823Smrg 341a96d7823Smrg 342a96d7823Smrg/* 343a96d7823Smrg * pcfReadAccel 344a96d7823Smrg * 345a96d7823Smrg * Fill in the accelerator information from the font file; used 346a96d7823Smrg * to read both BDF_ACCELERATORS and old style ACCELERATORS 347a96d7823Smrg */ 348a96d7823Smrg 349a96d7823Smrgstatic Bool 350a96d7823SmrgpcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file, 351a96d7823Smrg PCFTablePtr tables, int ntables, CARD32 type) 352a96d7823Smrg{ 353a96d7823Smrg CARD32 format; 354a96d7823Smrg CARD32 size; 355a96d7823Smrg 356a96d7823Smrg if (!pcfSeekToType(file, tables, ntables, type, &format, &size) || 357a96d7823Smrg IS_EOF(file)) 358a96d7823Smrg goto Bail; 359a96d7823Smrg format = pcfGetLSB32(file); 360a96d7823Smrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 361a96d7823Smrg !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) 362a96d7823Smrg { 363a96d7823Smrg goto Bail; 364a96d7823Smrg } 365a96d7823Smrg pFontInfo->noOverlap = pcfGetINT8(file, format); 366a96d7823Smrg pFontInfo->constantMetrics = pcfGetINT8(file, format); 367a96d7823Smrg pFontInfo->terminalFont = pcfGetINT8(file, format); 368a96d7823Smrg pFontInfo->constantWidth = pcfGetINT8(file, format); 369a96d7823Smrg pFontInfo->inkInside = pcfGetINT8(file, format); 370a96d7823Smrg pFontInfo->inkMetrics = pcfGetINT8(file, format); 371a96d7823Smrg pFontInfo->drawDirection = pcfGetINT8(file, format); 372a96d7823Smrg pFontInfo->anamorphic = FALSE; 373a96d7823Smrg pFontInfo->cachable = TRUE; 374a96d7823Smrg /* natural alignment */ pcfGetINT8(file, format); 375a96d7823Smrg pFontInfo->fontAscent = pcfGetINT32(file, format); 376a96d7823Smrg pFontInfo->fontDescent = pcfGetINT32(file, format); 377a96d7823Smrg pFontInfo->maxOverlap = pcfGetINT32(file, format); 378a96d7823Smrg if (IS_EOF(file)) goto Bail; 379a96d7823Smrg if (!pcfGetMetric(file, format, &pFontInfo->minbounds)) 380a96d7823Smrg goto Bail; 381a96d7823Smrg if (!pcfGetMetric(file, format, &pFontInfo->maxbounds)) 382a96d7823Smrg goto Bail; 383a96d7823Smrg if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) { 384a96d7823Smrg if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds)) 385a96d7823Smrg goto Bail; 386a96d7823Smrg if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds)) 387a96d7823Smrg goto Bail; 388a96d7823Smrg } else { 389a96d7823Smrg pFontInfo->ink_minbounds = pFontInfo->minbounds; 390a96d7823Smrg pFontInfo->ink_maxbounds = pFontInfo->maxbounds; 391a96d7823Smrg } 392a96d7823Smrg return TRUE; 393a96d7823SmrgBail: 394a96d7823Smrg return FALSE; 395a96d7823Smrg} 396a96d7823Smrg 397a96d7823Smrgint 398a96d7823SmrgpcfReadFont(FontPtr pFont, FontFilePtr file, 399a96d7823Smrg int bit, int byte, int glyph, int scan) 400a96d7823Smrg{ 401a96d7823Smrg CARD32 format; 402a96d7823Smrg CARD32 size; 403a96d7823Smrg BitmapFontPtr bitmapFont = 0; 404a96d7823Smrg int i; 405a96d7823Smrg PCFTablePtr tables = 0; 406a96d7823Smrg int ntables; 407a96d7823Smrg int nmetrics; 408a96d7823Smrg int nbitmaps; 409a96d7823Smrg int sizebitmaps; 410a96d7823Smrg int nink_metrics; 411a96d7823Smrg CharInfoPtr metrics = 0; 412a96d7823Smrg xCharInfo *ink_metrics = 0; 413a96d7823Smrg char *bitmaps = 0; 414a96d7823Smrg CharInfoPtr **encoding = 0; 415a96d7823Smrg int nencoding = 0; 416a96d7823Smrg int encodingOffset; 417a96d7823Smrg CARD32 bitmapSizes[GLYPHPADOPTIONS]; 418a96d7823Smrg CARD32 *offsets = 0; 419a96d7823Smrg Bool hasBDFAccelerators; 420a96d7823Smrg 421a96d7823Smrg pFont->info.nprops = 0; 422a96d7823Smrg pFont->info.props = 0; 423a96d7823Smrg pFont->info.isStringProp=0; 424a96d7823Smrg 425a96d7823Smrg if (!(tables = pcfReadTOC(file, &ntables))) 426a96d7823Smrg goto Bail; 427a96d7823Smrg 428a96d7823Smrg /* properties */ 429a96d7823Smrg 430a96d7823Smrg if (!pcfGetProperties(&pFont->info, file, tables, ntables)) 431a96d7823Smrg goto Bail; 432a96d7823Smrg 433a96d7823Smrg /* Use the old accelerators if no BDF accelerators are in the file */ 434a96d7823Smrg 435a96d7823Smrg hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); 436a96d7823Smrg if (!hasBDFAccelerators) 437a96d7823Smrg if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS)) 438a96d7823Smrg goto Bail; 439a96d7823Smrg 440a96d7823Smrg /* metrics */ 441a96d7823Smrg 442a96d7823Smrg if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) { 443a96d7823Smrg goto Bail; 444a96d7823Smrg } 445a96d7823Smrg format = pcfGetLSB32(file); 446a96d7823Smrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 447a96d7823Smrg !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { 448a96d7823Smrg goto Bail; 449a96d7823Smrg } 450a96d7823Smrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 451a96d7823Smrg nmetrics = pcfGetINT32(file, format); 452a96d7823Smrg else 453a96d7823Smrg nmetrics = pcfGetINT16(file, format); 454a96d7823Smrg if (IS_EOF(file)) goto Bail; 455a96d7823Smrg if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) { 456a96d7823Smrg pcfError("pcfReadFont(): invalid file format\n"); 457a96d7823Smrg goto Bail; 458a96d7823Smrg } 459a96d7823Smrg metrics = malloc(nmetrics * sizeof(CharInfoRec)); 460a96d7823Smrg if (!metrics) { 461a96d7823Smrg pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n", 462a96d7823Smrg nmetrics, (int) sizeof(CharInfoRec)); 463a96d7823Smrg goto Bail; 464a96d7823Smrg } 465a96d7823Smrg for (i = 0; i < nmetrics; i++) 466a96d7823Smrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { 467a96d7823Smrg if (!pcfGetMetric(file, format, &(metrics + i)->metrics)) 468a96d7823Smrg goto Bail; 469a96d7823Smrg } else { 470a96d7823Smrg if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics)) 471a96d7823Smrg goto Bail; 472a96d7823Smrg } 473a96d7823Smrg 474a96d7823Smrg /* bitmaps */ 475a96d7823Smrg 476a96d7823Smrg if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size)) 477a96d7823Smrg goto Bail; 478a96d7823Smrg format = pcfGetLSB32(file); 479a96d7823Smrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 480a96d7823Smrg goto Bail; 481a96d7823Smrg 482a96d7823Smrg nbitmaps = pcfGetINT32(file, format); 483a96d7823Smrg if (nbitmaps != nmetrics || IS_EOF(file)) 484a96d7823Smrg goto Bail; 485a96d7823Smrg /* nmetrics is already ok, so nbitmap also is */ 486a96d7823Smrg offsets = malloc(nbitmaps * sizeof(CARD32)); 487a96d7823Smrg if (!offsets) { 488a96d7823Smrg pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n", 489a96d7823Smrg nbitmaps, (int) sizeof(CARD32)); 490a96d7823Smrg goto Bail; 491a96d7823Smrg } 492a96d7823Smrg for (i = 0; i < nbitmaps; i++) { 493a96d7823Smrg offsets[i] = pcfGetINT32(file, format); 494a96d7823Smrg if (IS_EOF(file)) goto Bail; 495a96d7823Smrg } 496a96d7823Smrg 497a96d7823Smrg for (i = 0; i < GLYPHPADOPTIONS; i++) { 498a96d7823Smrg bitmapSizes[i] = pcfGetINT32(file, format); 499a96d7823Smrg if (IS_EOF(file)) goto Bail; 500a96d7823Smrg } 501a96d7823Smrg 502a96d7823Smrg sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)]; 503a96d7823Smrg /* guard against completely empty font */ 504a96d7823Smrg bitmaps = malloc(sizebitmaps ? sizebitmaps : 1); 505a96d7823Smrg if (!bitmaps) { 506a96d7823Smrg pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1); 507a96d7823Smrg goto Bail; 508a96d7823Smrg } 509a96d7823Smrg FontFileRead(file, bitmaps, sizebitmaps); 510a96d7823Smrg if (IS_EOF(file)) goto Bail; 511a96d7823Smrg position += sizebitmaps; 512a96d7823Smrg 513a96d7823Smrg if (PCF_BIT_ORDER(format) != bit) 514a96d7823Smrg BitOrderInvert((unsigned char *)bitmaps, sizebitmaps); 515a96d7823Smrg if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) { 516a96d7823Smrg switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) { 517a96d7823Smrg case 1: 518a96d7823Smrg break; 519a96d7823Smrg case 2: 520a96d7823Smrg TwoByteSwap((unsigned char *)bitmaps, sizebitmaps); 521a96d7823Smrg break; 522a96d7823Smrg case 4: 523a96d7823Smrg FourByteSwap((unsigned char *)bitmaps, sizebitmaps); 524a96d7823Smrg break; 525a96d7823Smrg } 526a96d7823Smrg } 527a96d7823Smrg if (PCF_GLYPH_PAD(format) != glyph) { 528a96d7823Smrg char *padbitmaps; 529a96d7823Smrg int sizepadbitmaps; 530a96d7823Smrg int old, 531a96d7823Smrg new; 532a96d7823Smrg xCharInfo *metric; 533a96d7823Smrg 534a96d7823Smrg sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)]; 535a96d7823Smrg padbitmaps = malloc(sizepadbitmaps); 536a96d7823Smrg if (!padbitmaps) { 537a96d7823Smrg pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); 538a96d7823Smrg goto Bail; 539a96d7823Smrg } 540a96d7823Smrg new = 0; 541a96d7823Smrg for (i = 0; i < nbitmaps; i++) { 542a96d7823Smrg old = offsets[i]; 543a96d7823Smrg metric = &metrics[i].metrics; 544a96d7823Smrg offsets[i] = new; 545a96d7823Smrg new += RepadBitmap(bitmaps + old, padbitmaps + new, 546a96d7823Smrg PCF_GLYPH_PAD(format), glyph, 547a96d7823Smrg metric->rightSideBearing - metric->leftSideBearing, 548a96d7823Smrg metric->ascent + metric->descent); 549a96d7823Smrg } 550a96d7823Smrg free(bitmaps); 551a96d7823Smrg bitmaps = padbitmaps; 552a96d7823Smrg } 553a96d7823Smrg for (i = 0; i < nbitmaps; i++) 554a96d7823Smrg metrics[i].bits = bitmaps + offsets[i]; 555a96d7823Smrg 556a96d7823Smrg free(offsets); 557a96d7823Smrg offsets = NULL; 558a96d7823Smrg 559a96d7823Smrg /* ink metrics ? */ 560a96d7823Smrg 561a96d7823Smrg ink_metrics = NULL; 562a96d7823Smrg if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) { 563a96d7823Smrg format = pcfGetLSB32(file); 564a96d7823Smrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && 565a96d7823Smrg !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { 566a96d7823Smrg goto Bail; 567a96d7823Smrg } 568a96d7823Smrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 569a96d7823Smrg nink_metrics = pcfGetINT32(file, format); 570a96d7823Smrg else 571a96d7823Smrg nink_metrics = pcfGetINT16(file, format); 572a96d7823Smrg if (IS_EOF(file)) goto Bail; 573a96d7823Smrg if (nink_metrics != nmetrics) 574a96d7823Smrg goto Bail; 575a96d7823Smrg /* nmetrics already checked */ 576a96d7823Smrg ink_metrics = malloc(nink_metrics * sizeof(xCharInfo)); 577a96d7823Smrg if (!ink_metrics) { 578a96d7823Smrg pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n", 579a96d7823Smrg nink_metrics, (int) sizeof(xCharInfo)); 580a96d7823Smrg goto Bail; 581a96d7823Smrg } 582a96d7823Smrg for (i = 0; i < nink_metrics; i++) 583a96d7823Smrg if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { 584a96d7823Smrg if (!pcfGetMetric(file, format, ink_metrics + i)) 585a96d7823Smrg goto Bail; 586a96d7823Smrg } else { 587a96d7823Smrg if (!pcfGetCompressedMetric(file, format, ink_metrics + i)) 588a96d7823Smrg goto Bail; 589a96d7823Smrg } 590a96d7823Smrg } 591a96d7823Smrg 592a96d7823Smrg /* encoding */ 593a96d7823Smrg 594a96d7823Smrg if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) 595a96d7823Smrg goto Bail; 596a96d7823Smrg format = pcfGetLSB32(file); 597a96d7823Smrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 598a96d7823Smrg goto Bail; 599a96d7823Smrg 600a96d7823Smrg pFont->info.firstCol = pcfGetINT16(file, format); 601a96d7823Smrg pFont->info.lastCol = pcfGetINT16(file, format); 602a96d7823Smrg pFont->info.firstRow = pcfGetINT16(file, format); 603a96d7823Smrg pFont->info.lastRow = pcfGetINT16(file, format); 604a96d7823Smrg pFont->info.defaultCh = pcfGetINT16(file, format); 605a96d7823Smrg if (IS_EOF(file)) goto Bail; 606a96d7823Smrg if (pFont->info.firstCol > pFont->info.lastCol || 607a96d7823Smrg pFont->info.firstRow > pFont->info.lastRow || 608a96d7823Smrg pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail; 609a96d7823Smrg 610a96d7823Smrg nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 611a96d7823Smrg (pFont->info.lastRow - pFont->info.firstRow + 1); 612a96d7823Smrg 613a96d7823Smrg encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*)); 614a96d7823Smrg if (!encoding) { 615a96d7823Smrg pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n", 616a96d7823Smrg nencoding, (int) sizeof(CharInfoPtr)); 617a96d7823Smrg goto Bail; 618a96d7823Smrg } 619a96d7823Smrg 620a96d7823Smrg pFont->info.allExist = TRUE; 621a96d7823Smrg for (i = 0; i < nencoding; i++) { 622a96d7823Smrg encodingOffset = pcfGetINT16(file, format); 623a96d7823Smrg if (IS_EOF(file)) goto Bail; 624a96d7823Smrg if (encodingOffset == 0xFFFF) { 625a96d7823Smrg pFont->info.allExist = FALSE; 626a96d7823Smrg } else { 627a96d7823Smrg if(!encoding[SEGMENT_MAJOR(i)]) { 628a96d7823Smrg encoding[SEGMENT_MAJOR(i)]= 629a96d7823Smrg calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); 630a96d7823Smrg if(!encoding[SEGMENT_MAJOR(i)]) 631a96d7823Smrg goto Bail; 632a96d7823Smrg } 633a96d7823Smrg ACCESSENCODINGL(encoding, i) = metrics + encodingOffset; 634a96d7823Smrg } 635a96d7823Smrg } 636a96d7823Smrg 637a96d7823Smrg /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 638a96d7823Smrg 639a96d7823Smrg if (hasBDFAccelerators) 640a96d7823Smrg if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS)) 641a96d7823Smrg goto Bail; 642a96d7823Smrg 643a96d7823Smrg bitmapFont = malloc(sizeof *bitmapFont); 644a96d7823Smrg if (!bitmapFont) { 645a96d7823Smrg pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n", 646a96d7823Smrg (int) sizeof *bitmapFont); 647a96d7823Smrg goto Bail; 648a96d7823Smrg } 649a96d7823Smrg 650a96d7823Smrg bitmapFont->version_num = PCF_FILE_VERSION; 651a96d7823Smrg bitmapFont->num_chars = nmetrics; 652a96d7823Smrg bitmapFont->num_tables = ntables; 653a96d7823Smrg bitmapFont->metrics = metrics; 654a96d7823Smrg bitmapFont->ink_metrics = ink_metrics; 655a96d7823Smrg bitmapFont->bitmaps = bitmaps; 656a96d7823Smrg bitmapFont->encoding = encoding; 657a96d7823Smrg bitmapFont->pDefault = (CharInfoPtr) 0; 658a96d7823Smrg if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { 659a96d7823Smrg unsigned int r, 660a96d7823Smrg c, 661a96d7823Smrg cols; 662a96d7823Smrg 663a96d7823Smrg r = pFont->info.defaultCh >> 8; 664a96d7823Smrg c = pFont->info.defaultCh & 0xFF; 665a96d7823Smrg if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && 666a96d7823Smrg pFont->info.firstCol <= c && c <= pFont->info.lastCol) { 667a96d7823Smrg cols = pFont->info.lastCol - pFont->info.firstCol + 1; 668a96d7823Smrg r = r - pFont->info.firstRow; 669a96d7823Smrg c = c - pFont->info.firstCol; 670a96d7823Smrg bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c); 671a96d7823Smrg } 672a96d7823Smrg } 673a96d7823Smrg bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; 674a96d7823Smrg pFont->fontPrivate = (pointer) bitmapFont; 675a96d7823Smrg pFont->get_glyphs = bitmapGetGlyphs; 676a96d7823Smrg pFont->get_metrics = bitmapGetMetrics; 677a96d7823Smrg pFont->unload_font = pcfUnloadFont; 678a96d7823Smrg pFont->unload_glyphs = NULL; 679a96d7823Smrg pFont->bit = bit; 680a96d7823Smrg pFont->byte = byte; 681a96d7823Smrg pFont->glyph = glyph; 682a96d7823Smrg pFont->scan = scan; 683a96d7823Smrg free(tables); 684a96d7823Smrg return Successful; 685a96d7823SmrgBail: 686a96d7823Smrg free(ink_metrics); 687a96d7823Smrg if(encoding) { 688a96d7823Smrg for(i=0; i<NUM_SEGMENTS(nencoding); i++) 689a96d7823Smrg free(encoding[i]); 690a96d7823Smrg } 691a96d7823Smrg free(encoding); 692a96d7823Smrg free(bitmaps); 693a96d7823Smrg free(metrics); 694a96d7823Smrg free(pFont->info.props); 695a96d7823Smrg pFont->info.nprops = 0; 696a96d7823Smrg pFont->info.props = 0; 697a96d7823Smrg free (pFont->info.isStringProp); 698a96d7823Smrg free(bitmapFont); 699a96d7823Smrg free(tables); 700a96d7823Smrg free(offsets); 701a96d7823Smrg return AllocError; 702a96d7823Smrg} 703a96d7823Smrg 704a96d7823Smrgint 705a96d7823SmrgpcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) 706a96d7823Smrg{ 707a96d7823Smrg PCFTablePtr tables; 708a96d7823Smrg int ntables; 709a96d7823Smrg CARD32 format; 710a96d7823Smrg CARD32 size; 711a96d7823Smrg int nencoding; 712a96d7823Smrg Bool hasBDFAccelerators; 713a96d7823Smrg 714a96d7823Smrg pFontInfo->isStringProp = NULL; 715a96d7823Smrg pFontInfo->props = NULL; 716a96d7823Smrg pFontInfo->nprops = 0; 717a96d7823Smrg 718a96d7823Smrg if (!(tables = pcfReadTOC(file, &ntables))) 719a96d7823Smrg goto Bail; 720a96d7823Smrg 721a96d7823Smrg /* properties */ 722a96d7823Smrg 723a96d7823Smrg if (!pcfGetProperties(pFontInfo, file, tables, ntables)) 724a96d7823Smrg goto Bail; 725a96d7823Smrg 726a96d7823Smrg /* Use the old accelerators if no BDF accelerators are in the file */ 727a96d7823Smrg 728a96d7823Smrg hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); 729a96d7823Smrg if (!hasBDFAccelerators) 730a96d7823Smrg if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS)) 731a96d7823Smrg goto Bail; 732a96d7823Smrg 733a96d7823Smrg /* encoding */ 734a96d7823Smrg 735a96d7823Smrg if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) 736a96d7823Smrg goto Bail; 737a96d7823Smrg format = pcfGetLSB32(file); 738a96d7823Smrg if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) 739a96d7823Smrg goto Bail; 740a96d7823Smrg 741a96d7823Smrg pFontInfo->firstCol = pcfGetINT16(file, format); 742a96d7823Smrg pFontInfo->lastCol = pcfGetINT16(file, format); 743a96d7823Smrg pFontInfo->firstRow = pcfGetINT16(file, format); 744a96d7823Smrg pFontInfo->lastRow = pcfGetINT16(file, format); 745a96d7823Smrg pFontInfo->defaultCh = pcfGetINT16(file, format); 746a96d7823Smrg if (IS_EOF(file)) goto Bail; 747a96d7823Smrg if (pFontInfo->firstCol > pFontInfo->lastCol || 748a96d7823Smrg pFontInfo->firstRow > pFontInfo->lastRow || 749a96d7823Smrg pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail; 750a96d7823Smrg 751a96d7823Smrg nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) * 752a96d7823Smrg (pFontInfo->lastRow - pFontInfo->firstRow + 1); 753a96d7823Smrg 754a96d7823Smrg pFontInfo->allExist = TRUE; 755a96d7823Smrg while (nencoding--) { 756a96d7823Smrg if (pcfGetINT16(file, format) == 0xFFFF) 757a96d7823Smrg pFontInfo->allExist = FALSE; 758a96d7823Smrg if (IS_EOF(file)) goto Bail; 759a96d7823Smrg } 760a96d7823Smrg if (IS_EOF(file)) goto Bail; 761a96d7823Smrg 762a96d7823Smrg /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 763a96d7823Smrg 764a96d7823Smrg if (hasBDFAccelerators) 765a96d7823Smrg if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS)) 766a96d7823Smrg goto Bail; 767a96d7823Smrg 768a96d7823Smrg free(tables); 769a96d7823Smrg return Successful; 770a96d7823SmrgBail: 771a96d7823Smrg pFontInfo->nprops = 0; 772a96d7823Smrg free (pFontInfo->props); 773a96d7823Smrg free (pFontInfo->isStringProp); 774a96d7823Smrg free(tables); 775a96d7823Smrg return AllocError; 776a96d7823Smrg} 777a96d7823Smrg 778a96d7823Smrgstatic void 779a96d7823SmrgpcfUnloadFont(FontPtr pFont) 780a96d7823Smrg{ 781a96d7823Smrg BitmapFontPtr bitmapFont; 782a96d7823Smrg int i,nencoding; 783a96d7823Smrg 784a96d7823Smrg bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 785a96d7823Smrg free(bitmapFont->ink_metrics); 786a96d7823Smrg if(bitmapFont->encoding) { 787a96d7823Smrg nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 788a96d7823Smrg (pFont->info.lastRow - pFont->info.firstRow + 1); 789a96d7823Smrg for(i=0; i<NUM_SEGMENTS(nencoding); i++) 790a96d7823Smrg free(bitmapFont->encoding[i]); 791a96d7823Smrg } 792a96d7823Smrg free(bitmapFont->encoding); 793a96d7823Smrg free(bitmapFont->bitmaps); 794a96d7823Smrg free(bitmapFont->metrics); 795a96d7823Smrg free(pFont->info.isStringProp); 796a96d7823Smrg free(pFont->info.props); 797a96d7823Smrg free(bitmapFont); 798a96d7823Smrg DestroyFontRec(pFont); 799a96d7823Smrg} 800