00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <ft2build.h>
00029
00030 #include FT_INTERNAL_DEBUG_H
00031 #include FT_INTERNAL_STREAM_H
00032 #include FT_INTERNAL_OBJECTS_H
00033
00034 #include "pcf.h"
00035 #include "pcfread.h"
00036
00037 #include "pcferror.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046 #undef FT_COMPONENT
00047 #define FT_COMPONENT trace_pcfread
00048
00049
00050 #ifdef FT_DEBUG_LEVEL_TRACE
00051 static const char* const tableNames[] =
00052 {
00053 "prop", "accl", "mtrcs", "bmps", "imtrcs",
00054 "enc", "swidth", "names", "accel"
00055 };
00056 #endif
00057
00058
00059 static
00060 const FT_Frame_Field pcf_toc_header[] =
00061 {
00062 #undef FT_STRUCTURE
00063 #define FT_STRUCTURE PCF_TocRec
00064
00065 FT_FRAME_START( 8 ),
00066 FT_FRAME_ULONG_LE( version ),
00067 FT_FRAME_ULONG_LE( count ),
00068 FT_FRAME_END
00069 };
00070
00071
00072 static
00073 const FT_Frame_Field pcf_table_header[] =
00074 {
00075 #undef FT_STRUCTURE
00076 #define FT_STRUCTURE PCF_TableRec
00077
00078 FT_FRAME_START( 16 ),
00079 FT_FRAME_ULONG_LE( type ),
00080 FT_FRAME_ULONG_LE( format ),
00081 FT_FRAME_ULONG_LE( size ),
00082 FT_FRAME_ULONG_LE( offset ),
00083 FT_FRAME_END
00084 };
00085
00086
00087 static FT_Error
00088 pcf_read_TOC( FT_Stream stream,
00089 PCF_Face face )
00090 {
00091 FT_Error error;
00092 PCF_Toc toc = &face->toc;
00093 PCF_Table tables;
00094
00095 FT_Memory memory = FT_FACE(face)->memory;
00096 FT_UInt n;
00097
00098
00099 if ( FT_STREAM_SEEK ( 0 ) ||
00100 FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) )
00101 return PCF_Err_Cannot_Open_Resource;
00102
00103 if ( toc->version != PCF_FILE_VERSION ||
00104 toc->count > FT_ARRAY_MAX( face->toc.tables ) ||
00105 toc->count == 0 )
00106 return PCF_Err_Invalid_File_Format;
00107
00108 if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
00109 return PCF_Err_Out_Of_Memory;
00110
00111 tables = face->toc.tables;
00112 for ( n = 0; n < toc->count; n++ )
00113 {
00114 if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )
00115 goto Exit;
00116 tables++;
00117 }
00118
00119
00120
00121
00122 tables = face->toc.tables;
00123
00124 for ( n = 0; n < toc->count - 1; n++ )
00125 {
00126 FT_UInt i, have_change;
00127
00128
00129 have_change = 0;
00130
00131 for ( i = 0; i < toc->count - 1 - n; i++ )
00132 {
00133 PCF_TableRec tmp;
00134
00135
00136 if ( tables[i].offset > tables[i + 1].offset )
00137 {
00138 tmp = tables[i];
00139 tables[i] = tables[i + 1];
00140 tables[i + 1] = tmp;
00141
00142 have_change = 1;
00143 }
00144
00145 if ( ( tables[i].size > tables[i + 1].offset ) ||
00146 ( tables[i].offset > tables[i + 1].offset - tables[i].size ) )
00147 return PCF_Err_Invalid_Offset;
00148 }
00149
00150 if ( !have_change )
00151 break;
00152 }
00153
00154 #ifdef FT_DEBUG_LEVEL_TRACE
00155
00156 {
00157 FT_UInt i, j;
00158 const char* name = "?";
00159
00160
00161 FT_TRACE4(( "pcf_read_TOC:\n" ));
00162
00163 FT_TRACE4(( " number of tables: %ld\n", face->toc.count ));
00164
00165 tables = face->toc.tables;
00166 for ( i = 0; i < toc->count; i++ )
00167 {
00168 for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );
00169 j++ )
00170 if ( tables[i].type == (FT_UInt)( 1 << j ) )
00171 name = tableNames[j];
00172
00173 FT_TRACE4(( " %d: type=%s, format=0x%X, "
00174 "size=%ld (0x%lX), offset=%ld (0x%lX)\n",
00175 i, name,
00176 tables[i].format,
00177 tables[i].size, tables[i].size,
00178 tables[i].offset, tables[i].offset ));
00179 }
00180 }
00181
00182 #endif
00183
00184 return PCF_Err_Ok;
00185
00186 Exit:
00187 FT_FREE( face->toc.tables );
00188 return error;
00189 }
00190
00191
00192 #define PCF_METRIC_SIZE 12
00193
00194 static
00195 const FT_Frame_Field pcf_metric_header[] =
00196 {
00197 #undef FT_STRUCTURE
00198 #define FT_STRUCTURE PCF_MetricRec
00199
00200 FT_FRAME_START( PCF_METRIC_SIZE ),
00201 FT_FRAME_SHORT_LE( leftSideBearing ),
00202 FT_FRAME_SHORT_LE( rightSideBearing ),
00203 FT_FRAME_SHORT_LE( characterWidth ),
00204 FT_FRAME_SHORT_LE( ascent ),
00205 FT_FRAME_SHORT_LE( descent ),
00206 FT_FRAME_SHORT_LE( attributes ),
00207 FT_FRAME_END
00208 };
00209
00210
00211 static
00212 const FT_Frame_Field pcf_metric_msb_header[] =
00213 {
00214 #undef FT_STRUCTURE
00215 #define FT_STRUCTURE PCF_MetricRec
00216
00217 FT_FRAME_START( PCF_METRIC_SIZE ),
00218 FT_FRAME_SHORT( leftSideBearing ),
00219 FT_FRAME_SHORT( rightSideBearing ),
00220 FT_FRAME_SHORT( characterWidth ),
00221 FT_FRAME_SHORT( ascent ),
00222 FT_FRAME_SHORT( descent ),
00223 FT_FRAME_SHORT( attributes ),
00224 FT_FRAME_END
00225 };
00226
00227
00228 #define PCF_COMPRESSED_METRIC_SIZE 5
00229
00230 static
00231 const FT_Frame_Field pcf_compressed_metric_header[] =
00232 {
00233 #undef FT_STRUCTURE
00234 #define FT_STRUCTURE PCF_Compressed_MetricRec
00235
00236 FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE ),
00237 FT_FRAME_BYTE( leftSideBearing ),
00238 FT_FRAME_BYTE( rightSideBearing ),
00239 FT_FRAME_BYTE( characterWidth ),
00240 FT_FRAME_BYTE( ascent ),
00241 FT_FRAME_BYTE( descent ),
00242 FT_FRAME_END
00243 };
00244
00245
00246 static FT_Error
00247 pcf_get_metric( FT_Stream stream,
00248 FT_ULong format,
00249 PCF_Metric metric )
00250 {
00251 FT_Error error = PCF_Err_Ok;
00252
00253
00254 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00255 {
00256 const FT_Frame_Field* fields;
00257
00258
00259
00260 fields = PCF_BYTE_ORDER( format ) == MSBFirst
00261 ? pcf_metric_msb_header
00262 : pcf_metric_header;
00263
00264
00265 (void)FT_STREAM_READ_FIELDS( fields, metric );
00266 }
00267 else
00268 {
00269 PCF_Compressed_MetricRec compr;
00270
00271
00272
00273 if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )
00274 goto Exit;
00275
00276 metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 );
00277 metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
00278 metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 );
00279 metric->ascent = (FT_Short)( compr.ascent - 0x80 );
00280 metric->descent = (FT_Short)( compr.descent - 0x80 );
00281 metric->attributes = 0;
00282 }
00283
00284 Exit:
00285 return error;
00286 }
00287
00288
00289 static FT_Error
00290 pcf_seek_to_table_type( FT_Stream stream,
00291 PCF_Table tables,
00292 FT_ULong ntables,
00293 FT_ULong type,
00294 FT_ULong *aformat,
00295 FT_ULong *asize )
00296 {
00297 FT_Error error = PCF_Err_Invalid_File_Format;
00298 FT_ULong i;
00299
00300
00301 for ( i = 0; i < ntables; i++ )
00302 if ( tables[i].type == type )
00303 {
00304 if ( stream->pos > tables[i].offset )
00305 {
00306 error = PCF_Err_Invalid_Stream_Skip;
00307 goto Fail;
00308 }
00309
00310 if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
00311 {
00312 error = PCF_Err_Invalid_Stream_Skip;
00313 goto Fail;
00314 }
00315
00316 *asize = tables[i].size;
00317 *aformat = tables[i].format;
00318
00319 return PCF_Err_Ok;
00320 }
00321
00322 Fail:
00323 *asize = 0;
00324 return error;
00325 }
00326
00327
00328 static FT_Bool
00329 pcf_has_table_type( PCF_Table tables,
00330 FT_ULong ntables,
00331 FT_ULong type )
00332 {
00333 FT_ULong i;
00334
00335
00336 for ( i = 0; i < ntables; i++ )
00337 if ( tables[i].type == type )
00338 return TRUE;
00339
00340 return FALSE;
00341 }
00342
00343
00344 #define PCF_PROPERTY_SIZE 9
00345
00346 static
00347 const FT_Frame_Field pcf_property_header[] =
00348 {
00349 #undef FT_STRUCTURE
00350 #define FT_STRUCTURE PCF_ParsePropertyRec
00351
00352 FT_FRAME_START( PCF_PROPERTY_SIZE ),
00353 FT_FRAME_LONG_LE( name ),
00354 FT_FRAME_BYTE ( isString ),
00355 FT_FRAME_LONG_LE( value ),
00356 FT_FRAME_END
00357 };
00358
00359
00360 static
00361 const FT_Frame_Field pcf_property_msb_header[] =
00362 {
00363 #undef FT_STRUCTURE
00364 #define FT_STRUCTURE PCF_ParsePropertyRec
00365
00366 FT_FRAME_START( PCF_PROPERTY_SIZE ),
00367 FT_FRAME_LONG( name ),
00368 FT_FRAME_BYTE( isString ),
00369 FT_FRAME_LONG( value ),
00370 FT_FRAME_END
00371 };
00372
00373
00374 FT_LOCAL_DEF( PCF_Property )
00375 pcf_find_property( PCF_Face face,
00376 const FT_String* prop )
00377 {
00378 PCF_Property properties = face->properties;
00379 FT_Bool found = 0;
00380 int i;
00381
00382
00383 for ( i = 0 ; i < face->nprops && !found; i++ )
00384 {
00385 if ( !ft_strcmp( properties[i].name, prop ) )
00386 found = 1;
00387 }
00388
00389 if ( found )
00390 return properties + i - 1;
00391 else
00392 return NULL;
00393 }
00394
00395
00396 static FT_Error
00397 pcf_get_properties( FT_Stream stream,
00398 PCF_Face face )
00399 {
00400 PCF_ParseProperty props = 0;
00401 PCF_Property properties;
00402 FT_ULong nprops, i;
00403 FT_ULong format, size;
00404 FT_Error error;
00405 FT_Memory memory = FT_FACE(face)->memory;
00406 FT_ULong string_size;
00407 FT_String* strings = 0;
00408
00409
00410 error = pcf_seek_to_table_type( stream,
00411 face->toc.tables,
00412 face->toc.count,
00413 PCF_PROPERTIES,
00414 &format,
00415 &size );
00416 if ( error )
00417 goto Bail;
00418
00419 if ( FT_READ_ULONG_LE( format ) )
00420 goto Bail;
00421
00422 FT_TRACE4(( "pcf_get_properties:\n" ));
00423
00424 FT_TRACE4(( " format = %ld\n", format ));
00425
00426 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00427 goto Bail;
00428
00429 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00430 (void)FT_READ_ULONG( nprops );
00431 else
00432 (void)FT_READ_ULONG_LE( nprops );
00433 if ( error )
00434 goto Bail;
00435
00436 FT_TRACE4(( " nprop = %d (truncate %d props)\n",
00437 (int)nprops, nprops - (int)nprops ));
00438
00439 nprops = (int)nprops;
00440
00441
00442 if ( nprops > size / PCF_PROPERTY_SIZE )
00443 {
00444 error = PCF_Err_Invalid_Table;
00445 goto Bail;
00446 }
00447
00448 face->nprops = (int)nprops;
00449
00450 if ( FT_NEW_ARRAY( props, nprops ) )
00451 goto Bail;
00452
00453 for ( i = 0; i < nprops; i++ )
00454 {
00455 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00456 {
00457 if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )
00458 goto Bail;
00459 }
00460 else
00461 {
00462 if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )
00463 goto Bail;
00464 }
00465 }
00466
00467
00468
00469
00470
00471
00472 if ( nprops & 3 )
00473 {
00474 i = 4 - ( nprops & 3 );
00475 if ( FT_STREAM_SKIP( i ) )
00476 {
00477 error = PCF_Err_Invalid_Stream_Skip;
00478 goto Bail;
00479 }
00480 }
00481
00482 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00483 (void)FT_READ_ULONG( string_size );
00484 else
00485 (void)FT_READ_ULONG_LE( string_size );
00486 if ( error )
00487 goto Bail;
00488
00489 FT_TRACE4(( " string_size = %ld\n", string_size ));
00490
00491
00492 if ( string_size > size - nprops * PCF_PROPERTY_SIZE )
00493 {
00494 error = PCF_Err_Invalid_Table;
00495 goto Bail;
00496 }
00497
00498 if ( FT_NEW_ARRAY( strings, string_size ) )
00499 goto Bail;
00500
00501 error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
00502 if ( error )
00503 goto Bail;
00504
00505 if ( FT_NEW_ARRAY( properties, nprops ) )
00506 goto Bail;
00507
00508 face->properties = properties;
00509
00510 for ( i = 0; i < nprops; i++ )
00511 {
00512 FT_Long name_offset = props[i].name;
00513
00514
00515 if ( ( name_offset < 0 ) ||
00516 ( (FT_ULong)name_offset > string_size ) )
00517 {
00518 error = PCF_Err_Invalid_Offset;
00519 goto Bail;
00520 }
00521
00522 if ( FT_STRDUP( properties[i].name, strings + name_offset ) )
00523 goto Bail;
00524
00525 FT_TRACE4(( " %s:", properties[i].name ));
00526
00527 properties[i].isString = props[i].isString;
00528
00529 if ( props[i].isString )
00530 {
00531 FT_Long value_offset = props[i].value;
00532
00533
00534 if ( ( value_offset < 0 ) ||
00535 ( (FT_ULong)value_offset > string_size ) )
00536 {
00537 error = PCF_Err_Invalid_Offset;
00538 goto Bail;
00539 }
00540
00541 if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )
00542 goto Bail;
00543
00544 FT_TRACE4(( " `%s'\n", properties[i].value.atom ));
00545 }
00546 else
00547 {
00548 properties[i].value.l = props[i].value;
00549
00550 FT_TRACE4(( " %d\n", properties[i].value.l ));
00551 }
00552 }
00553
00554 error = PCF_Err_Ok;
00555
00556 Bail:
00557 FT_FREE( props );
00558 FT_FREE( strings );
00559
00560 return error;
00561 }
00562
00563
00564 static FT_Error
00565 pcf_get_metrics( FT_Stream stream,
00566 PCF_Face face )
00567 {
00568 FT_Error error = PCF_Err_Ok;
00569 FT_Memory memory = FT_FACE(face)->memory;
00570 FT_ULong format, size;
00571 PCF_Metric metrics = 0;
00572 FT_ULong nmetrics, i;
00573
00574
00575 error = pcf_seek_to_table_type( stream,
00576 face->toc.tables,
00577 face->toc.count,
00578 PCF_METRICS,
00579 &format,
00580 &size );
00581 if ( error )
00582 return error;
00583
00584 if ( FT_READ_ULONG_LE( format ) )
00585 goto Bail;
00586
00587 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
00588 !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
00589 return PCF_Err_Invalid_File_Format;
00590
00591 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00592 {
00593 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00594 (void)FT_READ_ULONG( nmetrics );
00595 else
00596 (void)FT_READ_ULONG_LE( nmetrics );
00597 }
00598 else
00599 {
00600 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00601 (void)FT_READ_USHORT( nmetrics );
00602 else
00603 (void)FT_READ_USHORT_LE( nmetrics );
00604 }
00605 if ( error )
00606 return PCF_Err_Invalid_File_Format;
00607
00608 face->nmetrics = nmetrics;
00609
00610 FT_TRACE4(( "pcf_get_metrics:\n" ));
00611
00612 FT_TRACE4(( " number of metrics: %d\n", nmetrics ));
00613
00614
00615 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00616 {
00617 if ( nmetrics > size / PCF_METRIC_SIZE )
00618 return PCF_Err_Invalid_Table;
00619 }
00620 else
00621 {
00622 if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
00623 return PCF_Err_Invalid_Table;
00624 }
00625
00626 if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
00627 return PCF_Err_Out_Of_Memory;
00628
00629 metrics = face->metrics;
00630 for ( i = 0; i < nmetrics; i++ )
00631 {
00632 error = pcf_get_metric( stream, format, metrics + i );
00633
00634 metrics[i].bits = 0;
00635
00636 FT_TRACE5(( " idx %d: width=%d, "
00637 "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
00638 i,
00639 ( metrics + i )->characterWidth,
00640 ( metrics + i )->leftSideBearing,
00641 ( metrics + i )->rightSideBearing,
00642 ( metrics + i )->ascent,
00643 ( metrics + i )->descent,
00644 ( metrics + i )->attributes ));
00645
00646 if ( error )
00647 break;
00648 }
00649
00650 if ( error )
00651 FT_FREE( face->metrics );
00652
00653 Bail:
00654 return error;
00655 }
00656
00657
00658 static FT_Error
00659 pcf_get_bitmaps( FT_Stream stream,
00660 PCF_Face face )
00661 {
00662 FT_Error error = PCF_Err_Ok;
00663 FT_Memory memory = FT_FACE(face)->memory;
00664 FT_Long* offsets;
00665 FT_Long bitmapSizes[GLYPHPADOPTIONS];
00666 FT_ULong format, size;
00667 FT_ULong nbitmaps, i, sizebitmaps = 0;
00668
00669
00670 error = pcf_seek_to_table_type( stream,
00671 face->toc.tables,
00672 face->toc.count,
00673 PCF_BITMAPS,
00674 &format,
00675 &size );
00676 if ( error )
00677 return error;
00678
00679 error = FT_Stream_EnterFrame( stream, 8 );
00680 if ( error )
00681 return error;
00682
00683 format = FT_GET_ULONG_LE();
00684 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00685 nbitmaps = FT_GET_ULONG();
00686 else
00687 nbitmaps = FT_GET_ULONG_LE();
00688
00689 FT_Stream_ExitFrame( stream );
00690
00691 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00692 return PCF_Err_Invalid_File_Format;
00693
00694 FT_TRACE4(( "pcf_get_bitmaps:\n" ));
00695
00696 FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps ));
00697
00698
00699 if ( face->nmetrics < 0 || nbitmaps != ( FT_ULong )face->nmetrics )
00700 return PCF_Err_Invalid_File_Format;
00701
00702 if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
00703 return error;
00704
00705 for ( i = 0; i < nbitmaps; i++ )
00706 {
00707 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00708 (void)FT_READ_LONG( offsets[i] );
00709 else
00710 (void)FT_READ_LONG_LE( offsets[i] );
00711
00712 FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n",
00713 i, offsets[i], offsets[i] ));
00714 }
00715 if ( error )
00716 goto Bail;
00717
00718 for ( i = 0; i < GLYPHPADOPTIONS; i++ )
00719 {
00720 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00721 (void)FT_READ_LONG( bitmapSizes[i] );
00722 else
00723 (void)FT_READ_LONG_LE( bitmapSizes[i] );
00724 if ( error )
00725 goto Bail;
00726
00727 sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
00728
00729 FT_TRACE4(( " padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
00730 }
00731
00732 FT_TRACE4(( " %d bitmaps, padding index %ld\n",
00733 nbitmaps,
00734 PCF_GLYPH_PAD_INDEX( format ) ));
00735 FT_TRACE4(( " bitmap size = %d\n", sizebitmaps ));
00736
00737 FT_UNUSED( sizebitmaps );
00738
00739 for ( i = 0; i < nbitmaps; i++ )
00740 {
00741
00742 if ( ( offsets[i] < 0 ) ||
00743 ( (FT_ULong)offsets[i] > size ) )
00744 {
00745 FT_TRACE0(( "pcf_get_bitmaps:"
00746 " invalid offset to bitmap data of glyph %d\n", i ));
00747 }
00748 else
00749 face->metrics[i].bits = stream->pos + offsets[i];
00750 }
00751
00752 face->bitmapsFormat = format;
00753
00754 Bail:
00755 FT_FREE( offsets );
00756 return error;
00757 }
00758
00759
00760 static FT_Error
00761 pcf_get_encodings( FT_Stream stream,
00762 PCF_Face face )
00763 {
00764 FT_Error error = PCF_Err_Ok;
00765 FT_Memory memory = FT_FACE(face)->memory;
00766 FT_ULong format, size;
00767 int firstCol, lastCol;
00768 int firstRow, lastRow;
00769 int nencoding, encodingOffset;
00770 int i, j;
00771 PCF_Encoding tmpEncoding, encoding = 0;
00772
00773
00774 error = pcf_seek_to_table_type( stream,
00775 face->toc.tables,
00776 face->toc.count,
00777 PCF_BDF_ENCODINGS,
00778 &format,
00779 &size );
00780 if ( error )
00781 return error;
00782
00783 error = FT_Stream_EnterFrame( stream, 14 );
00784 if ( error )
00785 return error;
00786
00787 format = FT_GET_ULONG_LE();
00788
00789 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00790 {
00791 firstCol = FT_GET_SHORT();
00792 lastCol = FT_GET_SHORT();
00793 firstRow = FT_GET_SHORT();
00794 lastRow = FT_GET_SHORT();
00795 face->defaultChar = FT_GET_SHORT();
00796 }
00797 else
00798 {
00799 firstCol = FT_GET_SHORT_LE();
00800 lastCol = FT_GET_SHORT_LE();
00801 firstRow = FT_GET_SHORT_LE();
00802 lastRow = FT_GET_SHORT_LE();
00803 face->defaultChar = FT_GET_SHORT_LE();
00804 }
00805
00806 FT_Stream_ExitFrame( stream );
00807
00808 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00809 return PCF_Err_Invalid_File_Format;
00810
00811 FT_TRACE4(( "pdf_get_encodings:\n" ));
00812
00813 FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
00814 firstCol, lastCol, firstRow, lastRow ));
00815
00816 nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
00817
00818 if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )
00819 return PCF_Err_Out_Of_Memory;
00820
00821 error = FT_Stream_EnterFrame( stream, 2 * nencoding );
00822 if ( error )
00823 goto Bail;
00824
00825 for ( i = 0, j = 0 ; i < nencoding; i++ )
00826 {
00827 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00828 encodingOffset = FT_GET_SHORT();
00829 else
00830 encodingOffset = FT_GET_SHORT_LE();
00831
00832 if ( encodingOffset != -1 )
00833 {
00834 tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
00835 firstRow ) * 256 ) +
00836 ( ( i % ( lastCol - firstCol + 1 ) ) +
00837 firstCol );
00838
00839 tmpEncoding[j].glyph = (FT_Short)encodingOffset;
00840
00841 FT_TRACE5(( " code %d (0x%04X): idx %d\n",
00842 tmpEncoding[j].enc, tmpEncoding[j].enc,
00843 tmpEncoding[j].glyph ));
00844
00845 j++;
00846 }
00847 }
00848 FT_Stream_ExitFrame( stream );
00849
00850 if ( FT_NEW_ARRAY( encoding, j ) )
00851 goto Bail;
00852
00853 for ( i = 0; i < j; i++ )
00854 {
00855 encoding[i].enc = tmpEncoding[i].enc;
00856 encoding[i].glyph = tmpEncoding[i].glyph;
00857 }
00858
00859 face->nencodings = j;
00860 face->encodings = encoding;
00861 FT_FREE( tmpEncoding );
00862
00863 return error;
00864
00865 Bail:
00866 FT_FREE( encoding );
00867 FT_FREE( tmpEncoding );
00868 return error;
00869 }
00870
00871
00872 static
00873 const FT_Frame_Field pcf_accel_header[] =
00874 {
00875 #undef FT_STRUCTURE
00876 #define FT_STRUCTURE PCF_AccelRec
00877
00878 FT_FRAME_START( 20 ),
00879 FT_FRAME_BYTE ( noOverlap ),
00880 FT_FRAME_BYTE ( constantMetrics ),
00881 FT_FRAME_BYTE ( terminalFont ),
00882 FT_FRAME_BYTE ( constantWidth ),
00883 FT_FRAME_BYTE ( inkInside ),
00884 FT_FRAME_BYTE ( inkMetrics ),
00885 FT_FRAME_BYTE ( drawDirection ),
00886 FT_FRAME_SKIP_BYTES( 1 ),
00887 FT_FRAME_LONG_LE ( fontAscent ),
00888 FT_FRAME_LONG_LE ( fontDescent ),
00889 FT_FRAME_LONG_LE ( maxOverlap ),
00890 FT_FRAME_END
00891 };
00892
00893
00894 static
00895 const FT_Frame_Field pcf_accel_msb_header[] =
00896 {
00897 #undef FT_STRUCTURE
00898 #define FT_STRUCTURE PCF_AccelRec
00899
00900 FT_FRAME_START( 20 ),
00901 FT_FRAME_BYTE ( noOverlap ),
00902 FT_FRAME_BYTE ( constantMetrics ),
00903 FT_FRAME_BYTE ( terminalFont ),
00904 FT_FRAME_BYTE ( constantWidth ),
00905 FT_FRAME_BYTE ( inkInside ),
00906 FT_FRAME_BYTE ( inkMetrics ),
00907 FT_FRAME_BYTE ( drawDirection ),
00908 FT_FRAME_SKIP_BYTES( 1 ),
00909 FT_FRAME_LONG ( fontAscent ),
00910 FT_FRAME_LONG ( fontDescent ),
00911 FT_FRAME_LONG ( maxOverlap ),
00912 FT_FRAME_END
00913 };
00914
00915
00916 static FT_Error
00917 pcf_get_accel( FT_Stream stream,
00918 PCF_Face face,
00919 FT_ULong type )
00920 {
00921 FT_ULong format, size;
00922 FT_Error error = PCF_Err_Ok;
00923 PCF_Accel accel = &face->accel;
00924
00925
00926 error = pcf_seek_to_table_type( stream,
00927 face->toc.tables,
00928 face->toc.count,
00929 type,
00930 &format,
00931 &size );
00932 if ( error )
00933 goto Bail;
00934
00935 if ( FT_READ_ULONG_LE( format ) )
00936 goto Bail;
00937
00938 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
00939 !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
00940 goto Bail;
00941
00942 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00943 {
00944 if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )
00945 goto Bail;
00946 }
00947 else
00948 {
00949 if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
00950 goto Bail;
00951 }
00952
00953 error = pcf_get_metric( stream,
00954 format & ( ~PCF_FORMAT_MASK ),
00955 &(accel->minbounds) );
00956 if ( error )
00957 goto Bail;
00958
00959 error = pcf_get_metric( stream,
00960 format & ( ~PCF_FORMAT_MASK ),
00961 &(accel->maxbounds) );
00962 if ( error )
00963 goto Bail;
00964
00965 if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
00966 {
00967 error = pcf_get_metric( stream,
00968 format & ( ~PCF_FORMAT_MASK ),
00969 &(accel->ink_minbounds) );
00970 if ( error )
00971 goto Bail;
00972
00973 error = pcf_get_metric( stream,
00974 format & ( ~PCF_FORMAT_MASK ),
00975 &(accel->ink_maxbounds) );
00976 if ( error )
00977 goto Bail;
00978 }
00979 else
00980 {
00981 accel->ink_minbounds = accel->minbounds;
00982 accel->ink_maxbounds = accel->maxbounds;
00983 }
00984
00985 Bail:
00986 return error;
00987 }
00988
00989
00990 static FT_Error
00991 pcf_interpret_style( PCF_Face pcf )
00992 {
00993 FT_Error error = PCF_Err_Ok;
00994 FT_Face face = FT_FACE( pcf );
00995 FT_Memory memory = face->memory;
00996
00997 PCF_Property prop;
00998
00999 size_t nn, len;
01000 char* strings[4] = { NULL, NULL, NULL, NULL };
01001 size_t lengths[4];
01002
01003
01004 face->style_flags = 0;
01005
01006 prop = pcf_find_property( pcf, "SLANT" );
01007 if ( prop && prop->isString &&
01008 ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
01009 *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
01010 {
01011 face->style_flags |= FT_STYLE_FLAG_ITALIC;
01012 strings[2] = ( *(prop->value.atom) == 'O' ||
01013 *(prop->value.atom) == 'o' ) ? (char *)"Oblique"
01014 : (char *)"Italic";
01015 }
01016
01017 prop = pcf_find_property( pcf, "WEIGHT_NAME" );
01018 if ( prop && prop->isString &&
01019 ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
01020 {
01021 face->style_flags |= FT_STYLE_FLAG_BOLD;
01022 strings[1] = (char *)"Bold";
01023 }
01024
01025 prop = pcf_find_property( pcf, "SETWIDTH_NAME" );
01026 if ( prop && prop->isString &&
01027 *(prop->value.atom) &&
01028 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
01029 strings[3] = (char *)(prop->value.atom);
01030
01031 prop = pcf_find_property( pcf, "ADD_STYLE_NAME" );
01032 if ( prop && prop->isString &&
01033 *(prop->value.atom) &&
01034 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
01035 strings[0] = (char *)(prop->value.atom);
01036
01037 for ( len = 0, nn = 0; nn < 4; nn++ )
01038 {
01039 lengths[nn] = 0;
01040 if ( strings[nn] )
01041 {
01042 lengths[nn] = ft_strlen( strings[nn] );
01043 len += lengths[nn] + 1;
01044 }
01045 }
01046
01047 if ( len == 0 )
01048 {
01049 strings[0] = (char *)"Regular";
01050 lengths[0] = ft_strlen( strings[0] );
01051 len = lengths[0] + 1;
01052 }
01053
01054 {
01055 char* s;
01056
01057
01058 if ( FT_ALLOC( face->style_name, len ) )
01059 return error;
01060
01061 s = face->style_name;
01062
01063 for ( nn = 0; nn < 4; nn++ )
01064 {
01065 char* src = strings[nn];
01066
01067
01068 len = lengths[nn];
01069
01070 if ( src == NULL )
01071 continue;
01072
01073
01074 if ( s != face->style_name )
01075 *s++ = ' ';
01076
01077 ft_memcpy( s, src, len );
01078
01079
01080
01081 if ( nn == 0 || nn == 3 )
01082 {
01083 size_t mm;
01084
01085
01086 for ( mm = 0; mm < len; mm++ )
01087 if (s[mm] == ' ')
01088 s[mm] = '-';
01089 }
01090
01091 s += len;
01092 }
01093 *s = 0;
01094 }
01095
01096 return error;
01097 }
01098
01099
01100 FT_LOCAL_DEF( FT_Error )
01101 pcf_load_font( FT_Stream stream,
01102 PCF_Face face )
01103 {
01104 FT_Error error = PCF_Err_Ok;
01105 FT_Memory memory = FT_FACE(face)->memory;
01106 FT_Bool hasBDFAccelerators;
01107
01108
01109 error = pcf_read_TOC( stream, face );
01110 if ( error )
01111 goto Exit;
01112
01113 error = pcf_get_properties( stream, face );
01114 if ( error )
01115 goto Exit;
01116
01117
01118 hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
01119 face->toc.count,
01120 PCF_BDF_ACCELERATORS );
01121 if ( !hasBDFAccelerators )
01122 {
01123 error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
01124 if ( error )
01125 goto Exit;
01126 }
01127
01128
01129 error = pcf_get_metrics( stream, face );
01130 if ( error )
01131 goto Exit;
01132
01133
01134 error = pcf_get_bitmaps( stream, face );
01135 if ( error )
01136 goto Exit;
01137
01138
01139 error = pcf_get_encodings( stream, face );
01140 if ( error )
01141 goto Exit;
01142
01143
01144 if ( hasBDFAccelerators )
01145 {
01146 error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
01147 if ( error )
01148 goto Exit;
01149 }
01150
01151
01152
01153
01154 {
01155 FT_Face root = FT_FACE( face );
01156 PCF_Property prop;
01157
01158
01159 root->num_faces = 1;
01160 root->face_index = 0;
01161 root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
01162 FT_FACE_FLAG_HORIZONTAL |
01163 FT_FACE_FLAG_FAST_GLYPHS;
01164
01165 if ( face->accel.constantWidth )
01166 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
01167
01168 if ( ( error = pcf_interpret_style( face ) ) != 0 )
01169 goto Exit;
01170
01171 prop = pcf_find_property( face, "FAMILY_NAME" );
01172 if ( prop && prop->isString )
01173 {
01174 if ( FT_STRDUP( root->family_name, prop->value.atom ) )
01175 goto Exit;
01176 }
01177 else
01178 root->family_name = NULL;
01179
01180
01181
01182
01183
01184
01185
01186
01187 root->num_glyphs = face->nmetrics + 1;
01188
01189 root->num_fixed_sizes = 1;
01190 if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
01191 goto Exit;
01192
01193 {
01194 FT_Bitmap_Size* bsize = root->available_sizes;
01195 FT_Short resolution_x = 0, resolution_y = 0;
01196
01197
01198 FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
01199
01200 #if 0
01201 bsize->height = face->accel.maxbounds.ascent << 6;
01202 #endif
01203 bsize->height = (FT_Short)( face->accel.fontAscent +
01204 face->accel.fontDescent );
01205
01206 prop = pcf_find_property( face, "AVERAGE_WIDTH" );
01207 if ( prop )
01208 bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
01209 else
01210 bsize->width = (FT_Short)( bsize->height * 2/3 );
01211
01212 prop = pcf_find_property( face, "POINT_SIZE" );
01213 if ( prop )
01214
01215 bsize->size =
01216 (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
01217
01218 prop = pcf_find_property( face, "PIXEL_SIZE" );
01219 if ( prop )
01220 bsize->y_ppem = (FT_Short)prop->value.l << 6;
01221
01222 prop = pcf_find_property( face, "RESOLUTION_X" );
01223 if ( prop )
01224 resolution_x = (FT_Short)prop->value.l;
01225
01226 prop = pcf_find_property( face, "RESOLUTION_Y" );
01227 if ( prop )
01228 resolution_y = (FT_Short)prop->value.l;
01229
01230 if ( bsize->y_ppem == 0 )
01231 {
01232 bsize->y_ppem = bsize->size;
01233 if ( resolution_y )
01234 bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
01235 }
01236 if ( resolution_x && resolution_y )
01237 bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
01238 else
01239 bsize->x_ppem = bsize->y_ppem;
01240 }
01241
01242
01243 {
01244 PCF_Property charset_registry = 0, charset_encoding = 0;
01245
01246
01247 charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
01248 charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
01249
01250 if ( charset_registry && charset_registry->isString &&
01251 charset_encoding && charset_encoding->isString )
01252 {
01253 if ( FT_STRDUP( face->charset_encoding,
01254 charset_encoding->value.atom ) ||
01255 FT_STRDUP( face->charset_registry,
01256 charset_registry->value.atom ) )
01257 goto Exit;
01258 }
01259 }
01260 }
01261
01262 Exit:
01263 if ( error )
01264 {
01265
01266
01267 error = PCF_Err_Invalid_File_Format;
01268 }
01269
01270 return error;
01271 }
01272
01273
01274