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