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