1 /* bdfdrivr.c 2 3 FreeType font driver for bdf files 4 5 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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_XFREE86_NAME_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 BDF_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 = 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 = 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 = 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 FT_CALLBACK_TABLE_DEF 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 = BDF_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 len = 0; 247 248 for ( len = 0, nn = 0; nn < 4; nn++ ) 249 { 250 lengths[nn] = 0; 251 if ( strings[nn] ) 252 { 253 lengths[nn] = ft_strlen( strings[nn] ); 254 len += lengths[nn] + 1; 255 } 256 } 257 258 if ( len == 0 ) 259 { 260 strings[0] = (char *)"Regular"; 261 lengths[0] = ft_strlen( strings[0] ); 262 len = lengths[0] + 1; 263 } 264 265 { 266 char* s; 267 268 269 if ( FT_ALLOC( face->style_name, len ) ) 270 return error; 271 272 s = face->style_name; 273 274 for ( nn = 0; nn < 4; nn++ ) 275 { 276 char* src = strings[nn]; 277 278 279 len = lengths[nn]; 280 281 if ( src == NULL ) 282 continue; 283 284 /* separate elements with a space */ 285 if ( s != face->style_name ) 286 *s++ = ' '; 287 288 ft_memcpy( s, src, len ); 289 290 /* need to convert spaces to dashes for */ 291 /* add_style_name and setwidth_name */ 292 if ( nn == 0 || nn == 3 ) 293 { 294 size_t mm; 295 296 297 for ( mm = 0; mm < len; mm++ ) 298 if ( s[mm] == ' ' ) 299 s[mm] = '-'; 300 } 301 302 s += len; 303 } 304 *s = 0; 305 } 306 307 return error; 308 } 309 310 311 FT_CALLBACK_DEF( void ) BDF_Face_Done(FT_Face bdfface)312 BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */ 313 { 314 BDF_Face face = (BDF_Face)bdfface; 315 FT_Memory memory; 316 317 318 if ( !face ) 319 return; 320 321 memory = FT_FACE_MEMORY( face ); 322 323 bdf_free_font( face->bdffont ); 324 325 FT_FREE( face->en_table ); 326 327 FT_FREE( face->charset_encoding ); 328 FT_FREE( face->charset_registry ); 329 FT_FREE( bdfface->family_name ); 330 FT_FREE( bdfface->style_name ); 331 332 FT_FREE( bdfface->available_sizes ); 333 334 FT_FREE( face->bdffont ); 335 336 FT_TRACE4(( "BDF_Face_Done: done face\n" )); 337 } 338 339 340 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)341 BDF_Face_Init( FT_Stream stream, 342 FT_Face bdfface, /* BDF_Face */ 343 FT_Int face_index, 344 FT_Int num_params, 345 FT_Parameter* params ) 346 { 347 FT_Error error = BDF_Err_Ok; 348 BDF_Face face = (BDF_Face)bdfface; 349 FT_Memory memory = FT_FACE_MEMORY( face ); 350 351 bdf_font_t* font = NULL; 352 bdf_options_t options; 353 354 FT_UNUSED( num_params ); 355 FT_UNUSED( params ); 356 FT_UNUSED( face_index ); 357 358 359 if ( FT_STREAM_SEEK( 0 ) ) 360 goto Exit; 361 362 options.correct_metrics = 1; /* FZ XXX: options semantics */ 363 options.keep_unencoded = 1; 364 options.keep_comments = 0; 365 options.font_spacing = BDF_PROPORTIONAL; 366 367 error = bdf_load_font( stream, memory, &options, &font ); 368 if ( error == BDF_Err_Missing_Startfont_Field ) 369 { 370 FT_TRACE2(( "[not a valid BDF file]\n" )); 371 goto Fail; 372 } 373 else if ( error ) 374 goto Exit; 375 376 /* we have a bdf font: let's construct the face object */ 377 face->bdffont = font; 378 { 379 bdf_property_t* prop = NULL; 380 381 382 FT_TRACE4(( "number of glyphs: %d (%d)\n", 383 font->glyphs_size, 384 font->glyphs_used )); 385 FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n", 386 font->unencoded_size, 387 font->unencoded_used )); 388 389 bdfface->num_faces = 1; 390 bdfface->face_index = 0; 391 bdfface->face_flags = FT_FACE_FLAG_FIXED_SIZES | 392 FT_FACE_FLAG_HORIZONTAL | 393 FT_FACE_FLAG_FAST_GLYPHS; 394 395 prop = bdf_get_font_property( font, "SPACING" ); 396 if ( prop && prop->format == BDF_ATOM && 397 prop->value.atom && 398 ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' || 399 *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) ) 400 bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 401 402 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */ 403 /* FZ XXX: I need a font to implement this */ 404 405 prop = bdf_get_font_property( font, "FAMILY_NAME" ); 406 if ( prop && prop->value.atom ) 407 { 408 if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) ) 409 goto Exit; 410 } 411 else 412 bdfface->family_name = 0; 413 414 if ( ( error = bdf_interpret_style( face ) ) != 0 ) 415 goto Exit; 416 417 /* the number of glyphs (with one slot for the undefined glyph */ 418 /* at position 0 and all unencoded glyphs) */ 419 bdfface->num_glyphs = font->glyphs_size + 1; 420 421 bdfface->num_fixed_sizes = 1; 422 if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) ) 423 goto Exit; 424 425 { 426 FT_Bitmap_Size* bsize = bdfface->available_sizes; 427 FT_Short resolution_x = 0, resolution_y = 0; 428 429 430 FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) ); 431 432 bsize->height = (FT_Short)( font->font_ascent + font->font_descent ); 433 434 prop = bdf_get_font_property( font, "AVERAGE_WIDTH" ); 435 if ( prop ) 436 bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 ); 437 else 438 bsize->width = (FT_Short)( bsize->height * 2/3 ); 439 440 prop = bdf_get_font_property( font, "POINT_SIZE" ); 441 if ( prop ) 442 /* convert from 722.7 decipoints to 72 points per inch */ 443 bsize->size = 444 (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L ); 445 else 446 bsize->size = bsize->width << 6; 447 448 prop = bdf_get_font_property( font, "PIXEL_SIZE" ); 449 if ( prop ) 450 bsize->y_ppem = (FT_Short)prop->value.l << 6; 451 452 prop = bdf_get_font_property( font, "RESOLUTION_X" ); 453 if ( prop ) 454 resolution_x = (FT_Short)prop->value.l; 455 456 prop = bdf_get_font_property( font, "RESOLUTION_Y" ); 457 if ( prop ) 458 resolution_y = (FT_Short)prop->value.l; 459 460 if ( bsize->y_ppem == 0 ) 461 { 462 bsize->y_ppem = bsize->size; 463 if ( resolution_y ) 464 bsize->y_ppem = bsize->y_ppem * resolution_y / 72; 465 } 466 if ( resolution_x && resolution_y ) 467 bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y; 468 else 469 bsize->x_ppem = bsize->y_ppem; 470 } 471 472 /* encoding table */ 473 { 474 bdf_glyph_t* cur = font->glyphs; 475 unsigned long n; 476 477 478 if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) ) 479 goto Exit; 480 481 face->default_glyph = 0; 482 for ( n = 0; n < font->glyphs_size; n++ ) 483 { 484 (face->en_table[n]).enc = cur[n].encoding; 485 FT_TRACE4(( "idx %d, val 0x%lX\n", n, cur[n].encoding )); 486 (face->en_table[n]).glyph = (FT_Short)n; 487 488 if ( cur[n].encoding == font->default_char ) 489 { 490 if ( n < FT_UINT_MAX ) 491 face->default_glyph = (FT_UInt)n; 492 else 493 FT_TRACE1(( "idx %d is too large for this system\n", n )); 494 } 495 } 496 } 497 498 /* charmaps */ 499 { 500 bdf_property_t *charset_registry = 0, *charset_encoding = 0; 501 FT_Bool unicode_charmap = 0; 502 503 504 charset_registry = 505 bdf_get_font_property( font, "CHARSET_REGISTRY" ); 506 charset_encoding = 507 bdf_get_font_property( font, "CHARSET_ENCODING" ); 508 if ( charset_registry && charset_encoding ) 509 { 510 if ( charset_registry->format == BDF_ATOM && 511 charset_encoding->format == BDF_ATOM && 512 charset_registry->value.atom && 513 charset_encoding->value.atom ) 514 { 515 const char* s; 516 517 518 if ( FT_STRDUP( face->charset_encoding, 519 charset_encoding->value.atom ) || 520 FT_STRDUP( face->charset_registry, 521 charset_registry->value.atom ) ) 522 goto Exit; 523 524 /* Uh, oh, compare first letters manually to avoid dependency */ 525 /* on locales. */ 526 s = face->charset_registry; 527 if ( ( s[0] == 'i' || s[0] == 'I' ) && 528 ( s[1] == 's' || s[1] == 'S' ) && 529 ( s[2] == 'o' || s[2] == 'O' ) ) 530 { 531 s += 3; 532 if ( !ft_strcmp( s, "10646" ) || 533 ( !ft_strcmp( s, "8859" ) && 534 !ft_strcmp( face->charset_encoding, "1" ) ) ) 535 unicode_charmap = 1; 536 } 537 538 { 539 FT_CharMapRec charmap; 540 541 542 charmap.face = FT_FACE( face ); 543 charmap.encoding = FT_ENCODING_NONE; 544 /* initial platform/encoding should indicate unset status? */ 545 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; 546 charmap.encoding_id = TT_APPLE_ID_DEFAULT; 547 548 if ( unicode_charmap ) 549 { 550 charmap.encoding = FT_ENCODING_UNICODE; 551 charmap.platform_id = TT_PLATFORM_MICROSOFT; 552 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 553 } 554 555 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); 556 557 #if 0 558 /* Select default charmap */ 559 if ( bdfface->num_charmaps ) 560 bdfface->charmap = bdfface->charmaps[0]; 561 #endif 562 } 563 564 goto Exit; 565 } 566 } 567 568 /* otherwise assume Adobe standard encoding */ 569 570 { 571 FT_CharMapRec charmap; 572 573 574 charmap.face = FT_FACE( face ); 575 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 576 charmap.platform_id = TT_PLATFORM_ADOBE; 577 charmap.encoding_id = TT_ADOBE_ID_STANDARD; 578 579 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); 580 581 /* Select default charmap */ 582 if ( bdfface->num_charmaps ) 583 bdfface->charmap = bdfface->charmaps[0]; 584 } 585 } 586 } 587 588 Exit: 589 return error; 590 591 Fail: 592 BDF_Face_Done( bdfface ); 593 return BDF_Err_Unknown_File_Format; 594 } 595 596 597 FT_CALLBACK_DEF( FT_Error ) BDF_Size_Select(FT_Size size,FT_ULong strike_index)598 BDF_Size_Select( FT_Size size, 599 FT_ULong strike_index ) 600 { 601 bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont; 602 603 604 FT_Select_Metrics( size->face, strike_index ); 605 606 size->metrics.ascender = bdffont->font_ascent << 6; 607 size->metrics.descender = -bdffont->font_descent << 6; 608 size->metrics.max_advance = bdffont->bbx.width << 6; 609 610 return BDF_Err_Ok; 611 } 612 613 614 FT_CALLBACK_DEF( FT_Error ) BDF_Size_Request(FT_Size size,FT_Size_Request req)615 BDF_Size_Request( FT_Size size, 616 FT_Size_Request req ) 617 { 618 FT_Face face = size->face; 619 FT_Bitmap_Size* bsize = face->available_sizes; 620 bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont; 621 FT_Error error = BDF_Err_Invalid_Pixel_Size; 622 FT_Long height; 623 624 625 height = FT_REQUEST_HEIGHT( req ); 626 height = ( height + 32 ) >> 6; 627 628 switch ( req->type ) 629 { 630 case FT_SIZE_REQUEST_TYPE_NOMINAL: 631 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) ) 632 error = BDF_Err_Ok; 633 break; 634 635 case FT_SIZE_REQUEST_TYPE_REAL_DIM: 636 if ( height == ( bdffont->font_ascent + 637 bdffont->font_descent ) ) 638 error = BDF_Err_Ok; 639 break; 640 641 default: 642 error = BDF_Err_Unimplemented_Feature; 643 break; 644 } 645 646 if ( error ) 647 return error; 648 else 649 return BDF_Size_Select( size, 0 ); 650 } 651 652 653 654 FT_CALLBACK_DEF( FT_Error ) BDF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)655 BDF_Glyph_Load( FT_GlyphSlot slot, 656 FT_Size size, 657 FT_UInt glyph_index, 658 FT_Int32 load_flags ) 659 { 660 BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size ); 661 FT_Face face = FT_FACE( bdf ); 662 FT_Error error = BDF_Err_Ok; 663 FT_Bitmap* bitmap = &slot->bitmap; 664 bdf_glyph_t glyph; 665 int bpp = bdf->bdffont->bpp; 666 667 FT_UNUSED( load_flags ); 668 669 670 if ( !face || glyph_index >= (FT_UInt)face->num_glyphs ) 671 { 672 error = BDF_Err_Invalid_Argument; 673 goto Exit; 674 } 675 676 /* index 0 is the undefined glyph */ 677 if ( glyph_index == 0 ) 678 glyph_index = bdf->default_glyph; 679 else 680 glyph_index--; 681 682 /* slot, bitmap => freetype, glyph => bdflib */ 683 glyph = bdf->bdffont->glyphs[glyph_index]; 684 685 bitmap->rows = glyph.bbx.height; 686 bitmap->width = glyph.bbx.width; 687 if ( glyph.bpr > INT_MAX ) 688 FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n", 689 glyph.bpr )); 690 bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */ 691 692 /* note: we don't allocate a new array to hold the bitmap; */ 693 /* we can simply point to it */ 694 ft_glyphslot_set_bitmap( slot, glyph.bitmap ); 695 696 switch ( bpp ) 697 { 698 case 1: 699 bitmap->pixel_mode = FT_PIXEL_MODE_MONO; 700 break; 701 case 2: 702 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2; 703 break; 704 case 4: 705 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4; 706 break; 707 case 8: 708 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; 709 bitmap->num_grays = 256; 710 break; 711 } 712 713 slot->format = FT_GLYPH_FORMAT_BITMAP; 714 slot->bitmap_left = glyph.bbx.x_offset; 715 slot->bitmap_top = glyph.bbx.ascent; 716 717 slot->metrics.horiAdvance = glyph.dwidth << 6; 718 slot->metrics.horiBearingX = glyph.bbx.x_offset << 6; 719 slot->metrics.horiBearingY = glyph.bbx.ascent << 6; 720 slot->metrics.width = bitmap->width << 6; 721 slot->metrics.height = bitmap->rows << 6; 722 723 /* 724 * XXX DWIDTH1 and VVECTOR should be parsed and 725 * used here, provided such fonts do exist. 726 */ 727 ft_synthesize_vertical_metrics( &slot->metrics, 728 bdf->bdffont->bbx.height << 6 ); 729 730 Exit: 731 return error; 732 } 733 734 735 /* 736 * 737 * BDF SERVICE 738 * 739 */ 740 741 static FT_Error bdf_get_bdf_property(BDF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)742 bdf_get_bdf_property( BDF_Face face, 743 const char* prop_name, 744 BDF_PropertyRec *aproperty ) 745 { 746 bdf_property_t* prop; 747 748 749 FT_ASSERT( face && face->bdffont ); 750 751 prop = bdf_get_font_property( face->bdffont, prop_name ); 752 if ( prop ) 753 { 754 switch ( prop->format ) 755 { 756 case BDF_ATOM: 757 aproperty->type = BDF_PROPERTY_TYPE_ATOM; 758 aproperty->u.atom = prop->value.atom; 759 break; 760 761 case BDF_INTEGER: 762 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) 763 { 764 FT_TRACE1(( "bdf_get_bdf_property: " )); 765 FT_TRACE1(( "too large integer 0x%x is truncated\n" )); 766 } 767 aproperty->type = BDF_PROPERTY_TYPE_INTEGER; 768 aproperty->u.integer = (FT_Int32)prop->value.l; 769 break; 770 771 case BDF_CARDINAL: 772 if ( prop->value.ul > 0xFFFFFFFFUL ) 773 { 774 FT_TRACE1(( "bdf_get_bdf_property: " )); 775 FT_TRACE1(( "too large cardinal 0x%x is truncated\n" )); 776 } 777 aproperty->type = BDF_PROPERTY_TYPE_CARDINAL; 778 aproperty->u.cardinal = (FT_UInt32)prop->value.ul; 779 break; 780 781 default: 782 goto Fail; 783 } 784 return 0; 785 } 786 787 Fail: 788 return BDF_Err_Invalid_Argument; 789 } 790 791 792 static FT_Error bdf_get_charset_id(BDF_Face face,const char ** acharset_encoding,const char ** acharset_registry)793 bdf_get_charset_id( BDF_Face face, 794 const char* *acharset_encoding, 795 const char* *acharset_registry ) 796 { 797 *acharset_encoding = face->charset_encoding; 798 *acharset_registry = face->charset_registry; 799 800 return 0; 801 } 802 803 804 static const FT_Service_BDFRec bdf_service_bdf = 805 { 806 (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id, 807 (FT_BDF_GetPropertyFunc) bdf_get_bdf_property 808 }; 809 810 811 /* 812 * 813 * SERVICES LIST 814 * 815 */ 816 817 static const FT_ServiceDescRec bdf_services[] = 818 { 819 { FT_SERVICE_ID_BDF, &bdf_service_bdf }, 820 { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF }, 821 { NULL, NULL } 822 }; 823 824 825 FT_CALLBACK_DEF( FT_Module_Interface ) bdf_driver_requester(FT_Module module,const char * name)826 bdf_driver_requester( FT_Module module, 827 const char* name ) 828 { 829 FT_UNUSED( module ); 830 831 return ft_service_list_lookup( bdf_services, name ); 832 } 833 834 835 836 FT_CALLBACK_TABLE_DEF 837 const FT_Driver_ClassRec bdf_driver_class = 838 { 839 { 840 FT_MODULE_FONT_DRIVER | 841 FT_MODULE_DRIVER_NO_OUTLINES, 842 sizeof ( FT_DriverRec ), 843 844 "bdf", 845 0x10000L, 846 0x20000L, 847 848 0, 849 850 (FT_Module_Constructor)0, 851 (FT_Module_Destructor) 0, 852 (FT_Module_Requester) bdf_driver_requester 853 }, 854 855 sizeof ( BDF_FaceRec ), 856 sizeof ( FT_SizeRec ), 857 sizeof ( FT_GlyphSlotRec ), 858 859 BDF_Face_Init, 860 BDF_Face_Done, 861 0, /* FT_Size_InitFunc */ 862 0, /* FT_Size_DoneFunc */ 863 0, /* FT_Slot_InitFunc */ 864 0, /* FT_Slot_DoneFunc */ 865 866 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 867 ft_stub_set_char_sizes, 868 ft_stub_set_pixel_sizes, 869 #endif 870 BDF_Glyph_Load, 871 872 0, /* FT_Face_GetKerningFunc */ 873 0, /* FT_Face_AttachFunc */ 874 0, /* FT_Face_GetAdvancesFunc */ 875 876 BDF_Size_Request, 877 BDF_Size_Select 878 }; 879 880 881 /* END */ 882