1 /* pcfdrivr.c 2 3 FreeType font driver for pcf files 4 5 Copyright (C) 2000-2004, 2006-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 28 #include <ft2build.h> 29 30 #include FT_INTERNAL_DEBUG_H 31 #include FT_INTERNAL_STREAM_H 32 #include FT_INTERNAL_OBJECTS_H 33 #include FT_GZIP_H 34 #include FT_LZW_H 35 #include FT_BZIP2_H 36 #include FT_ERRORS_H 37 #include FT_BDF_H 38 #include FT_TRUETYPE_IDS_H 39 40 #include "pcf.h" 41 #include "pcfdrivr.h" 42 #include "pcfread.h" 43 44 #include "pcferror.h" 45 #include "pcfutil.h" 46 47 #undef FT_COMPONENT 48 #define FT_COMPONENT trace_pcfread 49 50 #include FT_SERVICE_BDF_H 51 #include FT_SERVICE_FONT_FORMAT_H 52 #include FT_SERVICE_PROPERTIES_H 53 #include FT_DRIVER_H 54 55 56 /*************************************************************************/ 57 /* */ 58 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 59 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 60 /* messages during execution. */ 61 /* */ 62 #undef FT_COMPONENT 63 #define FT_COMPONENT trace_pcfdriver 64 65 66 typedef struct PCF_CMapRec_ 67 { 68 FT_CMapRec root; 69 FT_ULong num_encodings; 70 PCF_Encoding encodings; 71 72 } PCF_CMapRec, *PCF_CMap; 73 74 75 FT_CALLBACK_DEF( FT_Error ) pcf_cmap_init(FT_CMap pcfcmap,FT_Pointer init_data)76 pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */ 77 FT_Pointer init_data ) 78 { 79 PCF_CMap cmap = (PCF_CMap)pcfcmap; 80 PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap ); 81 82 FT_UNUSED( init_data ); 83 84 85 cmap->num_encodings = face->nencodings; 86 cmap->encodings = face->encodings; 87 88 return FT_Err_Ok; 89 } 90 91 92 FT_CALLBACK_DEF( void ) pcf_cmap_done(FT_CMap pcfcmap)93 pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */ 94 { 95 PCF_CMap cmap = (PCF_CMap)pcfcmap; 96 97 98 cmap->encodings = NULL; 99 cmap->num_encodings = 0; 100 } 101 102 103 FT_CALLBACK_DEF( FT_UInt ) pcf_cmap_char_index(FT_CMap pcfcmap,FT_UInt32 charcode)104 pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */ 105 FT_UInt32 charcode ) 106 { 107 PCF_CMap cmap = (PCF_CMap)pcfcmap; 108 PCF_Encoding encodings = cmap->encodings; 109 FT_ULong min, max, mid; 110 FT_UInt result = 0; 111 112 113 min = 0; 114 max = cmap->num_encodings; 115 116 while ( min < max ) 117 { 118 FT_ULong code; 119 120 121 mid = ( min + max ) >> 1; 122 code = (FT_ULong)encodings[mid].enc; 123 124 if ( charcode == code ) 125 { 126 result = encodings[mid].glyph + 1; 127 break; 128 } 129 130 if ( charcode < code ) 131 max = mid; 132 else 133 min = mid + 1; 134 } 135 136 return result; 137 } 138 139 140 FT_CALLBACK_DEF( FT_UInt ) pcf_cmap_char_next(FT_CMap pcfcmap,FT_UInt32 * acharcode)141 pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */ 142 FT_UInt32 *acharcode ) 143 { 144 PCF_CMap cmap = (PCF_CMap)pcfcmap; 145 PCF_Encoding encodings = cmap->encodings; 146 FT_ULong min, max, mid; 147 FT_ULong charcode = *acharcode + 1; 148 FT_UInt result = 0; 149 150 151 min = 0; 152 max = cmap->num_encodings; 153 154 while ( min < max ) 155 { 156 FT_ULong code; 157 158 159 mid = ( min + max ) >> 1; 160 code = (FT_ULong)encodings[mid].enc; 161 162 if ( charcode == code ) 163 { 164 result = encodings[mid].glyph + 1; 165 goto Exit; 166 } 167 168 if ( charcode < code ) 169 max = mid; 170 else 171 min = mid + 1; 172 } 173 174 charcode = 0; 175 if ( min < cmap->num_encodings ) 176 { 177 charcode = (FT_ULong)encodings[min].enc; 178 result = encodings[min].glyph + 1; 179 } 180 181 Exit: 182 if ( charcode > 0xFFFFFFFFUL ) 183 { 184 FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" )); 185 *acharcode = 0; 186 /* XXX: result should be changed to indicate an overflow error */ 187 } 188 else 189 *acharcode = (FT_UInt32)charcode; 190 return result; 191 } 192 193 194 static 195 const FT_CMap_ClassRec pcf_cmap_class = 196 { 197 sizeof ( PCF_CMapRec ), 198 pcf_cmap_init, 199 pcf_cmap_done, 200 pcf_cmap_char_index, 201 pcf_cmap_char_next, 202 203 NULL, NULL, NULL, NULL, NULL 204 }; 205 206 207 FT_CALLBACK_DEF( void ) PCF_Face_Done(FT_Face pcfface)208 PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */ 209 { 210 PCF_Face face = (PCF_Face)pcfface; 211 FT_Memory memory; 212 213 214 if ( !face ) 215 return; 216 217 memory = FT_FACE_MEMORY( face ); 218 219 FT_FREE( face->encodings ); 220 FT_FREE( face->metrics ); 221 222 /* free properties */ 223 if ( face->properties ) 224 { 225 FT_Int i; 226 227 228 for ( i = 0; i < face->nprops; i++ ) 229 { 230 PCF_Property prop = &face->properties[i]; 231 232 233 if ( prop ) 234 { 235 FT_FREE( prop->name ); 236 if ( prop->isString ) 237 FT_FREE( prop->value.atom ); 238 } 239 } 240 241 FT_FREE( face->properties ); 242 } 243 244 FT_FREE( face->toc.tables ); 245 FT_FREE( pcfface->family_name ); 246 FT_FREE( pcfface->style_name ); 247 FT_FREE( pcfface->available_sizes ); 248 FT_FREE( face->charset_encoding ); 249 FT_FREE( face->charset_registry ); 250 251 /* close compressed stream if any */ 252 if ( pcfface->stream == &face->comp_stream ) 253 { 254 FT_Stream_Close( &face->comp_stream ); 255 pcfface->stream = face->comp_source; 256 } 257 } 258 259 260 FT_CALLBACK_DEF( FT_Error ) PCF_Face_Init(FT_Stream stream,FT_Face pcfface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)261 PCF_Face_Init( FT_Stream stream, 262 FT_Face pcfface, /* PCF_Face */ 263 FT_Int face_index, 264 FT_Int num_params, 265 FT_Parameter* params ) 266 { 267 PCF_Face face = (PCF_Face)pcfface; 268 FT_Error error; 269 270 FT_UNUSED( num_params ); 271 FT_UNUSED( params ); 272 273 274 FT_TRACE2(( "PCF driver\n" )); 275 276 error = pcf_load_font( stream, face, face_index ); 277 if ( error ) 278 { 279 PCF_Face_Done( pcfface ); 280 281 #if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \ 282 defined( FT_CONFIG_OPTION_USE_LZW ) || \ 283 defined( FT_CONFIG_OPTION_USE_BZIP2 ) 284 285 #ifdef FT_CONFIG_OPTION_USE_ZLIB 286 { 287 FT_Error error2; 288 289 290 /* this didn't work, try gzip support! */ 291 FT_TRACE2(( " ... try gzip stream\n" )); 292 error2 = FT_Stream_OpenGzip( &face->comp_stream, stream ); 293 if ( FT_ERR_EQ( error2, Unimplemented_Feature ) ) 294 goto Fail; 295 296 error = error2; 297 } 298 #endif /* FT_CONFIG_OPTION_USE_ZLIB */ 299 300 #ifdef FT_CONFIG_OPTION_USE_LZW 301 if ( error ) 302 { 303 FT_Error error3; 304 305 306 /* this didn't work, try LZW support! */ 307 FT_TRACE2(( " ... try LZW stream\n" )); 308 error3 = FT_Stream_OpenLZW( &face->comp_stream, stream ); 309 if ( FT_ERR_EQ( error3, Unimplemented_Feature ) ) 310 goto Fail; 311 312 error = error3; 313 } 314 #endif /* FT_CONFIG_OPTION_USE_LZW */ 315 316 #ifdef FT_CONFIG_OPTION_USE_BZIP2 317 if ( error ) 318 { 319 FT_Error error4; 320 321 322 /* this didn't work, try Bzip2 support! */ 323 FT_TRACE2(( " ... try Bzip2 stream\n" )); 324 error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream ); 325 if ( FT_ERR_EQ( error4, Unimplemented_Feature ) ) 326 goto Fail; 327 328 error = error4; 329 } 330 #endif /* FT_CONFIG_OPTION_USE_BZIP2 */ 331 332 if ( error ) 333 goto Fail; 334 335 face->comp_source = stream; 336 pcfface->stream = &face->comp_stream; 337 338 stream = pcfface->stream; 339 340 error = pcf_load_font( stream, face, face_index ); 341 if ( error ) 342 goto Fail; 343 344 #else /* !(FT_CONFIG_OPTION_USE_ZLIB || 345 FT_CONFIG_OPTION_USE_LZW || 346 FT_CONFIG_OPTION_USE_BZIP2) */ 347 348 goto Fail; 349 350 #endif 351 } 352 353 /* PCF cannot have multiple faces in a single font file. 354 * XXX: A non-zero face_index is already an invalid argument, but 355 * Type1, Type42 drivers have a convention to return 356 * an invalid argument error when the font could be 357 * opened by the specified driver. 358 */ 359 if ( face_index < 0 ) 360 goto Exit; 361 else if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) 362 { 363 FT_ERROR(( "PCF_Face_Init: invalid face index\n" )); 364 PCF_Face_Done( pcfface ); 365 return FT_THROW( Invalid_Argument ); 366 } 367 368 /* set up charmap */ 369 { 370 FT_String *charset_registry = face->charset_registry; 371 FT_String *charset_encoding = face->charset_encoding; 372 FT_Bool unicode_charmap = 0; 373 374 375 if ( charset_registry && charset_encoding ) 376 { 377 char* s = charset_registry; 378 379 380 /* Uh, oh, compare first letters manually to avoid dependency 381 on locales. */ 382 if ( ( s[0] == 'i' || s[0] == 'I' ) && 383 ( s[1] == 's' || s[1] == 'S' ) && 384 ( s[2] == 'o' || s[2] == 'O' ) ) 385 { 386 s += 3; 387 if ( !ft_strcmp( s, "10646" ) || 388 ( !ft_strcmp( s, "8859" ) && 389 !ft_strcmp( face->charset_encoding, "1" ) ) ) 390 unicode_charmap = 1; 391 /* another name for ASCII */ 392 else if ( !ft_strcmp( s, "646.1991" ) && 393 !ft_strcmp( face->charset_encoding, "IRV" ) ) 394 unicode_charmap = 1; 395 } 396 } 397 398 { 399 FT_CharMapRec charmap; 400 401 402 charmap.face = FT_FACE( face ); 403 charmap.encoding = FT_ENCODING_NONE; 404 /* initial platform/encoding should indicate unset status? */ 405 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; 406 charmap.encoding_id = TT_APPLE_ID_DEFAULT; 407 408 if ( unicode_charmap ) 409 { 410 charmap.encoding = FT_ENCODING_UNICODE; 411 charmap.platform_id = TT_PLATFORM_MICROSOFT; 412 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 413 } 414 415 error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL ); 416 } 417 } 418 419 Exit: 420 return error; 421 422 Fail: 423 FT_TRACE2(( " not a PCF file\n" )); 424 PCF_Face_Done( pcfface ); 425 error = FT_THROW( Unknown_File_Format ); /* error */ 426 goto Exit; 427 } 428 429 430 FT_CALLBACK_DEF( FT_Error ) PCF_Size_Select(FT_Size size,FT_ULong strike_index)431 PCF_Size_Select( FT_Size size, 432 FT_ULong strike_index ) 433 { 434 PCF_Accel accel = &( (PCF_Face)size->face )->accel; 435 436 437 FT_Select_Metrics( size->face, strike_index ); 438 439 size->metrics.ascender = accel->fontAscent * 64; 440 size->metrics.descender = -accel->fontDescent * 64; 441 size->metrics.max_advance = accel->maxbounds.characterWidth * 64; 442 443 return FT_Err_Ok; 444 } 445 446 447 FT_CALLBACK_DEF( FT_Error ) PCF_Size_Request(FT_Size size,FT_Size_Request req)448 PCF_Size_Request( FT_Size size, 449 FT_Size_Request req ) 450 { 451 PCF_Face face = (PCF_Face)size->face; 452 FT_Bitmap_Size* bsize = size->face->available_sizes; 453 FT_Error error = FT_ERR( Invalid_Pixel_Size ); 454 FT_Long height; 455 456 457 height = FT_REQUEST_HEIGHT( req ); 458 height = ( height + 32 ) >> 6; 459 460 switch ( req->type ) 461 { 462 case FT_SIZE_REQUEST_TYPE_NOMINAL: 463 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) ) 464 error = FT_Err_Ok; 465 break; 466 467 case FT_SIZE_REQUEST_TYPE_REAL_DIM: 468 if ( height == ( face->accel.fontAscent + 469 face->accel.fontDescent ) ) 470 error = FT_Err_Ok; 471 break; 472 473 default: 474 error = FT_THROW( Unimplemented_Feature ); 475 break; 476 } 477 478 if ( error ) 479 return error; 480 else 481 return PCF_Size_Select( size, 0 ); 482 } 483 484 485 FT_CALLBACK_DEF( FT_Error ) PCF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)486 PCF_Glyph_Load( FT_GlyphSlot slot, 487 FT_Size size, 488 FT_UInt glyph_index, 489 FT_Int32 load_flags ) 490 { 491 PCF_Face face = (PCF_Face)FT_SIZE_FACE( size ); 492 FT_Stream stream; 493 FT_Error error = FT_Err_Ok; 494 FT_Bitmap* bitmap = &slot->bitmap; 495 PCF_Metric metric; 496 FT_ULong bytes; 497 498 499 FT_TRACE1(( "PCF_Glyph_Load: glyph index %d\n", glyph_index )); 500 501 if ( !face ) 502 { 503 error = FT_THROW( Invalid_Face_Handle ); 504 goto Exit; 505 } 506 507 if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) 508 { 509 error = FT_THROW( Invalid_Argument ); 510 goto Exit; 511 } 512 513 stream = face->root.stream; 514 515 if ( glyph_index > 0 ) 516 glyph_index--; 517 518 metric = face->metrics + glyph_index; 519 520 bitmap->rows = (unsigned int)( metric->ascent + 521 metric->descent ); 522 bitmap->width = (unsigned int)( metric->rightSideBearing - 523 metric->leftSideBearing ); 524 bitmap->num_grays = 1; 525 bitmap->pixel_mode = FT_PIXEL_MODE_MONO; 526 527 switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) ) 528 { 529 case 1: 530 bitmap->pitch = (int)( ( bitmap->width + 7 ) >> 3 ); 531 break; 532 533 case 2: 534 bitmap->pitch = (int)( ( ( bitmap->width + 15 ) >> 4 ) << 1 ); 535 break; 536 537 case 4: 538 bitmap->pitch = (int)( ( ( bitmap->width + 31 ) >> 5 ) << 2 ); 539 break; 540 541 case 8: 542 bitmap->pitch = (int)( ( ( bitmap->width + 63 ) >> 6 ) << 3 ); 543 break; 544 545 default: 546 return FT_THROW( Invalid_File_Format ); 547 } 548 549 slot->format = FT_GLYPH_FORMAT_BITMAP; 550 slot->bitmap_left = metric->leftSideBearing; 551 slot->bitmap_top = metric->ascent; 552 553 slot->metrics.horiAdvance = (FT_Pos)( metric->characterWidth * 64 ); 554 slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 ); 555 slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 ); 556 slot->metrics.width = (FT_Pos)( ( metric->rightSideBearing - 557 metric->leftSideBearing ) * 64 ); 558 slot->metrics.height = (FT_Pos)( bitmap->rows * 64 ); 559 560 ft_synthesize_vertical_metrics( &slot->metrics, 561 ( face->accel.fontAscent + 562 face->accel.fontDescent ) * 64 ); 563 564 if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) 565 goto Exit; 566 567 /* XXX: to do: are there cases that need repadding the bitmap? */ 568 bytes = (FT_ULong)bitmap->pitch * bitmap->rows; 569 570 error = ft_glyphslot_alloc_bitmap( slot, (FT_ULong)bytes ); 571 if ( error ) 572 goto Exit; 573 574 if ( FT_STREAM_SEEK( metric->bits ) || 575 FT_STREAM_READ( bitmap->buffer, bytes ) ) 576 goto Exit; 577 578 if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst ) 579 BitOrderInvert( bitmap->buffer, bytes ); 580 581 if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) != 582 PCF_BIT_ORDER( face->bitmapsFormat ) ) ) 583 { 584 switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) ) 585 { 586 case 1: 587 break; 588 589 case 2: 590 TwoByteSwap( bitmap->buffer, bytes ); 591 break; 592 593 case 4: 594 FourByteSwap( bitmap->buffer, bytes ); 595 break; 596 } 597 } 598 599 Exit: 600 return error; 601 } 602 603 604 /* 605 * 606 * BDF SERVICE 607 * 608 */ 609 610 static FT_Error pcf_get_bdf_property(PCF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)611 pcf_get_bdf_property( PCF_Face face, 612 const char* prop_name, 613 BDF_PropertyRec *aproperty ) 614 { 615 PCF_Property prop; 616 617 618 prop = pcf_find_property( face, prop_name ); 619 if ( prop ) 620 { 621 if ( prop->isString ) 622 { 623 aproperty->type = BDF_PROPERTY_TYPE_ATOM; 624 aproperty->u.atom = prop->value.atom; 625 } 626 else 627 { 628 if ( prop->value.l > 0x7FFFFFFFL || 629 prop->value.l < ( -1 - 0x7FFFFFFFL ) ) 630 { 631 FT_TRACE1(( "pcf_get_bdf_property:" )); 632 FT_TRACE1(( " too large integer 0x%x is truncated\n" )); 633 } 634 635 /* 636 * The PCF driver loads all properties as signed integers. 637 * This really doesn't seem to be a problem, because this is 638 * sufficient for any meaningful values. 639 */ 640 aproperty->type = BDF_PROPERTY_TYPE_INTEGER; 641 aproperty->u.integer = (FT_Int32)prop->value.l; 642 } 643 644 return FT_Err_Ok; 645 } 646 647 return FT_THROW( Invalid_Argument ); 648 } 649 650 651 static FT_Error pcf_get_charset_id(PCF_Face face,const char ** acharset_encoding,const char ** acharset_registry)652 pcf_get_charset_id( PCF_Face face, 653 const char* *acharset_encoding, 654 const char* *acharset_registry ) 655 { 656 *acharset_encoding = face->charset_encoding; 657 *acharset_registry = face->charset_registry; 658 659 return FT_Err_Ok; 660 } 661 662 663 static const FT_Service_BDFRec pcf_service_bdf = 664 { 665 (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id, /* get_charset_id */ 666 (FT_BDF_GetPropertyFunc) pcf_get_bdf_property /* get_property */ 667 }; 668 669 670 /* 671 * PROPERTY SERVICE 672 * 673 */ 674 static FT_Error pcf_property_set(FT_Module module,const char * property_name,const void * value,FT_Bool value_is_string)675 pcf_property_set( FT_Module module, /* PCF_Driver */ 676 const char* property_name, 677 const void* value, 678 FT_Bool value_is_string ) 679 { 680 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES 681 682 FT_Error error = FT_Err_Ok; 683 PCF_Driver driver = (PCF_Driver)module; 684 685 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 686 FT_UNUSED( value_is_string ); 687 #endif 688 689 690 if ( !ft_strcmp( property_name, "no-long-family-names" ) ) 691 { 692 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 693 if ( value_is_string ) 694 { 695 const char* s = (const char*)value; 696 long lfn = ft_strtol( s, NULL, 10 ); 697 698 699 if ( lfn == 0 ) 700 driver->no_long_family_names = 0; 701 else if ( lfn == 1 ) 702 driver->no_long_family_names = 1; 703 else 704 return FT_THROW( Invalid_Argument ); 705 } 706 else 707 #endif 708 { 709 FT_Bool* no_long_family_names = (FT_Bool*)value; 710 711 712 driver->no_long_family_names = *no_long_family_names; 713 } 714 715 return error; 716 } 717 718 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ 719 720 FT_UNUSED( module ); 721 FT_UNUSED( value ); 722 FT_UNUSED( value_is_string ); 723 #ifndef FT_DEBUG_LEVEL_TRACE 724 FT_UNUSED( property_name ); 725 #endif 726 727 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ 728 729 FT_TRACE0(( "pcf_property_set: missing property `%s'\n", 730 property_name )); 731 return FT_THROW( Missing_Property ); 732 } 733 734 735 static FT_Error pcf_property_get(FT_Module module,const char * property_name,const void * value)736 pcf_property_get( FT_Module module, /* PCF_Driver */ 737 const char* property_name, 738 const void* value ) 739 { 740 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES 741 742 FT_Error error = FT_Err_Ok; 743 PCF_Driver driver = (PCF_Driver)module; 744 745 746 if ( !ft_strcmp( property_name, "no-long-family-names" ) ) 747 { 748 FT_Bool no_long_family_names = driver->no_long_family_names; 749 FT_Bool* val = (FT_Bool*)value; 750 751 752 *val = no_long_family_names; 753 754 return error; 755 } 756 757 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ 758 759 FT_UNUSED( module ); 760 FT_UNUSED( value ); 761 #ifndef FT_DEBUG_LEVEL_TRACE 762 FT_UNUSED( property_name ); 763 #endif 764 765 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ 766 767 FT_TRACE0(( "pcf_property_get: missing property `%s'\n", 768 property_name )); 769 return FT_THROW( Missing_Property ); 770 } 771 772 773 FT_DEFINE_SERVICE_PROPERTIESREC( 774 pcf_service_properties, 775 776 (FT_Properties_SetFunc)pcf_property_set, /* set_property */ 777 (FT_Properties_GetFunc)pcf_property_get ) /* get_property */ 778 779 780 /* 781 * 782 * SERVICE LIST 783 * 784 */ 785 786 static const FT_ServiceDescRec pcf_services[] = 787 { 788 { FT_SERVICE_ID_BDF, &pcf_service_bdf }, 789 { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_PCF }, 790 { FT_SERVICE_ID_PROPERTIES, &pcf_service_properties }, 791 { NULL, NULL } 792 }; 793 794 795 FT_CALLBACK_DEF( FT_Module_Interface ) pcf_driver_requester(FT_Module module,const char * name)796 pcf_driver_requester( FT_Module module, 797 const char* name ) 798 { 799 FT_UNUSED( module ); 800 801 return ft_service_list_lookup( pcf_services, name ); 802 } 803 804 805 FT_CALLBACK_DEF( FT_Error ) pcf_driver_init(FT_Module module)806 pcf_driver_init( FT_Module module ) /* PCF_Driver */ 807 { 808 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES 809 PCF_Driver driver = (PCF_Driver)module; 810 811 812 driver->no_long_family_names = 0; 813 #else 814 FT_UNUSED( module ); 815 #endif 816 817 return FT_Err_Ok; 818 } 819 820 821 FT_CALLBACK_DEF( void ) pcf_driver_done(FT_Module module)822 pcf_driver_done( FT_Module module ) /* PCF_Driver */ 823 { 824 FT_UNUSED( module ); 825 } 826 827 828 FT_CALLBACK_TABLE_DEF 829 const FT_Driver_ClassRec pcf_driver_class = 830 { 831 { 832 FT_MODULE_FONT_DRIVER | 833 FT_MODULE_DRIVER_NO_OUTLINES, 834 835 sizeof ( PCF_DriverRec ), 836 "pcf", 837 0x10000L, 838 0x20000L, 839 840 NULL, /* module-specific interface */ 841 842 pcf_driver_init, /* FT_Module_Constructor module_init */ 843 pcf_driver_done, /* FT_Module_Destructor module_done */ 844 pcf_driver_requester /* FT_Module_Requester get_interface */ 845 }, 846 847 sizeof ( PCF_FaceRec ), 848 sizeof ( FT_SizeRec ), 849 sizeof ( FT_GlyphSlotRec ), 850 851 PCF_Face_Init, /* FT_Face_InitFunc init_face */ 852 PCF_Face_Done, /* FT_Face_DoneFunc done_face */ 853 NULL, /* FT_Size_InitFunc init_size */ 854 NULL, /* FT_Size_DoneFunc done_size */ 855 NULL, /* FT_Slot_InitFunc init_slot */ 856 NULL, /* FT_Slot_DoneFunc done_slot */ 857 858 PCF_Glyph_Load, /* FT_Slot_LoadFunc load_glyph */ 859 860 NULL, /* FT_Face_GetKerningFunc get_kerning */ 861 NULL, /* FT_Face_AttachFunc attach_file */ 862 NULL, /* FT_Face_GetAdvancesFunc get_advances */ 863 864 PCF_Size_Request, /* FT_Size_RequestFunc request_size */ 865 PCF_Size_Select /* FT_Size_SelectFunc select_size */ 866 }; 867 868 869 /* END */ 870