3 FreeType font driver for pcf fonts
5 Copyright 2000-2010, 2012, 2013 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 FT_THROW( Cannot_Open_Resource
);
103 if ( toc
->version
!= PCF_FILE_VERSION
||
104 toc
->count
> FT_ARRAY_MAX( face
->toc
.tables
) ||
106 return FT_THROW( Invalid_File_Format
);
108 if ( FT_NEW_ARRAY( face
->toc
.tables
, toc
->count
) )
109 return FT_THROW( 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 FT_THROW( 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
= FT_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
= FT_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
= FT_THROW( Invalid_Stream_Skip
);
310 if ( FT_STREAM_SKIP( tables
[i
].offset
- stream
->pos
) )
312 error
= FT_THROW( 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
= NULL
;
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
= FT_THROW( 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
= FT_THROW( 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
= FT_THROW( Invalid_Table
);
498 /* allocate one more byte so that we have a final null byte */
499 if ( FT_NEW_ARRAY( strings
, string_size
+ 1 ) )
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
= FT_THROW( 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
= FT_THROW( 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
,
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 FT_THROW( 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 FT_THROW( Invalid_File_Format
);
609 face
->nmetrics
= nmetrics
;
612 return FT_THROW( 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 FT_THROW( Invalid_Table
);
626 if ( nmetrics
> size
/ PCF_COMPRESSED_METRIC_SIZE
)
627 return FT_THROW( Invalid_Table
);
630 if ( FT_NEW_ARRAY( face
->metrics
, nmetrics
) )
631 return FT_THROW( 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
,
667 FT_Memory memory
= FT_FACE( face
)->memory
;
668 FT_Long
* offsets
= NULL
;
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 FT_THROW( 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 FT_THROW( 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
,
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 encoding
= NULL
;
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 FT_THROW( 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( encoding
, nencoding
) )
823 return FT_THROW( Out_Of_Memory
);
825 error
= FT_Stream_EnterFrame( stream
, 2 * nencoding
);
830 for ( i
= firstRow
; i
<= lastRow
; i
++ )
832 for ( j
= firstCol
; j
<= lastCol
; j
++ )
834 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
835 encodingOffset
= FT_GET_SHORT();
837 encodingOffset
= FT_GET_SHORT_LE();
839 if ( encodingOffset
!= -1 )
841 encoding
[k
].enc
= i
* 256 + j
;
842 encoding
[k
].glyph
= (FT_Short
)encodingOffset
;
844 FT_TRACE5(( " code %d (0x%04X): idx %d\n",
845 encoding
[k
].enc
, encoding
[k
].enc
, encoding
[k
].glyph
));
851 FT_Stream_ExitFrame( stream
);
853 if ( FT_RENEW_ARRAY( encoding
, nencoding
, k
) )
856 face
->nencodings
= k
;
857 face
->encodings
= encoding
;
868 const FT_Frame_Field pcf_accel_header
[] =
871 #define FT_STRUCTURE PCF_AccelRec
873 FT_FRAME_START( 20 ),
874 FT_FRAME_BYTE ( noOverlap
),
875 FT_FRAME_BYTE ( constantMetrics
),
876 FT_FRAME_BYTE ( terminalFont
),
877 FT_FRAME_BYTE ( constantWidth
),
878 FT_FRAME_BYTE ( inkInside
),
879 FT_FRAME_BYTE ( inkMetrics
),
880 FT_FRAME_BYTE ( drawDirection
),
881 FT_FRAME_SKIP_BYTES( 1 ),
882 FT_FRAME_LONG_LE ( fontAscent
),
883 FT_FRAME_LONG_LE ( fontDescent
),
884 FT_FRAME_LONG_LE ( maxOverlap
),
890 const FT_Frame_Field pcf_accel_msb_header
[] =
893 #define FT_STRUCTURE PCF_AccelRec
895 FT_FRAME_START( 20 ),
896 FT_FRAME_BYTE ( noOverlap
),
897 FT_FRAME_BYTE ( constantMetrics
),
898 FT_FRAME_BYTE ( terminalFont
),
899 FT_FRAME_BYTE ( constantWidth
),
900 FT_FRAME_BYTE ( inkInside
),
901 FT_FRAME_BYTE ( inkMetrics
),
902 FT_FRAME_BYTE ( drawDirection
),
903 FT_FRAME_SKIP_BYTES( 1 ),
904 FT_FRAME_LONG ( fontAscent
),
905 FT_FRAME_LONG ( fontDescent
),
906 FT_FRAME_LONG ( maxOverlap
),
912 pcf_get_accel( FT_Stream stream
,
916 FT_ULong format
, size
;
918 PCF_Accel accel
= &face
->accel
;
921 error
= pcf_seek_to_table_type( stream
,
930 if ( FT_READ_ULONG_LE( format
) )
933 if ( !PCF_FORMAT_MATCH( format
, PCF_DEFAULT_FORMAT
) &&
934 !PCF_FORMAT_MATCH( format
, PCF_ACCEL_W_INKBOUNDS
) )
937 if ( PCF_BYTE_ORDER( format
) == MSBFirst
)
939 if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header
, accel
) )
944 if ( FT_STREAM_READ_FIELDS( pcf_accel_header
, accel
) )
948 error
= pcf_get_metric( stream
,
949 format
& ( ~PCF_FORMAT_MASK
),
950 &(accel
->minbounds
) );
954 error
= pcf_get_metric( stream
,
955 format
& ( ~PCF_FORMAT_MASK
),
956 &(accel
->maxbounds
) );
960 if ( PCF_FORMAT_MATCH( format
, PCF_ACCEL_W_INKBOUNDS
) )
962 error
= pcf_get_metric( stream
,
963 format
& ( ~PCF_FORMAT_MASK
),
964 &(accel
->ink_minbounds
) );
968 error
= pcf_get_metric( stream
,
969 format
& ( ~PCF_FORMAT_MASK
),
970 &(accel
->ink_maxbounds
) );
976 accel
->ink_minbounds
= accel
->minbounds
; /* I'm not sure about this */
977 accel
->ink_maxbounds
= accel
->maxbounds
;
986 pcf_interpret_style( PCF_Face pcf
)
988 FT_Error error
= FT_Err_Ok
;
989 FT_Face face
= FT_FACE( pcf
);
990 FT_Memory memory
= face
->memory
;
995 char* strings
[4] = { NULL
, NULL
, NULL
, NULL
};
999 face
->style_flags
= 0;
1001 prop
= pcf_find_property( pcf
, "SLANT" );
1002 if ( prop
&& prop
->isString
&&
1003 ( *(prop
->value
.atom
) == 'O' || *(prop
->value
.atom
) == 'o' ||
1004 *(prop
->value
.atom
) == 'I' || *(prop
->value
.atom
) == 'i' ) )
1006 face
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
1007 strings
[2] = ( *(prop
->value
.atom
) == 'O' ||
1008 *(prop
->value
.atom
) == 'o' ) ? (char *)"Oblique"
1012 prop
= pcf_find_property( pcf
, "WEIGHT_NAME" );
1013 if ( prop
&& prop
->isString
&&
1014 ( *(prop
->value
.atom
) == 'B' || *(prop
->value
.atom
) == 'b' ) )
1016 face
->style_flags
|= FT_STYLE_FLAG_BOLD
;
1017 strings
[1] = (char*)"Bold";
1020 prop
= pcf_find_property( pcf
, "SETWIDTH_NAME" );
1021 if ( prop
&& prop
->isString
&&
1022 *(prop
->value
.atom
) &&
1023 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
1024 strings
[3] = (char*)( prop
->value
.atom
);
1026 prop
= pcf_find_property( pcf
, "ADD_STYLE_NAME" );
1027 if ( prop
&& prop
->isString
&&
1028 *(prop
->value
.atom
) &&
1029 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
1030 strings
[0] = (char*)( prop
->value
.atom
);
1032 for ( len
= 0, nn
= 0; nn
< 4; nn
++ )
1037 lengths
[nn
] = ft_strlen( strings
[nn
] );
1038 len
+= lengths
[nn
] + 1;
1044 strings
[0] = (char*)"Regular";
1045 lengths
[0] = ft_strlen( strings
[0] );
1046 len
= lengths
[0] + 1;
1053 if ( FT_ALLOC( face
->style_name
, len
) )
1056 s
= face
->style_name
;
1058 for ( nn
= 0; nn
< 4; nn
++ )
1060 char* src
= strings
[nn
];
1068 /* separate elements with a space */
1069 if ( s
!= face
->style_name
)
1072 ft_memcpy( s
, src
, len
);
1074 /* need to convert spaces to dashes for */
1075 /* add_style_name and setwidth_name */
1076 if ( nn
== 0 || nn
== 3 )
1081 for ( mm
= 0; mm
< len
; mm
++ )
1095 FT_LOCAL_DEF( FT_Error
)
1096 pcf_load_font( FT_Stream stream
,
1099 FT_Error error
= FT_Err_Ok
;
1100 FT_Memory memory
= FT_FACE( face
)->memory
;
1101 FT_Bool hasBDFAccelerators
;
1104 error
= pcf_read_TOC( stream
, face
);
1108 error
= pcf_get_properties( stream
, face
);
1112 /* Use the old accelerators if no BDF accelerators are in the file. */
1113 hasBDFAccelerators
= pcf_has_table_type( face
->toc
.tables
,
1115 PCF_BDF_ACCELERATORS
);
1116 if ( !hasBDFAccelerators
)
1118 error
= pcf_get_accel( stream
, face
, PCF_ACCELERATORS
);
1124 error
= pcf_get_metrics( stream
, face
);
1129 error
= pcf_get_bitmaps( stream
, face
);
1134 error
= pcf_get_encodings( stream
, face
);
1138 /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
1139 if ( hasBDFAccelerators
)
1141 error
= pcf_get_accel( stream
, face
, PCF_BDF_ACCELERATORS
);
1146 /* XXX: TO DO: inkmetrics and glyph_names are missing */
1148 /* now construct the face object */
1150 FT_Face root
= FT_FACE( face
);
1154 root
->num_faces
= 1;
1155 root
->face_index
= 0;
1156 root
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
1157 FT_FACE_FLAG_HORIZONTAL
|
1158 FT_FACE_FLAG_FAST_GLYPHS
;
1160 if ( face
->accel
.constantWidth
)
1161 root
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
1163 if ( ( error
= pcf_interpret_style( face
) ) != 0 )
1166 prop
= pcf_find_property( face
, "FAMILY_NAME" );
1167 if ( prop
&& prop
->isString
)
1169 if ( FT_STRDUP( root
->family_name
, prop
->value
.atom
) )
1173 root
->family_name
= NULL
;
1176 * Note: We shift all glyph indices by +1 since we must
1177 * respect the convention that glyph 0 always corresponds
1178 * to the `missing glyph'.
1180 * This implies bumping the number of `available' glyphs by 1.
1182 root
->num_glyphs
= face
->nmetrics
+ 1;
1184 root
->num_fixed_sizes
= 1;
1185 if ( FT_NEW_ARRAY( root
->available_sizes
, 1 ) )
1189 FT_Bitmap_Size
* bsize
= root
->available_sizes
;
1190 FT_Short resolution_x
= 0, resolution_y
= 0;
1193 FT_MEM_ZERO( bsize
, sizeof ( FT_Bitmap_Size
) );
1196 bsize
->height
= face
->accel
.maxbounds
.ascent
<< 6;
1198 bsize
->height
= (FT_Short
)( face
->accel
.fontAscent
+
1199 face
->accel
.fontDescent
);
1201 prop
= pcf_find_property( face
, "AVERAGE_WIDTH" );
1203 bsize
->width
= (FT_Short
)( ( prop
->value
.l
+ 5 ) / 10 );
1205 bsize
->width
= (FT_Short
)( bsize
->height
* 2/3 );
1207 prop
= pcf_find_property( face
, "POINT_SIZE" );
1209 /* convert from 722.7 decipoints to 72 points per inch */
1211 (FT_Pos
)( ( prop
->value
.l
* 64 * 7200 + 36135L ) / 72270L );
1213 prop
= pcf_find_property( face
, "PIXEL_SIZE" );
1215 bsize
->y_ppem
= (FT_Short
)prop
->value
.l
<< 6;
1217 prop
= pcf_find_property( face
, "RESOLUTION_X" );
1219 resolution_x
= (FT_Short
)prop
->value
.l
;
1221 prop
= pcf_find_property( face
, "RESOLUTION_Y" );
1223 resolution_y
= (FT_Short
)prop
->value
.l
;
1225 if ( bsize
->y_ppem
== 0 )
1227 bsize
->y_ppem
= bsize
->size
;
1229 bsize
->y_ppem
= bsize
->y_ppem
* resolution_y
/ 72;
1231 if ( resolution_x
&& resolution_y
)
1232 bsize
->x_ppem
= bsize
->y_ppem
* resolution_x
/ resolution_y
;
1234 bsize
->x_ppem
= bsize
->y_ppem
;
1237 /* set up charset */
1239 PCF_Property charset_registry
= 0, charset_encoding
= 0;
1242 charset_registry
= pcf_find_property( face
, "CHARSET_REGISTRY" );
1243 charset_encoding
= pcf_find_property( face
, "CHARSET_ENCODING" );
1245 if ( charset_registry
&& charset_registry
->isString
&&
1246 charset_encoding
&& charset_encoding
->isString
)
1248 if ( FT_STRDUP( face
->charset_encoding
,
1249 charset_encoding
->value
.atom
) ||
1250 FT_STRDUP( face
->charset_registry
,
1251 charset_registry
->value
.atom
) )
1260 /* This is done to respect the behaviour of the original */
1261 /* PCF font driver. */
1262 error
= FT_THROW( Invalid_File_Format
);