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