3
FreeType font driver for pcf fonts
5
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
7
Francesco Zappa Nardelli
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
#include FT_INTERNAL_DEBUG_H
32
#include FT_INTERNAL_STREAM_H
33
#include FT_INTERNAL_OBJECTS_H
41
/*************************************************************************/
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. */
48
#define FT_COMPONENT trace_pcfread
51
#ifdef FT_DEBUG_LEVEL_TRACE
52
static const char* const tableNames[] =
54
"prop", "accl", "mtrcs", "bmps", "imtrcs",
55
"enc", "swidth", "names", "accel"
61
const FT_Frame_Field pcf_toc_header[] =
64
#define FT_STRUCTURE PCF_TocRec
67
FT_FRAME_ULONG_LE( version ),
68
FT_FRAME_ULONG_LE( count ),
74
const FT_Frame_Field pcf_table_header[] =
77
#define FT_STRUCTURE PCF_TableRec
80
FT_FRAME_ULONG_LE( type ),
81
FT_FRAME_ULONG_LE( format ),
82
FT_FRAME_ULONG_LE( size ),
83
FT_FRAME_ULONG_LE( offset ),
89
pcf_read_TOC( FT_Stream stream,
93
PCF_Toc toc = &face->toc;
96
FT_Memory memory = FT_FACE(face)->memory;
100
if ( FT_STREAM_SEEK ( 0 ) ||
101
FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) )
102
return PCF_Err_Cannot_Open_Resource;
104
if ( toc->version != PCF_FILE_VERSION ||
105
toc->count > FT_ARRAY_MAX( face->toc.tables ) ||
107
return PCF_Err_Invalid_File_Format;
109
if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
110
return PCF_Err_Out_Of_Memory;
112
tables = face->toc.tables;
113
for ( n = 0; n < toc->count; n++ )
115
if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )
120
/* Sort tables and check for overlaps. Because they are almost */
121
/* always ordered already, an in-place bubble sort with simultaneous */
122
/* boundary checking seems appropriate. */
123
tables = face->toc.tables;
125
for ( n = 0; n < toc->count - 1; n++ )
127
FT_UInt i, have_change;
132
for ( i = 0; i < toc->count - 1 - n; i++ )
137
if ( tables[i].offset > tables[i + 1].offset )
140
tables[i] = tables[i + 1];
146
if ( ( tables[i].size > tables[i + 1].offset ) ||
147
( tables[i].offset > tables[i + 1].offset - tables[i].size ) )
148
return PCF_Err_Invalid_Offset;
155
#ifdef FT_DEBUG_LEVEL_TRACE
159
const char* name = "?";
162
FT_TRACE4(( "pcf_read_TOC:\n" ));
164
FT_TRACE4(( " number of tables: %ld\n", face->toc.count ));
166
tables = face->toc.tables;
167
for ( i = 0; i < toc->count; i++ )
169
for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );
171
if ( tables[i].type == (FT_UInt)( 1 << j ) )
172
name = tableNames[j];
174
FT_TRACE4(( " %d: type=%s, format=0x%X, "
175
"size=%ld (0x%lX), offset=%ld (0x%lX)\n",
178
tables[i].size, tables[i].size,
179
tables[i].offset, tables[i].offset ));
188
FT_FREE( face->toc.tables );
193
#define PCF_METRIC_SIZE 12
196
const FT_Frame_Field pcf_metric_header[] =
199
#define FT_STRUCTURE PCF_MetricRec
201
FT_FRAME_START( PCF_METRIC_SIZE ),
202
FT_FRAME_SHORT_LE( leftSideBearing ),
203
FT_FRAME_SHORT_LE( rightSideBearing ),
204
FT_FRAME_SHORT_LE( characterWidth ),
205
FT_FRAME_SHORT_LE( ascent ),
206
FT_FRAME_SHORT_LE( descent ),
207
FT_FRAME_SHORT_LE( attributes ),
213
const FT_Frame_Field pcf_metric_msb_header[] =
216
#define FT_STRUCTURE PCF_MetricRec
218
FT_FRAME_START( PCF_METRIC_SIZE ),
219
FT_FRAME_SHORT( leftSideBearing ),
220
FT_FRAME_SHORT( rightSideBearing ),
221
FT_FRAME_SHORT( characterWidth ),
222
FT_FRAME_SHORT( ascent ),
223
FT_FRAME_SHORT( descent ),
224
FT_FRAME_SHORT( attributes ),
229
#define PCF_COMPRESSED_METRIC_SIZE 5
232
const FT_Frame_Field pcf_compressed_metric_header[] =
235
#define FT_STRUCTURE PCF_Compressed_MetricRec
237
FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE ),
238
FT_FRAME_BYTE( leftSideBearing ),
239
FT_FRAME_BYTE( rightSideBearing ),
240
FT_FRAME_BYTE( characterWidth ),
241
FT_FRAME_BYTE( ascent ),
242
FT_FRAME_BYTE( descent ),
248
pcf_get_metric( FT_Stream stream,
252
FT_Error error = PCF_Err_Ok;
255
if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
257
const FT_Frame_Field* fields;
260
/* parsing normal metrics */
261
fields = PCF_BYTE_ORDER( format ) == MSBFirst
262
? pcf_metric_msb_header
265
/* the following sets `error' but doesn't return in case of failure */
266
(void)FT_STREAM_READ_FIELDS( fields, metric );
270
PCF_Compressed_MetricRec compr;
273
/* parsing compressed metrics */
274
if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )
277
metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 );
278
metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
279
metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 );
280
metric->ascent = (FT_Short)( compr.ascent - 0x80 );
281
metric->descent = (FT_Short)( compr.descent - 0x80 );
282
metric->attributes = 0;
291
pcf_seek_to_table_type( FT_Stream stream,
293
FT_ULong ntables, /* same as PCF_Toc->count */
298
FT_Error error = PCF_Err_Invalid_File_Format;
302
for ( i = 0; i < ntables; i++ )
303
if ( tables[i].type == type )
305
if ( stream->pos > tables[i].offset )
307
error = PCF_Err_Invalid_Stream_Skip;
311
if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
313
error = PCF_Err_Invalid_Stream_Skip;
317
*asize = tables[i].size;
318
*aformat = tables[i].format;
330
pcf_has_table_type( PCF_Table tables,
331
FT_ULong ntables, /* same as PCF_Toc->count */
337
for ( i = 0; i < ntables; i++ )
338
if ( tables[i].type == type )
345
#define PCF_PROPERTY_SIZE 9
348
const FT_Frame_Field pcf_property_header[] =
351
#define FT_STRUCTURE PCF_ParsePropertyRec
353
FT_FRAME_START( PCF_PROPERTY_SIZE ),
354
FT_FRAME_LONG_LE( name ),
355
FT_FRAME_BYTE ( isString ),
356
FT_FRAME_LONG_LE( value ),
362
const FT_Frame_Field pcf_property_msb_header[] =
365
#define FT_STRUCTURE PCF_ParsePropertyRec
367
FT_FRAME_START( PCF_PROPERTY_SIZE ),
368
FT_FRAME_LONG( name ),
369
FT_FRAME_BYTE( isString ),
370
FT_FRAME_LONG( value ),
375
FT_LOCAL_DEF( PCF_Property )
376
pcf_find_property( PCF_Face face,
377
const FT_String* prop )
379
PCF_Property properties = face->properties;
384
for ( i = 0 ; i < face->nprops && !found; i++ )
386
if ( !ft_strcmp( properties[i].name, prop ) )
391
return properties + i - 1;
398
pcf_get_properties( FT_Stream stream,
401
PCF_ParseProperty props = 0;
402
PCF_Property properties;
404
FT_ULong format, size;
406
FT_Memory memory = FT_FACE(face)->memory;
407
FT_ULong string_size;
408
FT_String* strings = 0;
411
error = pcf_seek_to_table_type( stream,
420
if ( FT_READ_ULONG_LE( format ) )
423
FT_TRACE4(( "pcf_get_properties:\n" ));
425
FT_TRACE4(( " format = %ld\n", format ));
427
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
430
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
431
(void)FT_READ_ULONG( nprops );
433
(void)FT_READ_ULONG_LE( nprops );
437
FT_TRACE4(( " nprop = %d (truncate %d props)\n",
438
(int)nprops, nprops - (int)nprops ));
440
nprops = (int)nprops;
443
if ( nprops > size / PCF_PROPERTY_SIZE )
445
error = PCF_Err_Invalid_Table;
449
face->nprops = (int)nprops;
451
if ( FT_NEW_ARRAY( props, nprops ) )
454
for ( i = 0; i < nprops; i++ )
456
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
458
if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )
463
if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )
468
/* pad the property array */
470
/* clever here - nprops is the same as the number of odd-units read, */
471
/* as only isStringProp are odd length (Keith Packard) */
475
i = 4 - ( nprops & 3 );
476
if ( FT_STREAM_SKIP( i ) )
478
error = PCF_Err_Invalid_Stream_Skip;
483
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
484
(void)FT_READ_ULONG( string_size );
486
(void)FT_READ_ULONG_LE( string_size );
490
FT_TRACE4(( " string_size = %ld\n", string_size ));
493
if ( string_size > size - nprops * PCF_PROPERTY_SIZE )
495
error = PCF_Err_Invalid_Table;
499
if ( FT_NEW_ARRAY( strings, string_size ) )
502
error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
506
if ( FT_NEW_ARRAY( properties, nprops ) )
509
face->properties = properties;
511
for ( i = 0; i < nprops; i++ )
513
FT_Long name_offset = props[i].name;
516
if ( ( name_offset < 0 ) ||
517
( (FT_ULong)name_offset > string_size ) )
519
error = PCF_Err_Invalid_Offset;
523
if ( FT_STRDUP( properties[i].name, strings + name_offset ) )
526
FT_TRACE4(( " %s:", properties[i].name ));
528
properties[i].isString = props[i].isString;
530
if ( props[i].isString )
532
FT_Long value_offset = props[i].value;
535
if ( ( value_offset < 0 ) ||
536
( (FT_ULong)value_offset > string_size ) )
538
error = PCF_Err_Invalid_Offset;
542
if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )
545
FT_TRACE4(( " `%s'\n", properties[i].value.atom ));
549
properties[i].value.l = props[i].value;
551
FT_TRACE4(( " %d\n", properties[i].value.l ));
566
pcf_get_metrics( FT_Stream stream,
569
FT_Error error = PCF_Err_Ok;
570
FT_Memory memory = FT_FACE(face)->memory;
571
FT_ULong format, size;
572
PCF_Metric metrics = 0;
573
FT_ULong nmetrics, i;
576
error = pcf_seek_to_table_type( stream,
585
if ( FT_READ_ULONG_LE( format ) )
588
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
589
!PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
590
return PCF_Err_Invalid_File_Format;
592
if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
594
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
595
(void)FT_READ_ULONG( nmetrics );
597
(void)FT_READ_ULONG_LE( nmetrics );
601
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
602
(void)FT_READ_USHORT( nmetrics );
604
(void)FT_READ_USHORT_LE( nmetrics );
607
return PCF_Err_Invalid_File_Format;
609
face->nmetrics = nmetrics;
612
return PCF_Err_Invalid_Table;
614
FT_TRACE4(( "pcf_get_metrics:\n" ));
616
FT_TRACE4(( " number of metrics: %d\n", nmetrics ));
619
if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
621
if ( nmetrics > size / PCF_METRIC_SIZE )
622
return PCF_Err_Invalid_Table;
626
if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
627
return PCF_Err_Invalid_Table;
630
if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
631
return PCF_Err_Out_Of_Memory;
633
metrics = face->metrics;
634
for ( i = 0; i < nmetrics; i++ )
636
error = pcf_get_metric( stream, format, metrics + i );
640
FT_TRACE5(( " idx %d: width=%d, "
641
"lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
643
( metrics + i )->characterWidth,
644
( metrics + i )->leftSideBearing,
645
( metrics + i )->rightSideBearing,
646
( metrics + i )->ascent,
647
( metrics + i )->descent,
648
( metrics + i )->attributes ));
655
FT_FREE( face->metrics );
663
pcf_get_bitmaps( FT_Stream stream,
666
FT_Error error = PCF_Err_Ok;
667
FT_Memory memory = FT_FACE(face)->memory;
669
FT_Long bitmapSizes[GLYPHPADOPTIONS];
670
FT_ULong format, size;
671
FT_ULong nbitmaps, i, sizebitmaps = 0;
674
error = pcf_seek_to_table_type( stream,
683
error = FT_Stream_EnterFrame( stream, 8 );
687
format = FT_GET_ULONG_LE();
688
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
689
nbitmaps = FT_GET_ULONG();
691
nbitmaps = FT_GET_ULONG_LE();
693
FT_Stream_ExitFrame( stream );
695
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
696
return PCF_Err_Invalid_File_Format;
698
FT_TRACE4(( "pcf_get_bitmaps:\n" ));
700
FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps ));
702
/* XXX: PCF_Face->nmetrics is singed FT_Long, see pcf.h */
703
if ( face->nmetrics < 0 || nbitmaps != ( FT_ULong )face->nmetrics )
704
return PCF_Err_Invalid_File_Format;
706
if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
709
for ( i = 0; i < nbitmaps; i++ )
711
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
712
(void)FT_READ_LONG( offsets[i] );
714
(void)FT_READ_LONG_LE( offsets[i] );
716
FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n",
717
i, offsets[i], offsets[i] ));
722
for ( i = 0; i < GLYPHPADOPTIONS; i++ )
724
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
725
(void)FT_READ_LONG( bitmapSizes[i] );
727
(void)FT_READ_LONG_LE( bitmapSizes[i] );
731
sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
733
FT_TRACE4(( " padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
736
FT_TRACE4(( " %d bitmaps, padding index %ld\n",
738
PCF_GLYPH_PAD_INDEX( format ) ));
739
FT_TRACE4(( " bitmap size = %d\n", sizebitmaps ));
741
FT_UNUSED( sizebitmaps ); /* only used for debugging */
743
for ( i = 0; i < nbitmaps; i++ )
746
if ( ( offsets[i] < 0 ) ||
747
( (FT_ULong)offsets[i] > size ) )
749
FT_TRACE0(( "pcf_get_bitmaps:"
750
" invalid offset to bitmap data of glyph %d\n", i ));
753
face->metrics[i].bits = stream->pos + offsets[i];
756
face->bitmapsFormat = format;
765
pcf_get_encodings( FT_Stream stream,
768
FT_Error error = PCF_Err_Ok;
769
FT_Memory memory = FT_FACE(face)->memory;
770
FT_ULong format, size;
771
int firstCol, lastCol;
772
int firstRow, lastRow;
773
int nencoding, encodingOffset;
775
PCF_Encoding tmpEncoding, encoding = 0;
778
error = pcf_seek_to_table_type( stream,
787
error = FT_Stream_EnterFrame( stream, 14 );
791
format = FT_GET_ULONG_LE();
793
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
795
firstCol = FT_GET_SHORT();
796
lastCol = FT_GET_SHORT();
797
firstRow = FT_GET_SHORT();
798
lastRow = FT_GET_SHORT();
799
face->defaultChar = FT_GET_SHORT();
803
firstCol = FT_GET_SHORT_LE();
804
lastCol = FT_GET_SHORT_LE();
805
firstRow = FT_GET_SHORT_LE();
806
lastRow = FT_GET_SHORT_LE();
807
face->defaultChar = FT_GET_SHORT_LE();
810
FT_Stream_ExitFrame( stream );
812
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
813
return PCF_Err_Invalid_File_Format;
815
FT_TRACE4(( "pdf_get_encodings:\n" ));
817
FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
818
firstCol, lastCol, firstRow, lastRow ));
820
nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
822
if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )
823
return PCF_Err_Out_Of_Memory;
825
error = FT_Stream_EnterFrame( stream, 2 * nencoding );
829
for ( i = 0, j = 0 ; i < nencoding; i++ )
831
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
832
encodingOffset = FT_GET_SHORT();
834
encodingOffset = FT_GET_SHORT_LE();
836
if ( encodingOffset != -1 )
838
tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
840
( ( i % ( lastCol - firstCol + 1 ) ) +
843
tmpEncoding[j].glyph = (FT_Short)encodingOffset;
845
FT_TRACE5(( " code %d (0x%04X): idx %d\n",
846
tmpEncoding[j].enc, tmpEncoding[j].enc,
847
tmpEncoding[j].glyph ));
852
FT_Stream_ExitFrame( stream );
854
if ( FT_NEW_ARRAY( encoding, j ) )
857
for ( i = 0; i < j; i++ )
859
encoding[i].enc = tmpEncoding[i].enc;
860
encoding[i].glyph = tmpEncoding[i].glyph;
863
face->nencodings = j;
864
face->encodings = encoding;
865
FT_FREE( tmpEncoding );
871
FT_FREE( tmpEncoding );
877
const FT_Frame_Field pcf_accel_header[] =
880
#define FT_STRUCTURE PCF_AccelRec
882
FT_FRAME_START( 20 ),
883
FT_FRAME_BYTE ( noOverlap ),
884
FT_FRAME_BYTE ( constantMetrics ),
885
FT_FRAME_BYTE ( terminalFont ),
886
FT_FRAME_BYTE ( constantWidth ),
887
FT_FRAME_BYTE ( inkInside ),
888
FT_FRAME_BYTE ( inkMetrics ),
889
FT_FRAME_BYTE ( drawDirection ),
890
FT_FRAME_SKIP_BYTES( 1 ),
891
FT_FRAME_LONG_LE ( fontAscent ),
892
FT_FRAME_LONG_LE ( fontDescent ),
893
FT_FRAME_LONG_LE ( maxOverlap ),
899
const FT_Frame_Field pcf_accel_msb_header[] =
902
#define FT_STRUCTURE PCF_AccelRec
904
FT_FRAME_START( 20 ),
905
FT_FRAME_BYTE ( noOverlap ),
906
FT_FRAME_BYTE ( constantMetrics ),
907
FT_FRAME_BYTE ( terminalFont ),
908
FT_FRAME_BYTE ( constantWidth ),
909
FT_FRAME_BYTE ( inkInside ),
910
FT_FRAME_BYTE ( inkMetrics ),
911
FT_FRAME_BYTE ( drawDirection ),
912
FT_FRAME_SKIP_BYTES( 1 ),
913
FT_FRAME_LONG ( fontAscent ),
914
FT_FRAME_LONG ( fontDescent ),
915
FT_FRAME_LONG ( maxOverlap ),
921
pcf_get_accel( FT_Stream stream,
925
FT_ULong format, size;
926
FT_Error error = PCF_Err_Ok;
927
PCF_Accel accel = &face->accel;
930
error = pcf_seek_to_table_type( stream,
939
if ( FT_READ_ULONG_LE( format ) )
942
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
943
!PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
946
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
948
if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )
953
if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
957
error = pcf_get_metric( stream,
958
format & ( ~PCF_FORMAT_MASK ),
959
&(accel->minbounds) );
963
error = pcf_get_metric( stream,
964
format & ( ~PCF_FORMAT_MASK ),
965
&(accel->maxbounds) );
969
if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
971
error = pcf_get_metric( stream,
972
format & ( ~PCF_FORMAT_MASK ),
973
&(accel->ink_minbounds) );
977
error = pcf_get_metric( stream,
978
format & ( ~PCF_FORMAT_MASK ),
979
&(accel->ink_maxbounds) );
985
accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
986
accel->ink_maxbounds = accel->maxbounds;
995
pcf_interpret_style( PCF_Face pcf )
997
FT_Error error = PCF_Err_Ok;
998
FT_Face face = FT_FACE( pcf );
999
FT_Memory memory = face->memory;
1004
char* strings[4] = { NULL, NULL, NULL, NULL };
1008
face->style_flags = 0;
1010
prop = pcf_find_property( pcf, "SLANT" );
1011
if ( prop && prop->isString &&
1012
( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
1013
*(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
1015
face->style_flags |= FT_STYLE_FLAG_ITALIC;
1016
strings[2] = ( *(prop->value.atom) == 'O' ||
1017
*(prop->value.atom) == 'o' ) ? (char *)"Oblique"
1021
prop = pcf_find_property( pcf, "WEIGHT_NAME" );
1022
if ( prop && prop->isString &&
1023
( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
1025
face->style_flags |= FT_STYLE_FLAG_BOLD;
1026
strings[1] = (char *)"Bold";
1029
prop = pcf_find_property( pcf, "SETWIDTH_NAME" );
1030
if ( prop && prop->isString &&
1031
*(prop->value.atom) &&
1032
!( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
1033
strings[3] = (char *)(prop->value.atom);
1035
prop = pcf_find_property( pcf, "ADD_STYLE_NAME" );
1036
if ( prop && prop->isString &&
1037
*(prop->value.atom) &&
1038
!( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
1039
strings[0] = (char *)(prop->value.atom);
1041
for ( len = 0, nn = 0; nn < 4; nn++ )
1046
lengths[nn] = ft_strlen( strings[nn] );
1047
len += lengths[nn] + 1;
1053
strings[0] = (char *)"Regular";
1054
lengths[0] = ft_strlen( strings[0] );
1055
len = lengths[0] + 1;
1062
if ( FT_ALLOC( face->style_name, len ) )
1065
s = face->style_name;
1067
for ( nn = 0; nn < 4; nn++ )
1069
char* src = strings[nn];
1077
/* separate elements with a space */
1078
if ( s != face->style_name )
1081
ft_memcpy( s, src, len );
1083
/* need to convert spaces to dashes for */
1084
/* add_style_name and setwidth_name */
1085
if ( nn == 0 || nn == 3 )
1090
for ( mm = 0; mm < len; mm++ )
1104
FT_LOCAL_DEF( FT_Error )
1105
pcf_load_font( FT_Stream stream,
1108
FT_Error error = PCF_Err_Ok;
1109
FT_Memory memory = FT_FACE(face)->memory;
1110
FT_Bool hasBDFAccelerators;
1113
error = pcf_read_TOC( stream, face );
1117
error = pcf_get_properties( stream, face );
1121
/* Use the old accelerators if no BDF accelerators are in the file. */
1122
hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
1124
PCF_BDF_ACCELERATORS );
1125
if ( !hasBDFAccelerators )
1127
error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
1133
error = pcf_get_metrics( stream, face );
1138
error = pcf_get_bitmaps( stream, face );
1143
error = pcf_get_encodings( stream, face );
1147
/* BDF style accelerators (i.e. bounds based on encoded glyphs) */
1148
if ( hasBDFAccelerators )
1150
error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
1155
/* XXX: TO DO: inkmetrics and glyph_names are missing */
1157
/* now construct the face object */
1159
FT_Face root = FT_FACE( face );
1163
root->num_faces = 1;
1164
root->face_index = 0;
1165
root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
1166
FT_FACE_FLAG_HORIZONTAL |
1167
FT_FACE_FLAG_FAST_GLYPHS;
1169
if ( face->accel.constantWidth )
1170
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
1172
if ( ( error = pcf_interpret_style( face ) ) != 0 )
1175
prop = pcf_find_property( face, "FAMILY_NAME" );
1176
if ( prop && prop->isString )
1178
if ( FT_STRDUP( root->family_name, prop->value.atom ) )
1182
root->family_name = NULL;
1185
* Note: We shift all glyph indices by +1 since we must
1186
* respect the convention that glyph 0 always corresponds
1187
* to the `missing glyph'.
1189
* This implies bumping the number of `available' glyphs by 1.
1191
root->num_glyphs = face->nmetrics + 1;
1193
root->num_fixed_sizes = 1;
1194
if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
1198
FT_Bitmap_Size* bsize = root->available_sizes;
1199
FT_Short resolution_x = 0, resolution_y = 0;
1202
FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
1205
bsize->height = face->accel.maxbounds.ascent << 6;
1207
bsize->height = (FT_Short)( face->accel.fontAscent +
1208
face->accel.fontDescent );
1210
prop = pcf_find_property( face, "AVERAGE_WIDTH" );
1212
bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
1214
bsize->width = (FT_Short)( bsize->height * 2/3 );
1216
prop = pcf_find_property( face, "POINT_SIZE" );
1218
/* convert from 722.7 decipoints to 72 points per inch */
1220
(FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
1222
prop = pcf_find_property( face, "PIXEL_SIZE" );
1224
bsize->y_ppem = (FT_Short)prop->value.l << 6;
1226
prop = pcf_find_property( face, "RESOLUTION_X" );
1228
resolution_x = (FT_Short)prop->value.l;
1230
prop = pcf_find_property( face, "RESOLUTION_Y" );
1232
resolution_y = (FT_Short)prop->value.l;
1234
if ( bsize->y_ppem == 0 )
1236
bsize->y_ppem = bsize->size;
1238
bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
1240
if ( resolution_x && resolution_y )
1241
bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
1243
bsize->x_ppem = bsize->y_ppem;
1246
/* set up charset */
1248
PCF_Property charset_registry = 0, charset_encoding = 0;
1251
charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
1252
charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
1254
if ( charset_registry && charset_registry->isString &&
1255
charset_encoding && charset_encoding->isString )
1257
if ( FT_STRDUP( face->charset_encoding,
1258
charset_encoding->value.atom ) ||
1259
FT_STRDUP( face->charset_registry,
1260
charset_registry->value.atom ) )
1269
/* This is done to respect the behaviour of the original */
1270
/* PCF font driver. */
1271
error = PCF_Err_Invalid_File_Format;