snfread.c revision 41c30155
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 56#include <ctype.h> 57#include <X11/fonts/fntfilst.h> 58#include <X11/fonts/bitmap.h> 59#include "snfstr.h" 60 61#include <stdarg.h> 62 63static void _X_ATTRIBUTE_PRINTF(1, 2) 64snfError(const char* message, ...) 65{ 66 va_list args; 67 68 va_start(args, message); 69 70 fprintf(stderr, "SNF Error: "); 71 vfprintf(stderr, message, args); 72 va_end(args); 73} 74 75static void snfUnloadFont(FontPtr pFont); 76 77static int 78snfReadCharInfo(FontFilePtr file, CharInfoPtr charInfo, char *base) 79{ 80 snfCharInfoRec snfCharInfo; 81 82#define Width(m) ((m).rightSideBearing - (m).leftSideBearing) 83#define Height(m) ((m).ascent + (m).descent) 84 85 if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) != 86 sizeof(snfCharInfo)) { 87 return BadFontName; 88 } 89 charInfo->metrics = snfCharInfo.metrics; 90 if (snfCharInfo.exists) 91 charInfo->bits = base + snfCharInfo.byteOffset; 92 else 93 charInfo->bits = 0; 94 return Successful; 95} 96 97static int 98snfReadxCharInfo(FontFilePtr file, xCharInfo *charInfo) 99{ 100 snfCharInfoRec snfCharInfo; 101 102 if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) != 103 sizeof(snfCharInfo)) { 104 return BadFontName; 105 } 106 *charInfo = snfCharInfo.metrics; 107 return Successful; 108} 109 110static void 111snfCopyInfo(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo) 112{ 113 pFontInfo->firstCol = snfInfo->firstCol; 114 pFontInfo->lastCol = snfInfo->lastCol; 115 pFontInfo->firstRow = snfInfo->firstRow; 116 pFontInfo->lastRow = snfInfo->lastRow; 117 pFontInfo->defaultCh = snfInfo->chDefault; 118 pFontInfo->noOverlap = snfInfo->noOverlap; 119 pFontInfo->terminalFont = snfInfo->terminalFont; 120 pFontInfo->constantMetrics = snfInfo->constantMetrics; 121 pFontInfo->constantWidth = snfInfo->constantWidth; 122 pFontInfo->inkInside = snfInfo->inkInside; 123 pFontInfo->inkMetrics = snfInfo->inkMetrics; 124 pFontInfo->allExist = snfInfo->allExist; 125 pFontInfo->drawDirection = snfInfo->drawDirection; 126 pFontInfo->anamorphic = FALSE; 127 pFontInfo->cachable = TRUE; 128 pFontInfo->maxOverlap = 0; 129 pFontInfo->minbounds = snfInfo->minbounds.metrics; 130 pFontInfo->maxbounds = snfInfo->maxbounds.metrics; 131 pFontInfo->fontAscent = snfInfo->fontAscent; 132 pFontInfo->fontDescent = snfInfo->fontDescent; 133 pFontInfo->nprops = snfInfo->nProps; 134} 135 136static int 137snfReadProps(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo, FontFilePtr file) 138{ 139 char *strings; 140 FontPropPtr pfp; 141 snfFontPropPtr psnfp; 142 char *propspace; 143 int bytestoalloc; 144 int i; 145 146 bytestoalloc = snfInfo->nProps * sizeof(snfFontPropRec) + 147 BYTESOFSTRINGINFO(snfInfo); 148 propspace = malloc(bytestoalloc); 149 if (!propspace) { 150 snfError("snfReadProps(): Couldn't allocate propspace (%d)\n", bytestoalloc); 151 return AllocError; 152 } 153 154 if (FontFileRead(file, propspace, bytestoalloc) != bytestoalloc) { 155 free(propspace); 156 return BadFontName; 157 } 158 psnfp = (snfFontPropPtr) propspace; 159 160 strings = propspace + BYTESOFPROPINFO(snfInfo); 161 162 for (i = 0, pfp = pFontInfo->props; i < snfInfo->nProps; i++, pfp++, psnfp++) { 163 pfp->name = MakeAtom(&strings[psnfp->name], 164 (unsigned) strlen(&strings[psnfp->name]), 1); 165 pFontInfo->isStringProp[i] = psnfp->indirect; 166 if (psnfp->indirect) 167 pfp->value = (INT32) MakeAtom(&strings[psnfp->value], 168 (unsigned) strlen(&strings[psnfp->value]), 1); 169 else 170 pfp->value = psnfp->value; 171 } 172 173 free(propspace); 174 return Successful; 175} 176 177static int 178snfReadHeader(snfFontInfoPtr snfInfo, FontFilePtr file) 179{ 180 if (FontFileRead(file, (char *) snfInfo, sizeof *snfInfo) != sizeof *snfInfo) 181 return BadFontName; 182 183 if (snfInfo->version1 != FONT_FILE_VERSION || 184 snfInfo->version2 != FONT_FILE_VERSION) 185 return BadFontName; 186 return Successful; 187} 188 189static int snf_set; 190static int snf_bit, snf_byte, snf_glyph, snf_scan; 191 192void 193SnfSetFormat (int bit, int byte, int glyph, int scan) 194{ 195 snf_bit = bit; 196 snf_byte = byte; 197 snf_glyph = glyph; 198 snf_scan = scan; 199 snf_set = 1; 200} 201 202static void 203SnfGetFormat (int *bit, int *byte, int *glyph, int *scan) 204{ 205 if (!snf_set) 206 FontDefaultFormat (&snf_bit, &snf_byte, &snf_glyph, &snf_scan); 207 *bit = snf_bit; 208 *byte = snf_byte; 209 *glyph = snf_glyph; 210 *scan = snf_scan; 211} 212 213int 214snfReadFont(FontPtr pFont, FontFilePtr file, 215 int bit, int byte, int glyph, int scan) 216{ 217 snfFontInfoRec fi; 218 unsigned bytestoalloc; 219 int i, j; 220 char *fontspace; 221 BitmapFontPtr bitmapFont; 222 int num_chars; 223 int bitmapsSize; 224 int ret; 225 int metrics_off; 226 int encoding_off; 227 int props_off; 228 int isStringProp_off; 229 int ink_off; 230 char *bitmaps; 231 int def_bit, def_byte, def_glyph, def_scan; 232 233 ret = snfReadHeader(&fi, file); 234 if (ret != Successful) 235 return ret; 236 237 SnfGetFormat (&def_bit, &def_byte, &def_glyph, &def_scan); 238 239 /* 240 * we'll allocate one chunk of memory and split it among the various parts 241 * of the font: 242 * 243 * BitmapFontRec CharInfoRec's Glyphs Encoding DIX Properties Ink CharInfoRec's 244 * 245 * If the glyphpad is not the same as the font file, then the glyphs 246 * are allocated separately, to be later realloc'ed when we know 247 * how big to make them. 248 */ 249 250 bitmapsSize = BYTESOFGLYPHINFO(&fi); 251 num_chars = n2dChars(&fi); 252 bytestoalloc = sizeof(BitmapFontRec); /* bitmapFont */ 253 metrics_off = bytestoalloc; 254 bytestoalloc += num_chars * sizeof(CharInfoRec); /* metrics */ 255 encoding_off = bytestoalloc; 256 bytestoalloc += NUM_SEGMENTS(num_chars) * sizeof(CharInfoPtr**); 257 /* encoding */ 258 props_off = bytestoalloc; 259 bytestoalloc += fi.nProps * sizeof(FontPropRec); /* props */ 260 isStringProp_off = bytestoalloc; 261 bytestoalloc += fi.nProps * sizeof(char); /* isStringProp */ 262 bytestoalloc = (bytestoalloc + 3) & ~3; 263 ink_off = bytestoalloc; 264 if (fi.inkMetrics) 265 bytestoalloc += num_chars * sizeof(xCharInfo); /* ink_metrics */ 266 267 fontspace = malloc(bytestoalloc); 268 if (!fontspace) { 269 snfError("snfReadFont(): Couldn't allocate fontspace (%d)\n", bytestoalloc); 270 return AllocError; 271 } 272 bitmaps = malloc (bitmapsSize); 273 if (!bitmaps) 274 { 275 snfError("snfReadFont(): Couldn't allocate bitmaps (%d)\n", bitmapsSize); 276 free (fontspace); 277 return AllocError; 278 } 279 /* 280 * now fix up pointers 281 */ 282 283 bitmapFont = (BitmapFontPtr) fontspace; 284 bitmapFont->num_chars = num_chars; 285 bitmapFont->metrics = (CharInfoPtr) (fontspace + metrics_off); 286 bitmapFont->encoding = (CharInfoPtr **) (fontspace + encoding_off); 287 bitmapFont->bitmaps = bitmaps; 288 bitmapFont->pDefault = NULL; 289 bitmapFont->bitmapExtra = NULL; 290 pFont->info.props = (FontPropPtr) (fontspace + props_off); 291 pFont->info.isStringProp = (char *) (fontspace + isStringProp_off); 292 if (fi.inkMetrics) 293 bitmapFont->ink_metrics = (xCharInfo *) (fontspace + ink_off); 294 else 295 bitmapFont->ink_metrics = 0; 296 297 /* 298 * read the CharInfo 299 */ 300 301 ret = Successful; 302 memset(bitmapFont->encoding, 0, 303 NUM_SEGMENTS(num_chars)*sizeof(CharInfoPtr*)); 304 for (i = 0; ret == Successful && i < num_chars; i++) { 305 ret = snfReadCharInfo(file, &bitmapFont->metrics[i], bitmaps); 306 if (bitmapFont->metrics[i].bits) { 307 if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { 308 bitmapFont->encoding[SEGMENT_MAJOR(i)]= 309 calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); 310 if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { 311 ret = AllocError; 312 break; 313 } 314 } 315 ACCESSENCODINGL(bitmapFont->encoding,i) = &bitmapFont->metrics[i]; 316 } 317 } 318 319 if (ret != Successful) { 320 free(bitmaps); 321 if(bitmapFont->encoding) { 322 for(j=0; j<SEGMENT_MAJOR(i); j++) 323 free(bitmapFont->encoding[i]); 324 } 325 free(fontspace); 326 return ret; 327 } 328 /* 329 * read the glyphs 330 */ 331 332 if (FontFileRead(file, bitmaps, bitmapsSize) != bitmapsSize) { 333 free(bitmaps); 334 free(fontspace); 335 return BadFontName; 336 } 337 338 if (def_bit != bit) 339 BitOrderInvert((unsigned char *)bitmaps, bitmapsSize); 340 if ((def_byte == def_bit) != (bit == byte)) { 341 switch (bit == byte ? def_scan : scan) { 342 case 1: 343 break; 344 case 2: 345 TwoByteSwap((unsigned char *)bitmaps, bitmapsSize); 346 break; 347 case 4: 348 FourByteSwap((unsigned char *)bitmaps, bitmapsSize); 349 break; 350 } 351 } 352 if (def_glyph != glyph) { 353 char *padbitmaps; 354 int sizepadbitmaps; 355 int sizechar; 356 CharInfoPtr metric; 357 358 sizepadbitmaps = 0; 359 metric = bitmapFont->metrics; 360 for (i = 0; i < num_chars; i++) 361 { 362 if (metric->bits) 363 sizepadbitmaps += BYTES_FOR_GLYPH(metric,glyph); 364 metric++; 365 } 366 padbitmaps = malloc(sizepadbitmaps); 367 if (!padbitmaps) { 368 snfError("snfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); 369 free (bitmaps); 370 free (fontspace); 371 return AllocError; 372 } 373 metric = bitmapFont->metrics; 374 bitmapFont->bitmaps = padbitmaps; 375 for (i = 0; i < num_chars; i++) { 376 sizechar = RepadBitmap(metric->bits, padbitmaps, 377 def_glyph, glyph, 378 metric->metrics.rightSideBearing - 379 metric->metrics.leftSideBearing, 380 metric->metrics.ascent + metric->metrics.descent); 381 metric->bits = padbitmaps; 382 padbitmaps += sizechar; 383 metric++; 384 } 385 free(bitmaps); 386 } 387 388 /* now read and atom'ize properties */ 389 390 ret = snfReadProps(&fi, &pFont->info, file); 391 if (ret != Successful) { 392 free(fontspace); 393 return ret; 394 } 395 snfCopyInfo(&fi, &pFont->info); 396 397 /* finally, read the ink metrics if the exist */ 398 399 if (fi.inkMetrics) { 400 ret = Successful; 401 ret = snfReadxCharInfo(file, &pFont->info.ink_minbounds); 402 ret = snfReadxCharInfo(file, &pFont->info.ink_maxbounds); 403 for (i = 0; ret == Successful && i < num_chars; i++) 404 ret = snfReadxCharInfo(file, &bitmapFont->ink_metrics[i]); 405 if (ret != Successful) { 406 free(fontspace); 407 return ret; 408 } 409 } else { 410 pFont->info.ink_minbounds = pFont->info.minbounds; 411 pFont->info.ink_maxbounds = pFont->info.maxbounds; 412 } 413 414 if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { 415 unsigned int r, 416 c, 417 cols; 418 419 r = pFont->info.defaultCh >> 8; 420 c = pFont->info.defaultCh & 0xFF; 421 if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && 422 pFont->info.firstCol <= c && c <= pFont->info.lastCol) { 423 cols = pFont->info.lastCol - pFont->info.firstCol + 1; 424 r = r - pFont->info.firstRow; 425 c = c - pFont->info.firstCol; 426 bitmapFont->pDefault = &bitmapFont->metrics[r * cols + c]; 427 } 428 } 429 bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; 430 pFont->fontPrivate = (pointer) bitmapFont; 431 pFont->get_glyphs = bitmapGetGlyphs; 432 pFont->get_metrics = bitmapGetMetrics; 433 pFont->unload_font = snfUnloadFont; 434 pFont->unload_glyphs = NULL; 435 pFont->bit = bit; 436 pFont->byte = byte; 437 pFont->glyph = glyph; 438 pFont->scan = scan; 439 return Successful; 440} 441 442int 443snfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) 444{ 445 int ret; 446 snfFontInfoRec fi; 447 int bytestoskip; 448 int num_chars; 449 450 ret = snfReadHeader(&fi, file); 451 if (ret != Successful) 452 return ret; 453 snfCopyInfo(&fi, pFontInfo); 454 455 pFontInfo->props = malloc(fi.nProps * sizeof(FontPropRec)); 456 if (!pFontInfo->props) { 457 snfError("snfReadFontInfo(): Couldn't allocate props (%d*%d)\n", 458 fi.nProps, (int) sizeof(FontPropRec)); 459 return AllocError; 460 } 461 pFontInfo->isStringProp = malloc(fi.nProps * sizeof(char)); 462 if (!pFontInfo->isStringProp) { 463 snfError("snfReadFontInfo(): Couldn't allocate isStringProp (%d*%d)\n", 464 fi.nProps, (int) sizeof(char)); 465 free(pFontInfo->props); 466 return AllocError; 467 } 468 num_chars = n2dChars(&fi); 469 bytestoskip = num_chars * sizeof(snfCharInfoRec); /* charinfos */ 470 bytestoskip += BYTESOFGLYPHINFO(&fi); 471 (void)FontFileSkip(file, bytestoskip); 472 473 ret = snfReadProps(&fi, pFontInfo, file); 474 if (ret != Successful) { 475 free(pFontInfo->props); 476 free(pFontInfo->isStringProp); 477 return ret; 478 } 479 if (fi.inkMetrics) { 480 ret = snfReadxCharInfo(file, &pFontInfo->ink_minbounds); 481 if (ret != Successful) { 482 free(pFontInfo->props); 483 free(pFontInfo->isStringProp); 484 return ret; 485 } 486 ret = snfReadxCharInfo(file, &pFontInfo->ink_maxbounds); 487 if (ret != Successful) { 488 free(pFontInfo->props); 489 free(pFontInfo->isStringProp); 490 return ret; 491 } 492 } else { 493 pFontInfo->ink_minbounds = pFontInfo->minbounds; 494 pFontInfo->ink_maxbounds = pFontInfo->maxbounds; 495 } 496 return Successful; 497 498} 499 500static void 501snfUnloadFont(FontPtr pFont) 502{ 503 BitmapFontPtr bitmapFont; 504 505 bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 506 free (bitmapFont->bitmaps); 507 free (bitmapFont); 508 DestroyFontRec (pFont); 509} 510 511