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
;