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