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 ) 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 ) 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 ) 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 ) 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 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 == NULL ) 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 ) 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 ) 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 could not have multiple face in 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 FT_FACE_FLAG_FAST_GLYPHS; 406 407 prop = bdf_get_font_property( font, "SPACING" ); 408 if ( prop && prop->format == BDF_ATOM && 409 prop->value.atom && 410 ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' || 411 *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) ) 412 bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 413 414 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */ 415 /* FZ XXX: I need a font to implement this */ 416 417 prop = bdf_get_font_property( font, "FAMILY_NAME" ); 418 if ( prop && prop->value.atom ) 419 { 420 if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) ) 421 goto Exit; 422 } 423 else 424 bdfface->family_name = NULL; 425 426 if ( ( error = bdf_interpret_style( face ) ) != 0 ) 427 goto Exit; 428 429 /* the number of glyphs (with one slot for the undefined glyph */ 430 /* at position 0 and all unencoded glyphs) */ 431 bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); 432 433 bdfface->num_fixed_sizes = 1; 434 if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) ) 435 goto Exit; 436 437 { 438 FT_Bitmap_Size* bsize = bdfface->available_sizes; 439 FT_Short resolution_x = 0, resolution_y = 0; 440 441 442 FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) ); 443 444 bsize->height = (FT_Short)( font->font_ascent + font->font_descent ); 445 446 prop = bdf_get_font_property( font, "AVERAGE_WIDTH" ); 447 if ( prop ) 448 bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 ); 449 else 450 bsize->width = (FT_Short)( bsize->height * 2/3 ); 451 452 prop = bdf_get_font_property( font, "POINT_SIZE" ); 453 if ( prop ) 454 /* convert from 722.7 decipoints to 72 points per inch */ 455 bsize->size = 456 (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L ); 457 else 458 bsize->size = bsize->width << 6; 459 460 prop = bdf_get_font_property( font, "PIXEL_SIZE" ); 461 if ( prop ) 462 bsize->y_ppem = (FT_Short)prop->value.l << 6; 463 464 prop = bdf_get_font_property( font, "RESOLUTION_X" ); 465 if ( prop ) 466 resolution_x = (FT_Short)prop->value.l; 467 468 prop = bdf_get_font_property( font, "RESOLUTION_Y" ); 469 if ( prop ) 470 resolution_y = (FT_Short)prop->value.l; 471 472 if ( bsize->y_ppem == 0 ) 473 { 474 bsize->y_ppem = bsize->size; 475 if ( resolution_y ) 476 bsize->y_ppem = bsize->y_ppem * resolution_y / 72; 477 } 478 if ( resolution_x && resolution_y ) 479 bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y; 480 else 481 bsize->x_ppem = bsize->y_ppem; 482 } 483 484 /* encoding table */ 485 { 486 bdf_glyph_t* cur = font->glyphs; 487 unsigned long n; 488 489 490 if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) ) 491 goto Exit; 492 493 face->default_glyph = 0; 494 for ( n = 0; n < font->glyphs_size; n++ ) 495 { 496 (face->en_table[n]).enc = cur[n].encoding; 497 FT_TRACE4(( " idx %d, val 0x%lX\n", n, cur[n].encoding )); 498 (face->en_table[n]).glyph = (FT_UShort)n; 499 500 if ( cur[n].encoding == font->default_char ) 501 { 502 if ( n < FT_UINT_MAX ) 503 face->default_glyph = (FT_UInt)n; 504 else 505 FT_TRACE1(( "BDF_Face_Init:" 506 " idx %d is too large for this system\n", n )); 507 } 508 } 509 } 510 511 /* charmaps */ 512 { 513 bdf_property_t *charset_registry, *charset_encoding; 514 FT_Bool unicode_charmap = 0; 515 516 517 charset_registry = 518 bdf_get_font_property( font, "CHARSET_REGISTRY" ); 519 charset_encoding = 520 bdf_get_font_property( font, "CHARSET_ENCODING" ); 521 if ( charset_registry && charset_encoding ) 522 { 523 if ( charset_registry->format == BDF_ATOM && 524 charset_encoding->format == BDF_ATOM && 525 charset_registry->value.atom && 526 charset_encoding->value.atom ) 527 { 528 const char* s; 529 530 531 if ( FT_STRDUP( face->charset_encoding, 532 charset_encoding->value.atom ) || 533 FT_STRDUP( face->charset_registry, 534 charset_registry->value.atom ) ) 535 goto Exit; 536 537 /* Uh, oh, compare first letters manually to avoid dependency */ 538 /* on locales. */ 539 s = face->charset_registry; 540 if ( ( s[0] == 'i' || s[0] == 'I' ) && 541 ( s[1] == 's' || s[1] == 'S' ) && 542 ( s[2] == 'o' || s[2] == 'O' ) ) 543 { 544 s += 3; 545 if ( !ft_strcmp( s, "10646" ) || 546 ( !ft_strcmp( s, "8859" ) && 547 !ft_strcmp( face->charset_encoding, "1" ) ) ) 548 unicode_charmap = 1; 549 } 550 551 { 552 FT_CharMapRec charmap; 553 554 555 charmap.face = FT_FACE( face ); 556 charmap.encoding = FT_ENCODING_NONE; 557 /* initial platform/encoding should indicate unset status? */ 558 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; 559 charmap.encoding_id = TT_APPLE_ID_DEFAULT; 560 561 if ( unicode_charmap ) 562 { 563 charmap.encoding = FT_ENCODING_UNICODE; 564 charmap.platform_id = TT_PLATFORM_MICROSOFT; 565 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 566 } 567 568 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); 569 570 #if 0 571 /* Select default charmap */ 572 if ( bdfface->num_charmaps ) 573 bdfface->charmap = bdfface->charmaps[0]; 574 #endif 575 } 576 577 goto Exit; 578 } 579 } 580 581 /* otherwise assume Adobe standard encoding */ 582 583 { 584 FT_CharMapRec charmap; 585 586 587 charmap.face = FT_FACE( face ); 588 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 589 charmap.platform_id = TT_PLATFORM_ADOBE; 590 charmap.encoding_id = TT_ADOBE_ID_STANDARD; 591 592 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); 593 594 /* Select default charmap */ 595 if ( bdfface->num_charmaps ) 596 bdfface->charmap = bdfface->charmaps[0]; 597 } 598 } 599 } 600 601 Exit: 602 return error; 603 604 Fail: 605 BDF_Face_Done( bdfface ); 606 return FT_THROW( Unknown_File_Format ); 607 } 608 609 610 FT_CALLBACK_DEF( FT_Error ) 611 BDF_Size_Select( FT_Size size, 612 FT_ULong strike_index ) 613 { 614 bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont; 615 616 617 FT_Select_Metrics( size->face, strike_index ); 618 619 size->metrics.ascender = bdffont->font_ascent * 64; 620 size->metrics.descender = -bdffont->font_descent * 64; 621 size->metrics.max_advance = bdffont->bbx.width * 64; 622 623 return FT_Err_Ok; 624 } 625 626 627 FT_CALLBACK_DEF( FT_Error ) 628 BDF_Size_Request( FT_Size size, 629 FT_Size_Request req ) 630 { 631 FT_Face face = size->face; 632 FT_Bitmap_Size* bsize = face->available_sizes; 633 bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont; 634 FT_Error error = FT_ERR( Invalid_Pixel_Size ); 635 FT_Long height; 636 637 638 height = FT_REQUEST_HEIGHT( req ); 639 height = ( height + 32 ) >> 6; 640 641 switch ( req->type ) 642 { 643 case FT_SIZE_REQUEST_TYPE_NOMINAL: 644 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) ) 645 error = FT_Err_Ok; 646 break; 647 648 case FT_SIZE_REQUEST_TYPE_REAL_DIM: 649 if ( height == ( bdffont->font_ascent + 650 bdffont->font_descent ) ) 651 error = FT_Err_Ok; 652 break; 653 654 default: 655 error = FT_THROW( Unimplemented_Feature ); 656 break; 657 } 658 659 if ( error ) 660 return error; 661 else 662 return BDF_Size_Select( size, 0 ); 663 } 664 665 666 667 FT_CALLBACK_DEF( FT_Error ) 668 BDF_Glyph_Load( FT_GlyphSlot slot, 669 FT_Size size, 670 FT_UInt glyph_index, 671 FT_Int32 load_flags ) 672 { 673 BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size ); 674 FT_Face face = FT_FACE( bdf ); 675 FT_Error error = FT_Err_Ok; 676 FT_Bitmap* bitmap = &slot->bitmap; 677 bdf_glyph_t glyph; 678 int bpp = bdf->bdffont->bpp; 679 680 FT_UNUSED( load_flags ); 681 682 683 if ( !face ) 684 { 685 error = FT_THROW( Invalid_Face_Handle ); 686 goto Exit; 687 } 688 689 if ( glyph_index >= (FT_UInt)face->num_glyphs ) 690 { 691 error = FT_THROW( Invalid_Argument ); 692 goto Exit; 693 } 694 695 FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index )); 696 697 /* index 0 is the undefined glyph */ 698 if ( glyph_index == 0 ) 699 glyph_index = bdf->default_glyph; 700 else 701 glyph_index--; 702 703 /* slot, bitmap => freetype, glyph => bdflib */ 704 glyph = bdf->bdffont->glyphs[glyph_index]; 705 706 bitmap->rows = glyph.bbx.height; 707 bitmap->width = glyph.bbx.width; 708 if ( glyph.bpr > INT_MAX ) 709 FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n", 710 glyph.bpr )); 711 bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */ 712 713 /* note: we don't allocate a new array to hold the bitmap; */ 714 /* we can simply point to it */ 715 ft_glyphslot_set_bitmap( slot, glyph.bitmap ); 716 717 switch ( bpp ) 718 { 719 case 1: 720 bitmap->pixel_mode = FT_PIXEL_MODE_MONO; 721 break; 722 case 2: 723 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2; 724 break; 725 case 4: 726 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4; 727 break; 728 case 8: 729 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; 730 bitmap->num_grays = 256; 731 break; 732 } 733 734 slot->format = FT_GLYPH_FORMAT_BITMAP; 735 slot->bitmap_left = glyph.bbx.x_offset; 736 slot->bitmap_top = glyph.bbx.ascent; 737 738 slot->metrics.horiAdvance = (FT_Pos)( glyph.dwidth * 64 ); 739 slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 ); 740 slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 ); 741 slot->metrics.width = (FT_Pos)( bitmap->width * 64 ); 742 slot->metrics.height = (FT_Pos)( bitmap->rows * 64 ); 743 744 /* 745 * XXX DWIDTH1 and VVECTOR should be parsed and 746 * used here, provided such fonts do exist. 747 */ 748 ft_synthesize_vertical_metrics( &slot->metrics, 749 bdf->bdffont->bbx.height * 64 ); 750 751 Exit: 752 return error; 753 } 754 755 756 /* 757 * 758 * BDF SERVICE 759 * 760 */ 761 762 static FT_Error 763 bdf_get_bdf_property( BDF_Face face, 764 const char* prop_name, 765 BDF_PropertyRec *aproperty ) 766 { 767 bdf_property_t* prop; 768 769 770 FT_ASSERT( face && face->bdffont ); 771 772 prop = bdf_get_font_property( face->bdffont, prop_name ); 773 if ( prop ) 774 { 775 switch ( prop->format ) 776 { 777 case BDF_ATOM: 778 aproperty->type = BDF_PROPERTY_TYPE_ATOM; 779 aproperty->u.atom = prop->value.atom; 780 break; 781 782 case BDF_INTEGER: 783 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) 784 { 785 FT_TRACE1(( "bdf_get_bdf_property:" 786 " too large integer 0x%x is truncated\n" )); 787 } 788 aproperty->type = BDF_PROPERTY_TYPE_INTEGER; 789 aproperty->u.integer = (FT_Int32)prop->value.l; 790 break; 791 792 case BDF_CARDINAL: 793 if ( prop->value.ul > 0xFFFFFFFFUL ) 794 { 795 FT_TRACE1(( "bdf_get_bdf_property:" 796 " too large cardinal 0x%x is truncated\n" )); 797 } 798 aproperty->type = BDF_PROPERTY_TYPE_CARDINAL; 799 aproperty->u.cardinal = (FT_UInt32)prop->value.ul; 800 break; 801 802 default: 803 goto Fail; 804 } 805 return 0; 806 } 807 808 Fail: 809 return FT_THROW( Invalid_Argument ); 810 } 811 812 813 static FT_Error 814 bdf_get_charset_id( BDF_Face face, 815 const char* *acharset_encoding, 816 const char* *acharset_registry ) 817 { 818 *acharset_encoding = face->charset_encoding; 819 *acharset_registry = face->charset_registry; 820 821 return 0; 822 } 823 824 825 static const FT_Service_BDFRec bdf_service_bdf = 826 { 827 (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id, /* get_charset_id */ 828 (FT_BDF_GetPropertyFunc) bdf_get_bdf_property /* get_property */ 829 }; 830 831 832 /* 833 * 834 * SERVICES LIST 835 * 836 */ 837 838 static const FT_ServiceDescRec bdf_services[] = 839 { 840 { FT_SERVICE_ID_BDF, &bdf_service_bdf }, 841 { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF }, 842 { NULL, NULL } 843 }; 844 845 846 FT_CALLBACK_DEF( FT_Module_Interface ) 847 bdf_driver_requester( FT_Module module, 848 const char* name ) 849 { 850 FT_UNUSED( module ); 851 852 return ft_service_list_lookup( bdf_services, name ); 853 } 854 855 856 857 FT_CALLBACK_TABLE_DEF 858 const FT_Driver_ClassRec bdf_driver_class = 859 { 860 { 861 FT_MODULE_FONT_DRIVER | 862 FT_MODULE_DRIVER_NO_OUTLINES, 863 sizeof ( FT_DriverRec ), 864 865 "bdf", 866 0x10000L, 867 0x20000L, 868 869 0, /* module-specific interface */ 870 871 0, /* FT_Module_Constructor module_init */ 872 0, /* FT_Module_Destructor module_done */ 873 bdf_driver_requester /* FT_Module_Requester get_interface */ 874 }, 875 876 sizeof ( BDF_FaceRec ), 877 sizeof ( FT_SizeRec ), 878 sizeof ( FT_GlyphSlotRec ), 879 880 BDF_Face_Init, /* FT_Face_InitFunc init_face */ 881 BDF_Face_Done, /* FT_Face_DoneFunc done_face */ 882 0, /* FT_Size_InitFunc init_size */ 883 0, /* FT_Size_DoneFunc done_size */ 884 0, /* FT_Slot_InitFunc init_slot */ 885 0, /* FT_Slot_DoneFunc done_slot */ 886 887 BDF_Glyph_Load, /* FT_Slot_LoadFunc load_glyph */ 888 889 0, /* FT_Face_GetKerningFunc get_kerning */ 890 0, /* FT_Face_AttachFunc attach_file */ 891 0, /* FT_Face_GetAdvancesFunc get_advances */ 892 893 BDF_Size_Request, /* FT_Size_RequestFunc request_size */ 894 BDF_Size_Select /* FT_Size_SelectFunc select_size */ 895 }; 896 897 898 /* END */ 899