snfread.c revision a96d7823
1/************************************************************************ 2Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, and distribute this software and its 7documentation for any purpose and without fee is hereby granted, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Digital not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. 13 14DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20SOFTWARE. 21 22************************************************************************/ 23 24/* 25 26Copyright 1994, 1998 The Open Group 27 28Permission to use, copy, modify, distribute, and sell this software and its 29documentation for any purpose is hereby granted without fee, provided that 30the above copyright notice appear in all copies and that both that 31copyright notice and this permission notice appear in supporting 32documentation. 33 34The above copyright notice and this permission notice shall be included 35in all copies or substantial portions of the Software. 36 37THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 38OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 39MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 40IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 41OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 42ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 43OTHER DEALINGS IN THE SOFTWARE. 44 45Except as contained in this notice, the name of The Open Group shall 46not be used in advertising or otherwise to promote the sale, use or 47other dealings in this Software without prior written authorization 48from The Open Group. 49 50*/ 51 52#ifdef HAVE_CONFIG_H 53#include <config.h> 54#endif 55#include "libxfontint.h" 56 57#include <ctype.h> 58#include <X11/fonts/fntfilst.h> 59#include <X11/fonts/bitmap.h> 60#include "snfstr.h" 61 62#include <stdarg.h> 63 64static void _X_ATTRIBUTE_PRINTF(1, 2) 65snfError(const char* message, ...) 66{ 67 va_list args; 68 69 va_start(args, message); 70 71 fprintf(stderr, "SNF Error: "); 72 vfprintf(stderr, message, args); 73 va_end(args); 74} 75 76static void snfUnloadFont(FontPtr pFont); 77 78static int 79snfReadCharInfo(FontFilePtr file, CharInfoPtr charInfo, char *base) 80{ 81 snfCharInfoRec snfCharInfo; 82 83#define Width(m) ((m).rightSideBearing - (m).leftSideBearing) 84#define Height(m) ((m).ascent + (m).descent) 85 86 if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) != 87 sizeof(snfCharInfo)) { 88 return BadFontName; 89 } 90 charInfo->metrics = snfCharInfo.metrics; 91 if (snfCharInfo.exists) 92 charInfo->bits = base + snfCharInfo.byteOffset; 93 else 94 charInfo->bits = 0; 95 return Successful; 96} 97 98static int 99snfReadxCharInfo(FontFilePtr file, xCharInfo *charInfo) 100{ 101 snfCharInfoRec snfCharInfo; 102 103 if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) != 104 sizeof(snfCharInfo)) { 105 return BadFontName; 106 } 107 *charInfo = snfCharInfo.metrics; 108 return Successful; 109} 110 111static void 112snfCopyInfo(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo) 113{ 114 pFontInfo->firstCol = snfInfo->firstCol; 115 pFontInfo->lastCol = snfInfo->lastCol; 116 pFontInfo->firstRow = snfInfo->firstRow; 117 pFontInfo->lastRow = snfInfo->lastRow; 118 pFontInfo->defaultCh = snfInfo->chDefault; 119 pFontInfo->noOverlap = snfInfo->noOverlap; 120 pFontInfo->terminalFont = snfInfo->terminalFont; 121 pFontInfo->constantMetrics = snfInfo->constantMetrics; 122 pFontInfo->constantWidth = snfInfo->constantWidth; 123 pFontInfo->inkInside = snfInfo->inkInside; 124 pFontInfo->inkMetrics = snfInfo->inkMetrics; 125 pFontInfo->allExist = snfInfo->allExist; 126 pFontInfo->drawDirection = snfInfo->drawDirection; 127 pFontInfo->anamorphic = FALSE; 128 pFontInfo->cachable = TRUE; 129 pFontInfo->maxOverlap = 0; 130 pFontInfo->minbounds = snfInfo->minbounds.metrics; 131 pFontInfo->maxbounds = snfInfo->maxbounds.metrics; 132 pFontInfo->fontAscent = snfInfo->fontAscent; 133 pFontInfo->fontDescent = snfInfo->fontDescent; 134 pFontInfo->nprops = snfInfo->nProps; 135} 136 137static int 138snfReadProps(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo, FontFilePtr file) 139{ 140 char *strings; 141 FontPropPtr pfp; 142 snfFontPropPtr psnfp; 143 char *propspace; 144 int bytestoalloc; 145 int i; 146 147 bytestoalloc = snfInfo->nProps * sizeof(snfFontPropRec) + 148 BYTESOFSTRINGINFO(snfInfo); 149 propspace = malloc(bytestoalloc); 150 if (!propspace) { 151 snfError("snfReadProps(): Couldn't allocate propspace (%d)\n", bytestoalloc); 152 return AllocError; 153 } 154 155 if (FontFileRead(file, propspace, bytestoalloc) != bytestoalloc) { 156 free(propspace); 157 return BadFontName; 158 } 159 psnfp = (snfFontPropPtr) propspace; 160 161 strings = propspace + BYTESOFPROPINFO(snfInfo); 162 163 for (i = 0, pfp = pFontInfo->props; i < snfInfo->nProps; i++, pfp++, psnfp++) { 164 pfp->name = MakeAtom(&strings[psnfp->name], 165 (unsigned) strlen(&strings[psnfp->name]), 1); 166 pFontInfo->isStringProp[i] = psnfp->indirect; 167 if (psnfp->indirect) 168 pfp->value = (INT32) MakeAtom(&strings[psnfp->value], 169 (unsigned) strlen(&strings[psnfp->value]), 1); 170 else 171 pfp->value = psnfp->value; 172 } 173 174 free(propspace); 175 return Successful; 176} 177 178static int 179snfReadHeader(snfFontInfoPtr snfInfo, FontFilePtr file) 180{ 181 if (FontFileRead(file, (char *) snfInfo, sizeof *snfInfo) != sizeof *snfInfo) 182 return BadFontName; 183 184 if (snfInfo->version1 != FONT_FILE_VERSION || 185 snfInfo->version2 != FONT_FILE_VERSION) 186 return BadFontName; 187 return Successful; 188} 189 190static int snf_set; 191static int snf_bit, snf_byte, snf_glyph, snf_scan; 192 193void 194SnfSetFormat (int bit, int byte, int glyph, int scan) 195{ 196 snf_bit = bit; 197 snf_byte = byte; 198 snf_glyph = glyph; 199 snf_scan = scan; 200 snf_set = 1; 201} 202 203static void 204SnfGetFormat (int *bit, int *byte, int *glyph, int *scan) 205{ 206 if (!snf_set) 207 FontDefaultFormat (&snf_bit, &snf_byte, &snf_glyph, &snf_scan); 208 *bit = snf_bit; 209 *byte = snf_byte; 210 *glyph = snf_glyph; 211 *scan = snf_scan; 212} 213 214int 215snfReadFont(FontPtr pFont, FontFilePtr file, 216 int bit, int byte, int glyph, int scan) 217{ 218 snfFontInfoRec fi; 219 unsigned bytestoalloc; 220 int i, j; 221 char *fontspace; 222 BitmapFontPtr bitmapFont; 223 int num_chars; 224 int bitmapsSize; 225 int ret; 226 int metrics_off; 227 int encoding_off; 228 int props_off; 229 int isStringProp_off; 230 int ink_off; 231 char *bitmaps; 232 int def_bit, def_byte, def_glyph, def_scan; 233 234 ret = snfReadHeader(&fi, file); 235 if (ret != Successful) 236 return ret; 237 238 SnfGetFormat (&def_bit, &def_byte, &def_glyph, &def_scan); 239 240 /* 241 * we'll allocate one chunk of memory and split it among the various parts 242 * of the font: 243 * 244 * BitmapFontRec CharInfoRec's Glyphs Encoding DIX Properties Ink CharInfoRec's 245 * 246 * If the glyphpad is not the same as the font file, then the glyphs 247 * are allocated separately, to be later realloc'ed when we know 248 * how big to make them. 249 */ 250 251 bitmapsSize = BYTESOFGLYPHINFO(&fi); 252 num_chars = n2dChars(&fi); 253 bytestoalloc = sizeof(BitmapFontRec); /* bitmapFont */ 254 metrics_off = bytestoalloc; 255 bytestoalloc += num_chars * sizeof(CharInfoRec); /* metrics */ 256 encoding_off = bytestoalloc; 257 bytestoalloc += NUM_SEGMENTS(num_chars) * sizeof(CharInfoPtr**); 258 /* encoding */ 259 props_off = bytestoalloc; 260 bytestoalloc += fi.nProps * sizeof(FontPropRec); /* props */ 261 isStringProp_off = bytestoalloc; 262 bytestoalloc += fi.nProps * sizeof(char); /* isStringProp */ 263 bytestoalloc = (bytestoalloc + 3) & ~3; 264 ink_off = bytestoalloc; 265 if (fi.inkMetrics) 266 bytestoalloc += num_chars * sizeof(xCharInfo); /* ink_metrics */ 267 268 fontspace = malloc(bytestoalloc); 269 if (!fontspace) { 270 snfError("snfReadFont(): Couldn't allocate fontspace (%d)\n", bytestoalloc); 271 return AllocError; 272 } 273 bitmaps = malloc (bitmapsSize); 274 if (!bitmaps) 275 { 276 snfError("snfReadFont(): Couldn't allocate bitmaps (%d)\n", bitmapsSize); 277 free (fontspace); 278 return AllocError; 279 } 280 /* 281 * now fix up pointers 282 */ 283 284 bitmapFont = (BitmapFontPtr) fontspace; 285 bitmapFont->num_chars = num_chars; 286 bitmapFont->metrics = (CharInfoPtr) (fontspace + metrics_off); 287 bitmapFont->encoding = (CharInfoPtr **) (fontspace + encoding_off); 288 bitmapFont->bitmaps = bitmaps; 289 bitmapFont->pDefault = NULL; 290 bitmapFont->bitmapExtra = NULL; 291 pFont->info.props = (FontPropPtr) (fontspace + props_off); 292 pFont->info.isStringProp = (char *) (fontspace + isStringProp_off); 293 if (fi.inkMetrics) 294 bitmapFont->ink_metrics = (xCharInfo *) (fontspace + ink_off); 295 else 296 bitmapFont->ink_metrics = 0; 297 298 /* 299 * read the CharInfo 300 */ 301 302 ret = Successful; 303 memset(bitmapFont->encoding, 0, 304 NUM_SEGMENTS(num_chars)*sizeof(CharInfoPtr*)); 305 for (i = 0; ret == Successful && i < num_chars; i++) { 306 ret = snfReadCharInfo(file, &bitmapFont->metrics[i], bitmaps); 307 if (bitmapFont->metrics[i].bits) { 308 if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { 309 bitmapFont->encoding[SEGMENT_MAJOR(i)]= 310 calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); 311 if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { 312 ret = AllocError; 313 break; 314 } 315 } 316 ACCESSENCODINGL(bitmapFont->encoding,i) = &bitmapFont->metrics[i]; 317 } 318 } 319 320 if (ret != Successful) { 321 free(bitmaps); 322 if(bitmapFont->encoding) { 323 for(j=0; j<SEGMENT_MAJOR(i); j++) 324 free(bitmapFont->encoding[i]); 325 } 326 free(fontspace); 327 return ret; 328 } 329 /* 330 * read the glyphs 331 */ 332 333 if (FontFileRead(file, bitmaps, bitmapsSize) != bitmapsSize) { 334 free(bitmaps); 335 free(fontspace); 336 return BadFontName; 337 } 338 339 if (def_bit != bit) 340 BitOrderInvert((unsigned char *)bitmaps, bitmapsSize); 341 if ((def_byte == def_bit) != (bit == byte)) { 342 switch (bit == byte ? def_scan : scan) { 343 case 1: 344 break; 345 case 2: 346 TwoByteSwap((unsigned char *)bitmaps, bitmapsSize); 347 break; 348 case 4: 349 FourByteSwap((unsigned char *)bitmaps, bitmapsSize); 350 break; 351 } 352 } 353 if (def_glyph != glyph) { 354 char *padbitmaps; 355 int sizepadbitmaps; 356 int sizechar; 357 CharInfoPtr metric; 358 359 sizepadbitmaps = 0; 360 metric = bitmapFont->metrics; 361 for (i = 0; i < num_chars; i++) 362 { 363 if (metric->bits) 364 sizepadbitmaps += BYTES_FOR_GLYPH(metric,glyph); 365 metric++; 366 } 367 padbitmaps = malloc(sizepadbitmaps); 368 if (!padbitmaps) { 369 snfError("snfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); 370 free (bitmaps); 371 free (fontspace); 372 return AllocError; 373 } 374 metric = bitmapFont->metrics; 375 bitmapFont->bitmaps = padbitmaps; 376 for (i = 0; i < num_chars; i++) { 377 sizechar = RepadBitmap(metric->bits, padbitmaps, 378 def_glyph, glyph, 379 metric->metrics.rightSideBearing - 380 metric->metrics.leftSideBearing, 381 metric->metrics.ascent + metric->metrics.descent); 382 metric->bits = padbitmaps; 383 padbitmaps += sizechar; 384 metric++; 385 } 386 free(bitmaps); 387 } 388 389 /* now read and atom'ize properties */ 390 391 ret = snfReadProps(&fi, &pFont->info, file); 392 if (ret != Successful) { 393 free(fontspace); 394 return ret; 395 } 396 snfCopyInfo(&fi, &pFont->info); 397 398 /* finally, read the ink metrics if the exist */ 399 400 if (fi.inkMetrics) { 401 ret = Successful; 402 ret = snfReadxCharInfo(file, &pFont->info.ink_minbounds); 403 ret = snfReadxCharInfo(file, &pFont->info.ink_maxbounds); 404 for (i = 0; ret == Successful && i < num_chars; i++) 405 ret = snfReadxCharInfo(file, &bitmapFont->ink_metrics[i]); 406 if (ret != Successful) { 407 free(fontspace); 408 return ret; 409 } 410 } else { 411 pFont->info.ink_minbounds = pFont->info.minbounds; 412 pFont->info.ink_maxbounds = pFont->info.maxbounds; 413 } 414 415 if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { 416 unsigned int r, 417 c, 418 cols; 419 420 r = pFont->info.defaultCh >> 8; 421 c = pFont->info.defaultCh & 0xFF; 422 if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && 423 pFont->info.firstCol <= c && c <= pFont->info.lastCol) { 424 cols = pFont->info.lastCol - pFont->info.firstCol + 1; 425 r = r - pFont->info.firstRow; 426 c = c - pFont->info.firstCol; 427 bitmapFont->pDefault = &bitmapFont->metrics[r * cols + c]; 428 } 429 } 430 bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; 431 pFont->fontPrivate = (pointer) bitmapFont; 432 pFont->get_glyphs = bitmapGetGlyphs; 433 pFont->get_metrics = bitmapGetMetrics; 434 pFont->unload_font = snfUnloadFont; 435 pFont->unload_glyphs = NULL; 436 pFont->bit = bit; 437 pFont->byte = byte; 438 pFont->glyph = glyph; 439 pFont->scan = scan; 440 return Successful; 441} 442 443int 444snfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) 445{ 446 int ret; 447 snfFontInfoRec fi; 448 int bytestoskip; 449 int num_chars; 450 451 ret = snfReadHeader(&fi, file); 452 if (ret != Successful) 453 return ret; 454 snfCopyInfo(&fi, pFontInfo); 455 456 pFontInfo->props = malloc(fi.nProps * sizeof(FontPropRec)); 457 if (!pFontInfo->props) { 458 snfError("snfReadFontInfo(): Couldn't allocate props (%d*%d)\n", 459 fi.nProps, (int) sizeof(FontPropRec)); 460 return AllocError; 461 } 462 pFontInfo->isStringProp = malloc(fi.nProps * sizeof(char)); 463 if (!pFontInfo->isStringProp) { 464 snfError("snfReadFontInfo(): Couldn't allocate isStringProp (%d*%d)\n", 465 fi.nProps, (int) sizeof(char)); 466 free(pFontInfo->props); 467 return AllocError; 468 } 469 num_chars = n2dChars(&fi); 470 bytestoskip = num_chars * sizeof(snfCharInfoRec); /* charinfos */ 471 bytestoskip += BYTESOFGLYPHINFO(&fi); 472 (void)FontFileSkip(file, bytestoskip); 473 474 ret = snfReadProps(&fi, pFontInfo, file); 475 if (ret != Successful) { 476 free(pFontInfo->props); 477 free(pFontInfo->isStringProp); 478 return ret; 479 } 480 if (fi.inkMetrics) { 481 ret = snfReadxCharInfo(file, &pFontInfo->ink_minbounds); 482 if (ret != Successful) { 483 free(pFontInfo->props); 484 free(pFontInfo->isStringProp); 485 return ret; 486 } 487 ret = snfReadxCharInfo(file, &pFontInfo->ink_maxbounds); 488 if (ret != Successful) { 489 free(pFontInfo->props); 490 free(pFontInfo->isStringProp); 491 return ret; 492 } 493 } else { 494 pFontInfo->ink_minbounds = pFontInfo->minbounds; 495 pFontInfo->ink_maxbounds = pFontInfo->maxbounds; 496 } 497 return Successful; 498 499} 500 501static void 502snfUnloadFont(FontPtr pFont) 503{ 504 BitmapFontPtr bitmapFont; 505 506 bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 507 free (bitmapFont->bitmaps); 508 free (bitmapFont); 509 DestroyFontRec (pFont); 510} 511 512