3 FreeType font driver for pcf fonts
5 Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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
40 /*************************************************************************/
42 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
43 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
44 /* messages during execution. */
47 #define FT_COMPONENT trace_pcfread
50 #ifdef FT_DEBUG_LEVEL_TRACE
51 static const char* const tableNames
[] =
53 "prop", "accl", "mtrcs", "bmps", "imtrcs",
54 "enc", "swidth", "names", "accel"
60 const FT_Frame_Field pcf_toc_header
[] =
63 #define FT_STRUCTURE PCF_TocRec
66 FT_FRAME_ULONG_LE( version
),
67 FT_FRAME_ULONG_LE( count
),
73 const FT_Frame_Field pcf_table_header
[] =
76 #define FT_STRUCTURE PCF_TableRec
79 FT_FRAME_ULONG_LE( type
),
80 FT_FRAME_ULONG_LE( format
),
81 FT_FRAME_ULONG_LE( size
),
82 FT_FRAME_ULONG_LE( offset
),
88 pcf_read_TOC( FT_Stream stream
,
92 PCF_Toc toc
= &face
->toc
;
95 FT_Memory memory
= FT_FACE(face
)->memory
;
99 if ( FT_STREAM_SEEK ( 0 ) ||
100 FT_STREAM_READ_FIELDS ( pcf_toc_header
, toc
) )
101 return PCF_Err_Cannot_Open_Resource
;
103 if ( toc
->version
!= PCF_FILE_VERSION
||
104 toc
->count
> FT_ARRAY_MAX( face
->toc
.tables
) ||
106 return PCF_Err_Invalid_File_Format
;
108 if ( FT_NEW_ARRAY( face
->toc
.tables
, toc
->count
) )
109 return PCF_Err_Out_Of_Memory
;
111 tables
= face
->toc
.tables
;
112 for ( n
= 0; n
< toc
->count
; n
++ )
114 if ( FT_STREAM_READ_FIELDS( pcf_table_header
, tables
) )
119 /* Sort tables and check for overlaps. Because they are almost */
120 /* always ordered already, an in-place bubble sort with simultaneous */
121 /* boundary checking seems appropriate. */
122 tables
= face
->toc
.tables
;
124 for ( n
= 0; n
< toc
->count
- 1; n
++ )
126 FT_UInt i
, have_change
;
131 for ( i
= 0; i
< toc
->count
- 1 - n
; i
++ )
136 if ( tables
[i
].offset
> tables
[i
+ 1].offset
)
139 tables
[i
] = tables
[i
+ 1];
145 if ( ( tables
[i
].size
> tables
[i
+ 1].offset
) ||
146 ( tables
[i
].offset
> tables
[i
+ 1].offset
- tables
[i
].size
) )
147 return PCF_Err_Invalid_Offset
;
154 #ifdef FT_DEBUG_LEVEL_TRACE
158 const char* name
= "?";
161 FT_TRACE4(( "pcf_read_TOC:\n" ));
163 FT_TRACE4(( " number of tables: %ld\n", face
->toc
.count
));
165 tables
= face
->toc
.tables
;
166 for ( i
= 0; i
< toc
->count
; i
++ )
168 for ( j
= 0; j
< sizeof ( tableNames
) / sizeof ( tableNames
[0] );
170 if ( tables
[i
].type
== (FT_UInt
)( 1 << j
) )
171 name
= tableNames
[j
];
173 FT_TRACE4(( " %d: type=%s, format=0x%X, "
174 "size=%ld (0x%lX), offset=%ld (0x%lX)\n",
177 tables
[i
].size
, tables
[i
].size
,
178 tables
[i
].offset
, tables
[i
].offset
));
187 FT_FREE( face
->toc
.tables
);
192 #define PCF_METRIC_SIZE 12
195 const FT_Frame_Field pcf_metric_header
[] =
198 #define FT_STRUCTURE PCF_MetricRec
200 FT_FRAME_START( PCF_METRIC_SIZE
),
201 FT_FRAME_SHORT_LE( leftSideBearing
),
202 FT_FRAME_SHORT_LE( rightSideBearing
),
203 FT_FRAME_SHORT_LE( characterWidth
),
204 FT_FRAME_SHORT_LE( ascent
),
205 FT_FRAME_SHORT_LE( descent
),
206 FT_FRAME_SHORT_LE( attributes
),
212 const FT_Frame_Field pcf_metric_msb_header
[] =
215 #define FT_STRUCTURE PCF_MetricRec
217 FT_FRAME_START( PCF_METRIC_SIZE
),
218 FT_FRAME_SHORT( leftSideBearing
),
219 FT_FRAME_SHORT( rightSideBearing
),
220 FT_FRAME_SHORT( characterWidth
),
221 FT_FRAME_SHORT( ascent
),
222 FT_FRAME_SHORT( descent
),
223 FT_FRAME_SHORT( attributes
),
228 #define PCF_COMPRESSED_METRIC_SIZE 5
231 const FT_Frame_Field pcf_compressed_metric_header
[] =
234 #define FT_STRUCTURE PCF_Compressed_MetricRec
236 FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE
),
237 FT_FRAME_BYTE( leftSideBearing
),
238 FT_FRAME_BYTE( rightSideBearing
),
239 FT_FRAME_BYTE( characterWidth
),
240 FT_FRAME_BYTE( ascent
),
241 FT_FRAME_BYTE( descent
),
247 pcf_get_metric( FT_Stream stream
,
251 FT_Error error
= PCF_Err_Ok
;
254 if ( PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
256 const FT_Frame_Field
* fields
;
259 /* parsing normal metrics */
260 fields
= PCF_BYTE_ORDER( format
) == MSBFirst
261 ? pcf_metric_msb_header
264 /* the following sets `error' but doesn't return in case of failure */
265 (void)FT_STREAM_READ_FIELDS( fields
, metric
);
269 PCF_Compressed_MetricRec compr
;
272 /* parsing compressed metrics */
273 if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header
, &compr
) )
276 metric
->leftSideBearing
= (FT_Short
)( compr
.leftSideBearing
- 0x80 );
277 metric
->rightSideBearing
= (FT_Short
)( compr
.rightSideBearing
- 0x80 );
278 metric
->characterWidth
= (FT_Short
)( compr
.characterWidth
- 0x80 );
279 metric
->ascent
= (FT_Short
)( compr
.ascent
- 0x80 );
280 metric
->descent
= (FT_Short
)( compr
.descent
- 0x80 );
281 metric
->attributes
= 0;
290 pcf_seek_to_table_type( FT_Stream stream
,
292 FT_ULong ntables
, /* same as PCF_Toc->count */
297 FT_Error error
= PCF_Err_Invalid_File_Format
;
301 for ( i
= 0; i
< ntables
; i
++ )
302 if ( tables
[i
].type
== type
)
304 if ( stream
->pos
> tables
[i
].offset
)
306 error
= PCF_Err_Invalid_Stream_Skip
;
310 if ( FT_STREAM_SKIP( tables
[i
].offset
- stream
->pos
) )
312 error
= PCF_Err_Invalid_Stream_Skip
;
316 *asize
= tables
[i
].size
;
317 *aformat
= tables
[i
].format
;
329 pcf_has_table_type( PCF_Table tables
,
330 FT_ULong ntables
, /* same as PCF_Toc->count */
336 for ( i
= 0; i
< ntables
; i
++ )
337 if ( tables
[i
].type
== type
)
344 #define PCF_PROPERTY_SIZE 9
347 const FT_Frame_Field pcf_property_header
[] =
350 #define FT_STRUCTURE PCF_ParsePropertyRec
352 FT_FRAME_START( PCF_PROPERTY_SIZE
),
353 FT_FRAME_LONG_LE( name
),
354 FT_FRAME_BYTE ( isString
),
355 FT_FRAME_LONG_LE( value
),
361 const FT_Frame_Field pcf_property_msb_header
[] =
364 #define FT_STRUCTURE PCF_ParsePropertyRec
366 FT_FRAME_START( PCF_PROPERTY_SIZE
),
367 FT_FRAME_LONG( name
),
368 FT_FRAME_BYTE( isString
),
369 FT_FRAME_LONG( value
),
374 FT_LOCAL_DEF( PCF_Property
)
375 pcf_find_property( PCF_Face face
,
376 const FT_String
* prop
)
378 PCF_Property properties
= face
->properties
;
383 for ( i
= 0 ; i
< face
->nprops
&& !found
; i
++ )
385 if ( !ft_strcmp( properties
[i
].name
, prop
) )
390 return properties
+ i
- 1;
397 pcf_get_properties( FT_Stream stream
,
400 PCF_ParseProperty props
= 0;
401 PCF_Property properties
;
403 FT_ULong format
, size
;
405 FT_Memory memory
= FT_FACE(face
)->memory
;
406 FT_ULong string_size
;
407 FT_String
* strings
= 0;
410 error
= pcf_seek_to_table_type( stream
,
419 if ( FT_READ_ULONG_LE( format
) )
422 FT_TRACE4(( "pcf_get_properties:\n" ));
424 FT_TRACE4(( " format = %ld\n", format
));
426 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
429 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
430 (void)FT_READ_ULONG( nprops
);
432 (void)FT_READ_ULONG_LE( nprops
);
436 FT_TRACE4(( " nprop = %d (truncate %d props)\n",
437 (int)nprops
, nprops
- (int)nprops
));
439 nprops
= (int)nprops
;
442 if ( nprops
> size
/ PCF_PROPERTY_SIZE
)
444 error
= PCF_Err_Invalid_Table
;
448 face
->nprops
= (int)nprops
;
450 if ( FT_NEW_ARRAY( props
, nprops
) )
453 for ( i
= 0; i
< nprops
; i
++ )
455 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
457 if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header
, props
+ i
) )
462 if ( FT_STREAM_READ_FIELDS( pcf_property_header
, props
+ i
) )
467 /* pad the property array */
469 /* clever here - nprops is the same as the number of odd-units read, */
470 /* as only isStringProp are odd length (Keith Packard) */
474 i
= 4 - ( nprops
& 3 );
475 if ( FT_STREAM_SKIP( i
) )
477 error
= PCF_Err_Invalid_Stream_Skip
;
482 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
483 (void)FT_READ_ULONG( string_size
);
485 (void)FT_READ_ULONG_LE( string_size
);
489 FT_TRACE4(( " string_size = %ld\n", string_size
));
492 if ( string_size
> size
- nprops
* PCF_PROPERTY_SIZE
)
494 error
= PCF_Err_Invalid_Table
;
498 if ( FT_NEW_ARRAY( strings
, string_size
) )
501 error
= FT_Stream_Read( stream
, (FT_Byte
*)strings
, string_size
);
505 if ( FT_NEW_ARRAY( properties
, nprops
) )
508 face
->properties
= properties
;
510 for ( i
= 0; i
< nprops
; i
++ )
512 FT_Long name_offset
= props
[i
].name
;
515 if ( ( name_offset
< 0 ) ||
516 ( (FT_ULong
)name_offset
> string_size
) )
518 error
= PCF_Err_Invalid_Offset
;
522 if ( FT_STRDUP( properties
[i
].name
, strings
+ name_offset
) )
525 FT_TRACE4(( " %s:", properties
[i
].name
));
527 properties
[i
].isString
= props
[i
].isString
;
529 if ( props
[i
].isString
)
531 FT_Long value_offset
= props
[i
].value
;
534 if ( ( value_offset
< 0 ) ||
535 ( (FT_ULong
)value_offset
> string_size
) )
537 error
= PCF_Err_Invalid_Offset
;
541 if ( FT_STRDUP( properties
[i
].value
.atom
, strings
+ value_offset
) )
544 FT_TRACE4(( " `%s'\n", properties
[i
].value
.atom
));
548 properties
[i
].value
.l
= props
[i
].value
;
550 FT_TRACE4(( " %d\n", properties
[i
].value
.l
));
565 pcf_get_metrics( FT_Stream stream
,
568 FT_Error error
= PCF_Err_Ok
;
569 FT_Memory memory
= FT_FACE(face
)->memory
;
570 FT_ULong format
, size
;
571 PCF_Metric metrics
= 0;
572 FT_ULong nmetrics
, i
;
575 error
= pcf_seek_to_table_type( stream
,
584 if ( FT_READ_ULONG_LE( format
) )
587 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) &&
588 !PCF_FORMAT_MATCH( format
, PCF_COMPRESSED_METRICS
) )
589 return PCF_Err_Invalid_File_Format
;
591 if ( PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
593 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
594 (void)FT_READ_ULONG( nmetrics
);
596 (void)FT_READ_ULONG_LE( nmetrics
);
600 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
601 (void)FT_READ_USHORT( nmetrics
);
603 (void)FT_READ_USHORT_LE( nmetrics
);
606 return PCF_Err_Invalid_File_Format
;
608 face
->nmetrics
= nmetrics
;
610 FT_TRACE4(( "pcf_get_metrics:\n" ));
612 FT_TRACE4(( " number of metrics: %d\n", nmetrics
));
615 if ( PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
617 if ( nmetrics
> size
/ PCF_METRIC_SIZE
)
618 return PCF_Err_Invalid_Table
;
622 if ( nmetrics
> size
/ PCF_COMPRESSED_METRIC_SIZE
)
623 return PCF_Err_Invalid_Table
;
626 if ( FT_NEW_ARRAY( face
->metrics
, nmetrics
) )
627 return PCF_Err_Out_Of_Memory
;
629 metrics
= face
->metrics
;
630 for ( i
= 0; i
< nmetrics
; i
++ )
632 error
= pcf_get_metric( stream
, format
, metrics
+ i
);
636 FT_TRACE5(( " idx %d: width=%d, "
637 "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
639 ( metrics
+ i
)->characterWidth
,
640 ( metrics
+ i
)->leftSideBearing
,
641 ( metrics
+ i
)->rightSideBearing
,
642 ( metrics
+ i
)->ascent
,
643 ( metrics
+ i
)->descent
,
644 ( metrics
+ i
)->attributes
));
651 FT_FREE( face
->metrics
);
659 pcf_get_bitmaps( FT_Stream stream
,
662 FT_Error error
= PCF_Err_Ok
;
663 FT_Memory memory
= FT_FACE(face
)->memory
;
665 FT_Long bitmapSizes
[GLYPHPADOPTIONS
];
666 FT_ULong format
, size
;
667 FT_ULong nbitmaps
, i
, sizebitmaps
= 0;
670 error
= pcf_seek_to_table_type( stream
,
679 error
= FT_Stream_EnterFrame( stream
, 8 );
683 format
= FT_GET_ULONG_LE();
684 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
685 nbitmaps
= FT_GET_ULONG();
687 nbitmaps
= FT_GET_ULONG_LE();
689 FT_Stream_ExitFrame( stream
);
691 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
692 return PCF_Err_Invalid_File_Format
;
694 FT_TRACE4(( "pcf_get_bitmaps:\n" ));
696 FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps
));
698 /* XXX: PCF_Face->nmetrics is singed FT_Long, see pcf.h */
699 if ( face
->nmetrics
< 0 || nbitmaps
!= ( FT_ULong
)face
->nmetrics
)
700 return PCF_Err_Invalid_File_Format
;
702 if ( FT_NEW_ARRAY( offsets
, nbitmaps
) )
705 for ( i
= 0; i
< nbitmaps
; i
++ )
707 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
708 (void)FT_READ_LONG( offsets
[i
] );
710 (void)FT_READ_LONG_LE( offsets
[i
] );
712 FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n",
713 i
, offsets
[i
], offsets
[i
] ));
718 for ( i
= 0; i
< GLYPHPADOPTIONS
; i
++ )
720 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
721 (void)FT_READ_LONG( bitmapSizes
[i
] );
723 (void)FT_READ_LONG_LE( bitmapSizes
[i
] );
727 sizebitmaps
= bitmapSizes
[PCF_GLYPH_PAD_INDEX( format
)];
729 FT_TRACE4(( " padding %d implies a size of %ld\n", i
, bitmapSizes
[i
] ));
732 FT_TRACE4(( " %d bitmaps, padding index %ld\n",
734 PCF_GLYPH_PAD_INDEX( format
) ));
735 FT_TRACE4(( " bitmap size = %d\n", sizebitmaps
));
737 FT_UNUSED( sizebitmaps
); /* only used for debugging */
739 for ( i
= 0; i
< nbitmaps
; i
++ )
742 if ( ( offsets
[i
] < 0 ) ||
743 ( (FT_ULong
)offsets
[i
] > size
) )
745 FT_TRACE0(( "pcf_get_bitmaps:"
746 " invalid offset to bitmap data of glyph %d\n", i
));
749 face
->metrics
[i
].bits
= stream
->pos
+ offsets
[i
];
752 face
->bitmapsFormat
= format
;
761 pcf_get_encodings( FT_Stream stream
,
764 FT_Error error
= PCF_Err_Ok
;
765 FT_Memory memory
= FT_FACE(face
)->memory
;
766 FT_ULong format
, size
;
767 int firstCol
, lastCol
;
768 int firstRow
, lastRow
;
769 int nencoding
, encodingOffset
;
771 PCF_Encoding tmpEncoding
, encoding
= 0;
774 error
= pcf_seek_to_table_type( stream
,
783 error
= FT_Stream_EnterFrame( stream
, 14 );
787 format
= FT_GET_ULONG_LE();
789 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
791 firstCol
= FT_GET_SHORT();
792 lastCol
= FT_GET_SHORT();
793 firstRow
= FT_GET_SHORT();
794 lastRow
= FT_GET_SHORT();
795 face
->defaultChar
= FT_GET_SHORT();
799 firstCol
= FT_GET_SHORT_LE();
800 lastCol
= FT_GET_SHORT_LE();
801 firstRow
= FT_GET_SHORT_LE();
802 lastRow
= FT_GET_SHORT_LE();
803 face
->defaultChar
= FT_GET_SHORT_LE();
806 FT_Stream_ExitFrame( stream
);
808 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) )
809 return PCF_Err_Invalid_File_Format
;
811 FT_TRACE4(( "pdf_get_encodings:\n" ));
813 FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
814 firstCol
, lastCol
, firstRow
, lastRow
));
816 nencoding
= ( lastCol
- firstCol
+ 1 ) * ( lastRow
- firstRow
+ 1 );
818 if ( FT_NEW_ARRAY( tmpEncoding
, nencoding
) )
819 return PCF_Err_Out_Of_Memory
;
821 error
= FT_Stream_EnterFrame( stream
, 2 * nencoding
);
825 for ( i
= 0, j
= 0 ; i
< nencoding
; i
++ )
827 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
828 encodingOffset
= FT_GET_SHORT();
830 encodingOffset
= FT_GET_SHORT_LE();
832 if ( encodingOffset
!= -1 )
834 tmpEncoding
[j
].enc
= ( ( ( i
/ ( lastCol
- firstCol
+ 1 ) ) +
836 ( ( i
% ( lastCol
- firstCol
+ 1 ) ) +
839 tmpEncoding
[j
].glyph
= (FT_Short
)encodingOffset
;
841 FT_TRACE5(( " code %d (0x%04X): idx %d\n",
842 tmpEncoding
[j
].enc
, tmpEncoding
[j
].enc
,
843 tmpEncoding
[j
].glyph
));
848 FT_Stream_ExitFrame( stream
);
850 if ( FT_NEW_ARRAY( encoding
, j
) )
853 for ( i
= 0; i
< j
; i
++ )
855 encoding
[i
].enc
= tmpEncoding
[i
].enc
;
856 encoding
[i
].glyph
= tmpEncoding
[i
].glyph
;
859 face
->nencodings
= j
;
860 face
->encodings
= encoding
;
861 FT_FREE( tmpEncoding
);
867 FT_FREE( tmpEncoding
);
873 const FT_Frame_Field pcf_accel_header
[] =
876 #define FT_STRUCTURE PCF_AccelRec
878 FT_FRAME_START( 20 ),
879 FT_FRAME_BYTE ( noOverlap
),
880 FT_FRAME_BYTE ( constantMetrics
),
881 FT_FRAME_BYTE ( terminalFont
),
882 FT_FRAME_BYTE ( constantWidth
),
883 FT_FRAME_BYTE ( inkInside
),
884 FT_FRAME_BYTE ( inkMetrics
),
885 FT_FRAME_BYTE ( drawDirection
),
886 FT_FRAME_SKIP_BYTES( 1 ),
887 FT_FRAME_LONG_LE ( fontAscent
),
888 FT_FRAME_LONG_LE ( fontDescent
),
889 FT_FRAME_LONG_LE ( maxOverlap
),
895 const FT_Frame_Field pcf_accel_msb_header
[] =
898 #define FT_STRUCTURE PCF_AccelRec
900 FT_FRAME_START( 20 ),
901 FT_FRAME_BYTE ( noOverlap
),
902 FT_FRAME_BYTE ( constantMetrics
),
903 FT_FRAME_BYTE ( terminalFont
),
904 FT_FRAME_BYTE ( constantWidth
),
905 FT_FRAME_BYTE ( inkInside
),
906 FT_FRAME_BYTE ( inkMetrics
),
907 FT_FRAME_BYTE ( drawDirection
),
908 FT_FRAME_SKIP_BYTES( 1 ),
909 FT_FRAME_LONG ( fontAscent
),
910 FT_FRAME_LONG ( fontDescent
),
911 FT_FRAME_LONG ( maxOverlap
),
917 pcf_get_accel( FT_Stream stream
,
921 FT_ULong format
, size
;
922 FT_Error error
= PCF_Err_Ok
;
923 PCF_Accel accel
= &face
->accel
;
926 error
= pcf_seek_to_table_type( stream
,
935 if ( FT_READ_ULONG_LE( format
) )
938 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) &&
939 !PCF_FORMAT_MATCH( format
, PCF_ACCEL_W_INKBOUNDS
) )
942 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
944 if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header
, accel
) )
949 if ( FT_STREAM_READ_FIELDS( pcf_accel_header
, accel
) )
953 error
= pcf_get_metric( stream
,
954 format
& ( ~PCF_FORMAT_MASK
),
955 &(accel
->minbounds
) );
959 error
= pcf_get_metric( stream
,
960 format
& ( ~PCF_FORMAT_MASK
),
961 &(accel
->maxbounds
) );
965 if ( PCF_FORMAT_MATCH( format
, PCF_ACCEL_W_INKBOUNDS
) )
967 error
= pcf_get_metric( stream
,
968 format
& ( ~PCF_FORMAT_MASK
),
969 &(accel
->ink_minbounds
) );
973 error
= pcf_get_metric( stream
,
974 format
& ( ~PCF_FORMAT_MASK
),
975 &(accel
->ink_maxbounds
) );
981 accel
->ink_minbounds
= accel
->minbounds
; /* I'm not sure about this */
982 accel
->ink_maxbounds
= accel
->maxbounds
;
991 pcf_interpret_style( PCF_Face pcf
)
993 FT_Error error
= PCF_Err_Ok
;
994 FT_Face face
= FT_FACE( pcf
);
995 FT_Memory memory
= face
->memory
;
1000 char* strings
[4] = { NULL
, NULL
, NULL
, NULL
};
1004 face
->style_flags
= 0;
1006 prop
= pcf_find_property( pcf
, "SLANT" );
1007 if ( prop
&& prop
->isString
&&
1008 ( *(prop
->value
.atom
) == 'O' || *(prop
->value
.atom
) == 'o' ||
1009 *(prop
->value
.atom
) == 'I' || *(prop
->value
.atom
) == 'i' ) )
1011 face
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
1012 strings
[2] = ( *(prop
->value
.atom
) == 'O' ||
1013 *(prop
->value
.atom
) == 'o' ) ? (char *)"Oblique"
1017 prop
= pcf_find_property( pcf
, "WEIGHT_NAME" );
1018 if ( prop
&& prop
->isString
&&
1019 ( *(prop
->value
.atom
) == 'B' || *(prop
->value
.atom
) == 'b' ) )
1021 face
->style_flags
|= FT_STYLE_FLAG_BOLD
;
1022 strings
[1] = (char *)"Bold";
1025 prop
= pcf_find_property( pcf
, "SETWIDTH_NAME" );
1026 if ( prop
&& prop
->isString
&&
1027 *(prop
->value
.atom
) &&
1028 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
1029 strings
[3] = (char *)(prop
->value
.atom
);
1031 prop
= pcf_find_property( pcf
, "ADD_STYLE_NAME" );
1032 if ( prop
&& prop
->isString
&&
1033 *(prop
->value
.atom
) &&
1034 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
1035 strings
[0] = (char *)(prop
->value
.atom
);
1037 for ( len
= 0, nn
= 0; nn
< 4; nn
++ )
1042 lengths
[nn
] = ft_strlen( strings
[nn
] );
1043 len
+= lengths
[nn
] + 1;
1049 strings
[0] = (char *)"Regular";
1050 lengths
[0] = ft_strlen( strings
[0] );
1051 len
= lengths
[0] + 1;
1058 if ( FT_ALLOC( face
->style_name
, len
) )
1061 s
= face
->style_name
;
1063 for ( nn
= 0; nn
< 4; nn
++ )
1065 char* src
= strings
[nn
];
1073 /* separate elements with a space */
1074 if ( s
!= face
->style_name
)
1077 ft_memcpy( s
, src
, len
);
1079 /* need to convert spaces to dashes for */
1080 /* add_style_name and setwidth_name */
1081 if ( nn
== 0 || nn
== 3 )
1086 for ( mm
= 0; mm
< len
; mm
++ )
1100 FT_LOCAL_DEF( FT_Error
)
1101 pcf_load_font( FT_Stream stream
,
1104 FT_Error error
= PCF_Err_Ok
;
1105 FT_Memory memory
= FT_FACE(face
)->memory
;
1106 FT_Bool hasBDFAccelerators
;
1109 error
= pcf_read_TOC( stream
, face
);
1113 error
= pcf_get_properties( stream
, face
);
1117 /* Use the old accelerators if no BDF accelerators are in the file. */
1118 hasBDFAccelerators
= pcf_has_table_type( face
->toc
.tables
,
1120 PCF_BDF_ACCELERATORS
);
1121 if ( !hasBDFAccelerators
)
1123 error
= pcf_get_accel( stream
, face
, PCF_ACCELERATORS
);
1129 error
= pcf_get_metrics( stream
, face
);
1134 error
= pcf_get_bitmaps( stream
, face
);
1139 error
= pcf_get_encodings( stream
, face
);
1143 /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
1144 if ( hasBDFAccelerators
)
1146 error
= pcf_get_accel( stream
, face
, PCF_BDF_ACCELERATORS
);
1151 /* XXX: TO DO: inkmetrics and glyph_names are missing */
1153 /* now construct the face object */
1155 FT_Face root
= FT_FACE( face
);
1159 root
->num_faces
= 1;
1160 root
->face_index
= 0;
1161 root
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
1162 FT_FACE_FLAG_HORIZONTAL
|
1163 FT_FACE_FLAG_FAST_GLYPHS
;
1165 if ( face
->accel
.constantWidth
)
1166 root
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
1168 if ( ( error
= pcf_interpret_style( face
) ) != 0 )
1171 prop
= pcf_find_property( face
, "FAMILY_NAME" );
1172 if ( prop
&& prop
->isString
)
1174 if ( FT_STRDUP( root
->family_name
, prop
->value
.atom
) )
1178 root
->family_name
= NULL
;
1181 * Note: We shift all glyph indices by +1 since we must
1182 * respect the convention that glyph 0 always corresponds
1183 * to the `missing glyph'.
1185 * This implies bumping the number of `available' glyphs by 1.
1187 root
->num_glyphs
= face
->nmetrics
+ 1;
1189 root
->num_fixed_sizes
= 1;
1190 if ( FT_NEW_ARRAY( root
->available_sizes
, 1 ) )
1194 FT_Bitmap_Size
* bsize
= root
->available_sizes
;
1195 FT_Short resolution_x
= 0, resolution_y
= 0;
1198 FT_MEM_ZERO( bsize
, sizeof ( FT_Bitmap_Size
) );
1201 bsize
->height
= face
->accel
.maxbounds
.ascent
<< 6;
1203 bsize
->height
= (FT_Short
)( face
->accel
.fontAscent
+
1204 face
->accel
.fontDescent
);
1206 prop
= pcf_find_property( face
, "AVERAGE_WIDTH" );
1208 bsize
->width
= (FT_Short
)( ( prop
->value
.l
+ 5 ) / 10 );
1210 bsize
->width
= (FT_Short
)( bsize
->height
* 2/3 );
1212 prop
= pcf_find_property( face
, "POINT_SIZE" );
1214 /* convert from 722.7 decipoints to 72 points per inch */
1216 (FT_Pos
)( ( prop
->value
.l
* 64 * 7200 + 36135L ) / 72270L );
1218 prop
= pcf_find_property( face
, "PIXEL_SIZE" );
1220 bsize
->y_ppem
= (FT_Short
)prop
->value
.l
<< 6;
1222 prop
= pcf_find_property( face
, "RESOLUTION_X" );
1224 resolution_x
= (FT_Short
)prop
->value
.l
;
1226 prop
= pcf_find_property( face
, "RESOLUTION_Y" );
1228 resolution_y
= (FT_Short
)prop
->value
.l
;
1230 if ( bsize
->y_ppem
== 0 )
1232 bsize
->y_ppem
= bsize
->size
;
1234 bsize
->y_ppem
= bsize
->y_ppem
* resolution_y
/ 72;
1236 if ( resolution_x
&& resolution_y
)
1237 bsize
->x_ppem
= bsize
->y_ppem
* resolution_x
/ resolution_y
;
1239 bsize
->x_ppem
= bsize
->y_ppem
;
1242 /* set up charset */
1244 PCF_Property charset_registry
= 0, charset_encoding
= 0;
1247 charset_registry
= pcf_find_property( face
, "CHARSET_REGISTRY" );
1248 charset_encoding
= pcf_find_property( face
, "CHARSET_ENCODING" );
1250 if ( charset_registry
&& charset_registry
->isString
&&
1251 charset_encoding
&& charset_encoding
->isString
)
1253 if ( FT_STRDUP( face
->charset_encoding
,
1254 charset_encoding
->value
.atom
) ||
1255 FT_STRDUP( face
->charset_registry
,
1256 charset_registry
->value
.atom
) )
1265 /* This is done to respect the behaviour of the original */
1266 /* PCF font driver. */
1267 error
= PCF_Err_Invalid_File_Format
;