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 cmap,FT_Pointer init_data)78 pcf_cmap_init( FT_CMap cmap, /* PCF_CMap */ 79 FT_Pointer init_data ) 80 { 81 PCF_CMap pcfcmap = (PCF_CMap)cmap; 82 PCF_Face face = (PCF_Face)FT_CMAP_FACE( cmap ); 83 84 FT_UNUSED( init_data ); 85 86 87 pcfcmap->enc = &face->enc; 88 89 return FT_Err_Ok; 90 } 91 92 93 FT_CALLBACK_DEF( void ) pcf_cmap_done(FT_CMap cmap)94 pcf_cmap_done( FT_CMap cmap ) /* PCF_CMap */ 95 { 96 PCF_CMap pcfcmap = (PCF_CMap)cmap; 97 98 99 pcfcmap->enc = NULL; 100 } 101 102 103 FT_CALLBACK_DEF( FT_UInt ) pcf_cmap_char_index(FT_CMap cmap,FT_UInt32 charcode)104 pcf_cmap_char_index( FT_CMap cmap, /* PCF_CMap */ 105 FT_UInt32 charcode ) 106 { 107 PCF_Enc enc = ( (PCF_CMap)cmap )->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 cmap,FT_UInt32 * acharcode)124 pcf_cmap_char_next( FT_CMap cmap, /* PCF_CMap */ 125 FT_UInt32 *acharcode ) 126 { 127 PCF_Enc enc = ( (PCF_CMap)cmap )->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 face)173 PCF_Face_Done( FT_Face face ) /* PCF_Face */ 174 { 175 PCF_Face pcfface = (PCF_Face)face; 176 FT_Memory memory; 177 178 179 if ( !face ) 180 return; 181 182 memory = FT_FACE_MEMORY( face ); 183 184 FT_FREE( pcfface->metrics ); 185 FT_FREE( pcfface->enc.offset ); 186 187 /* free properties */ 188 if ( pcfface->properties ) 189 { 190 FT_Int i; 191 192 193 for ( i = 0; i < pcfface->nprops; i++ ) 194 { 195 PCF_Property prop = &pcfface->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( pcfface->properties ); 207 } 208 209 FT_FREE( pcfface->toc.tables ); 210 FT_FREE( face->family_name ); 211 FT_FREE( face->style_name ); 212 FT_FREE( face->available_sizes ); 213 FT_FREE( pcfface->charset_encoding ); 214 FT_FREE( pcfface->charset_registry ); 215 216 /* close compressed stream if any */ 217 if ( face->stream == &pcfface->comp_stream ) 218 { 219 FT_Stream_Close( &pcfface->comp_stream ); 220 face->stream = pcfface->comp_source; 221 } 222 } 223 224 225 FT_CALLBACK_DEF( FT_Error ) PCF_Face_Init(FT_Stream stream,FT_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)226 PCF_Face_Init( FT_Stream stream, 227 FT_Face face, /* PCF_Face */ 228 FT_Int face_index, 229 FT_Int num_params, 230 FT_Parameter* params ) 231 { 232 PCF_Face pcfface = (PCF_Face)face; 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, pcfface, face_index ); 242 if ( error ) 243 { 244 PCF_Face_Done( face ); 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( &pcfface->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( &pcfface->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( &pcfface->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 pcfface->comp_source = stream; 301 face->stream = &pcfface->comp_stream; 302 303 stream = face->stream; 304 305 error = pcf_load_font( stream, pcfface, 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( face ); 330 return FT_THROW( Invalid_Argument ); 331 } 332 333 /* set up charmap */ 334 { 335 FT_String *charset_registry = pcfface->charset_registry; 336 FT_String *charset_encoding = pcfface->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( pcfface->charset_encoding, "1" ) ) ) 355 unicode_charmap = 1; 356 /* another name for ASCII */ 357 else if ( !ft_strcmp( s, "646.1991" ) && 358 !ft_strcmp( pcfface->charset_encoding, "IRV" ) ) 359 unicode_charmap = 1; 360 } 361 } 362 363 { 364 FT_CharMapRec charmap; 365 366 367 charmap.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( face ); 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 FT_CALLBACK_DEF( FT_Error ) pcf_get_bdf_property(FT_Face face,const char * prop_name,BDF_PropertyRec * aproperty)573 pcf_get_bdf_property( FT_Face face, /* PCF_Face */ 574 const char* prop_name, 575 BDF_PropertyRec *aproperty ) 576 { 577 PCF_Face pcfface = (PCF_Face)face; 578 PCF_Property prop; 579 580 581 prop = pcf_find_property( pcfface, prop_name ); 582 if ( prop ) 583 { 584 if ( prop->isString ) 585 { 586 aproperty->type = BDF_PROPERTY_TYPE_ATOM; 587 aproperty->u.atom = prop->value.atom; 588 } 589 else 590 { 591 if ( prop->value.l > 0x7FFFFFFFL || 592 prop->value.l < ( -1 - 0x7FFFFFFFL ) ) 593 { 594 FT_TRACE2(( "pcf_get_bdf_property:" 595 " too large integer 0x%lx is truncated\n", 596 prop->value.l )); 597 } 598 599 /* 600 * The PCF driver loads all properties as signed integers. 601 * This really doesn't seem to be a problem, because this is 602 * sufficient for any meaningful values. 603 */ 604 aproperty->type = BDF_PROPERTY_TYPE_INTEGER; 605 aproperty->u.integer = (FT_Int32)prop->value.l; 606 } 607 608 return FT_Err_Ok; 609 } 610 611 return FT_THROW( Invalid_Argument ); 612 } 613 614 615 FT_CALLBACK_DEF( FT_Error ) pcf_get_charset_id(FT_Face face,const char ** acharset_encoding,const char ** acharset_registry)616 pcf_get_charset_id( FT_Face face, /* PCF_Face */ 617 const char* *acharset_encoding, 618 const char* *acharset_registry ) 619 { 620 PCF_Face pcfface = (PCF_Face)face; 621 622 623 *acharset_encoding = pcfface->charset_encoding; 624 *acharset_registry = pcfface->charset_registry; 625 626 return FT_Err_Ok; 627 } 628 629 630 static const FT_Service_BDFRec pcf_service_bdf = 631 { 632 (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id, /* get_charset_id */ 633 (FT_BDF_GetPropertyFunc) pcf_get_bdf_property /* get_property */ 634 }; 635 636 637 /* 638 * PROPERTY SERVICE 639 * 640 */ 641 FT_CALLBACK_DEF( FT_Error ) pcf_property_set(FT_Module module,const char * property_name,const void * value,FT_Bool value_is_string)642 pcf_property_set( FT_Module module, /* PCF_Driver */ 643 const char* property_name, 644 const void* value, 645 FT_Bool value_is_string ) 646 { 647 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES 648 649 FT_Error error = FT_Err_Ok; 650 PCF_Driver driver = (PCF_Driver)module; 651 652 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 653 FT_UNUSED( value_is_string ); 654 #endif 655 656 657 if ( !ft_strcmp( property_name, "no-long-family-names" ) ) 658 { 659 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 660 if ( value_is_string ) 661 { 662 const char* s = (const char*)value; 663 long lfn = ft_strtol( s, NULL, 10 ); 664 665 666 if ( lfn == 0 ) 667 driver->no_long_family_names = 0; 668 else if ( lfn == 1 ) 669 driver->no_long_family_names = 1; 670 else 671 return FT_THROW( Invalid_Argument ); 672 } 673 else 674 #endif 675 { 676 FT_Bool* no_long_family_names = (FT_Bool*)value; 677 678 679 driver->no_long_family_names = *no_long_family_names; 680 } 681 682 return error; 683 } 684 685 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ 686 687 FT_UNUSED( module ); 688 FT_UNUSED( value ); 689 FT_UNUSED( value_is_string ); 690 #ifndef FT_DEBUG_LEVEL_TRACE 691 FT_UNUSED( property_name ); 692 #endif 693 694 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ 695 696 FT_TRACE2(( "pcf_property_set: missing property `%s'\n", 697 property_name )); 698 return FT_THROW( Missing_Property ); 699 } 700 701 702 FT_CALLBACK_DEF( FT_Error ) pcf_property_get(FT_Module module,const char * property_name,void * value)703 pcf_property_get( FT_Module module, /* PCF_Driver */ 704 const char* property_name, 705 void* value ) 706 { 707 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES 708 709 FT_Error error = FT_Err_Ok; 710 PCF_Driver driver = (PCF_Driver)module; 711 712 713 if ( !ft_strcmp( property_name, "no-long-family-names" ) ) 714 { 715 FT_Bool no_long_family_names = driver->no_long_family_names; 716 FT_Bool* val = (FT_Bool*)value; 717 718 719 *val = no_long_family_names; 720 721 return error; 722 } 723 724 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ 725 726 FT_UNUSED( module ); 727 FT_UNUSED( value ); 728 #ifndef FT_DEBUG_LEVEL_TRACE 729 FT_UNUSED( property_name ); 730 #endif 731 732 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ 733 734 FT_TRACE2(( "pcf_property_get: missing property `%s'\n", 735 property_name )); 736 return FT_THROW( Missing_Property ); 737 } 738 739 740 FT_DEFINE_SERVICE_PROPERTIESREC( 741 pcf_service_properties, 742 743 (FT_Properties_SetFunc)pcf_property_set, /* set_property */ 744 (FT_Properties_GetFunc)pcf_property_get ) /* get_property */ 745 746 747 /* 748 * 749 * SERVICE LIST 750 * 751 */ 752 753 static const FT_ServiceDescRec pcf_services[] = 754 { 755 { FT_SERVICE_ID_BDF, &pcf_service_bdf }, 756 { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_PCF }, 757 { FT_SERVICE_ID_PROPERTIES, &pcf_service_properties }, 758 { NULL, NULL } 759 }; 760 761 762 FT_CALLBACK_DEF( FT_Module_Interface ) pcf_driver_requester(FT_Module module,const char * name)763 pcf_driver_requester( FT_Module module, 764 const char* name ) 765 { 766 FT_UNUSED( module ); 767 768 return ft_service_list_lookup( pcf_services, name ); 769 } 770 771 772 FT_CALLBACK_DEF( FT_Error ) pcf_driver_init(FT_Module module)773 pcf_driver_init( FT_Module module ) /* PCF_Driver */ 774 { 775 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES 776 PCF_Driver driver = (PCF_Driver)module; 777 778 779 driver->no_long_family_names = 0; 780 #else 781 FT_UNUSED( module ); 782 #endif 783 784 return FT_Err_Ok; 785 } 786 787 788 FT_CALLBACK_DEF( void ) pcf_driver_done(FT_Module module)789 pcf_driver_done( FT_Module module ) /* PCF_Driver */ 790 { 791 FT_UNUSED( module ); 792 } 793 794 795 FT_CALLBACK_TABLE_DEF 796 const FT_Driver_ClassRec pcf_driver_class = 797 { 798 { 799 FT_MODULE_FONT_DRIVER | 800 FT_MODULE_DRIVER_NO_OUTLINES, 801 802 sizeof ( PCF_DriverRec ), 803 "pcf", 804 0x10000L, 805 0x20000L, 806 807 NULL, /* module-specific interface */ 808 809 pcf_driver_init, /* FT_Module_Constructor module_init */ 810 pcf_driver_done, /* FT_Module_Destructor module_done */ 811 pcf_driver_requester /* FT_Module_Requester get_interface */ 812 }, 813 814 sizeof ( PCF_FaceRec ), 815 sizeof ( FT_SizeRec ), 816 sizeof ( FT_GlyphSlotRec ), 817 818 PCF_Face_Init, /* FT_Face_InitFunc init_face */ 819 PCF_Face_Done, /* FT_Face_DoneFunc done_face */ 820 NULL, /* FT_Size_InitFunc init_size */ 821 NULL, /* FT_Size_DoneFunc done_size */ 822 NULL, /* FT_Slot_InitFunc init_slot */ 823 NULL, /* FT_Slot_DoneFunc done_slot */ 824 825 PCF_Glyph_Load, /* FT_Slot_LoadFunc load_glyph */ 826 827 NULL, /* FT_Face_GetKerningFunc get_kerning */ 828 NULL, /* FT_Face_AttachFunc attach_file */ 829 NULL, /* FT_Face_GetAdvancesFunc get_advances */ 830 831 PCF_Size_Request, /* FT_Size_RequestFunc request_size */ 832 PCF_Size_Select /* FT_Size_SelectFunc select_size */ 833 }; 834 835 836 /* END */ 837