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