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