51#define FT_COMPONENT bdflib
63 static const bdf_property_t bdf_properties_[] =
65 {
"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } },
66 {
"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
67 {
"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
68 {
"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
69 {
"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
70 {
"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } },
71 {
"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } },
72 {
"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } },
73 {
"COPYRIGHT", BDF_ATOM, 1, { 0 } },
74 {
"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } },
75 {
"DESTINATION", BDF_CARDINAL, 1, { 0 } },
76 {
"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } },
77 {
"END_SPACE", BDF_INTEGER, 1, { 0 } },
78 {
"FACE_NAME", BDF_ATOM, 1, { 0 } },
79 {
"FAMILY_NAME", BDF_ATOM, 1, { 0 } },
80 {
"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
81 {
"FONT", BDF_ATOM, 1, { 0 } },
82 {
"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } },
83 {
"FONT_ASCENT", BDF_INTEGER, 1, { 0 } },
84 {
"FONT_DESCENT", BDF_INTEGER, 1, { 0 } },
85 {
"FOUNDRY", BDF_ATOM, 1, { 0 } },
86 {
"FULL_NAME", BDF_ATOM, 1, { 0 } },
87 {
"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } },
88 {
"MAX_SPACE", BDF_INTEGER, 1, { 0 } },
89 {
"MIN_SPACE", BDF_INTEGER, 1, { 0 } },
90 {
"NORM_SPACE", BDF_INTEGER, 1, { 0 } },
91 {
"NOTICE", BDF_ATOM, 1, { 0 } },
92 {
"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
93 {
"POINT_SIZE", BDF_INTEGER, 1, { 0 } },
94 {
"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
95 {
"RAW_ASCENT", BDF_INTEGER, 1, { 0 } },
96 {
"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
97 {
"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
98 {
"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
99 {
"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
100 {
"RAW_DESCENT", BDF_INTEGER, 1, { 0 } },
101 {
"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } },
102 {
"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
103 {
"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } },
104 {
"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } },
105 {
"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } },
106 {
"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
107 {
"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } },
108 {
"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } },
109 {
"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } },
110 {
"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
111 {
"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
112 {
"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
113 {
"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
114 {
"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
115 {
"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
116 {
"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
117 {
"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
118 {
"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
119 {
"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
120 {
"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
121 {
"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
122 {
"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } },
123 {
"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } },
124 {
"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } },
125 {
"RESOLUTION", BDF_INTEGER, 1, { 0 } },
126 {
"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } },
127 {
"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } },
128 {
"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } },
129 {
"SLANT", BDF_ATOM, 1, { 0 } },
130 {
"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
131 {
"SPACING", BDF_ATOM, 1, { 0 } },
132 {
"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
133 {
"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
134 {
"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
135 {
"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
136 {
"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
137 {
"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
138 {
"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
139 {
"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
140 {
"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
141 {
"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
142 {
"WEIGHT", BDF_CARDINAL, 1, { 0 } },
143 {
"WEIGHT_NAME", BDF_ATOM, 1, { 0 } },
144 {
"X_HEIGHT", BDF_INTEGER, 1, { 0 } },
145 {
"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } },
146 {
"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } },
149 static const unsigned long
150 num_bdf_properties_ =
sizeof ( bdf_properties_ ) /
151 sizeof ( bdf_properties_[0] );
154#define ACMSG1 "FONT_ASCENT property missing. " \
155 "Added `FONT_ASCENT %hd'.\n"
156#define ACMSG2 "FONT_DESCENT property missing. " \
157 "Added `FONT_DESCENT %hd'.\n"
158#define ACMSG3 "Font width != actual width. Old: %d New: %d.\n"
159#define ACMSG4 "Font left bearing != actual left bearing. " \
160 "Old: %hd New: %hd.\n"
161#define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n"
162#define ACMSG6 "Font descent != actual descent. Old: %d New: %d.\n"
163#define ACMSG7 "Font height != actual height. Old: %d New: %d.\n"
164#define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n"
165#define ACMSG9 "SWIDTH field missing at line %lu. Set automatically.\n"
166#define ACMSG10 "DWIDTH field missing at line %lu. Set to glyph width.\n"
167#define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"
168#define ACMSG13 "Glyph %lu extra rows removed.\n"
169#define ACMSG14 "Glyph %lu extra columns removed.\n"
170#define ACMSG15 "Incorrect glyph count: %lu indicated but %lu found.\n"
171#define ACMSG16 "Glyph %lu missing columns padded with zero bits.\n"
172#define ACMSG17 "Adjusting number of glyphs to %lu.\n"
175#define ERRMSG1 "[line %lu] Missing `%s' line.\n"
176#define ERRMSG2 "[line %lu] Font header corrupted or missing fields.\n"
177#define ERRMSG3 "[line %lu] Font glyphs corrupted or missing fields.\n"
178#define ERRMSG4 "[line %lu] BBX too big.\n"
179#define ERRMSG5 "[line %lu] `%s' value too big.\n"
180#define ERRMSG6 "[line %lu] Input line too long.\n"
181#define ERRMSG7 "[line %lu] Font name too long.\n"
182#define ERRMSG8 "[line %lu] Invalid `%s' value.\n"
183#define ERRMSG9 "[line %lu] Invalid keyword.\n"
186#define DBGMSG1 " [%6lu] %s"
187#define DBGMSG2 " (0x%lX)\n"
228 (*bdf_line_func_t_)(
char* line,
229 unsigned long linelen,
230 unsigned long lineno,
235#define setsbit( m, cc ) \
236 ( m[(FT_Byte)(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )
237#define sbitset( m, cc ) \
238 ( m[(FT_Byte)(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )
242 bdf_strtok_(
char* line,
245 while ( *line && *line != delim )
251 while ( *line && *line == delim )
260 static const unsigned char a2i[128] =
262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
269 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
280 static const unsigned char ddigits[32] =
282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 bdf_atoul_(
const char* s )
296 for ( v = 0; sbitset( ddigits, *s ); s++ )
298 if ( v < ( FT_ULONG_MAX - 9 ) / 10 )
299 v = v * 10 + a2i[(int)*s];
313 bdf_atol_(
const char* s )
327 for ( v = 0; sbitset( ddigits, *s ); s++ )
329 if ( v < ( FT_LONG_MAX - 9 ) / 10 )
330 v = v * 10 + a2i[(int)*s];
343 static unsigned short
344 bdf_atous_(
const char* s )
349 for ( v = 0; sbitset( ddigits, *s ); s++ )
351 if ( v < ( FT_USHORT_MAX - 9 ) / 10 )
352 v = (
unsigned short)( v * 10 + a2i[(
int)*s] );
366 bdf_atos_(
const char* s )
380 for ( v = 0; sbitset( ddigits, *s ); s++ )
382 if ( v < ( SHRT_MAX - 9 ) / 10 )
383 v = (short)( v * 10 + a2i[(
int)*s] );
396 FT_COMPARE_DEF(
int )
397 by_encoding(
const void* a,
400 bdf_glyph_t *c1, *c2;
403 c1 = (bdf_glyph_t *)a;
404 c2 = (bdf_glyph_t *)b;
406 if ( c1->encoding < c2->encoding )
409 if ( c1->encoding > c2->encoding )
417 bdf_create_property(
const char* name,
423 FT_Memory memory = font->memory;
424 FT_Error error = FT_Err_Ok;
430 if ( ft_hash_str_lookup( name, &(font->proptbl) ) )
433 if ( FT_QRENEW_ARRAY( font->user_props,
435 font->nuser_props + 1 ) )
438 p = font->user_props + font->nuser_props;
440 if ( FT_STRDUP( p->name, name ) )
445 p->value.atom = NULL;
447 n = num_bdf_properties_ + font->nuser_props;
449 error = ft_hash_str_insert( p->name, n, &(font->proptbl), memory );
460 static bdf_property_t*
461 bdf_get_property(
const char* name,
467 if ( name == NULL || *name == 0 )
470 if ( ( propid = ft_hash_str_lookup( name, &(font->proptbl) ) ) == NULL )
473 if ( *propid >= num_bdf_properties_ )
474 return font->user_props + ( *propid - num_bdf_properties_ );
476 return (bdf_property_t*)bdf_properties_ + *propid;
489#define BDF_START_ 0x0001U
490#define BDF_FONT_NAME_ 0x0002U
491#define BDF_SIZE_ 0x0004U
492#define BDF_FONT_BBX_ 0x0008U
493#define BDF_PROPS_ 0x0010U
494#define BDF_GLYPHS_ 0x0020U
495#define BDF_GLYPH_ 0x0040U
496#define BDF_ENCODING_ 0x0080U
497#define BDF_SWIDTH_ 0x0100U
498#define BDF_DWIDTH_ 0x0200U
499#define BDF_BBX_ 0x0400U
500#define BDF_BITMAP_ 0x0800U
502#define BDF_GLYPH_BITS_ ( BDF_GLYPH_ | \
511 bdf_add_comment_( bdf_font_t* font,
516 FT_Memory memory = font->memory;
517 FT_Error error = FT_Err_Ok;
527 if ( FT_QRENEW_ARRAY( font->comments,
529 font->comments_len + len + 1 ) )
532 cp = font->comments + font->comments_len;
534 FT_MEM_COPY( cp, comment, len );
537 font->comments_len += len + 1;
547 bdf_is_atom_(
char* line,
548 unsigned long linelen,
560 while ( *ep && *ep !=
' ' )
566 p = bdf_get_property( sp, font );
569 if ( p && p->format != BDF_ATOM )
586 while ( *sp ==
' ' );
598 while ( *ep ==
' ' );
609 bdf_add_property_( bdf_font_t* font,
612 unsigned long lineno )
615 bdf_property_t *prop, *fp;
616 FT_Memory memory = font->memory;
617 FT_Error error = FT_Err_Ok;
623 if ( ( propid = ft_hash_str_lookup( name, font->internal ) ) != NULL )
627 fp = font->props + *propid;
629 switch ( fp->format )
633 FT_FREE( fp->value.atom );
635 if ( value && value[0] != 0 )
637 if ( FT_STRDUP( fp->value.atom, value ) )
643 fp->value.l = bdf_atol_( value );
647 fp->value.ul = bdf_atoul_( value );
659 propid = ft_hash_str_lookup( name, &(font->proptbl) );
662 error = bdf_create_property( name, BDF_ATOM, font );
665 propid = ft_hash_str_lookup( name, &(font->proptbl) );
669 if ( font->props_used == font->props_size )
671 if ( FT_QRENEW_ARRAY( font->props,
673 font->props_size + 1 ) )
679 if ( *propid >= num_bdf_properties_ )
680 prop = font->user_props + ( *propid - num_bdf_properties_ );
682 prop = (bdf_property_t*)bdf_properties_ + *propid;
684 fp = font->props + font->props_used;
686 fp->name = prop->name;
687 fp->format = prop->format;
688 fp->builtin = prop->builtin;
690 switch ( prop->format )
693 fp->value.atom = NULL;
694 if ( value && value[0] )
696 if ( FT_STRDUP( fp->value.atom, value ) )
702 fp->value.l = bdf_atol_( value );
706 fp->value.ul = bdf_atoul_( value );
711 error = ft_hash_str_insert( fp->name,
726 bdf_parse_end_(
char* line,
727 unsigned long linelen,
728 unsigned long lineno,
735 FT_UNUSED( linelen );
746 bdf_parse_start_(
char* line,
747 unsigned long linelen,
748 unsigned long lineno,
754 bdf_parse_glyphs_(
char* line,
755 unsigned long linelen,
756 unsigned long lineno,
763 bdf_parse_bitmap_(
char* line,
764 unsigned long linelen,
765 unsigned long lineno,
769 bdf_glyph_t* glyph = p->glyph;
771 unsigned long i, nibbles;
777 nibbles = glyph->bpr << 1;
778 bp = glyph->bitmap + p->row * glyph->bpr;
780 if ( nibbles > linelen )
782 FT_TRACE2((
"bdf_parse_bitmap_: " ACMSG16, glyph->encoding ));
786 for ( i = 0; i < nibbles; i++ )
790 x += 9 * ( x & 0x40 ) >> 6;
796 *bp = (
unsigned char)( x << 4 );
802 if ( p->row >= (
unsigned long)glyph->bbx.height )
803 *(bdf_line_func_t_*)next = bdf_parse_glyphs_;
811 bdf_parse_glyphs_(
char* line,
812 unsigned long linelen,
813 unsigned long lineno,
817 bdf_font_t* font = p->font;
819 FT_Memory memory = font->memory;
820 FT_Error error = FT_Err_Ok;
826 if ( ft_strncmp( line,
"COMMENT", 7 ) == 0 )
828 if ( p->flags & BDF_KEEP_COMMENTS )
829 error = bdf_add_comment_( font, line, linelen );
835 if ( ft_strncmp( line,
"ENDFONT", 7 ) == 0 )
837 if ( p->flags & BDF_GLYPH_BITS_ )
840 FT_ERROR((
"bdf_parse_glyphs_: " ERRMSG1, lineno,
"ENDCHAR" ));
841 error = FT_THROW( Corrupted_Font_Glyphs );
846 ft_qsort( (
char *)font->glyphs,
848 sizeof ( bdf_glyph_t ),
851 p->flags &= ~BDF_START_;
853 *(bdf_line_func_t_*)next = bdf_parse_end_;
859 if ( ft_strncmp( line,
"ENDCHAR", 7 ) == 0 )
862 FT_FREE( p->glyph_name );
865 p->flags &= ~BDF_GLYPH_BITS_;
872 if ( p->flags & BDF_GLYPH_ &&
873 p->glyph_enc == -1 &&
874 !( p->flags & BDF_KEEP_UNENCODED ) )
878 if ( ft_strncmp( line,
"STARTCHAR ", 10 ) == 0 )
880 if ( p->flags & BDF_GLYPH_BITS_ )
883 FT_ERROR((
"bdf_parse_glyphs_: " ERRMSG1, lineno,
"ENDCHAR" ));
884 error = FT_THROW( Missing_Startchar_Field );
888 line = bdf_strtok_( line,
' ' );
890 if ( FT_STRDUP( p->glyph_name, line ) )
893 p->flags |= BDF_GLYPH_;
895 FT_TRACE4(( DBGMSG1, lineno, line ));
901 if ( ft_strncmp( line,
"ENCODING ", 9 ) == 0 )
903 if ( !( p->flags & BDF_GLYPH_ ) )
906 FT_ERROR((
"bdf_parse_glyphs_: " ERRMSG1, lineno,
"STARTCHAR" ));
907 error = FT_THROW( Missing_Startchar_Field );
911 line = bdf_strtok_( line,
' ' );
913 p->glyph_enc = bdf_atol_( line );
917 if ( p->glyph_enc < -1 )
921 line = bdf_strtok_( line,
' ' );
923 if ( p->glyph_enc == -1 && *line )
924 p->glyph_enc = bdf_atol_( line );
926 if ( p->glyph_enc < -1 || p->glyph_enc >= 0x110000L )
929 FT_TRACE4(( DBGMSG2, p->glyph_enc ));
931 if ( p->glyph_enc >= 0 )
935 if ( font->glyphs_used == font->glyphs_size )
937 if ( FT_RENEW_ARRAY( font->glyphs,
939 font->glyphs_size + 64 ) )
942 font->glyphs_size += 64;
945 glyph = font->glyphs + font->glyphs_used++;
946 glyph->name = p->glyph_name;
947 glyph->encoding = (
unsigned long)p->glyph_enc;
949 else if ( p->flags & BDF_KEEP_UNENCODED )
952 if ( font->unencoded_used == font->unencoded_size )
954 if ( FT_RENEW_ARRAY( font->unencoded ,
955 font->unencoded_size,
956 font->unencoded_size + 4 ) )
959 font->unencoded_size += 4;
962 glyph = font->unencoded + font->unencoded_used;
963 glyph->name = p->glyph_name;
964 glyph->encoding = font->unencoded_used++;
970 FT_FREE( p->glyph_name );
974 p->glyph_name = NULL;
976 p->flags |= BDF_ENCODING_;
981 if ( !( p->flags & BDF_ENCODING_ ) )
982 goto Missing_Encoding;
988 if ( ft_strncmp( line,
"SWIDTH ", 7 ) == 0 )
990 line = bdf_strtok_( line,
' ' );
991 glyph->swidth = bdf_atous_( line );
993 p->flags |= BDF_SWIDTH_;
998 if ( ft_strncmp( line,
"DWIDTH ", 7 ) == 0 )
1000 line = bdf_strtok_( line,
' ' );
1001 glyph->dwidth = bdf_atous_( line );
1003 if ( !( p->flags & BDF_SWIDTH_ ) )
1007 FT_TRACE2((
"bdf_parse_glyphs_: " ACMSG9, lineno ));
1009 glyph->swidth = (
unsigned short)FT_MulDiv(
1010 glyph->dwidth, 72000L,
1011 (FT_Long)( font->point_size *
1012 font->resolution_x ) );
1015 p->flags |= BDF_DWIDTH_;
1020 if ( p->flags & BDF_BITMAP_ )
1024 if ( ft_strncmp( line,
"BBX ", 4 ) == 0 )
1026 line = bdf_strtok_( line,
' ' );
1027 glyph->bbx.width = bdf_atous_( line );
1028 line = bdf_strtok_( line,
' ' );
1029 glyph->bbx.height = bdf_atous_( line );
1030 line = bdf_strtok_( line,
' ' );
1031 glyph->bbx.x_offset = bdf_atos_( line );
1032 line = bdf_strtok_( line,
' ' );
1033 glyph->bbx.y_offset = bdf_atos_( line );
1036 glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset );
1037 glyph->bbx.descent = (short)( -glyph->bbx.y_offset );
1041 p->maxas = (short)FT_MAX( glyph->bbx.ascent, p->maxas );
1042 p->maxds = (short)FT_MAX( glyph->bbx.descent, p->maxds );
1044 p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );
1046 p->maxrb = (short)FT_MAX( p->rbearing, p->maxrb );
1047 p->minlb = (short)FT_MIN( glyph->bbx.x_offset, p->minlb );
1048 p->maxlb = (short)FT_MAX( glyph->bbx.x_offset, p->maxlb );
1050 if ( !( p->flags & BDF_DWIDTH_ ) )
1054 FT_TRACE2((
"bdf_parse_glyphs_: " ACMSG10, lineno ));
1055 glyph->dwidth = glyph->bbx.width;
1060 if ( p->flags & BDF_CORRECT_METRICS )
1063 unsigned short sw = (
unsigned short)FT_MulDiv(
1064 glyph->dwidth, 72000L,
1065 (FT_Long)( font->point_size *
1066 font->resolution_x ) );
1069 if ( sw != glyph->swidth )
1073 FT_TRACE2((
"bdf_parse_glyphs_: " ACMSG8 ));
1077 p->flags |= BDF_BBX_;
1082 if ( ft_strncmp( line,
"BITMAP", 6 ) == 0 )
1084 unsigned long bitmap_size;
1087 if ( !( p->flags & BDF_BBX_ ) )
1090 FT_ERROR((
"bdf_parse_glyphs_: " ERRMSG1, lineno,
"BBX" ));
1091 error = FT_THROW( Missing_Bbx_Field );
1096 glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3;
1098 bitmap_size = glyph->bpr * glyph->bbx.height;
1099 if ( glyph->bpr > 0xFFFFU || bitmap_size > 0xFFFFU )
1101 FT_ERROR((
"bdf_parse_glyphs_: " ERRMSG4, lineno ));
1102 error = FT_THROW( Bbx_Too_Big );
1106 glyph->bytes = (
unsigned short)bitmap_size;
1108 if ( !bitmap_size || FT_ALLOC( glyph->bitmap, glyph->bytes ) )
1112 p->flags |= BDF_BITMAP_;
1113 *(bdf_line_func_t_*)next = bdf_parse_bitmap_;
1118 FT_ERROR((
"bdf_parse_glyphs_: " ERRMSG9, lineno ));
1119 error = FT_THROW( Invalid_File_Format );
1124 FT_ERROR((
"bdf_parse_glyphs_: " ERRMSG1, lineno,
"ENCODING" ));
1125 error = FT_THROW( Missing_Encoding_Field );
1128 if ( error && ( p->flags & BDF_GLYPH_ ) )
1129 FT_FREE( p->glyph_name );
1137 bdf_parse_properties_(
char* line,
1138 unsigned long linelen,
1139 unsigned long lineno,
1143 bdf_font_t* font = p->font;
1144 FT_Error error = FT_Err_Ok;
1148 FT_UNUSED( lineno );
1152 if ( ft_strncmp( line,
"COMMENT", 7 ) == 0 )
1154 if ( p->flags & BDF_KEEP_COMMENTS )
1155 error = bdf_add_comment_( font, line, linelen );
1161 if ( ft_strncmp( line,
"ENDPROPERTIES", 13 ) == 0 )
1163 *(bdf_line_func_t_*)next = bdf_parse_start_;
1169 if ( ft_strncmp( line,
"_XFREE86_GLYPH_RANGES", 21 ) == 0 )
1172 if ( bdf_is_atom_( line, linelen, &name, &value, p->font ) )
1174 error = bdf_add_property_( font, name, value, lineno );
1180 value = bdf_strtok_( line,
' ' );
1182 error = bdf_add_property_( font, line, value, lineno );
1194 bdf_parse_start_(
char* line,
1195 unsigned long linelen,
1196 unsigned long lineno,
1201 FT_Memory memory = p->memory;
1202 FT_Error error = FT_Err_Ok;
1204 FT_UNUSED( lineno );
1209 if ( !( p->flags & BDF_START_ ) )
1211 if ( ft_strncmp( line,
"STARTFONT", 9 ) != 0 )
1213 error = FT_THROW( Missing_Startfont_Field );
1217 p->flags |= BDF_START_;
1219 if ( FT_NEW( p->font ) )
1222 p->font->memory = memory;
1231 if ( ft_strncmp( line,
"COMMENT", 7 ) == 0 )
1233 if ( p->flags & BDF_KEEP_COMMENTS )
1234 error = bdf_add_comment_( font, line, linelen );
1240 if ( !( p->flags & BDF_PROPS_ ) &&
1241 ft_strncmp( line,
"STARTPROPERTIES ", 16 ) == 0 )
1243 line = bdf_strtok_( line,
' ' );
1244 font->props_size = bdf_atoul_( line );
1246 if ( font->props_size < 2 )
1247 font->props_size = 2;
1250 if ( font->props_size > p->size / 4 )
1252 font->props_size = 0;
1254 FT_ERROR((
"bdf_parse_start_: " ERRMSG5, lineno,
"STARTPROPERTIES" ));
1255 error = FT_THROW( Invalid_Argument );
1259 if ( FT_NEW_ARRAY( font->props, font->props_size ) )
1261 font->props_size = 0;
1265 if ( FT_QNEW( font->internal ) )
1267 error = ft_hash_str_init( font->internal, memory );
1273 bdf_property_t* prop = (bdf_property_t*)bdf_properties_;
1274 FT_Hash proptbl = &font->proptbl;
1278 error = ft_hash_str_init( proptbl, memory );
1281 for ( i = 0; i < num_bdf_properties_; i++, prop++ )
1283 error = ft_hash_str_insert( prop->name, i, proptbl, memory );
1289 p->flags |= BDF_PROPS_;
1291 *(bdf_line_func_t_*)next = bdf_parse_properties_;
1297 if ( ft_strncmp( line,
"FONTBOUNDINGBOX ", 16 ) == 0 )
1299 line = bdf_strtok_( line,
' ' );
1300 font->bbx.width = bdf_atous_( line );
1301 line = bdf_strtok_( line,
' ' );
1302 font->bbx.height = bdf_atous_( line );
1303 line = bdf_strtok_( line,
' ' );
1304 font->bbx.x_offset = bdf_atos_( line );
1305 line = bdf_strtok_( line,
' ' );
1306 font->bbx.y_offset = bdf_atos_( line );
1308 font->bbx.ascent = (short)( font->bbx.height +
1309 font->bbx.y_offset );
1311 font->bbx.descent = (short)( -font->bbx.y_offset );
1313 p->flags |= BDF_FONT_BBX_;
1319 if ( ft_strncmp( line,
"FONT ", 5 ) == 0 )
1324 line = bdf_strtok_( line,
' ' );
1327 FT_FREE( font->name );
1329 if ( FT_STRDUP( font->name, line ) )
1334 for ( i = 0; i < 11; i++ )
1336 while ( *line && *line !=
'-' )
1346 font->spacing = BDF_CHARCELL;
1350 font->spacing = BDF_MONOWIDTH;
1355 font->spacing = BDF_PROPORTIONAL;
1359 p->flags |= BDF_FONT_NAME_;
1365 if ( ft_strncmp( line,
"SIZE ", 5 ) == 0 )
1367 line = bdf_strtok_( line,
' ' );
1368 font->point_size = bdf_atoul_( line );
1369 line = bdf_strtok_( line,
' ' );
1370 font->resolution_x = bdf_atoul_( line );
1371 line = bdf_strtok_( line,
' ' );
1372 font->resolution_y = bdf_atoul_( line );
1375 line = bdf_strtok_( line,
' ' );
1381 bpp = bdf_atous_( line );
1393 if ( font->bpp != bpp )
1394 FT_TRACE2((
"bdf_parse_start_: " ACMSG11, font->bpp ));
1399 p->flags |= BDF_SIZE_;
1405 if ( ft_strncmp( line,
"CHARS ", 6 ) == 0 )
1408 if ( !( p->flags & BDF_FONT_NAME_ ) )
1411 FT_ERROR((
"bdf_parse_start_: " ERRMSG1, lineno,
"FONT" ));
1412 error = FT_THROW( Missing_Font_Field );
1415 if ( !( p->flags & BDF_SIZE_ ) )
1418 FT_ERROR((
"bdf_parse_start_: " ERRMSG1, lineno,
"SIZE" ));
1419 error = FT_THROW( Missing_Size_Field );
1422 if ( !( p->flags & BDF_FONT_BBX_ ) )
1425 FT_ERROR((
"bdf_parse_start_: " ERRMSG1, lineno,
"FONTBOUNDINGBOX" ));
1426 error = FT_THROW( Missing_Fontboundingbox_Field );
1430 line = bdf_strtok_( line,
' ' );
1431 p->cnt = font->glyphs_size = bdf_atoul_( line );
1434 if ( p->cnt > p->size / 20 )
1436 p->cnt = font->glyphs_size = p->size / 20;
1437 FT_TRACE2((
"bdf_parse_start_: " ACMSG17, p->cnt ));
1442 font->glyphs_size = 64;
1446 if ( p->cnt >= 0x110000UL )
1448 FT_ERROR((
"bdf_parse_start_: " ERRMSG5, lineno,
"CHARS" ));
1449 error = FT_THROW( Invalid_Argument );
1453 if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )
1456 p->flags |= BDF_GLYPHS_;
1458 *(bdf_line_func_t_*)next = bdf_parse_glyphs_;
1463 FT_ERROR((
"bdf_parse_start_: " ERRMSG9, lineno ));
1464 error = FT_THROW( Invalid_File_Format );
1472 bdf_readstream_( FT_Stream stream,
1474 unsigned long* lno )
1476 bdf_line_func_t_ cb = bdf_parse_start_;
1477 unsigned long lineno, buf_size;
1478 unsigned long bytes, start, end, cursor, avail;
1480 FT_Memory memory = stream->memory;
1481 FT_Error error = FT_Err_Ok;
1487 if ( FT_QALLOC( buf, buf_size ) )
1495 bytes = FT_Stream_TryRead( stream,
1496 (FT_Byte*)buf + cursor, buf_size - cursor );
1497 avail = cursor + bytes;
1502 while ( start < avail && buf[start] <
' ' )
1507 while ( end < avail && buf[end] >=
' ' )
1521 if ( buf_size >= 65536UL )
1523 FT_ERROR((
"bdf_readstream_: " ERRMSG6, lineno ));
1524 error = FT_THROW( Invalid_File_Format );
1529 new_size = buf_size * 4;
1530 if ( FT_QREALLOC( buf, buf_size, new_size ) )
1534 buf_size = new_size;
1538 cursor = avail - start;
1540 FT_MEM_MOVE( buf, buf + start, cursor );
1550 if ( buf[start] !=
'#' )
1552 error = (*cb)( buf + start, end - start, lineno, p, (
void*)&cb );
1576 FT_LOCAL_DEF( FT_Error )
1577 bdf_load_font( FT_Stream stream,
1579 unsigned long flags,
1582 unsigned long lineno = 0;
1583 bdf_parse_t_ *p = NULL;
1585 FT_Error error = FT_Err_Ok;
1593 p->size = stream->size;
1596 error = bdf_readstream_( stream, p, &lineno );
1604 if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used )
1606 FT_TRACE2((
"bdf_load_font: " ACMSG15, p->cnt,
1607 p->font->glyphs_used + p->font->unencoded_used ));
1612 if ( p->flags & BDF_CORRECT_METRICS &&
1613 ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) )
1615 if ( p->maxrb - p->minlb != p->font->bbx.width )
1617 FT_TRACE2((
"bdf_load_font: " ACMSG3,
1618 p->font->bbx.width, p->maxrb - p->minlb ));
1619 p->font->bbx.width = (
unsigned short)( p->maxrb - p->minlb );
1622 if ( p->font->bbx.x_offset != p->minlb )
1624 FT_TRACE2((
"bdf_load_font: " ACMSG4,
1625 p->font->bbx.x_offset, p->minlb ));
1626 p->font->bbx.x_offset = p->minlb;
1629 if ( p->font->bbx.ascent != p->maxas )
1631 FT_TRACE2((
"bdf_load_font: " ACMSG5,
1632 p->font->bbx.ascent, p->maxas ));
1633 p->font->bbx.ascent = p->maxas;
1636 if ( p->font->bbx.descent != p->maxds )
1638 FT_TRACE2((
"bdf_load_font: " ACMSG6,
1639 p->font->bbx.descent, p->maxds ));
1640 p->font->bbx.descent = p->maxds;
1641 p->font->bbx.y_offset = (short)( -p->maxds );
1644 if ( p->maxas + p->maxds != p->font->bbx.height )
1646 FT_TRACE2((
"bdf_load_font: " ACMSG7,
1647 p->font->bbx.height, p->maxas + p->maxds ));
1648 p->font->bbx.height = (
unsigned short)( p->maxas + p->maxds );
1653 if ( p->flags & BDF_START_ )
1656 if ( !( p->flags & BDF_GLYPHS_ ) )
1659 FT_ERROR((
"bdf_load_font: " ERRMSG2, lineno ));
1660 error = FT_THROW( Corrupted_Font_Header );
1666 FT_ERROR((
"bdf_load_font: " ERRMSG3, lineno ));
1667 error = FT_THROW( Corrupted_Font_Glyphs );
1672 if ( !p->font && !error )
1673 error = FT_THROW( Invalid_File_Format );
1680 FT_FREE( p->glyph_name );
1687 bdf_free_font( p->font );
1695 FT_LOCAL_DEF(
void )
1696 bdf_free_font( bdf_font_t* font )
1698 bdf_property_t* prop;
1700 bdf_glyph_t* glyphs;
1707 memory = font->memory;
1709 FT_FREE( font->name );
1712 if ( font->internal )
1714 ft_hash_str_free( font->internal, memory );
1715 FT_FREE( font->internal );
1719 FT_FREE( font->comments );
1722 for ( i = 0; i < font->props_size; i++ )
1724 if ( font->props[i].format == BDF_ATOM )
1725 FT_FREE( font->props[i].value.atom );
1728 FT_FREE( font->props );
1731 for ( i = 0, glyphs = font->glyphs;
1732 i < font->glyphs_used; i++, glyphs++ )
1734 FT_FREE( glyphs->name );
1735 FT_FREE( glyphs->bitmap );
1738 for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used;
1741 FT_FREE( glyphs->name );
1742 FT_FREE( glyphs->bitmap );
1745 FT_FREE( font->glyphs );
1746 FT_FREE( font->unencoded );
1749 ft_hash_str_free( &(font->proptbl), memory );
1752 for ( prop = font->user_props, i = 0;
1753 i < font->nuser_props; i++, prop++ )
1754 FT_FREE( prop->name );
1756 FT_FREE( font->user_props );
1762 FT_LOCAL_DEF( bdf_property_t * )
1763 bdf_get_font_property( bdf_font_t* font,
1769 if ( font == NULL || font->props_size == 0 || name == NULL || *name == 0 )
1772 propid = ft_hash_str_lookup( name, font->internal );
1774 return propid ? ( font->props + *propid ) : NULL;