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#include "src/util/replace.h" 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 _X_ATTRIBUTE_PRINTF(1, 2) 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 = mallocarray(fi.nProps, sizeof(FontPropRec)); 458 if (!pFontInfo->props) { 459 snfError("snfReadFontInfo(): Couldn't allocate props (%d*%d)\n", 460 fi.nProps, (int) sizeof(FontPropRec)); 461 return AllocError; 462 } 463 pFontInfo->isStringProp = mallocarray(fi.nProps, sizeof(char)); 464 if (!pFontInfo->isStringProp) { 465 snfError("snfReadFontInfo(): Couldn't allocate isStringProp (%d*%d)\n", 466 fi.nProps, (int) sizeof(char)); 467 free(pFontInfo->props); 468 return AllocError; 469 } 470 num_chars = n2dChars(&fi); 471 bytestoskip = num_chars * sizeof(snfCharInfoRec); /* charinfos */ 472 bytestoskip += BYTESOFGLYPHINFO(&fi); 473 (void)FontFileSkip(file, bytestoskip); 474 475 ret = snfReadProps(&fi, pFontInfo, file); 476 if (ret != Successful) { 477 free(pFontInfo->props); 478 free(pFontInfo->isStringProp); 479 return ret; 480 } 481 if (fi.inkMetrics) { 482 ret = snfReadxCharInfo(file, &pFontInfo->ink_minbounds); 483 if (ret != Successful) { 484 free(pFontInfo->props); 485 free(pFontInfo->isStringProp); 486 return ret; 487 } 488 ret = snfReadxCharInfo(file, &pFontInfo->ink_maxbounds); 489 if (ret != Successful) { 490 free(pFontInfo->props); 491 free(pFontInfo->isStringProp); 492 return ret; 493 } 494 } else { 495 pFontInfo->ink_minbounds = pFontInfo->minbounds; 496 pFontInfo->ink_maxbounds = pFontInfo->maxbounds; 497 } 498 return Successful; 499 500} 501 502static void 503snfUnloadFont(FontPtr pFont) 504{ 505 BitmapFontPtr bitmapFont; 506 507 bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 508 free (bitmapFont->bitmaps); 509 free (bitmapFont); 510 DestroyFontRec (pFont); 511} 512 513