1 /* pcfread.c 2 3 FreeType font driver for pcf fonts 4 5 Copyright 2000-2001, 2002 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 34 #include "pcf.h" 35 #include "pcfdriver.h" 36 37 #include "pcferror.h" 38 39 40 /*************************************************************************/ 41 /* */ 42 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 43 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 44 /* messages during execution. */ 45 /* */ 46 #undef FT_COMPONENT 47 #define FT_COMPONENT trace_pcfread 48 49 50 #if defined( FT_DEBUG_LEVEL_TRACE ) 51 static const char* tableNames[] = 52 { 53 "prop", "accl", "mtrcs", "bmps", "imtrcs", 54 "enc", "swidth", "names", "accel" 55 }; 56 #endif 57 58 59 static 60 const FT_Frame_Field pcf_toc_header[] = 61 { 62 #undef FT_STRUCTURE 63 #define FT_STRUCTURE PCF_TocRec 64 65 FT_FRAME_START( 8 ), 66 FT_FRAME_ULONG_LE( version ), 67 FT_FRAME_ULONG_LE( count ), 68 FT_FRAME_END 69 }; 70 71 72 static 73 const FT_Frame_Field pcf_table_header[] = 74 { 75 #undef FT_STRUCTURE 76 #define FT_STRUCTURE PCF_TableRec 77 78 FT_FRAME_START( 16 ), 79 FT_FRAME_ULONG_LE( type ), 80 FT_FRAME_ULONG_LE( format ), 81 FT_FRAME_ULONG_LE( size ), 82 FT_FRAME_ULONG_LE( offset ), 83 FT_FRAME_END 84 }; 85 86 87 static FT_Error pcf_read_TOC(FT_Stream stream,PCF_Face face)88 pcf_read_TOC( FT_Stream stream, 89 PCF_Face face ) 90 { 91 FT_Error error; 92 PCF_Toc toc = &face->toc; 93 PCF_Table tables; 94 95 FT_Memory memory = FT_FACE(face)->memory; 96 FT_UInt n; 97 98 99 if ( FT_STREAM_SEEK ( 0 ) || 100 FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) ) 101 return PCF_Err_Cannot_Open_Resource; 102 103 if ( toc->version != PCF_FILE_VERSION ) 104 return PCF_Err_Invalid_File_Format; 105 106 if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) 107 return PCF_Err_Out_Of_Memory; 108 109 tables = face->toc.tables; 110 for ( n = 0; n < toc->count; n++ ) 111 { 112 if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) ) 113 goto Exit; 114 tables++; 115 } 116 117 #if defined( FT_DEBUG_LEVEL_TRACE ) 118 119 { 120 FT_UInt i, j; 121 const char* name = "?"; 122 123 124 FT_TRACE4(( "Tables count: %ld\n", face->toc.count )); 125 tables = face->toc.tables; 126 for ( i = 0; i < toc->count; i++ ) 127 { 128 for( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ ) 129 if ( tables[i].type == (FT_UInt)( 1 << j ) ) 130 name = tableNames[j]; 131 132 FT_TRACE4(( "Table %d: type=%-6s format=0x%04lX " 133 "size=0x%06lX (%8ld) offset=0x%04lX\n", 134 i, name, 135 tables[i].format, 136 tables[i].size, tables[i].size, 137 tables[i].offset )); 138 } 139 } 140 141 #endif 142 143 return PCF_Err_Ok; 144 145 Exit: 146 FT_FREE( face->toc.tables ); 147 return error; 148 } 149 150 151 static 152 const FT_Frame_Field pcf_metric_header[] = 153 { 154 #undef FT_STRUCTURE 155 #define FT_STRUCTURE PCF_MetricRec 156 157 FT_FRAME_START( 12 ), 158 FT_FRAME_SHORT_LE( leftSideBearing ), 159 FT_FRAME_SHORT_LE( rightSideBearing ), 160 FT_FRAME_SHORT_LE( characterWidth ), 161 FT_FRAME_SHORT_LE( ascent ), 162 FT_FRAME_SHORT_LE( descent ), 163 FT_FRAME_SHORT_LE( attributes ), 164 FT_FRAME_END 165 }; 166 167 168 static 169 const FT_Frame_Field pcf_metric_msb_header[] = 170 { 171 #undef FT_STRUCTURE 172 #define FT_STRUCTURE PCF_MetricRec 173 174 FT_FRAME_START( 12 ), 175 FT_FRAME_SHORT( leftSideBearing ), 176 FT_FRAME_SHORT( rightSideBearing ), 177 FT_FRAME_SHORT( characterWidth ), 178 FT_FRAME_SHORT( ascent ), 179 FT_FRAME_SHORT( descent ), 180 FT_FRAME_SHORT( attributes ), 181 FT_FRAME_END 182 }; 183 184 185 static 186 const FT_Frame_Field pcf_compressed_metric_header[] = 187 { 188 #undef FT_STRUCTURE 189 #define FT_STRUCTURE PCF_Compressed_MetricRec 190 191 FT_FRAME_START( 5 ), 192 FT_FRAME_BYTE( leftSideBearing ), 193 FT_FRAME_BYTE( rightSideBearing ), 194 FT_FRAME_BYTE( characterWidth ), 195 FT_FRAME_BYTE( ascent ), 196 FT_FRAME_BYTE( descent ), 197 FT_FRAME_END 198 }; 199 200 201 static FT_Error pcf_get_metric(FT_Stream stream,FT_ULong format,PCF_Metric metric)202 pcf_get_metric( FT_Stream stream, 203 FT_ULong format, 204 PCF_Metric metric ) 205 { 206 FT_Error error = PCF_Err_Ok; 207 208 209 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) 210 { 211 const FT_Frame_Field* fields; 212 213 214 /* parsing normal metrics */ 215 fields = PCF_BYTE_ORDER( format ) == MSBFirst 216 ? pcf_metric_msb_header 217 : pcf_metric_header; 218 219 /* the following sets 'error' but doesn't return in case of failure */ 220 (void)FT_STREAM_READ_FIELDS( fields, metric ); 221 } 222 else 223 { 224 PCF_Compressed_MetricRec compr; 225 226 227 /* parsing compressed metrics */ 228 if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) ) 229 goto Exit; 230 231 metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 ); 232 metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 ); 233 metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 ); 234 metric->ascent = (FT_Short)( compr.ascent - 0x80 ); 235 metric->descent = (FT_Short)( compr.descent - 0x80 ); 236 metric->attributes = 0; 237 } 238 239 Exit: 240 return error; 241 } 242 243 244 static FT_Error pcf_seek_to_table_type(FT_Stream stream,PCF_Table tables,FT_Int ntables,FT_ULong type,FT_ULong * aformat,FT_ULong * asize)245 pcf_seek_to_table_type( FT_Stream stream, 246 PCF_Table tables, 247 FT_Int ntables, 248 FT_ULong type, 249 FT_ULong *aformat, 250 FT_ULong *asize ) 251 { 252 FT_Error error = 0; 253 FT_Int i; 254 255 256 for ( i = 0; i < ntables; i++ ) 257 if ( tables[i].type == type ) 258 { 259 if ( stream->pos > tables[i].offset ) 260 return PCF_Err_Invalid_Stream_Skip; 261 262 if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) ) 263 return PCF_Err_Invalid_Stream_Skip; 264 265 *asize = tables[i].size; /* unused - to be removed */ 266 *aformat = tables[i].format; 267 268 return PCF_Err_Ok; 269 } 270 271 return PCF_Err_Invalid_File_Format; 272 } 273 274 275 static FT_Bool pcf_has_table_type(PCF_Table tables,FT_Int ntables,FT_ULong type)276 pcf_has_table_type( PCF_Table tables, 277 FT_Int ntables, 278 FT_ULong type ) 279 { 280 FT_Int i; 281 282 283 for ( i = 0; i < ntables; i++ ) 284 if ( tables[i].type == type ) 285 return TRUE; 286 287 return FALSE; 288 } 289 290 291 static 292 const FT_Frame_Field pcf_property_header[] = 293 { 294 #undef FT_STRUCTURE 295 #define FT_STRUCTURE PCF_ParsePropertyRec 296 297 FT_FRAME_START( 9 ), 298 FT_FRAME_LONG_LE( name ), 299 FT_FRAME_BYTE ( isString ), 300 FT_FRAME_LONG_LE( value ), 301 FT_FRAME_END 302 }; 303 304 305 static 306 const FT_Frame_Field pcf_property_msb_header[] = 307 { 308 #undef FT_STRUCTURE 309 #define FT_STRUCTURE PCF_ParsePropertyRec 310 311 FT_FRAME_START( 9 ), 312 FT_FRAME_LONG( name ), 313 FT_FRAME_BYTE( isString ), 314 FT_FRAME_LONG( value ), 315 FT_FRAME_END 316 }; 317 318 319 static PCF_Property pcf_find_property(PCF_Face face,const FT_String * prop)320 pcf_find_property( PCF_Face face, 321 const FT_String* prop ) 322 { 323 PCF_Property properties = face->properties; 324 FT_Bool found = 0; 325 int i; 326 327 328 for ( i = 0 ; i < face->nprops && !found; i++ ) 329 { 330 if ( !ft_strcmp( properties[i].name, prop ) ) 331 found = 1; 332 } 333 334 if ( found ) 335 return properties + i - 1; 336 else 337 return NULL; 338 } 339 340 341 static FT_Error pcf_get_properties(FT_Stream stream,PCF_Face face)342 pcf_get_properties( FT_Stream stream, 343 PCF_Face face ) 344 { 345 PCF_ParseProperty props = 0; 346 PCF_Property properties = 0; 347 FT_Int nprops, i; 348 FT_ULong format, size; 349 FT_Error error; 350 FT_Memory memory = FT_FACE(face)->memory; 351 FT_ULong string_size; 352 FT_String* strings = 0; 353 354 355 error = pcf_seek_to_table_type( stream, 356 face->toc.tables, 357 face->toc.count, 358 PCF_PROPERTIES, 359 &format, 360 &size ); 361 if ( error ) 362 goto Bail; 363 364 if ( FT_READ_ULONG_LE( format ) ) 365 goto Bail; 366 367 FT_TRACE4(( "get_prop: format = %ld\n", format )); 368 369 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) 370 goto Bail; 371 372 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 373 (void)FT_READ_ULONG( nprops ); 374 else 375 (void)FT_READ_ULONG_LE( nprops ); 376 if ( error ) 377 goto Bail; 378 379 FT_TRACE4(( "get_prop: nprop = %d\n", nprops )); 380 381 if ( FT_NEW_ARRAY( props, nprops ) ) 382 goto Bail; 383 384 for ( i = 0; i < nprops; i++ ) 385 { 386 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 387 { 388 if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) ) 389 goto Bail; 390 } 391 else 392 { 393 if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) ) 394 goto Bail; 395 } 396 } 397 398 /* pad the property array */ 399 /* */ 400 /* clever here - nprops is the same as the number of odd-units read, */ 401 /* as only isStringProp are odd length (Keith Packard) */ 402 /* */ 403 if ( nprops & 3 ) 404 { 405 i = 4 - ( nprops & 3 ); 406 FT_Stream_Skip( stream, i ); 407 } 408 409 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 410 (void)FT_READ_ULONG( string_size ); 411 else 412 (void)FT_READ_ULONG_LE( string_size ); 413 if ( error ) 414 goto Bail; 415 416 FT_TRACE4(( "get_prop: string_size = %ld\n", string_size )); 417 418 if ( FT_NEW_ARRAY( strings, string_size ) ) 419 goto Bail; 420 421 error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size ); 422 if ( error ) 423 goto Bail; 424 425 if ( FT_NEW_ARRAY( properties, nprops ) ) 426 goto Bail; 427 428 for ( i = 0; i < nprops; i++ ) 429 { 430 /* XXX: make atom */ 431 if ( FT_NEW_ARRAY( properties[i].name, 432 ft_strlen( strings + props[i].name ) + 1 ) ) 433 goto Bail; 434 ft_strcpy( properties[i].name,strings + props[i].name ); 435 436 properties[i].isString = props[i].isString; 437 438 if ( props[i].isString ) 439 { 440 if ( FT_NEW_ARRAY( properties[i].value.atom, 441 ft_strlen( strings + props[i].value ) + 1 ) ) 442 goto Bail; 443 ft_strcpy( properties[i].value.atom, strings + props[i].value ); 444 } 445 else 446 properties[i].value.integer = props[i].value; 447 } 448 449 face->properties = properties; 450 face->nprops = nprops; 451 452 FT_FREE( props ); 453 FT_FREE( strings ); 454 455 return PCF_Err_Ok; 456 457 Bail: 458 FT_FREE( props ); 459 FT_FREE( strings ); 460 461 return error; 462 } 463 464 465 static FT_Error pcf_get_metrics(FT_Stream stream,PCF_Face face)466 pcf_get_metrics( FT_Stream stream, 467 PCF_Face face ) 468 { 469 FT_Error error = PCF_Err_Ok; 470 FT_Memory memory = FT_FACE(face)->memory; 471 FT_ULong format = 0; 472 FT_ULong size = 0; 473 PCF_Metric metrics = 0; 474 int i; 475 int nmetrics = -1; 476 477 478 error = pcf_seek_to_table_type( stream, 479 face->toc.tables, 480 face->toc.count, 481 PCF_METRICS, 482 &format, 483 &size ); 484 if ( error ) 485 return error; 486 487 error = FT_READ_ULONG_LE( format ); 488 489 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && 490 !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) 491 return PCF_Err_Invalid_File_Format; 492 493 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) 494 { 495 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 496 (void)FT_READ_ULONG( nmetrics ); 497 else 498 (void)FT_READ_ULONG_LE( nmetrics ); 499 } 500 else 501 { 502 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 503 (void)FT_READ_USHORT( nmetrics ); 504 else 505 (void)FT_READ_USHORT_LE( nmetrics ); 506 } 507 if ( error || nmetrics == -1 ) 508 return PCF_Err_Invalid_File_Format; 509 510 face->nmetrics = nmetrics; 511 512 if ( FT_NEW_ARRAY( face->metrics, nmetrics ) ) 513 return PCF_Err_Out_Of_Memory; 514 515 metrics = face->metrics; 516 for ( i = 0; i < nmetrics; i++ ) 517 { 518 pcf_get_metric( stream, format, metrics + i ); 519 520 metrics[i].bits = 0; 521 522 FT_TRACE4(( "%d : width=%d, " 523 "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n", 524 i, 525 ( metrics + i )->characterWidth, 526 ( metrics + i )->leftSideBearing, 527 ( metrics + i )->rightSideBearing, 528 ( metrics + i )->ascent, 529 ( metrics + i )->descent, 530 ( metrics + i )->attributes )); 531 532 if ( error ) 533 break; 534 } 535 536 if ( error ) 537 FT_FREE( face->metrics ); 538 return error; 539 } 540 541 542 static FT_Error pcf_get_bitmaps(FT_Stream stream,PCF_Face face)543 pcf_get_bitmaps( FT_Stream stream, 544 PCF_Face face ) 545 { 546 FT_Error error = PCF_Err_Ok; 547 FT_Memory memory = FT_FACE(face)->memory; 548 FT_Long* offsets; 549 FT_Long bitmapSizes[GLYPHPADOPTIONS]; 550 FT_ULong format, size; 551 int nbitmaps, i, sizebitmaps = 0; 552 char* bitmaps; 553 554 555 error = pcf_seek_to_table_type( stream, 556 face->toc.tables, 557 face->toc.count, 558 PCF_BITMAPS, 559 &format, 560 &size ); 561 if ( error ) 562 return error; 563 564 error = FT_Stream_EnterFrame( stream, 8 ); 565 if ( error ) 566 return error; 567 568 format = FT_GET_ULONG_LE(); 569 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 570 nbitmaps = FT_GET_ULONG(); 571 else 572 nbitmaps = FT_GET_ULONG_LE(); 573 574 FT_Stream_ExitFrame( stream ); 575 576 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) 577 return PCF_Err_Invalid_File_Format; 578 579 if ( nbitmaps != face->nmetrics ) 580 return PCF_Err_Invalid_File_Format; 581 582 if ( FT_NEW_ARRAY( offsets, nbitmaps ) ) 583 return error; 584 585 for ( i = 0; i < nbitmaps; i++ ) 586 { 587 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 588 (void)FT_READ_LONG( offsets[i] ); 589 else 590 (void)FT_READ_LONG_LE( offsets[i] ); 591 592 FT_TRACE4(( "bitmap %d is at offset %ld\n", i, offsets[i] )); 593 } 594 if ( error ) 595 goto Bail; 596 597 for ( i = 0; i < GLYPHPADOPTIONS; i++ ) 598 { 599 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 600 (void)FT_READ_LONG( bitmapSizes[i] ); 601 else 602 (void)FT_READ_LONG_LE( bitmapSizes[i] ); 603 if ( error ) 604 goto Bail; 605 606 sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )]; 607 608 FT_TRACE4(( "padding %d implies a size of %ld\n", i, bitmapSizes[i] )); 609 } 610 611 FT_TRACE4(( " %d bitmaps, padding index %ld\n", 612 nbitmaps, 613 PCF_GLYPH_PAD_INDEX( format ) )); 614 FT_TRACE4(( "bitmap size = %d\n", sizebitmaps )); 615 616 FT_UNUSED( sizebitmaps ); /* only used for debugging */ 617 618 for ( i = 0; i < nbitmaps; i++ ) 619 face->metrics[i].bits = stream->pos + offsets[i]; 620 621 face->bitmapsFormat = format; 622 623 FT_FREE ( offsets ); 624 return error; 625 626 Bail: 627 FT_FREE ( offsets ); 628 FT_FREE ( bitmaps ); 629 return error; 630 } 631 632 633 static FT_Error pcf_get_encodings(FT_Stream stream,PCF_Face face)634 pcf_get_encodings( FT_Stream stream, 635 PCF_Face face ) 636 { 637 FT_Error error = PCF_Err_Ok; 638 FT_Memory memory = FT_FACE(face)->memory; 639 FT_ULong format, size; 640 int firstCol, lastCol; 641 int firstRow, lastRow; 642 int nencoding, encodingOffset; 643 int i, j; 644 PCF_Encoding tmpEncoding, encoding = 0; 645 646 647 error = pcf_seek_to_table_type( stream, 648 face->toc.tables, 649 face->toc.count, 650 PCF_BDF_ENCODINGS, 651 &format, 652 &size ); 653 if ( error ) 654 return error; 655 656 error = FT_Stream_EnterFrame( stream, 14 ); 657 if ( error ) 658 return error; 659 660 format = FT_GET_ULONG_LE(); 661 662 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 663 { 664 firstCol = FT_GET_SHORT(); 665 lastCol = FT_GET_SHORT(); 666 firstRow = FT_GET_SHORT(); 667 lastRow = FT_GET_SHORT(); 668 face->defaultChar = FT_GET_SHORT(); 669 } 670 else 671 { 672 firstCol = FT_GET_SHORT_LE(); 673 lastCol = FT_GET_SHORT_LE(); 674 firstRow = FT_GET_SHORT_LE(); 675 lastRow = FT_GET_SHORT_LE(); 676 face->defaultChar = FT_GET_SHORT_LE(); 677 } 678 679 FT_Stream_ExitFrame( stream ); 680 681 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) 682 return PCF_Err_Invalid_File_Format; 683 684 FT_TRACE4(( "enc: firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", 685 firstCol, lastCol, firstRow, lastRow )); 686 687 nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 ); 688 689 if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) ) 690 return PCF_Err_Out_Of_Memory; 691 692 error = FT_Stream_EnterFrame( stream, 2 * nencoding ); 693 if ( error ) 694 goto Bail; 695 696 for ( i = 0, j = 0 ; i < nencoding; i++ ) 697 { 698 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 699 encodingOffset = FT_GET_SHORT(); 700 else 701 encodingOffset = FT_GET_SHORT_LE(); 702 703 if ( encodingOffset != -1 ) 704 { 705 tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) + 706 firstRow ) * 256 ) + 707 ( ( i % ( lastCol - firstCol + 1 ) ) + 708 firstCol ); 709 710 tmpEncoding[j].glyph = (FT_Short)encodingOffset; 711 j++; 712 } 713 714 FT_TRACE4(( "enc n. %d ; Uni %ld ; Glyph %d\n", 715 i, tmpEncoding[j - 1].enc, encodingOffset )); 716 } 717 FT_Stream_ExitFrame( stream ); 718 719 if ( FT_NEW_ARRAY( encoding, j ) ) 720 goto Bail; 721 722 for ( i = 0; i < j; i++ ) 723 { 724 encoding[i].enc = tmpEncoding[i].enc; 725 encoding[i].glyph = tmpEncoding[i].glyph; 726 } 727 728 face->nencodings = j; 729 face->encodings = encoding; 730 FT_FREE( tmpEncoding ); 731 732 return error; 733 734 Bail: 735 FT_FREE( encoding ); 736 FT_FREE( tmpEncoding ); 737 return error; 738 } 739 740 741 static 742 const FT_Frame_Field pcf_accel_header[] = 743 { 744 #undef FT_STRUCTURE 745 #define FT_STRUCTURE PCF_AccelRec 746 747 FT_FRAME_START( 20 ), 748 FT_FRAME_BYTE ( noOverlap ), 749 FT_FRAME_BYTE ( constantMetrics ), 750 FT_FRAME_BYTE ( terminalFont ), 751 FT_FRAME_BYTE ( constantWidth ), 752 FT_FRAME_BYTE ( inkInside ), 753 FT_FRAME_BYTE ( inkMetrics ), 754 FT_FRAME_BYTE ( drawDirection ), 755 FT_FRAME_SKIP_BYTES( 1 ), 756 FT_FRAME_LONG_LE ( fontAscent ), 757 FT_FRAME_LONG_LE ( fontDescent ), 758 FT_FRAME_LONG_LE ( maxOverlap ), 759 FT_FRAME_END 760 }; 761 762 763 static 764 const FT_Frame_Field pcf_accel_msb_header[] = 765 { 766 #undef FT_STRUCTURE 767 #define FT_STRUCTURE PCF_AccelRec 768 769 FT_FRAME_START( 20 ), 770 FT_FRAME_BYTE ( noOverlap ), 771 FT_FRAME_BYTE ( constantMetrics ), 772 FT_FRAME_BYTE ( terminalFont ), 773 FT_FRAME_BYTE ( constantWidth ), 774 FT_FRAME_BYTE ( inkInside ), 775 FT_FRAME_BYTE ( inkMetrics ), 776 FT_FRAME_BYTE ( drawDirection ), 777 FT_FRAME_SKIP_BYTES( 1 ), 778 FT_FRAME_LONG ( fontAscent ), 779 FT_FRAME_LONG ( fontDescent ), 780 FT_FRAME_LONG ( maxOverlap ), 781 FT_FRAME_END 782 }; 783 784 785 static FT_Error pcf_get_accel(FT_Stream stream,PCF_Face face,FT_ULong type)786 pcf_get_accel( FT_Stream stream, 787 PCF_Face face, 788 FT_ULong type ) 789 { 790 FT_ULong format, size; 791 FT_Error error = PCF_Err_Ok; 792 PCF_Accel accel = &face->accel; 793 794 795 error = pcf_seek_to_table_type( stream, 796 face->toc.tables, 797 face->toc.count, 798 type, 799 &format, 800 &size ); 801 if ( error ) 802 goto Bail; 803 804 error = FT_READ_ULONG_LE( format ); 805 806 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && 807 !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) 808 goto Bail; 809 810 if ( PCF_BYTE_ORDER( format ) == MSBFirst ) 811 { 812 if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) ) 813 goto Bail; 814 } 815 else 816 { 817 if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) ) 818 goto Bail; 819 } 820 821 error = pcf_get_metric( stream, 822 format & ( ~PCF_FORMAT_MASK ), 823 &(accel->minbounds) ); 824 if ( error ) 825 goto Bail; 826 827 error = pcf_get_metric( stream, 828 format & ( ~PCF_FORMAT_MASK ), 829 &(accel->maxbounds) ); 830 if ( error ) 831 goto Bail; 832 833 if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) 834 { 835 error = pcf_get_metric( stream, 836 format & ( ~PCF_FORMAT_MASK ), 837 &(accel->ink_minbounds) ); 838 if ( error ) 839 goto Bail; 840 841 error = pcf_get_metric( stream, 842 format & ( ~PCF_FORMAT_MASK ), 843 &(accel->ink_maxbounds) ); 844 if ( error ) 845 goto Bail; 846 } 847 else 848 { 849 accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */ 850 accel->ink_maxbounds = accel->maxbounds; 851 } 852 return error; 853 854 Bail: 855 return error; 856 } 857 858 859 FT_LOCAL_DEF( FT_Error ) pcf_load_font(FT_Stream stream,PCF_Face face)860 pcf_load_font( FT_Stream stream, 861 PCF_Face face ) 862 { 863 FT_Error error = PCF_Err_Ok; 864 FT_Memory memory = FT_FACE(face)->memory; 865 FT_Bool hasBDFAccelerators; 866 867 868 error = pcf_read_TOC( stream, face ); 869 if ( error ) 870 goto Exit; 871 872 error = pcf_get_properties( stream, face ); 873 if ( error ) 874 goto Exit; 875 876 /* Use the old accelerators if no BDF accelerators are in the file. */ 877 hasBDFAccelerators = pcf_has_table_type( face->toc.tables, 878 face->toc.count, 879 PCF_BDF_ACCELERATORS ); 880 if ( !hasBDFAccelerators ) 881 { 882 error = pcf_get_accel( stream, face, PCF_ACCELERATORS ); 883 if ( error ) 884 goto Exit; 885 } 886 887 /* metrics */ 888 error = pcf_get_metrics( stream, face ); 889 if ( error ) 890 goto Exit; 891 892 /* bitmaps */ 893 error = pcf_get_bitmaps( stream, face ); 894 if ( error ) 895 goto Exit; 896 897 /* encodings */ 898 error = pcf_get_encodings( stream, face ); 899 if ( error ) 900 goto Exit; 901 902 /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ 903 if ( hasBDFAccelerators ) 904 { 905 error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS ); 906 if ( error ) 907 goto Exit; 908 } 909 910 /* XXX: TO DO: inkmetrics and glyph_names are missing */ 911 912 /* now construct the face object */ 913 { 914 FT_Face root = FT_FACE( face ); 915 PCF_Property prop; 916 int size_set = 0; 917 918 919 root->num_faces = 1; 920 root->face_index = 0; 921 root->face_flags = FT_FACE_FLAG_FIXED_SIZES | 922 FT_FACE_FLAG_HORIZONTAL | 923 FT_FACE_FLAG_FAST_GLYPHS; 924 925 if ( face->accel.constantWidth ) 926 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 927 928 root->style_flags = 0; 929 prop = pcf_find_property( face, "SLANT" ); 930 if ( prop != NULL ) 931 if ( prop->isString ) 932 if ( ( *(prop->value.atom) == 'O' ) || 933 ( *(prop->value.atom) == 'I' ) ) 934 root->style_flags |= FT_STYLE_FLAG_ITALIC; 935 936 prop = pcf_find_property( face, "WEIGHT_NAME" ); 937 if ( prop != NULL ) 938 if ( prop->isString ) 939 if ( *(prop->value.atom) == 'B' ) 940 root->style_flags |= FT_STYLE_FLAG_BOLD; 941 942 root->style_name = (char *)"Regular"; 943 944 if ( root->style_flags & FT_STYLE_FLAG_BOLD ) { 945 if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) 946 root->style_name = (char *)"Bold Italic"; 947 else 948 root->style_name = (char *)"Bold"; 949 } 950 else if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) 951 root->style_name = (char *)"Italic"; 952 953 prop = pcf_find_property( face, "FAMILY_NAME" ); 954 if ( prop != NULL ) 955 { 956 if ( prop->isString ) 957 { 958 int l = ft_strlen( prop->value.atom ) + 1; 959 960 961 if ( FT_NEW_ARRAY( root->family_name, l ) ) 962 goto Exit; 963 ft_strcpy( root->family_name, prop->value.atom ); 964 } 965 } 966 else 967 root->family_name = 0; 968 969 root->num_glyphs = face->nmetrics; 970 971 root->num_fixed_sizes = 1; 972 if ( FT_NEW_ARRAY( root->available_sizes, 1 ) ) 973 goto Exit; 974 975 prop = pcf_find_property( face, "PIXEL_SIZE" ); 976 if ( prop != NULL ) 977 { 978 root->available_sizes->height = 979 root->available_sizes->width = (FT_Short)( prop->value.integer ); 980 981 size_set = 1; 982 } 983 else 984 { 985 prop = pcf_find_property( face, "POINT_SIZE" ); 986 if ( prop != NULL ) 987 { 988 PCF_Property xres, yres, avgw; 989 990 991 xres = pcf_find_property( face, "RESOLUTION_X" ); 992 yres = pcf_find_property( face, "RESOLUTION_Y" ); 993 avgw = pcf_find_property( face, "AVERAGE_WIDTH" ); 994 995 if ( ( yres != NULL ) && ( xres != NULL ) ) 996 { 997 root->available_sizes->height = 998 (FT_Short)( prop->value.integer * 999 yres->value.integer / 720 ); 1000 1001 root->available_sizes->width = 1002 (FT_Short)( prop->value.integer * 1003 xres->value.integer / 720 ); 1004 1005 size_set = 1; 1006 } 1007 } 1008 } 1009 1010 if (size_set == 0 ) 1011 { 1012 root->available_sizes->width = 12; 1013 root->available_sizes->height = 12; 1014 } 1015 1016 /* set-up charset */ 1017 { 1018 PCF_Property charset_registry = 0, charset_encoding = 0; 1019 1020 1021 charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" ); 1022 charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" ); 1023 1024 if ( ( charset_registry != NULL ) && 1025 ( charset_encoding != NULL ) ) 1026 { 1027 if ( ( charset_registry->isString ) && 1028 ( charset_encoding->isString ) ) 1029 { 1030 if ( FT_NEW_ARRAY( face->charset_encoding, 1031 ft_strlen( charset_encoding->value.atom ) + 1 ) ) 1032 goto Exit; 1033 1034 if ( FT_NEW_ARRAY( face->charset_registry, 1035 ft_strlen( charset_registry->value.atom ) + 1 ) ) 1036 goto Exit; 1037 1038 ft_strcpy( face->charset_registry, charset_registry->value.atom ); 1039 ft_strcpy( face->charset_encoding, charset_encoding->value.atom ); 1040 } 1041 } 1042 } 1043 } 1044 1045 Exit: 1046 if ( error ) 1047 { 1048 /* this is done to respect the behaviour of the original */ 1049 /* PCF font driver. */ 1050 error = PCF_Err_Invalid_File_Format; 1051 } 1052 1053 return error; 1054 } 1055 1056 1057 /* END */ 1058