46#define FT_COMPONENT pcfread
49#ifdef FT_DEBUG_LEVEL_TRACE
50 static const char*
const tableNames[] =
66 const FT_Frame_Field pcf_toc_header[] =
69#define FT_STRUCTURE PCF_TocRec
72 FT_FRAME_ULONG_LE( version ),
73 FT_FRAME_ULONG_LE( count ),
79 const FT_Frame_Field pcf_table_header[] =
82#define FT_STRUCTURE PCF_TableRec
85 FT_FRAME_ULONG_LE( type ),
86 FT_FRAME_ULONG_LE( format ),
87 FT_FRAME_ULONG_LE( size ),
88 FT_FRAME_ULONG_LE( offset ),
94 pcf_read_TOC( FT_Stream stream,
98 PCF_Toc toc = &face->toc;
101 FT_Memory memory = FT_FACE( face )->memory;
107 if ( FT_STREAM_SEEK( 0 ) ||
108 FT_STREAM_READ_FIELDS( pcf_toc_header, toc ) )
109 return FT_THROW( Cannot_Open_Resource );
111 if ( toc->version != PCF_FILE_VERSION ||
113 return FT_THROW( Invalid_File_Format );
115 if ( stream->size < 16 )
116 return FT_THROW( Invalid_File_Format );
120 if ( toc->count > ( stream->size >> 4 ) ||
123 FT_TRACE0((
"pcf_read_TOC: adjusting number of tables"
124 " (from %lu to %lu)\n",
126 FT_MIN( stream->size >> 4, 9 ) ));
127 toc->count = FT_MIN( stream->size >> 4, 9 );
130 if ( FT_QNEW_ARRAY( face->toc.tables, toc->count ) )
133 tables = face->toc.tables;
134 for ( n = 0; n < toc->count; n++ )
136 if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )
144 tables = face->toc.tables;
146 for ( n = 0; n < toc->count - 1; n++ )
148 FT_UInt i, have_change;
153 for ( i = 0; i < toc->count - 1 - n; i++ )
158 if ( tables[i].offset > tables[i + 1].offset )
161 tables[i] = tables[i + 1];
167 if ( ( tables[i].size > tables[i + 1].offset ) ||
168 ( tables[i].offset > tables[i + 1].offset - tables[i].size ) )
170 error = FT_THROW( Invalid_Offset );
200 tables = face->toc.tables;
203 for ( n = 0; n < toc->count - 1; n++ )
206 if ( ( tables->size > size ) ||
207 ( tables->offset > size - tables->size ) )
209 error = FT_THROW( Invalid_Table );
216 if ( ( tables->offset > size ) )
218 error = FT_THROW( Invalid_Table );
222 if ( tables->size > size - tables->offset )
223 tables->size = size - tables->offset;
225#ifdef FT_DEBUG_LEVEL_TRACE
229 const char* name =
"?";
232 FT_TRACE4((
"pcf_read_TOC:\n" ));
234 FT_TRACE4((
" number of tables: %lu\n", face->toc.count ));
236 tables = face->toc.tables;
237 for ( i = 0; i < toc->count; i++ )
239 for ( j = 0; j <
sizeof ( tableNames ) /
sizeof ( tableNames[0] );
241 if ( tables[i].type == 1UL << j )
242 name = tableNames[j];
244 FT_TRACE4((
" %u: type=%s, format=0x%lX,"
245 " size=%lu (0x%lX), offset=%lu (0x%lX)\n",
248 tables[i].size, tables[i].size,
249 tables[i].offset, tables[i].offset ));
258 FT_FREE( face->toc.tables );
263#define PCF_METRIC_SIZE 12
266 const FT_Frame_Field pcf_metric_header[] =
269#define FT_STRUCTURE PCF_MetricRec
271 FT_FRAME_START( PCF_METRIC_SIZE ),
272 FT_FRAME_SHORT_LE( leftSideBearing ),
273 FT_FRAME_SHORT_LE( rightSideBearing ),
274 FT_FRAME_SHORT_LE( characterWidth ),
275 FT_FRAME_SHORT_LE( ascent ),
276 FT_FRAME_SHORT_LE( descent ),
277 FT_FRAME_SHORT_LE( attributes ),
283 const FT_Frame_Field pcf_metric_msb_header[] =
286#define FT_STRUCTURE PCF_MetricRec
288 FT_FRAME_START( PCF_METRIC_SIZE ),
289 FT_FRAME_SHORT( leftSideBearing ),
290 FT_FRAME_SHORT( rightSideBearing ),
291 FT_FRAME_SHORT( characterWidth ),
292 FT_FRAME_SHORT( ascent ),
293 FT_FRAME_SHORT( descent ),
294 FT_FRAME_SHORT( attributes ),
299#define PCF_COMPRESSED_METRIC_SIZE 5
302 const FT_Frame_Field pcf_compressed_metric_header[] =
305#define FT_STRUCTURE PCF_Compressed_MetricRec
307 FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE ),
308 FT_FRAME_BYTE( leftSideBearing ),
309 FT_FRAME_BYTE( rightSideBearing ),
310 FT_FRAME_BYTE( characterWidth ),
311 FT_FRAME_BYTE( ascent ),
312 FT_FRAME_BYTE( descent ),
318 pcf_get_metric( FT_Stream stream,
322 FT_Error error = FT_Err_Ok;
325 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
327 const FT_Frame_Field* fields;
331 fields = ( PCF_BYTE_ORDER( format ) == MSBFirst )
332 ? pcf_metric_msb_header
336 (void)FT_STREAM_READ_FIELDS( fields, metric );
340 PCF_Compressed_MetricRec compr;
344 if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )
347 metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 );
348 metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
349 metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 );
350 metric->ascent = (FT_Short)( compr.ascent - 0x80 );
351 metric->descent = (FT_Short)( compr.descent - 0x80 );
352 metric->attributes = 0;
355 FT_TRACE5((
" width=%d,"
357 " ascent=%d, descent=%d,"
359 metric->characterWidth,
360 metric->leftSideBearing,
361 metric->rightSideBearing,
364 metric->attributes ));
372 pcf_seek_to_table_type( FT_Stream stream,
379 FT_Error error = FT_ERR( Invalid_File_Format );
383 for ( i = 0; i < ntables; i++ )
384 if ( tables[i].type == type )
386 if ( stream->pos > tables[i].offset )
388 error = FT_THROW( Invalid_Stream_Skip );
392 if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
394 error = FT_THROW( Invalid_Stream_Skip );
398 *asize = tables[i].size;
399 *aformat = tables[i].format;
411 pcf_has_table_type( PCF_Table tables,
418 for ( i = 0; i < ntables; i++ )
419 if ( tables[i].type == type )
426#define PCF_PROPERTY_SIZE 9
429 const FT_Frame_Field pcf_property_header[] =
432#define FT_STRUCTURE PCF_ParsePropertyRec
434 FT_FRAME_START( PCF_PROPERTY_SIZE ),
435 FT_FRAME_LONG_LE( name ),
436 FT_FRAME_BYTE ( isString ),
437 FT_FRAME_LONG_LE( value ),
443 const FT_Frame_Field pcf_property_msb_header[] =
446#define FT_STRUCTURE PCF_ParsePropertyRec
448 FT_FRAME_START( PCF_PROPERTY_SIZE ),
449 FT_FRAME_LONG( name ),
450 FT_FRAME_BYTE( isString ),
451 FT_FRAME_LONG( value ),
456 FT_LOCAL_DEF( PCF_Property )
457 pcf_find_property( PCF_Face face,
458 const FT_String* prop )
460 PCF_Property properties = face->properties;
465 for ( i = 0; i < face->nprops && !found; i++ )
467 if ( !ft_strcmp( properties[i].name, prop ) )
472 return properties + i - 1;
479 pcf_get_properties( FT_Stream stream,
482 PCF_ParseProperty props = NULL;
483 PCF_Property properties = NULL;
484 FT_ULong nprops, orig_nprops, i;
485 FT_ULong format, size;
487 FT_Memory memory = FT_FACE( face )->memory;
488 FT_ULong string_size;
489 FT_String* strings = NULL;
492 error = pcf_seek_to_table_type( stream,
501 if ( FT_READ_ULONG_LE( format ) )
504 FT_TRACE4((
"pcf_get_properties:\n" ));
505 FT_TRACE4((
" format: 0x%lX (%s)\n",
507 PCF_BYTE_ORDER( format ) == MSBFirst ?
"MSB" :
"LSB" ));
509 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
512 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
513 (void)FT_READ_ULONG( orig_nprops );
515 (
void)FT_READ_ULONG_LE( orig_nprops );
519 FT_TRACE4((
" number of properties: %lu\n", orig_nprops ));
522 if ( orig_nprops > size / PCF_PROPERTY_SIZE )
524 error = FT_THROW( Invalid_Table );
532 if ( orig_nprops > 256 )
534 FT_TRACE0((
"pcf_get_properties:"
535 " only loading first 256 properties\n" ));
539 nprops = orig_nprops;
541 face->nprops = (int)nprops;
543 if ( FT_QNEW_ARRAY( props, nprops ) )
546 for ( i = 0; i < nprops; i++ )
548 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
550 if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )
555 if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )
563 if ( FT_STREAM_SKIP( ( orig_nprops - nprops ) * PCF_PROPERTY_SIZE ) )
565 error = FT_THROW( Invalid_Stream_Skip );
574 if ( orig_nprops & 3 )
576 i = 4 - ( orig_nprops & 3 );
577 if ( FT_STREAM_SKIP( i ) )
579 error = FT_THROW( Invalid_Stream_Skip );
584 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
585 (void)FT_READ_ULONG( string_size );
587 (
void)FT_READ_ULONG_LE( string_size );
591 FT_TRACE4((
" string size: %lu\n", string_size ));
594 if ( string_size > size - orig_nprops * PCF_PROPERTY_SIZE )
596 error = FT_THROW( Invalid_Table );
602 if ( string_size > 16777472 )
604 FT_TRACE0((
"pcf_get_properties:"
605 " loading only 16777472 bytes of strings array\n" ));
606 string_size = 16777472;
610 if ( FT_QALLOC( strings, string_size + 1 ) ||
611 FT_STREAM_READ( strings, string_size ) )
614 strings[string_size] =
'\0';
617 if ( FT_NEW_ARRAY( properties, nprops ) )
620 face->properties = properties;
623 for ( i = 0; i < nprops; i++ )
625 FT_Long name_offset = props[i].name;
628 if ( ( name_offset < 0 ) ||
629 ( (FT_ULong)name_offset > string_size ) )
631 error = FT_THROW( Invalid_Offset );
635 if ( FT_STRDUP( properties[i].name, strings + name_offset ) )
638 FT_TRACE4((
" %s:", properties[i].name ));
640 properties[i].isString = props[i].isString;
642 if ( props[i].isString )
644 FT_Long value_offset = props[i].value;
647 if ( ( value_offset < 0 ) ||
648 ( (FT_ULong)value_offset > string_size ) )
650 error = FT_THROW( Invalid_Offset );
654 if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )
657 FT_TRACE4((
" `%s'\n", properties[i].value.atom ));
661 properties[i].value.l = props[i].value;
663 FT_TRACE4((
" %ld\n", properties[i].value.l ));
678 pcf_get_metrics( FT_Stream stream,
682 FT_Memory memory = FT_FACE( face )->memory;
683 FT_ULong format, size;
684 PCF_Metric metrics = NULL;
685 FT_ULong nmetrics, orig_nmetrics, i;
688 error = pcf_seek_to_table_type( stream,
697 if ( FT_READ_ULONG_LE( format ) )
700 FT_TRACE4((
"pcf_get_metrics:\n" ));
701 FT_TRACE4((
" format: 0x%lX (%s, %s)\n",
703 PCF_BYTE_ORDER( format ) == MSBFirst ?
"MSB" :
"LSB",
704 PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ?
705 "compressed" :
"uncompressed" ));
707 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
708 !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
709 return FT_THROW( Invalid_File_Format );
711 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
713 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
714 (void)FT_READ_ULONG( orig_nmetrics );
716 (
void)FT_READ_ULONG_LE( orig_nmetrics );
720 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
721 (void)FT_READ_USHORT( orig_nmetrics );
723 (
void)FT_READ_USHORT_LE( orig_nmetrics );
726 return FT_THROW( Invalid_File_Format );
728 FT_TRACE4((
" number of metrics: %lu\n", orig_nmetrics ));
731 if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
733 if ( orig_nmetrics > size / PCF_METRIC_SIZE )
734 return FT_THROW( Invalid_Table );
738 if ( orig_nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
739 return FT_THROW( Invalid_Table );
742 if ( !orig_nmetrics )
743 return FT_THROW( Invalid_Table );
759 if ( orig_nmetrics > 65534 )
761 FT_TRACE0((
"pcf_get_metrics:"
762 " only loading first 65534 metrics\n" ));
766 nmetrics = orig_nmetrics;
768 face->nmetrics = nmetrics + 1;
770 if ( FT_QNEW_ARRAY( face->metrics, face->nmetrics ) )
774 metrics = face->metrics + 1;
777 for ( i = 1; i < face->nmetrics; i++, metrics++ )
779 FT_TRACE5((
" idx %lu:", i ));
780 error = pcf_get_metric( stream, format, metrics );
790 if ( metrics->rightSideBearing < metrics->leftSideBearing ||
791 metrics->ascent < -metrics->descent )
793 metrics->characterWidth = 0;
794 metrics->leftSideBearing = 0;
795 metrics->rightSideBearing = 0;
797 metrics->descent = 0;
799 FT_TRACE0((
"pcf_get_metrics:"
800 " invalid metrics for glyph %lu\n", i ));
805 FT_FREE( face->metrics );
813 pcf_get_bitmaps( FT_Stream stream,
817 FT_ULong bitmapSizes[GLYPHPADOPTIONS];
818 FT_ULong format, size, pos;
819 FT_ULong nbitmaps, orig_nbitmaps, i, sizebitmaps = 0;
822 error = pcf_seek_to_table_type( stream,
831 error = FT_Stream_EnterFrame( stream, 8 );
835 format = FT_GET_ULONG_LE();
836 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
837 orig_nbitmaps = FT_GET_ULONG();
839 orig_nbitmaps = FT_GET_ULONG_LE();
841 FT_Stream_ExitFrame( stream );
843 FT_TRACE4((
"pcf_get_bitmaps:\n" ));
844 FT_TRACE4((
" format: 0x%lX\n", format ));
845 FT_TRACE4((
" (%s, %s,\n",
846 PCF_BYTE_ORDER( format ) == MSBFirst
847 ?
"most significant byte first"
848 :
"least significant byte first",
849 PCF_BIT_ORDER( format ) == MSBFirst
850 ?
"most significant bit first"
851 :
"least significant bit first" ));
852 FT_TRACE4((
" padding=%d bit%s, scanning=%d bit%s)\n",
853 8 << PCF_GLYPH_PAD_INDEX( format ),
854 ( 8 << PCF_GLYPH_PAD_INDEX( format ) ) == 1 ?
"" :
"s",
855 8 << PCF_SCAN_UNIT_INDEX( format ),
856 ( 8 << PCF_SCAN_UNIT_INDEX( format ) ) == 1 ?
"" :
"s" ));
858 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
859 return FT_THROW( Invalid_File_Format );
861 FT_TRACE4((
" number of bitmaps: %lu\n", orig_nbitmaps ));
864 if ( orig_nbitmaps > 65534 )
866 FT_TRACE0((
"pcf_get_bitmaps:"
867 " only loading first 65534 bitmaps\n" ));
871 nbitmaps = orig_nbitmaps;
874 if ( nbitmaps != face->nmetrics - 1 )
875 return FT_THROW( Invalid_File_Format );
878 pos = stream->pos + nbitmaps * 4 + 4 * 4;
881 for ( i = 1; i <= nbitmaps; i++ )
886 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
887 (void)FT_READ_ULONG( offset );
889 (
void)FT_READ_ULONG_LE( offset );
891 FT_TRACE5((
" bitmap %lu: offset %lu (0x%lX)\n",
892 i, offset, offset ));
898 FT_TRACE0((
"pcf_get_bitmaps:"
899 " invalid offset to bitmap data of glyph %lu\n", i ));
900 face->metrics[i].bits = pos;
903 face->metrics[i].bits = pos + offset;
908 for ( i = 0; i < GLYPHPADOPTIONS; i++ )
910 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
911 (void)FT_READ_ULONG( bitmapSizes[i] );
913 (
void)FT_READ_ULONG_LE( bitmapSizes[i] );
917 sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
919 FT_TRACE4((
" %d-bit padding implies a size of %lu\n",
920 8 << i, bitmapSizes[i] ));
923 FT_TRACE4((
" %lu bitmaps, using %d-bit padding\n",
925 8 << PCF_GLYPH_PAD_INDEX( format ) ));
926 FT_TRACE4((
" bitmap size: %lu\n", sizebitmaps ));
928 FT_UNUSED( sizebitmaps );
930 face->bitmapsFormat = format;
941#define PCF_ENC_SIZE 10
944 const FT_Frame_Field pcf_enc_header[] =
947#define FT_STRUCTURE PCF_EncRec
949 FT_FRAME_START( PCF_ENC_SIZE ),
950 FT_FRAME_USHORT_LE( firstCol ),
951 FT_FRAME_USHORT_LE( lastCol ),
952 FT_FRAME_USHORT_LE( firstRow ),
953 FT_FRAME_USHORT_LE( lastRow ),
954 FT_FRAME_USHORT_LE( defaultChar ),
960 const FT_Frame_Field pcf_enc_msb_header[] =
963#define FT_STRUCTURE PCF_EncRec
965 FT_FRAME_START( PCF_ENC_SIZE ),
966 FT_FRAME_USHORT( firstCol ),
967 FT_FRAME_USHORT( lastCol ),
968 FT_FRAME_USHORT( firstRow ),
969 FT_FRAME_USHORT( lastRow ),
970 FT_FRAME_USHORT( defaultChar ),
976 pcf_get_encodings( FT_Stream stream,
980 FT_Memory memory = FT_FACE( face )->memory;
981 FT_ULong format, size;
982 PCF_Enc enc = &face->enc;
985 FT_UShort defaultCharRow, defaultCharCol;
986 FT_UShort encodingOffset, defaultCharEncodingOffset;
991 error = pcf_seek_to_table_type( stream,
1000 if ( FT_READ_ULONG_LE( format ) )
1003 FT_TRACE4((
"pcf_get_encodings:\n" ));
1004 FT_TRACE4((
" format: 0x%lX (%s)\n",
1006 PCF_BYTE_ORDER( format ) == MSBFirst ?
"MSB" :
"LSB" ));
1008 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
1009 !PCF_FORMAT_MATCH( format, PCF_BDF_ENCODINGS ) )
1010 return FT_THROW( Invalid_File_Format );
1012 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
1014 if ( FT_STREAM_READ_FIELDS( pcf_enc_msb_header, enc ) )
1019 if ( FT_STREAM_READ_FIELDS( pcf_enc_header, enc ) )
1023 FT_TRACE4((
" firstCol 0x%X, lastCol 0x%X\n",
1024 enc->firstCol, enc->lastCol ));
1025 FT_TRACE4((
" firstRow 0x%X, lastRow 0x%X\n",
1026 enc->firstRow, enc->lastRow ));
1027 FT_TRACE4((
" defaultChar 0x%X\n",
1028 enc->defaultChar ));
1031 if ( enc->firstCol > enc->lastCol ||
1032 enc->lastCol > 0xFF ||
1033 enc->firstRow > enc->lastRow ||
1034 enc->lastRow > 0xFF )
1035 return FT_THROW( Invalid_Table );
1037 FT_TRACE5((
"\n" ));
1039 defaultCharRow = enc->defaultChar >> 8;
1040 defaultCharCol = enc->defaultChar & 0xFF;
1043 if ( defaultCharRow < enc->firstRow ||
1044 defaultCharRow > enc->lastRow ||
1045 defaultCharCol < enc->firstCol ||
1046 defaultCharCol > enc->lastCol )
1048 enc->defaultChar = enc->firstRow * 256U + enc->firstCol;
1049 FT_TRACE0((
"pcf_get_encodings:"
1050 " Invalid default character set to %u\n",
1051 enc->defaultChar ));
1053 defaultCharRow = enc->firstRow;
1054 defaultCharCol = enc->firstCol;
1057 nencoding = (FT_ULong)( enc->lastCol - enc->firstCol + 1 ) *
1058 (FT_ULong)( enc->lastRow - enc->firstRow + 1 );
1060 error = FT_Stream_EnterFrame( stream, 2 * nencoding );
1074 pos = stream->cursor +
1075 2 * ( ( defaultCharRow - enc->firstRow ) *
1076 ( enc->lastCol - enc->firstCol + 1 ) +
1077 defaultCharCol - enc->firstCol );
1079 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
1080 defaultCharEncodingOffset = FT_PEEK_USHORT( pos );
1082 defaultCharEncodingOffset = FT_PEEK_USHORT_LE( pos );
1084 if ( defaultCharEncodingOffset == 0xFFFF )
1086 FT_TRACE0((
"pcf_get_encodings:"
1087 " No glyph for default character,\n" ));
1089 " setting it to the first glyph of the font\n" ));
1090 defaultCharEncodingOffset = 1;
1094 defaultCharEncodingOffset++;
1096 if ( defaultCharEncodingOffset >= face->nmetrics )
1098 FT_TRACE0((
"pcf_get_encodings:"
1099 " Invalid glyph index for default character,\n" ));
1101 " setting it to the first glyph of the font\n" ));
1102 defaultCharEncodingOffset = 1;
1107 face->metrics[0] = face->metrics[defaultCharEncodingOffset];
1109 if ( FT_QNEW_ARRAY( enc->offset, nencoding ) )
1113 offset = enc->offset;
1114 for ( i = enc->firstRow; i <= enc->lastRow; i++ )
1116 for ( j = enc->firstCol; j <= enc->lastCol; j++ )
1122 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
1123 encodingOffset = FT_GET_USHORT();
1125 encodingOffset = FT_GET_USHORT_LE();
1128 *offset++ = encodingOffset == 0xFFFF ? 0xFFFF
1129 : encodingOffset + 1;
1132 FT_Stream_ExitFrame( stream );
1140 const FT_Frame_Field pcf_accel_header[] =
1143#define FT_STRUCTURE PCF_AccelRec
1145 FT_FRAME_START( 20 ),
1146 FT_FRAME_BYTE ( noOverlap ),
1147 FT_FRAME_BYTE ( constantMetrics ),
1148 FT_FRAME_BYTE ( terminalFont ),
1149 FT_FRAME_BYTE ( constantWidth ),
1150 FT_FRAME_BYTE ( inkInside ),
1151 FT_FRAME_BYTE ( inkMetrics ),
1152 FT_FRAME_BYTE ( drawDirection ),
1153 FT_FRAME_SKIP_BYTES( 1 ),
1154 FT_FRAME_LONG_LE ( fontAscent ),
1155 FT_FRAME_LONG_LE ( fontDescent ),
1156 FT_FRAME_LONG_LE ( maxOverlap ),
1162 const FT_Frame_Field pcf_accel_msb_header[] =
1165#define FT_STRUCTURE PCF_AccelRec
1167 FT_FRAME_START( 20 ),
1168 FT_FRAME_BYTE ( noOverlap ),
1169 FT_FRAME_BYTE ( constantMetrics ),
1170 FT_FRAME_BYTE ( terminalFont ),
1171 FT_FRAME_BYTE ( constantWidth ),
1172 FT_FRAME_BYTE ( inkInside ),
1173 FT_FRAME_BYTE ( inkMetrics ),
1174 FT_FRAME_BYTE ( drawDirection ),
1175 FT_FRAME_SKIP_BYTES( 1 ),
1176 FT_FRAME_LONG ( fontAscent ),
1177 FT_FRAME_LONG ( fontDescent ),
1178 FT_FRAME_LONG ( maxOverlap ),
1184 pcf_get_accel( FT_Stream stream,
1188 FT_ULong format, size;
1190 PCF_Accel accel = &face->accel;
1193 error = pcf_seek_to_table_type( stream,
1202 if ( FT_READ_ULONG_LE( format ) )
1205 FT_TRACE4((
"pcf_get_accel%s:\n",
1206 type == PCF_BDF_ACCELERATORS ?
" (getting BDF accelerators)"
1208 FT_TRACE4((
" format: 0x%lX (%s, %s)\n",
1210 PCF_BYTE_ORDER( format ) == MSBFirst ?
"MSB" :
"LSB",
1211 PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ?
1212 "accelerated" :
"not accelerated" ));
1214 if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
1215 !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
1218 if ( PCF_BYTE_ORDER( format ) == MSBFirst )
1220 if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )
1225 if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
1229 FT_TRACE5((
" noOverlap=%s, constantMetrics=%s,"
1230 " terminalFont=%s, constantWidth=%s\n",
1231 accel->noOverlap ?
"yes" :
"no",
1232 accel->constantMetrics ?
"yes" :
"no",
1233 accel->terminalFont ?
"yes" :
"no",
1234 accel->constantWidth ?
"yes" :
"no" ));
1235 FT_TRACE5((
" inkInside=%s, inkMetrics=%s, drawDirection=%s\n",
1236 accel->inkInside ?
"yes" :
"no",
1237 accel->inkMetrics ?
"yes" :
"no",
1238 accel->drawDirection ?
"RTL" :
"LTR" ));
1239 FT_TRACE5((
" fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n",
1242 accel->maxOverlap ));
1245 if ( FT_ABS( accel->fontAscent ) > 0x7FFF )
1247 accel->fontAscent = accel->fontAscent < 0 ? -0x7FFF : 0x7FFF;
1248 FT_TRACE0((
"pfc_get_accel: clamping font ascent to value %ld\n",
1249 accel->fontAscent ));
1251 if ( FT_ABS( accel->fontDescent ) > 0x7FFF )
1253 accel->fontDescent = accel->fontDescent < 0 ? -0x7FFF : 0x7FFF;
1254 FT_TRACE0((
"pfc_get_accel: clamping font descent to value %ld\n",
1255 accel->fontDescent ));
1258 FT_TRACE5((
" minbounds:" ));
1259 error = pcf_get_metric( stream,
1260 format & ( ~PCF_FORMAT_MASK ),
1261 &(accel->minbounds) );
1265 FT_TRACE5((
" maxbounds:" ));
1266 error = pcf_get_metric( stream,
1267 format & ( ~PCF_FORMAT_MASK ),
1268 &(accel->maxbounds) );
1272 if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
1274 FT_TRACE5((
" ink minbounds:" ));
1275 error = pcf_get_metric( stream,
1276 format & ( ~PCF_FORMAT_MASK ),
1277 &(accel->ink_minbounds) );
1281 FT_TRACE5((
" ink maxbounds:" ));
1282 error = pcf_get_metric( stream,
1283 format & ( ~PCF_FORMAT_MASK ),
1284 &(accel->ink_maxbounds) );
1290 accel->ink_minbounds = accel->minbounds;
1291 accel->ink_maxbounds = accel->maxbounds;
1300 pcf_interpret_style( PCF_Face pcf )
1302 FT_Error error = FT_Err_Ok;
1303 FT_Face face = FT_FACE( pcf );
1304 FT_Memory memory = face->memory;
1308 const char* strings[4] = { NULL, NULL, NULL, NULL };
1309 size_t lengths[4], nn, len;
1312 face->style_flags = 0;
1314 prop = pcf_find_property( pcf,
"SLANT" );
1315 if ( prop && prop->isString &&
1316 ( *(prop->value.atom) ==
'O' || *(prop->value.atom) ==
'o' ||
1317 *(prop->value.atom) ==
'I' || *(prop->value.atom) ==
'i' ) )
1319 face->style_flags |= FT_STYLE_FLAG_ITALIC;
1320 strings[2] = ( *(prop->value.atom) ==
'O' ||
1321 *(prop->value.atom) ==
'o' ) ?
"Oblique"
1325 prop = pcf_find_property( pcf,
"WEIGHT_NAME" );
1326 if ( prop && prop->isString &&
1327 ( *(prop->value.atom) ==
'B' || *(prop->value.atom) ==
'b' ) )
1329 face->style_flags |= FT_STYLE_FLAG_BOLD;
1330 strings[1] =
"Bold";
1333 prop = pcf_find_property( pcf,
"SETWIDTH_NAME" );
1334 if ( prop && prop->isString &&
1335 *(prop->value.atom) &&
1336 !( *(prop->value.atom) ==
'N' || *(prop->value.atom) ==
'n' ) )
1337 strings[3] = (
const char*)( prop->value.atom );
1339 prop = pcf_find_property( pcf,
"ADD_STYLE_NAME" );
1340 if ( prop && prop->isString &&
1341 *(prop->value.atom) &&
1342 !( *(prop->value.atom) ==
'N' || *(prop->value.atom) ==
'n' ) )
1343 strings[0] = (
const char*)( prop->value.atom );
1345 for ( len = 0, nn = 0; nn < 4; nn++ )
1350 lengths[nn] = ft_strlen( strings[nn] );
1351 len += lengths[nn] + 1;
1357 strings[0] =
"Regular";
1358 lengths[0] = ft_strlen( strings[0] );
1359 len = lengths[0] + 1;
1366 if ( FT_QALLOC( face->style_name, len ) )
1369 s = face->style_name;
1371 for ( nn = 0; nn < 4; nn++ )
1373 const char* src = strings[nn];
1382 if ( s != face->style_name )
1385 ft_memcpy( s, src, len );
1389 if ( nn == 0 || nn == 3 )
1394 for ( mm = 0; mm < len; mm++ )
1408 FT_LOCAL_DEF( FT_Error )
1409 pcf_load_font( FT_Stream stream,
1411 FT_Long face_index )
1413 FT_Face root = FT_FACE( face );
1415 FT_Memory memory = FT_FACE( face )->memory;
1416 FT_Bool hasBDFAccelerators;
1419 error = pcf_read_TOC( stream, face );
1423 root->num_faces = 1;
1424 root->face_index = 0;
1427 if ( face_index < 0 )
1430 error = pcf_get_properties( stream, face );
1435 hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
1437 PCF_BDF_ACCELERATORS );
1438 if ( !hasBDFAccelerators )
1440 error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
1446 error = pcf_get_metrics( stream, face );
1451 error = pcf_get_bitmaps( stream, face );
1456 error = pcf_get_encodings( stream, face );
1461 if ( hasBDFAccelerators )
1463 error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
1475 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
1476 FT_FACE_FLAG_HORIZONTAL;
1478 if ( face->accel.constantWidth )
1479 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
1481 if ( FT_SET_ERROR( pcf_interpret_style( face ) ) )
1484 prop = pcf_find_property( face,
"FAMILY_NAME" );
1485 if ( prop && prop->isString )
1488#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
1490 PCF_Driver driver = (PCF_Driver)FT_FACE_DRIVER( face );
1493 if ( !driver->no_long_family_names )
1506 PCF_Property foundry_prop, point_size_prop, average_width_prop;
1508 int l = ft_strlen( prop->value.atom ) + 1;
1512 foundry_prop = pcf_find_property( face,
"FOUNDRY" );
1513 point_size_prop = pcf_find_property( face,
"POINT_SIZE" );
1514 average_width_prop = pcf_find_property( face,
"AVERAGE_WIDTH" );
1516 if ( point_size_prop && average_width_prop )
1518 if ( average_width_prop->value.l >= point_size_prop->value.l )
1522 l += ft_strlen(
" Wide" );
1526 if ( foundry_prop && foundry_prop->isString )
1528 l += ft_strlen( foundry_prop->value.atom ) + 1;
1530 if ( FT_QALLOC( root->family_name, l ) )
1533 ft_strcpy( root->family_name, foundry_prop->value.atom );
1534 ft_strcat( root->family_name,
" " );
1535 ft_strcat( root->family_name, prop->value.atom );
1539 if ( FT_QALLOC( root->family_name, l ) )
1542 ft_strcpy( root->family_name, prop->value.atom );
1546 ft_strcat( root->family_name,
" Wide" );
1553 if ( FT_STRDUP( root->family_name, prop->value.atom ) )
1558 root->family_name = NULL;
1560 root->num_glyphs = (FT_Long)face->nmetrics;
1562 root->num_fixed_sizes = 1;
1563 if ( FT_NEW( root->available_sizes ) )
1567 FT_Bitmap_Size* bsize = root->available_sizes;
1568 FT_Short resolution_x = 0, resolution_y = 0;
1574 bsize->height = face->accel.maxbounds.ascent << 6;
1577#ifdef FT_DEBUG_LEVEL_TRACE
1578 if ( face->accel.fontAscent + face->accel.fontDescent < 0 )
1579 FT_TRACE0((
"pcf_load_font: negative height\n" ));
1581 if ( FT_ABS( face->accel.fontAscent +
1582 face->accel.fontDescent ) > 0x7FFF )
1584 bsize->height = 0x7FFF;
1585 FT_TRACE0((
"pcf_load_font: clamping height to value %d\n",
1589 bsize->height = FT_ABS( (FT_Short)( face->accel.fontAscent +
1590 face->accel.fontDescent ) );
1592 prop = pcf_find_property( face,
"AVERAGE_WIDTH" );
1595#ifdef FT_DEBUG_LEVEL_TRACE
1596 if ( prop->value.l < 0 )
1597 FT_TRACE0((
"pcf_load_font: negative average width\n" ));
1599 if ( ( FT_ABS( prop->value.l ) > 0x7FFFL * 10 - 5 ) )
1601 bsize->width = 0x7FFF;
1602 FT_TRACE0((
"pcf_load_font: clamping average width to value %d\n",
1606 bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
1611 bsize->width = ( bsize->height * 2 + 1 ) / 3;
1614 prop = pcf_find_property( face,
"POINT_SIZE" );
1617#ifdef FT_DEBUG_LEVEL_TRACE
1618 if ( prop->value.l < 0 )
1619 FT_TRACE0((
"pcf_load_font: negative point size\n" ));
1622 if ( FT_ABS( prop->value.l ) > 0x504C2L )
1624 bsize->size = 0x7FFF;
1625 FT_TRACE0((
"pcf_load_font: clamping point size to value %ld\n",
1629 bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
1634 prop = pcf_find_property( face,
"PIXEL_SIZE" );
1637#ifdef FT_DEBUG_LEVEL_TRACE
1638 if ( prop->value.l < 0 )
1639 FT_TRACE0((
"pcf_load_font: negative pixel size\n" ));
1641 if ( FT_ABS( prop->value.l ) > 0x7FFF )
1643 bsize->y_ppem = 0x7FFF << 6;
1644 FT_TRACE0((
"pcf_load_font: clamping pixel size to value %ld\n",
1648 bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
1651 prop = pcf_find_property( face,
"RESOLUTION_X" );
1654#ifdef FT_DEBUG_LEVEL_TRACE
1655 if ( prop->value.l < 0 )
1656 FT_TRACE0((
"pcf_load_font: negative X resolution\n" ));
1658 if ( FT_ABS( prop->value.l ) > 0x7FFF )
1660 resolution_x = 0x7FFF;
1661 FT_TRACE0((
"pcf_load_font: clamping X resolution to value %d\n",
1665 resolution_x = FT_ABS( (FT_Short)prop->value.l );
1668 prop = pcf_find_property( face,
"RESOLUTION_Y" );
1671#ifdef FT_DEBUG_LEVEL_TRACE
1672 if ( prop->value.l < 0 )
1673 FT_TRACE0((
"pcf_load_font: negative Y resolution\n" ));
1675 if ( FT_ABS( prop->value.l ) > 0x7FFF )
1677 resolution_y = 0x7FFF;
1678 FT_TRACE0((
"pcf_load_font: clamping Y resolution to value %d\n",
1682 resolution_y = FT_ABS( (FT_Short)prop->value.l );
1685 if ( bsize->y_ppem == 0 )
1687 bsize->y_ppem = bsize->size;
1689 bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 );
1691 if ( resolution_x && resolution_y )
1692 bsize->x_ppem = FT_MulDiv( bsize->y_ppem,
1696 bsize->x_ppem = bsize->y_ppem;
1701 PCF_Property charset_registry, charset_encoding;
1704 charset_registry = pcf_find_property( face,
"CHARSET_REGISTRY" );
1705 charset_encoding = pcf_find_property( face,
"CHARSET_ENCODING" );
1707 if ( charset_registry && charset_registry->isString &&
1708 charset_encoding && charset_encoding->isString )
1710 if ( FT_STRDUP( face->charset_encoding,
1711 charset_encoding->value.atom ) ||
1712 FT_STRDUP( face->charset_registry,
1713 charset_registry->value.atom ) )
1724 error = FT_THROW( Invalid_File_Format );