1 /* bdfdrivr.c 2 3 FreeType font driver for bdf files 4 5 Copyright (C) 2001-2008, 2011, 2013, 2014 by 6 Francesco Zappa Nardelli 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 */ 26 27 #include <ft2build.h> 28 29 #include FT_INTERNAL_DEBUG_H 30 #include FT_INTERNAL_STREAM_H 31 #include FT_INTERNAL_OBJECTS_H 32 #include FT_BDF_H 33 #include FT_TRUETYPE_IDS_H 34 35 #include FT_SERVICE_BDF_H 36 #include FT_SERVICE_FONT_FORMAT_H 37 38 #include "bdf.h" 39 #include "bdfdrivr.h" 40 41 #include "bdferror.h" 42 43 44 /************************************************************************** 45 * 46 * The macro FT_COMPONENT is used in trace mode. It is an implicit 47 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 48 * messages during execution. 49 */ 50 #undef FT_COMPONENT 51 #define FT_COMPONENT trace_bdfdriver 52 53 54 typedef struct BDF_CMapRec_ 55 { 56 FT_CMapRec cmap; 57 FT_ULong num_encodings; /* ftobjs.h: FT_CMap->clazz->size */ 58 BDF_encoding_el* encodings; 59 60 } BDF_CMapRec, *BDF_CMap; 61 62 63 FT_CALLBACK_DEF( FT_Error ) bdf_cmap_init(FT_CMap bdfcmap,FT_Pointer init_data)64 bdf_cmap_init( FT_CMap bdfcmap, 65 FT_Pointer init_data ) 66 { 67 BDF_CMap cmap = (BDF_CMap)bdfcmap; 68 BDF_Face face = (BDF_Face)FT_CMAP_FACE( cmap ); 69 FT_UNUSED( init_data ); 70 71 72 cmap->num_encodings = face->bdffont->glyphs_used; 73 cmap->encodings = face->en_table; 74 75 return FT_Err_Ok; 76 } 77 78 79 FT_CALLBACK_DEF( void ) bdf_cmap_done(FT_CMap bdfcmap)80 bdf_cmap_done( FT_CMap bdfcmap ) 81 { 82 BDF_CMap cmap = (BDF_CMap)bdfcmap; 83 84 85 cmap->encodings = NULL; 86 cmap->num_encodings = 0; 87 } 88 89 90 FT_CALLBACK_DEF( FT_UInt ) bdf_cmap_char_index(FT_CMap bdfcmap,FT_UInt32 charcode)91 bdf_cmap_char_index( FT_CMap bdfcmap, 92 FT_UInt32 charcode ) 93 { 94 BDF_CMap cmap = (BDF_CMap)bdfcmap; 95 BDF_encoding_el* encodings = cmap->encodings; 96 FT_ULong min, max, mid; /* num_encodings */ 97 FT_UShort result = 0; /* encodings->glyph */ 98 99 100 min = 0; 101 max = cmap->num_encodings; 102 103 while ( min < max ) 104 { 105 FT_ULong code; 106 107 108 mid = ( min + max ) >> 1; 109 code = (FT_ULong)encodings[mid].enc; 110 111 if ( charcode == code ) 112 { 113 /* increase glyph index by 1 -- */ 114 /* we reserve slot 0 for the undefined glyph */ 115 result = encodings[mid].glyph + 1; 116 break; 117 } 118 119 if ( charcode < code ) 120 max = mid; 121 else 122 min = mid + 1; 123 } 124 125 return result; 126 } 127 128 129 FT_CALLBACK_DEF( FT_UInt ) bdf_cmap_char_next(FT_CMap bdfcmap,FT_UInt32 * acharcode)130 bdf_cmap_char_next( FT_CMap bdfcmap, 131 FT_UInt32 *acharcode ) 132 { 133 BDF_CMap cmap = (BDF_CMap)bdfcmap; 134 BDF_encoding_el* encodings = cmap->encodings; 135 FT_ULong min, max, mid; /* num_encodings */ 136 FT_UShort result = 0; /* encodings->glyph */ 137 FT_ULong charcode = *acharcode + 1; 138 139 140 min = 0; 141 max = cmap->num_encodings; 142 143 while ( min < max ) 144 { 145 FT_ULong code; /* same as BDF_encoding_el.enc */ 146 147 148 mid = ( min + max ) >> 1; 149 code = (FT_ULong)encodings[mid].enc; 150 151 if ( charcode == code ) 152 { 153 /* increase glyph index by 1 -- */ 154 /* we reserve slot 0 for the undefined glyph */ 155 result = encodings[mid].glyph + 1; 156 goto Exit; 157 } 158 159 if ( charcode < code ) 160 max = mid; 161 else 162 min = mid + 1; 163 } 164 165 charcode = 0; 166 if ( min < cmap->num_encodings ) 167 { 168 charcode = (FT_ULong)encodings[min].enc; 169 result = encodings[min].glyph + 1; 170 } 171 172 Exit: 173 if ( charcode > 0xFFFFFFFFUL ) 174 { 175 FT_TRACE1(( "bdf_cmap_char_next: charcode 0x%x > 32bit API" )); 176 *acharcode = 0; 177 /* XXX: result should be changed to indicate an overflow error */ 178 } 179 else 180 *acharcode = (FT_UInt32)charcode; 181 return result; 182 } 183 184 185 static 186 const FT_CMap_ClassRec bdf_cmap_class = 187 { 188 sizeof ( BDF_CMapRec ), 189 bdf_cmap_init, 190 bdf_cmap_done, 191 bdf_cmap_char_index, 192 bdf_cmap_char_next, 193 194 NULL, NULL, NULL, NULL, NULL 195 }; 196 197 198 static FT_Error bdf_interpret_style(BDF_Face bdf)199 bdf_interpret_style( BDF_Face bdf ) 200 { 201 FT_Error error = FT_Err_Ok; 202 FT_Face face = FT_FACE( bdf ); 203 FT_Memory memory = face->memory; 204 bdf_font_t* font = bdf->bdffont; 205 bdf_property_t* prop; 206 207 char* strings[4] = { NULL, NULL, NULL, NULL }; 208 size_t nn, len, lengths[4]; 209 210 211 face->style_flags = 0; 212 213 prop = bdf_get_font_property( font, (char *)"SLANT" ); 214 if ( prop && prop->format == BDF_ATOM && 215 prop->value.atom && 216 ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' || 217 *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) ) 218 { 219 face->style_flags |= FT_STYLE_FLAG_ITALIC; 220 strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ) 221 ? (char *)"Oblique" 222 : (char *)"Italic"; 223 } 224 225 prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" ); 226 if ( prop && prop->format == BDF_ATOM && 227 prop->value.atom && 228 ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) ) 229 { 230 face->style_flags |= FT_STYLE_FLAG_BOLD; 231 strings[1] = (char *)"Bold"; 232 } 233 234 prop = bdf_get_font_property( font, (char *)"SETWIDTH_NAME" ); 235 if ( prop && prop->format == BDF_ATOM && 236 prop->value.atom && *(prop->value.atom) && 237 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) 238 strings[3] = (char *)(prop->value.atom); 239 240 prop = bdf_get_font_property( font, (char *)"ADD_STYLE_NAME" ); 241 if ( prop && prop->format == BDF_ATOM && 242 prop->value.atom && *(prop->value.atom) && 243 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) 244 strings[0] = (char *)(prop->value.atom); 245 246 for ( len = 0, nn = 0; nn < 4; nn++ ) 247 { 248 lengths[nn] = 0; 249 if ( strings[nn] ) 250 { 251 lengths[nn] = ft_strlen( strings[nn] ); 252 len += lengths[nn] + 1; 253 } 254 } 255 256 if ( len == 0 ) 257 { 258 strings[0] = (char *)"Regular"; 259 lengths[0] = ft_strlen( strings[0] ); 260 len = lengths[0] + 1; 261 } 262 263 { 264 char* s; 265 266 267 if ( FT_ALLOC( face->style_name, len ) ) 268 return error; 269 270 s = face->style_name; 271 272 for ( nn = 0; nn < 4; nn++ ) 273 { 274 char* src = strings[nn]; 275 276 277 len = lengths[nn]; 278 279 if ( !src ) 280 continue; 281 282 /* separate elements with a space */ 283 if ( s != face->style_name ) 284 *s++ = ' '; 285 286 ft_memcpy( s, src, len ); 287 288 /* need to convert spaces to dashes for */ 289 /* add_style_name and setwidth_name */ 290 if ( nn == 0 || nn == 3 ) 291 { 292 size_t mm; 293 294 295 for ( mm = 0; mm < len; mm++ ) 296 if ( s[mm] == ' ' ) 297 s[mm] = '-'; 298 } 299 300 s += len; 301 } 302 *s = 0; 303 } 304 305 return error; 306 } 307 308 309 FT_CALLBACK_DEF( void ) BDF_Face_Done(FT_Face bdfface)310 BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */ 311 { 312 BDF_Face face = (BDF_Face)bdfface; 313 FT_Memory memory; 314 315 316 if ( !face ) 317 return; 318 319 memory = FT_FACE_MEMORY( face ); 320 321 bdf_free_font( face->bdffont ); 322 323 FT_FREE( face->en_table ); 324 325 FT_FREE( face->charset_encoding ); 326 FT_FREE( face->charset_registry ); 327 FT_FREE( bdfface->family_name ); 328 FT_FREE( bdfface->style_name ); 329 330 FT_FREE( bdfface->available_sizes ); 331 332 FT_FREE( face->bdffont ); 333 } 334 335 336 FT_CALLBACK_DEF( FT_Error ) BDF_Face_Init(FT_Stream stream,FT_Face bdfface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)337 BDF_Face_Init( FT_Stream stream, 338 FT_Face bdfface, /* BDF_Face */ 339 FT_Int face_index, 340 FT_Int num_params, 341 FT_Parameter* params ) 342 { 343 FT_Error error = FT_Err_Ok; 344 BDF_Face face = (BDF_Face)bdfface; 345 FT_Memory memory = FT_FACE_MEMORY( face ); 346 347 bdf_font_t* font = NULL; 348 bdf_options_t options; 349 350 FT_UNUSED( num_params ); 351 FT_UNUSED( params ); 352 353 354 FT_TRACE2(( "BDF driver\n" )); 355 356 if ( FT_STREAM_SEEK( 0 ) ) 357 goto Exit; 358 359 options.correct_metrics = 1; /* FZ XXX: options semantics */ 360 options.keep_unencoded = 1; 361 options.keep_comments = 0; 362 options.font_spacing = BDF_PROPORTIONAL; 363 364 error = bdf_load_font( stream, memory, &options, &font ); 365 if ( FT_ERR_EQ( error, Missing_Startfont_Field ) ) 366 { 367 FT_TRACE2(( " not a BDF file\n" )); 368 goto Fail; 369 } 370 else if ( error ) 371 goto Exit; 372 373 /* we have a bdf font: let's construct the face object */ 374 face->bdffont = font; 375 376 /* BDF cannot have multiple faces in a single font file. 377 * XXX: non-zero face_index is already invalid argument, but 378 * Type1, Type42 driver has a convention to return 379 * an invalid argument error when the font could be 380 * opened by the specified driver. 381 */ 382 if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) 383 { 384 FT_ERROR(( "BDF_Face_Init: invalid face index\n" )); 385 BDF_Face_Done( bdfface ); 386 return FT_THROW( Invalid_Argument ); 387 } 388 389 { 390 bdf_property_t* prop = NULL; 391 392 393 FT_TRACE4(( " number of glyphs: allocated %d (used %d)\n", 394 font->glyphs_size, 395 font->glyphs_used )); 396 FT_TRACE4(( " number of unencoded glyphs: allocated %d (used %d)\n", 397 font->unencoded_size, 398 font->unencoded_used )); 399 400 bdfface->num_faces = 1; 401 bdfface->face_index = 0; 402 403 bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES | 404 FT_FACE_FLAG_HORIZONTAL; 405 406 prop = bdf_get_font_property( font, "SPACING" ); 407 if ( prop && prop->format == BDF_ATOM && 408 prop->value.atom && 409 ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' || 410 *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) ) 411 bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 412 413 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */ 414 /* FZ XXX: I need a font to implement this */ 415 416 prop = bdf_get_font_property( font, "FAMILY_NAME" ); 417 if ( prop && prop->value.atom ) 418 { 419 if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) ) 420 goto Exit; 421 } 422 else 423 bdfface->family_name = NULL; 424 425 if ( FT_SET_ERROR( bdf_interpret_style( face ) ) ) 426 goto Exit; 427 428 /* the number of glyphs (with one slot for the undefined glyph */ 429 /* at position 0 and all unencoded glyphs) */ 430 bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); 431 432 bdfface->num_fixed_sizes = 1; 433 if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) ) 434 goto Exit; 435 436 { 437 FT_Bitmap_Size* bsize = bdfface->available_sizes; 438 FT_Short resolution_x = 0, resolution_y = 0; 439 long value; 440 441 442 FT_ZERO( bsize ); 443 444 /* sanity checks */ 445 if ( font->font_ascent > 0x7FFF || font->font_ascent < -0x7FFF ) 446 { 447 font->font_ascent = font->font_ascent < 0 ? -0x7FFF : 0x7FFF; 448 FT_TRACE0(( "BDF_Face_Init: clamping font ascent to value %d\n", 449 font->font_ascent )); 450 } 451 if ( font->font_descent > 0x7FFF || font->font_descent < -0x7FFF ) 452 { 453 font->font_descent = font->font_descent < 0 ? -0x7FFF : 0x7FFF; 454 FT_TRACE0(( "BDF_Face_Init: clamping font descent to value %d\n", 455 font->font_descent )); 456 } 457 458 bsize->height = (FT_Short)( font->font_ascent + font->font_descent ); 459 460 prop = bdf_get_font_property( font, "AVERAGE_WIDTH" ); 461 if ( prop ) 462 { 463 #ifdef FT_DEBUG_LEVEL_TRACE 464 if ( prop->value.l < 0 ) 465 FT_TRACE0(( "BDF_Face_Init: negative average width\n" )); 466 #endif 467 if ( prop->value.l > 0x7FFFL * 10 - 5 || 468 prop->value.l < -( 0x7FFFL * 10 - 5 ) ) 469 { 470 bsize->width = 0x7FFF; 471 FT_TRACE0(( "BDF_Face_Init: clamping average width to value %d\n", 472 bsize->width )); 473 } 474 else 475 bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) ); 476 } 477 else 478 { 479 /* this is a heuristical value */ 480 bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 ); 481 } 482 483 prop = bdf_get_font_property( font, "POINT_SIZE" ); 484 if ( prop ) 485 { 486 #ifdef FT_DEBUG_LEVEL_TRACE 487 if ( prop->value.l < 0 ) 488 FT_TRACE0(( "BDF_Face_Init: negative point size\n" )); 489 #endif 490 /* convert from 722.7 decipoints to 72 points per inch */ 491 if ( prop->value.l > 0x504C2L || /* 0x7FFF * 72270/7200 */ 492 prop->value.l < -0x504C2L ) 493 { 494 bsize->size = 0x7FFF; 495 FT_TRACE0(( "BDF_Face_Init: clamping point size to value %d\n", 496 bsize->size )); 497 } 498 else 499 bsize->size = FT_MulDiv( FT_ABS( prop->value.l ), 500 64 * 7200, 501 72270L ); 502 } 503 else if ( font->point_size ) 504 { 505 if ( font->point_size > 0x7FFF ) 506 { 507 bsize->size = 0x7FFF; 508 FT_TRACE0(( "BDF_Face_Init: clamping point size to value %d\n", 509 bsize->size )); 510 } 511 else 512 bsize->size = (FT_Pos)font->point_size << 6; 513 } 514 else 515 { 516 /* this is a heuristical value */ 517 bsize->size = bsize->width * 64; 518 } 519 520 prop = bdf_get_font_property( font, "PIXEL_SIZE" ); 521 if ( prop ) 522 { 523 #ifdef FT_DEBUG_LEVEL_TRACE 524 if ( prop->value.l < 0 ) 525 FT_TRACE0(( "BDF_Face_Init: negative pixel size\n" )); 526 #endif 527 if ( prop->value.l > 0x7FFF || prop->value.l < -0x7FFF ) 528 { 529 bsize->y_ppem = 0x7FFF << 6; 530 FT_TRACE0(( "BDF_Face_Init: clamping pixel size to value %d\n", 531 bsize->y_ppem )); 532 } 533 else 534 bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6; 535 } 536 537 prop = bdf_get_font_property( font, "RESOLUTION_X" ); 538 if ( prop ) 539 value = prop->value.l; 540 else 541 value = (long)font->resolution_x; 542 if ( value ) 543 { 544 #ifdef FT_DEBUG_LEVEL_TRACE 545 if ( value < 0 ) 546 FT_TRACE0(( "BDF_Face_Init: negative X resolution\n" )); 547 #endif 548 if ( value > 0x7FFF || value < -0x7FFF ) 549 { 550 resolution_x = 0x7FFF; 551 FT_TRACE0(( "BDF_Face_Init: clamping X resolution to value %d\n", 552 resolution_x )); 553 } 554 else 555 resolution_x = FT_ABS( (FT_Short)value ); 556 } 557 558 prop = bdf_get_font_property( font, "RESOLUTION_Y" ); 559 if ( prop ) 560 value = prop->value.l; 561 else 562 value = (long)font->resolution_y; 563 if ( value ) 564 { 565 #ifdef FT_DEBUG_LEVEL_TRACE 566 if ( value < 0 ) 567 FT_TRACE0(( "BDF_Face_Init: negative Y resolution\n" )); 568 #endif 569 if ( value > 0x7FFF || value < -0x7FFF ) 570 { 571 resolution_y = 0x7FFF; 572 FT_TRACE0(( "BDF_Face_Init: clamping Y resolution to value %d\n", 573 resolution_y )); 574 } 575 else 576 resolution_y = FT_ABS( (FT_Short)value ); 577 } 578 579 if ( bsize->y_ppem == 0 ) 580 { 581 bsize->y_ppem = bsize->size; 582 if ( resolution_y ) 583 bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 ); 584 } 585 if ( resolution_x && resolution_y ) 586 bsize->x_ppem = FT_MulDiv( bsize->y_ppem, 587 resolution_x, 588 resolution_y ); 589 else 590 bsize->x_ppem = bsize->y_ppem; 591 } 592 593 /* encoding table */ 594 { 595 bdf_glyph_t* cur = font->glyphs; 596 unsigned long n; 597 598 599 if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) ) 600 goto Exit; 601 602 face->default_glyph = 0; 603 for ( n = 0; n < font->glyphs_size; n++ ) 604 { 605 (face->en_table[n]).enc = cur[n].encoding; 606 FT_TRACE4(( " idx %d, val 0x%lX\n", n, cur[n].encoding )); 607 (face->en_table[n]).glyph = (FT_UShort)n; 608 609 if ( cur[n].encoding == font->default_char ) 610 { 611 if ( n < FT_UINT_MAX ) 612 face->default_glyph = (FT_UInt)n; 613 else 614 FT_TRACE1(( "BDF_Face_Init:" 615 " idx %d is too large for this system\n", n )); 616 } 617 } 618 } 619 620 /* charmaps */ 621 { 622 bdf_property_t *charset_registry, *charset_encoding; 623 FT_Bool unicode_charmap = 0; 624 625 626 charset_registry = 627 bdf_get_font_property( font, "CHARSET_REGISTRY" ); 628 charset_encoding = 629 bdf_get_font_property( font, "CHARSET_ENCODING" ); 630 if ( charset_registry && charset_encoding ) 631 { 632 if ( charset_registry->format == BDF_ATOM && 633 charset_encoding->format == BDF_ATOM && 634 charset_registry->value.atom && 635 charset_encoding->value.atom ) 636 { 637 const char* s; 638 639 640 if ( FT_STRDUP( face->charset_encoding, 641 charset_encoding->value.atom ) || 642 FT_STRDUP( face->charset_registry, 643 charset_registry->value.atom ) ) 644 goto Exit; 645 646 /* Uh, oh, compare first letters manually to avoid dependency */ 647 /* on locales. */ 648 s = face->charset_registry; 649 if ( ( s[0] == 'i' || s[0] == 'I' ) && 650 ( s[1] == 's' || s[1] == 'S' ) && 651 ( s[2] == 'o' || s[2] == 'O' ) ) 652 { 653 s += 3; 654 if ( !ft_strcmp( s, "10646" ) || 655 ( !ft_strcmp( s, "8859" ) && 656 !ft_strcmp( face->charset_encoding, "1" ) ) ) 657 unicode_charmap = 1; 658 /* another name for ASCII */ 659 else if ( !ft_strcmp( s, "646.1991" ) && 660 !ft_strcmp( face->charset_encoding, "IRV" ) ) 661 unicode_charmap = 1; 662 } 663 664 { 665 FT_CharMapRec charmap; 666 667 668 charmap.face = FT_FACE( face ); 669 charmap.encoding = FT_ENCODING_NONE; 670 /* initial platform/encoding should indicate unset status? */ 671 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; 672 charmap.encoding_id = TT_APPLE_ID_DEFAULT; 673 674 if ( unicode_charmap ) 675 { 676 charmap.encoding = FT_ENCODING_UNICODE; 677 charmap.platform_id = TT_PLATFORM_MICROSOFT; 678 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 679 } 680 681 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); 682 } 683 684 goto Exit; 685 } 686 } 687 688 /* otherwise assume Adobe standard encoding */ 689 690 { 691 FT_CharMapRec charmap; 692 693 694 charmap.face = FT_FACE( face ); 695 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 696 charmap.platform_id = TT_PLATFORM_ADOBE; 697 charmap.encoding_id = TT_ADOBE_ID_STANDARD; 698 699 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); 700 701 /* Select default charmap */ 702 if ( bdfface->num_charmaps ) 703 bdfface->charmap = bdfface->charmaps[0]; 704 } 705 } 706 } 707 708 Exit: 709 return error; 710 711 Fail: 712 BDF_Face_Done( bdfface ); 713 return FT_THROW( Unknown_File_Format ); 714 } 715 716 717 FT_CALLBACK_DEF( FT_Error ) BDF_Size_Select(FT_Size size,FT_ULong strike_index)718 BDF_Size_Select( FT_Size size, 719 FT_ULong strike_index ) 720 { 721 bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont; 722 723 724 FT_Select_Metrics( size->face, strike_index ); 725 726 size->metrics.ascender = bdffont->font_ascent * 64; 727 size->metrics.descender = -bdffont->font_descent * 64; 728 size->metrics.max_advance = bdffont->bbx.width * 64; 729 730 return FT_Err_Ok; 731 } 732 733 734 FT_CALLBACK_DEF( FT_Error ) BDF_Size_Request(FT_Size size,FT_Size_Request req)735 BDF_Size_Request( FT_Size size, 736 FT_Size_Request req ) 737 { 738 FT_Face face = size->face; 739 FT_Bitmap_Size* bsize = face->available_sizes; 740 bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont; 741 FT_Error error = FT_ERR( Invalid_Pixel_Size ); 742 FT_Long height; 743 744 745 height = FT_REQUEST_HEIGHT( req ); 746 height = ( height + 32 ) >> 6; 747 748 switch ( req->type ) 749 { 750 case FT_SIZE_REQUEST_TYPE_NOMINAL: 751 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) ) 752 error = FT_Err_Ok; 753 break; 754 755 case FT_SIZE_REQUEST_TYPE_REAL_DIM: 756 if ( height == ( bdffont->font_ascent + 757 bdffont->font_descent ) ) 758 error = FT_Err_Ok; 759 break; 760 761 default: 762 error = FT_THROW( Unimplemented_Feature ); 763 break; 764 } 765 766 if ( error ) 767 return error; 768 else 769 return BDF_Size_Select( size, 0 ); 770 } 771 772 773 774 FT_CALLBACK_DEF( FT_Error ) BDF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)775 BDF_Glyph_Load( FT_GlyphSlot slot, 776 FT_Size size, 777 FT_UInt glyph_index, 778 FT_Int32 load_flags ) 779 { 780 BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size ); 781 FT_Face face = FT_FACE( bdf ); 782 FT_Error error = FT_Err_Ok; 783 FT_Bitmap* bitmap = &slot->bitmap; 784 bdf_glyph_t glyph; 785 int bpp = bdf->bdffont->bpp; 786 787 FT_UNUSED( load_flags ); 788 789 790 if ( !face ) 791 { 792 error = FT_THROW( Invalid_Face_Handle ); 793 goto Exit; 794 } 795 796 if ( glyph_index >= (FT_UInt)face->num_glyphs ) 797 { 798 error = FT_THROW( Invalid_Argument ); 799 goto Exit; 800 } 801 802 FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index )); 803 804 /* index 0 is the undefined glyph */ 805 if ( glyph_index == 0 ) 806 glyph_index = bdf->default_glyph; 807 else 808 glyph_index--; 809 810 /* slot, bitmap => freetype, glyph => bdflib */ 811 glyph = bdf->bdffont->glyphs[glyph_index]; 812 813 bitmap->rows = glyph.bbx.height; 814 bitmap->width = glyph.bbx.width; 815 if ( glyph.bpr > FT_INT_MAX ) 816 FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n", 817 glyph.bpr )); 818 bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */ 819 820 /* note: we don't allocate a new array to hold the bitmap; */ 821 /* we can simply point to it */ 822 ft_glyphslot_set_bitmap( slot, glyph.bitmap ); 823 824 switch ( bpp ) 825 { 826 case 1: 827 bitmap->pixel_mode = FT_PIXEL_MODE_MONO; 828 break; 829 case 2: 830 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2; 831 break; 832 case 4: 833 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4; 834 break; 835 case 8: 836 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; 837 bitmap->num_grays = 256; 838 break; 839 } 840 841 slot->format = FT_GLYPH_FORMAT_BITMAP; 842 slot->bitmap_left = glyph.bbx.x_offset; 843 slot->bitmap_top = glyph.bbx.ascent; 844 845 slot->metrics.horiAdvance = (FT_Pos)( glyph.dwidth * 64 ); 846 slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 ); 847 slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 ); 848 slot->metrics.width = (FT_Pos)( bitmap->width * 64 ); 849 slot->metrics.height = (FT_Pos)( bitmap->rows * 64 ); 850 851 /* 852 * XXX DWIDTH1 and VVECTOR should be parsed and 853 * used here, provided such fonts do exist. 854 */ 855 ft_synthesize_vertical_metrics( &slot->metrics, 856 bdf->bdffont->bbx.height * 64 ); 857 858 Exit: 859 return error; 860 } 861 862 863 /* 864 * 865 * BDF SERVICE 866 * 867 */ 868 869 static FT_Error bdf_get_bdf_property(BDF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)870 bdf_get_bdf_property( BDF_Face face, 871 const char* prop_name, 872 BDF_PropertyRec *aproperty ) 873 { 874 bdf_property_t* prop; 875 876 877 FT_ASSERT( face && face->bdffont ); 878 879 prop = bdf_get_font_property( face->bdffont, prop_name ); 880 if ( prop ) 881 { 882 switch ( prop->format ) 883 { 884 case BDF_ATOM: 885 aproperty->type = BDF_PROPERTY_TYPE_ATOM; 886 aproperty->u.atom = prop->value.atom; 887 break; 888 889 case BDF_INTEGER: 890 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) 891 { 892 FT_TRACE1(( "bdf_get_bdf_property:" 893 " too large integer 0x%x is truncated\n" )); 894 } 895 aproperty->type = BDF_PROPERTY_TYPE_INTEGER; 896 aproperty->u.integer = (FT_Int32)prop->value.l; 897 break; 898 899 case BDF_CARDINAL: 900 if ( prop->value.ul > 0xFFFFFFFFUL ) 901 { 902 FT_TRACE1(( "bdf_get_bdf_property:" 903 " too large cardinal 0x%x is truncated\n" )); 904 } 905 aproperty->type = BDF_PROPERTY_TYPE_CARDINAL; 906 aproperty->u.cardinal = (FT_UInt32)prop->value.ul; 907 break; 908 909 default: 910 goto Fail; 911 } 912 return 0; 913 } 914 915 Fail: 916 return FT_THROW( Invalid_Argument ); 917 } 918 919 920 static FT_Error bdf_get_charset_id(BDF_Face face,const char ** acharset_encoding,const char ** acharset_registry)921 bdf_get_charset_id( BDF_Face face, 922 const char* *acharset_encoding, 923 const char* *acharset_registry ) 924 { 925 *acharset_encoding = face->charset_encoding; 926 *acharset_registry = face->charset_registry; 927 928 return 0; 929 } 930 931 932 static const FT_Service_BDFRec bdf_service_bdf = 933 { 934 (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id, /* get_charset_id */ 935 (FT_BDF_GetPropertyFunc) bdf_get_bdf_property /* get_property */ 936 }; 937 938 939 /* 940 * 941 * SERVICES LIST 942 * 943 */ 944 945 static const FT_ServiceDescRec bdf_services[] = 946 { 947 { FT_SERVICE_ID_BDF, &bdf_service_bdf }, 948 { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF }, 949 { NULL, NULL } 950 }; 951 952 953 FT_CALLBACK_DEF( FT_Module_Interface ) bdf_driver_requester(FT_Module module,const char * name)954 bdf_driver_requester( FT_Module module, 955 const char* name ) 956 { 957 FT_UNUSED( module ); 958 959 return ft_service_list_lookup( bdf_services, name ); 960 } 961 962 963 964 FT_CALLBACK_TABLE_DEF 965 const FT_Driver_ClassRec bdf_driver_class = 966 { 967 { 968 FT_MODULE_FONT_DRIVER | 969 FT_MODULE_DRIVER_NO_OUTLINES, 970 sizeof ( FT_DriverRec ), 971 972 "bdf", 973 0x10000L, 974 0x20000L, 975 976 NULL, /* module-specific interface */ 977 978 NULL, /* FT_Module_Constructor module_init */ 979 NULL, /* FT_Module_Destructor module_done */ 980 bdf_driver_requester /* FT_Module_Requester get_interface */ 981 }, 982 983 sizeof ( BDF_FaceRec ), 984 sizeof ( FT_SizeRec ), 985 sizeof ( FT_GlyphSlotRec ), 986 987 BDF_Face_Init, /* FT_Face_InitFunc init_face */ 988 BDF_Face_Done, /* FT_Face_DoneFunc done_face */ 989 NULL, /* FT_Size_InitFunc init_size */ 990 NULL, /* FT_Size_DoneFunc done_size */ 991 NULL, /* FT_Slot_InitFunc init_slot */ 992 NULL, /* FT_Slot_DoneFunc done_slot */ 993 994 BDF_Glyph_Load, /* FT_Slot_LoadFunc load_glyph */ 995 996 NULL, /* FT_Face_GetKerningFunc get_kerning */ 997 NULL, /* FT_Face_AttachFunc attach_file */ 998 NULL, /* FT_Face_GetAdvancesFunc get_advances */ 999 1000 BDF_Size_Request, /* FT_Size_RequestFunc request_size */ 1001 BDF_Size_Select /* FT_Size_SelectFunc select_size */ 1002 }; 1003 1004 1005 /* END */ 1006