3 FreeType font driver for pcf fonts
5 Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by
6 Francesco Zappa Nardelli
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_INTERNAL_STREAM_H
32 #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 #if defined( 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 #if defined( 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
,
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
,
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\n", nprops
));
440 if ( nprops
> size
/ PCF_PROPERTY_SIZE
)
442 error
= PCF_Err_Invalid_Table
;
446 face
->nprops
= nprops
;
448 if ( FT_NEW_ARRAY( props
, nprops
) )
451 for ( i
= 0; i
< nprops
; i
++ )
453 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
455 if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header
, props
+ i
) )
460 if ( FT_STREAM_READ_FIELDS( pcf_property_header
, props
+ i
) )
465 /* pad the property array */
467 /* clever here - nprops is the same as the number of odd-units read, */
468 /* as only isStringProp are odd length (Keith Packard) */
472 i
= 4 - ( nprops
& 3 );
473 FT_Stream_Skip( stream
, i
);
476 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
477 (void)FT_READ_ULONG( string_size
);
479 (void)FT_READ_ULONG_LE( string_size
);
483 FT_TRACE4(( " string_size = %ld\n", string_size
));
486 if ( string_size
> size
- nprops
* PCF_PROPERTY_SIZE
)
488 error
= PCF_Err_Invalid_Table
;
492 if ( FT_NEW_ARRAY( strings
, string_size
) )
495 error
= FT_Stream_Read( stream
, (FT_Byte
*)strings
, string_size
);
499 if ( FT_NEW_ARRAY( properties
, nprops
) )
502 face
->properties
= properties
;
504 for ( i
= 0; i
< nprops
; i
++ )
506 FT_Long name_offset
= props
[i
].name
;
509 if ( ( name_offset
< 0 ) ||
510 ( (FT_ULong
)name_offset
> string_size
) )
512 error
= PCF_Err_Invalid_Offset
;
516 if ( FT_STRDUP( properties
[i
].name
, strings
+ name_offset
) )
519 FT_TRACE4(( " %s:", properties
[i
].name
));
521 properties
[i
].isString
= props
[i
].isString
;
523 if ( props
[i
].isString
)
525 FT_Long value_offset
= props
[i
].value
;
528 if ( ( value_offset
< 0 ) ||
529 ( (FT_ULong
)value_offset
> string_size
) )
531 error
= PCF_Err_Invalid_Offset
;
535 if ( FT_STRDUP( properties
[i
].value
.atom
, strings
+ value_offset
) )
538 FT_TRACE4(( " `%s'\n", properties
[i
].value
.atom
));
542 properties
[i
].value
.integer
= props
[i
].value
;
544 FT_TRACE4(( " %d\n", properties
[i
].value
.integer
));
559 pcf_get_metrics( FT_Stream stream
,
562 FT_Error error
= PCF_Err_Ok
;
563 FT_Memory memory
= FT_FACE(face
)->memory
;
564 FT_ULong format
, size
;
565 PCF_Metric metrics
= 0;
566 FT_ULong nmetrics
, i
;
569 error
= pcf_seek_to_table_type( stream
,
578 if ( FT_READ_ULONG_LE( format
) )
581 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) &&
582 !PCF_FORMAT_MATCH( format
, PCF_COMPRESSED_METRICS
) )
583 return PCF_Err_Invalid_File_Format
;
585 if ( PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
587 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
588 (void)FT_READ_ULONG( nmetrics
);
590 (void)FT_READ_ULONG_LE( nmetrics
);
594 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
595 (void)FT_READ_USHORT( nmetrics
);
597 (void)FT_READ_USHORT_LE( nmetrics
);
600 return PCF_Err_Invalid_File_Format
;
602 face
->nmetrics
= nmetrics
;
604 FT_TRACE4(( "pcf_get_metrics:\n" ));
606 FT_TRACE4(( " number of metrics: %d\n", nmetrics
));
609 if ( PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
611 if ( nmetrics
> size
/ PCF_METRIC_SIZE
)
612 return PCF_Err_Invalid_Table
;
616 if ( nmetrics
> size
/ PCF_COMPRESSED_METRIC_SIZE
)
617 return PCF_Err_Invalid_Table
;
620 if ( FT_NEW_ARRAY( face
->metrics
, nmetrics
) )
621 return PCF_Err_Out_Of_Memory
;
623 metrics
= face
->metrics
;
624 for ( i
= 0; i
< nmetrics
; i
++ )
626 pcf_get_metric( stream
, format
, metrics
+ i
);
630 FT_TRACE5(( " idx %d: width=%d, "
631 "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
633 ( metrics
+ i
)->characterWidth
,
634 ( metrics
+ i
)->leftSideBearing
,
635 ( metrics
+ i
)->rightSideBearing
,
636 ( metrics
+ i
)->ascent
,
637 ( metrics
+ i
)->descent
,
638 ( metrics
+ i
)->attributes
));
645 FT_FREE( face
->metrics
);
653 pcf_get_bitmaps( FT_Stream stream
,
656 FT_Error error
= PCF_Err_Ok
;
657 FT_Memory memory
= FT_FACE(face
)->memory
;
659 FT_Long bitmapSizes
[GLYPHPADOPTIONS
];
660 FT_ULong format
, size
;
661 int nbitmaps
, i
, sizebitmaps
= 0;
664 error
= pcf_seek_to_table_type( stream
,
673 error
= FT_Stream_EnterFrame( stream
, 8 );
677 format
= FT_GET_ULONG_LE();
678 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
679 nbitmaps
= FT_GET_ULONG();
681 nbitmaps
= FT_GET_ULONG_LE();
683 FT_Stream_ExitFrame( stream
);
685 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
686 return PCF_Err_Invalid_File_Format
;
688 FT_TRACE4(( "pcf_get_bitmaps:\n" ));
690 FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps
));
692 if ( nbitmaps
!= face
->nmetrics
)
693 return PCF_Err_Invalid_File_Format
;
695 if ( FT_NEW_ARRAY( offsets
, nbitmaps
) )
698 for ( i
= 0; i
< nbitmaps
; i
++ )
700 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
701 (void)FT_READ_LONG( offsets
[i
] );
703 (void)FT_READ_LONG_LE( offsets
[i
] );
705 FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n",
706 i
, offsets
[i
], offsets
[i
] ));
711 for ( i
= 0; i
< GLYPHPADOPTIONS
; i
++ )
713 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
714 (void)FT_READ_LONG( bitmapSizes
[i
] );
716 (void)FT_READ_LONG_LE( bitmapSizes
[i
] );
720 sizebitmaps
= bitmapSizes
[PCF_GLYPH_PAD_INDEX( format
)];
722 FT_TRACE4(( " padding %d implies a size of %ld\n", i
, bitmapSizes
[i
] ));
725 FT_TRACE4(( " %d bitmaps, padding index %ld\n",
727 PCF_GLYPH_PAD_INDEX( format
) ));
728 FT_TRACE4(( " bitmap size = %d\n", sizebitmaps
));
730 FT_UNUSED( sizebitmaps
); /* only used for debugging */
732 for ( i
= 0; i
< nbitmaps
; i
++ )
735 if ( ( offsets
[i
] < 0 ) ||
736 ( (FT_ULong
)offsets
[i
] > size
) )
738 FT_ERROR(( "pcf_get_bitmaps:"));
739 FT_ERROR(( " invalid offset to bitmap data of glyph %d\n", i
));
742 face
->metrics
[i
].bits
= stream
->pos
+ offsets
[i
];
745 face
->bitmapsFormat
= format
;
754 pcf_get_encodings( FT_Stream stream
,
757 FT_Error error
= PCF_Err_Ok
;
758 FT_Memory memory
= FT_FACE(face
)->memory
;
759 FT_ULong format
, size
;
760 int firstCol
, lastCol
;
761 int firstRow
, lastRow
;
762 int nencoding
, encodingOffset
;
764 PCF_Encoding tmpEncoding
, encoding
= 0;
767 error
= pcf_seek_to_table_type( stream
,
776 error
= FT_Stream_EnterFrame( stream
, 14 );
780 format
= FT_GET_ULONG_LE();
782 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
784 firstCol
= FT_GET_SHORT();
785 lastCol
= FT_GET_SHORT();
786 firstRow
= FT_GET_SHORT();
787 lastRow
= FT_GET_SHORT();
788 face
->defaultChar
= FT_GET_SHORT();
792 firstCol
= FT_GET_SHORT_LE();
793 lastCol
= FT_GET_SHORT_LE();
794 firstRow
= FT_GET_SHORT_LE();
795 lastRow
= FT_GET_SHORT_LE();
796 face
->defaultChar
= FT_GET_SHORT_LE();
799 FT_Stream_ExitFrame( stream
);
801 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
802 return PCF_Err_Invalid_File_Format
;
804 FT_TRACE4(( "pdf_get_encodings:\n" ));
806 FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
807 firstCol
, lastCol
, firstRow
, lastRow
));
809 nencoding
= ( lastCol
- firstCol
+ 1 ) * ( lastRow
- firstRow
+ 1 );
811 if ( FT_NEW_ARRAY( tmpEncoding
, nencoding
) )
812 return PCF_Err_Out_Of_Memory
;
814 error
= FT_Stream_EnterFrame( stream
, 2 * nencoding
);
818 for ( i
= 0, j
= 0 ; i
< nencoding
; i
++ )
820 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
821 encodingOffset
= FT_GET_SHORT();
823 encodingOffset
= FT_GET_SHORT_LE();
825 if ( encodingOffset
!= -1 )
827 tmpEncoding
[j
].enc
= ( ( ( i
/ ( lastCol
- firstCol
+ 1 ) ) +
829 ( ( i
% ( lastCol
- firstCol
+ 1 ) ) +
832 tmpEncoding
[j
].glyph
= (FT_Short
)encodingOffset
;
834 FT_TRACE5(( " code %d (0x%04X): idx %d\n",
835 tmpEncoding
[j
].enc
, tmpEncoding
[j
].enc
,
836 tmpEncoding
[j
].glyph
));
841 FT_Stream_ExitFrame( stream
);
843 if ( FT_NEW_ARRAY( encoding
, j
) )
846 for ( i
= 0; i
< j
; i
++ )
848 encoding
[i
].enc
= tmpEncoding
[i
].enc
;
849 encoding
[i
].glyph
= tmpEncoding
[i
].glyph
;
852 face
->nencodings
= j
;
853 face
->encodings
= encoding
;
854 FT_FREE( tmpEncoding
);
860 FT_FREE( tmpEncoding
);
866 const FT_Frame_Field pcf_accel_header
[] =
869 #define FT_STRUCTURE PCF_AccelRec
871 FT_FRAME_START( 20 ),
872 FT_FRAME_BYTE ( noOverlap
),
873 FT_FRAME_BYTE ( constantMetrics
),
874 FT_FRAME_BYTE ( terminalFont
),
875 FT_FRAME_BYTE ( constantWidth
),
876 FT_FRAME_BYTE ( inkInside
),
877 FT_FRAME_BYTE ( inkMetrics
),
878 FT_FRAME_BYTE ( drawDirection
),
879 FT_FRAME_SKIP_BYTES( 1 ),
880 FT_FRAME_LONG_LE ( fontAscent
),
881 FT_FRAME_LONG_LE ( fontDescent
),
882 FT_FRAME_LONG_LE ( maxOverlap
),
888 const FT_Frame_Field pcf_accel_msb_header
[] =
891 #define FT_STRUCTURE PCF_AccelRec
893 FT_FRAME_START( 20 ),
894 FT_FRAME_BYTE ( noOverlap
),
895 FT_FRAME_BYTE ( constantMetrics
),
896 FT_FRAME_BYTE ( terminalFont
),
897 FT_FRAME_BYTE ( constantWidth
),
898 FT_FRAME_BYTE ( inkInside
),
899 FT_FRAME_BYTE ( inkMetrics
),
900 FT_FRAME_BYTE ( drawDirection
),
901 FT_FRAME_SKIP_BYTES( 1 ),
902 FT_FRAME_LONG ( fontAscent
),
903 FT_FRAME_LONG ( fontDescent
),
904 FT_FRAME_LONG ( maxOverlap
),
910 pcf_get_accel( FT_Stream stream
,
914 FT_ULong format
, size
;
915 FT_Error error
= PCF_Err_Ok
;
916 PCF_Accel accel
= &face
->accel
;
919 error
= pcf_seek_to_table_type( stream
,
928 if ( FT_READ_ULONG_LE( format
) )
931 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) &&
932 !PCF_FORMAT_MATCH( format
, PCF_ACCEL_W_INKBOUNDS
) )
935 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
937 if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header
, accel
) )
942 if ( FT_STREAM_READ_FIELDS( pcf_accel_header
, accel
) )
946 error
= pcf_get_metric( stream
,
947 format
& ( ~PCF_FORMAT_MASK
),
948 &(accel
->minbounds
) );
952 error
= pcf_get_metric( stream
,
953 format
& ( ~PCF_FORMAT_MASK
),
954 &(accel
->maxbounds
) );
958 if ( PCF_FORMAT_MATCH( format
, PCF_ACCEL_W_INKBOUNDS
) )
960 error
= pcf_get_metric( stream
,
961 format
& ( ~PCF_FORMAT_MASK
),
962 &(accel
->ink_minbounds
) );
966 error
= pcf_get_metric( stream
,
967 format
& ( ~PCF_FORMAT_MASK
),
968 &(accel
->ink_maxbounds
) );
974 accel
->ink_minbounds
= accel
->minbounds
; /* I'm not sure about this */
975 accel
->ink_maxbounds
= accel
->maxbounds
;
984 pcf_interpret_style( PCF_Face pcf
)
986 FT_Error error
= PCF_Err_Ok
;
987 FT_Face face
= FT_FACE( pcf
);
988 FT_Memory memory
= face
->memory
;
993 char* strings
[4] = { NULL
, NULL
, NULL
, NULL
};
997 face
->style_flags
= 0;
999 prop
= pcf_find_property( pcf
, "SLANT" );
1000 if ( prop
&& prop
->isString
&&
1001 ( *(prop
->value
.atom
) == 'O' || *(prop
->value
.atom
) == 'o' ||
1002 *(prop
->value
.atom
) == 'I' || *(prop
->value
.atom
) == 'i' ) )
1004 face
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
1005 strings
[2] = ( *(prop
->value
.atom
) == 'O' ||
1006 *(prop
->value
.atom
) == 'o' ) ? (char *)"Oblique"
1010 prop
= pcf_find_property( pcf
, "WEIGHT_NAME" );
1011 if ( prop
&& prop
->isString
&&
1012 ( *(prop
->value
.atom
) == 'B' || *(prop
->value
.atom
) == 'b' ) )
1014 face
->style_flags
|= FT_STYLE_FLAG_BOLD
;
1015 strings
[1] = (char *)"Bold";
1018 prop
= pcf_find_property( pcf
, "SETWIDTH_NAME" );
1019 if ( prop
&& prop
->isString
&&
1020 *(prop
->value
.atom
) &&
1021 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
1022 strings
[3] = (char *)(prop
->value
.atom
);
1024 prop
= pcf_find_property( pcf
, "ADD_STYLE_NAME" );
1025 if ( prop
&& prop
->isString
&&
1026 *(prop
->value
.atom
) &&
1027 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
1028 strings
[0] = (char *)(prop
->value
.atom
);
1030 for ( len
= 0, nn
= 0; nn
< 4; nn
++ )
1035 lengths
[nn
] = ft_strlen( strings
[nn
] );
1036 len
+= lengths
[nn
] + 1;
1042 strings
[0] = (char *)"Regular";
1043 lengths
[0] = ft_strlen( strings
[0] );
1044 len
= lengths
[0] + 1;
1051 if ( FT_ALLOC( face
->style_name
, len
) )
1054 s
= face
->style_name
;
1056 for ( nn
= 0; nn
< 4; nn
++ )
1058 char* src
= strings
[nn
];
1066 /* separate elements with a space */
1067 if ( s
!= face
->style_name
)
1070 ft_memcpy( s
, src
, len
);
1072 /* need to convert spaces to dashes for */
1073 /* add_style_name and setwidth_name */
1074 if ( nn
== 0 || nn
== 3 )
1079 for ( mm
= 0; mm
< len
; mm
++ )
1093 FT_LOCAL_DEF( FT_Error
)
1094 pcf_load_font( FT_Stream stream
,
1097 FT_Error error
= PCF_Err_Ok
;
1098 FT_Memory memory
= FT_FACE(face
)->memory
;
1099 FT_Bool hasBDFAccelerators
;
1102 error
= pcf_read_TOC( stream
, face
);
1106 error
= pcf_get_properties( stream
, face
);
1110 /* Use the old accelerators if no BDF accelerators are in the file. */
1111 hasBDFAccelerators
= pcf_has_table_type( face
->toc
.tables
,
1113 PCF_BDF_ACCELERATORS
);
1114 if ( !hasBDFAccelerators
)
1116 error
= pcf_get_accel( stream
, face
, PCF_ACCELERATORS
);
1122 error
= pcf_get_metrics( stream
, face
);
1127 error
= pcf_get_bitmaps( stream
, face
);
1132 error
= pcf_get_encodings( stream
, face
);
1136 /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
1137 if ( hasBDFAccelerators
)
1139 error
= pcf_get_accel( stream
, face
, PCF_BDF_ACCELERATORS
);
1144 /* XXX: TO DO: inkmetrics and glyph_names are missing */
1146 /* now construct the face object */
1148 FT_Face root
= FT_FACE( face
);
1152 root
->num_faces
= 1;
1153 root
->face_index
= 0;
1154 root
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
1155 FT_FACE_FLAG_HORIZONTAL
|
1156 FT_FACE_FLAG_FAST_GLYPHS
;
1158 if ( face
->accel
.constantWidth
)
1159 root
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
1161 if ( ( error
= pcf_interpret_style( face
) ) != 0 )
1164 prop
= pcf_find_property( face
, "FAMILY_NAME" );
1165 if ( prop
&& prop
->isString
)
1167 if ( FT_STRDUP( root
->family_name
, prop
->value
.atom
) )
1171 root
->family_name
= NULL
;
1174 * Note: We shift all glyph indices by +1 since we must
1175 * respect the convention that glyph 0 always corresponds
1176 * to the `missing glyph'.
1178 * This implies bumping the number of `available' glyphs by 1.
1180 root
->num_glyphs
= face
->nmetrics
+ 1;
1182 root
->num_fixed_sizes
= 1;
1183 if ( FT_NEW_ARRAY( root
->available_sizes
, 1 ) )
1187 FT_Bitmap_Size
* bsize
= root
->available_sizes
;
1188 FT_Short resolution_x
= 0, resolution_y
= 0;
1191 FT_MEM_ZERO( bsize
, sizeof ( FT_Bitmap_Size
) );
1194 bsize
->height
= face
->accel
.maxbounds
.ascent
<< 6;
1196 bsize
->height
= (FT_Short
)( face
->accel
.fontAscent
+
1197 face
->accel
.fontDescent
);
1199 prop
= pcf_find_property( face
, "AVERAGE_WIDTH" );
1201 bsize
->width
= (FT_Short
)( ( prop
->value
.integer
+ 5 ) / 10 );
1203 bsize
->width
= (FT_Short
)( bsize
->height
* 2/3 );
1205 prop
= pcf_find_property( face
, "POINT_SIZE" );
1207 /* convert from 722.7 decipoints to 72 points per inch */
1209 (FT_Pos
)( ( prop
->value
.integer
* 64 * 7200 + 36135L ) / 72270L );
1211 prop
= pcf_find_property( face
, "PIXEL_SIZE" );
1213 bsize
->y_ppem
= (FT_Short
)prop
->value
.integer
<< 6;
1215 prop
= pcf_find_property( face
, "RESOLUTION_X" );
1217 resolution_x
= (FT_Short
)prop
->value
.integer
;
1219 prop
= pcf_find_property( face
, "RESOLUTION_Y" );
1221 resolution_y
= (FT_Short
)prop
->value
.integer
;
1223 if ( bsize
->y_ppem
== 0 )
1225 bsize
->y_ppem
= bsize
->size
;
1227 bsize
->y_ppem
= bsize
->y_ppem
* resolution_y
/ 72;
1229 if ( resolution_x
&& resolution_y
)
1230 bsize
->x_ppem
= bsize
->y_ppem
* resolution_x
/ resolution_y
;
1232 bsize
->x_ppem
= bsize
->y_ppem
;
1235 /* set up charset */
1237 PCF_Property charset_registry
= 0, charset_encoding
= 0;
1240 charset_registry
= pcf_find_property( face
, "CHARSET_REGISTRY" );
1241 charset_encoding
= pcf_find_property( face
, "CHARSET_ENCODING" );
1243 if ( charset_registry
&& charset_registry
->isString
&&
1244 charset_encoding
&& charset_encoding
->isString
)
1246 if ( FT_STRDUP( face
->charset_encoding
,
1247 charset_encoding
->value
.atom
) ||
1248 FT_STRDUP( face
->charset_registry
,
1249 charset_registry
->value
.atom
) )
1258 /* This is done to respect the behaviour of the original */
1259 /* PCF font driver. */
1260 error
= PCF_Err_Invalid_File_Format
;