3 FreeType font driver for bdf files
5 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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
29 #include FT_INTERNAL_DEBUG_H
30 #include FT_INTERNAL_STREAM_H
31 #include FT_INTERNAL_OBJECTS_H
34 #include FT_SERVICE_BDF_H
35 #include FT_SERVICE_XFREE86_NAME_H
43 /*************************************************************************/
45 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
46 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
47 /* messages during execution. */
50 #define FT_COMPONENT trace_bdfdriver
53 typedef struct BDF_CMapRec_
56 FT_ULong num_encodings
; /* ftobjs.h: FT_CMap->clazz->size */
57 BDF_encoding_el
* encodings
;
59 } BDF_CMapRec
, *BDF_CMap
;
62 FT_CALLBACK_DEF( FT_Error
)
63 bdf_cmap_init( FT_CMap bdfcmap
,
64 FT_Pointer init_data
)
66 BDF_CMap cmap
= (BDF_CMap
)bdfcmap
;
67 BDF_Face face
= (BDF_Face
)FT_CMAP_FACE( cmap
);
68 FT_UNUSED( init_data
);
71 cmap
->num_encodings
= face
->bdffont
->glyphs_used
;
72 cmap
->encodings
= face
->en_table
;
78 FT_CALLBACK_DEF( void )
79 bdf_cmap_done( FT_CMap bdfcmap
)
81 BDF_CMap cmap
= (BDF_CMap
)bdfcmap
;
84 cmap
->encodings
= NULL
;
85 cmap
->num_encodings
= 0;
89 FT_CALLBACK_DEF( FT_UInt
)
90 bdf_cmap_char_index( FT_CMap bdfcmap
,
93 BDF_CMap cmap
= (BDF_CMap
)bdfcmap
;
94 BDF_encoding_el
* encodings
= cmap
->encodings
;
95 FT_ULong min
, max
, mid
; /* num_encodings */
96 FT_UShort result
= 0; /* encodings->glyph */
100 max
= cmap
->num_encodings
;
107 mid
= ( min
+ max
) >> 1;
108 code
= encodings
[mid
].enc
;
110 if ( charcode
== code
)
112 /* increase glyph index by 1 -- */
113 /* we reserve slot 0 for the undefined glyph */
114 result
= encodings
[mid
].glyph
+ 1;
118 if ( charcode
< code
)
128 FT_CALLBACK_DEF( FT_UInt
)
129 bdf_cmap_char_next( FT_CMap bdfcmap
,
130 FT_UInt32
*acharcode
)
132 BDF_CMap cmap
= (BDF_CMap
)bdfcmap
;
133 BDF_encoding_el
* encodings
= cmap
->encodings
;
134 FT_ULong min
, max
, mid
; /* num_encodings */
135 FT_UShort result
= 0; /* encodings->glyph */
136 FT_ULong charcode
= *acharcode
+ 1;
140 max
= cmap
->num_encodings
;
144 FT_ULong code
; /* same as BDF_encoding_el.enc */
147 mid
= ( min
+ max
) >> 1;
148 code
= encodings
[mid
].enc
;
150 if ( charcode
== code
)
152 /* increase glyph index by 1 -- */
153 /* we reserve slot 0 for the undefined glyph */
154 result
= encodings
[mid
].glyph
+ 1;
158 if ( charcode
< code
)
165 if ( min
< cmap
->num_encodings
)
167 charcode
= encodings
[min
].enc
;
168 result
= encodings
[min
].glyph
+ 1;
172 if ( charcode
> 0xFFFFFFFFUL
)
174 FT_TRACE1(( "bdf_cmap_char_next: charcode 0x%x > 32bit API" ));
176 /* XXX: result should be changed to indicate an overflow error */
179 *acharcode
= (FT_UInt32
)charcode
;
184 FT_CALLBACK_TABLE_DEF
185 const FT_CMap_ClassRec bdf_cmap_class
=
187 sizeof ( BDF_CMapRec
),
193 NULL
, NULL
, NULL
, NULL
, NULL
198 bdf_interpret_style( BDF_Face bdf
)
200 FT_Error error
= BDF_Err_Ok
;
201 FT_Face face
= FT_FACE( bdf
);
202 FT_Memory memory
= face
->memory
;
203 bdf_font_t
* font
= bdf
->bdffont
;
204 bdf_property_t
* prop
;
206 char* strings
[4] = { NULL
, NULL
, NULL
, NULL
};
207 size_t nn
, len
, lengths
[4];
210 face
->style_flags
= 0;
212 prop
= bdf_get_font_property( font
, (char *)"SLANT" );
213 if ( prop
&& prop
->format
== BDF_ATOM
&&
215 ( *(prop
->value
.atom
) == 'O' || *(prop
->value
.atom
) == 'o' ||
216 *(prop
->value
.atom
) == 'I' || *(prop
->value
.atom
) == 'i' ) )
218 face
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
219 strings
[2] = ( *(prop
->value
.atom
) == 'O' || *(prop
->value
.atom
) == 'o' )
224 prop
= bdf_get_font_property( font
, (char *)"WEIGHT_NAME" );
225 if ( prop
&& prop
->format
== BDF_ATOM
&&
227 ( *(prop
->value
.atom
) == 'B' || *(prop
->value
.atom
) == 'b' ) )
229 face
->style_flags
|= FT_STYLE_FLAG_BOLD
;
230 strings
[1] = (char *)"Bold";
233 prop
= bdf_get_font_property( font
, (char *)"SETWIDTH_NAME" );
234 if ( prop
&& prop
->format
== BDF_ATOM
&&
235 prop
->value
.atom
&& *(prop
->value
.atom
) &&
236 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
237 strings
[3] = (char *)(prop
->value
.atom
);
239 prop
= bdf_get_font_property( font
, (char *)"ADD_STYLE_NAME" );
240 if ( prop
&& prop
->format
== BDF_ATOM
&&
241 prop
->value
.atom
&& *(prop
->value
.atom
) &&
242 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
243 strings
[0] = (char *)(prop
->value
.atom
);
247 for ( len
= 0, nn
= 0; nn
< 4; nn
++ )
252 lengths
[nn
] = ft_strlen( strings
[nn
] );
253 len
+= lengths
[nn
] + 1;
259 strings
[0] = (char *)"Regular";
260 lengths
[0] = ft_strlen( strings
[0] );
261 len
= lengths
[0] + 1;
268 if ( FT_ALLOC( face
->style_name
, len
) )
271 s
= face
->style_name
;
273 for ( nn
= 0; nn
< 4; nn
++ )
275 char* src
= strings
[nn
];
283 /* separate elements with a space */
284 if ( s
!= face
->style_name
)
287 ft_memcpy( s
, src
, len
);
289 /* need to convert spaces to dashes for */
290 /* add_style_name and setwidth_name */
291 if ( nn
== 0 || nn
== 3 )
296 for ( mm
= 0; mm
< len
; mm
++ )
310 FT_CALLBACK_DEF( void )
311 BDF_Face_Done( FT_Face bdfface
) /* BDF_Face */
313 BDF_Face face
= (BDF_Face
)bdfface
;
320 memory
= FT_FACE_MEMORY( face
);
322 bdf_free_font( face
->bdffont
);
324 FT_FREE( face
->en_table
);
326 FT_FREE( face
->charset_encoding
);
327 FT_FREE( face
->charset_registry
);
328 FT_FREE( bdfface
->family_name
);
329 FT_FREE( bdfface
->style_name
);
331 FT_FREE( bdfface
->available_sizes
);
333 FT_FREE( face
->bdffont
);
335 FT_TRACE4(( "BDF_Face_Done: done face\n" ));
339 FT_CALLBACK_DEF( FT_Error
)
340 BDF_Face_Init( FT_Stream stream
,
341 FT_Face bdfface
, /* BDF_Face */
344 FT_Parameter
* params
)
346 FT_Error error
= BDF_Err_Ok
;
347 BDF_Face face
= (BDF_Face
)bdfface
;
348 FT_Memory memory
= FT_FACE_MEMORY( face
);
350 bdf_font_t
* font
= NULL
;
351 bdf_options_t options
;
353 FT_UNUSED( num_params
);
355 FT_UNUSED( face_index
);
358 if ( FT_STREAM_SEEK( 0 ) )
361 options
.correct_metrics
= 1; /* FZ XXX: options semantics */
362 options
.keep_unencoded
= 1;
363 options
.keep_comments
= 0;
364 options
.font_spacing
= BDF_PROPORTIONAL
;
366 error
= bdf_load_font( stream
, memory
, &options
, &font
);
367 if ( error
== BDF_Err_Missing_Startfont_Field
)
369 FT_TRACE2(( "[not a valid BDF file]\n" ));
375 /* we have a bdf font: let's construct the face object */
376 face
->bdffont
= font
;
378 bdf_property_t
* prop
= NULL
;
381 FT_TRACE4(( "number of glyphs: %d (%d)\n",
383 font
->glyphs_used
));
384 FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n",
385 font
->unencoded_size
,
386 font
->unencoded_used
));
388 bdfface
->num_faces
= 1;
389 bdfface
->face_index
= 0;
390 bdfface
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
391 FT_FACE_FLAG_HORIZONTAL
|
392 FT_FACE_FLAG_FAST_GLYPHS
;
394 prop
= bdf_get_font_property( font
, "SPACING" );
395 if ( prop
&& prop
->format
== BDF_ATOM
&&
397 ( *(prop
->value
.atom
) == 'M' || *(prop
->value
.atom
) == 'm' ||
398 *(prop
->value
.atom
) == 'C' || *(prop
->value
.atom
) == 'c' ) )
399 bdfface
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
401 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
402 /* FZ XXX: I need a font to implement this */
404 prop
= bdf_get_font_property( font
, "FAMILY_NAME" );
405 if ( prop
&& prop
->value
.atom
)
407 if ( FT_STRDUP( bdfface
->family_name
, prop
->value
.atom
) )
411 bdfface
->family_name
= 0;
413 if ( ( error
= bdf_interpret_style( face
) ) != 0 )
416 /* the number of glyphs (with one slot for the undefined glyph */
417 /* at position 0 and all unencoded glyphs) */
418 bdfface
->num_glyphs
= font
->glyphs_size
+ 1;
420 bdfface
->num_fixed_sizes
= 1;
421 if ( FT_NEW_ARRAY( bdfface
->available_sizes
, 1 ) )
425 FT_Bitmap_Size
* bsize
= bdfface
->available_sizes
;
426 FT_Short resolution_x
= 0, resolution_y
= 0;
429 FT_MEM_ZERO( bsize
, sizeof ( FT_Bitmap_Size
) );
431 bsize
->height
= (FT_Short
)( font
->font_ascent
+ font
->font_descent
);
433 prop
= bdf_get_font_property( font
, "AVERAGE_WIDTH" );
435 bsize
->width
= (FT_Short
)( ( prop
->value
.l
+ 5 ) / 10 );
437 bsize
->width
= (FT_Short
)( bsize
->height
* 2/3 );
439 prop
= bdf_get_font_property( font
, "POINT_SIZE" );
441 /* convert from 722.7 decipoints to 72 points per inch */
443 (FT_Pos
)( ( prop
->value
.l
* 64 * 7200 + 36135L ) / 72270L );
445 bsize
->size
= bsize
->width
<< 6;
447 prop
= bdf_get_font_property( font
, "PIXEL_SIZE" );
449 bsize
->y_ppem
= (FT_Short
)prop
->value
.l
<< 6;
451 prop
= bdf_get_font_property( font
, "RESOLUTION_X" );
453 resolution_x
= (FT_Short
)prop
->value
.l
;
455 prop
= bdf_get_font_property( font
, "RESOLUTION_Y" );
457 resolution_y
= (FT_Short
)prop
->value
.l
;
459 if ( bsize
->y_ppem
== 0 )
461 bsize
->y_ppem
= bsize
->size
;
463 bsize
->y_ppem
= bsize
->y_ppem
* resolution_y
/ 72;
465 if ( resolution_x
&& resolution_y
)
466 bsize
->x_ppem
= bsize
->y_ppem
* resolution_x
/ resolution_y
;
468 bsize
->x_ppem
= bsize
->y_ppem
;
473 bdf_glyph_t
* cur
= font
->glyphs
;
477 if ( FT_NEW_ARRAY( face
->en_table
, font
->glyphs_size
) )
480 face
->default_glyph
= 0;
481 for ( n
= 0; n
< font
->glyphs_size
; n
++ )
483 (face
->en_table
[n
]).enc
= cur
[n
].encoding
;
484 FT_TRACE4(( "idx %d, val 0x%lX\n", n
, cur
[n
].encoding
));
485 (face
->en_table
[n
]).glyph
= (FT_Short
)n
;
487 if ( cur
[n
].encoding
== font
->default_char
)
489 if ( n
< FT_UINT_MAX
)
490 face
->default_glyph
= (FT_UInt
)n
;
492 FT_TRACE1(( "idx %d is too large for this system\n", n
));
499 bdf_property_t
*charset_registry
= 0, *charset_encoding
= 0;
500 FT_Bool unicode_charmap
= 0;
504 bdf_get_font_property( font
, "CHARSET_REGISTRY" );
506 bdf_get_font_property( font
, "CHARSET_ENCODING" );
507 if ( charset_registry
&& charset_encoding
)
509 if ( charset_registry
->format
== BDF_ATOM
&&
510 charset_encoding
->format
== BDF_ATOM
&&
511 charset_registry
->value
.atom
&&
512 charset_encoding
->value
.atom
)
517 if ( FT_STRDUP( face
->charset_encoding
,
518 charset_encoding
->value
.atom
) ||
519 FT_STRDUP( face
->charset_registry
,
520 charset_registry
->value
.atom
) )
523 /* Uh, oh, compare first letters manually to avoid dependency */
525 s
= face
->charset_registry
;
526 if ( ( s
[0] == 'i' || s
[0] == 'I' ) &&
527 ( s
[1] == 's' || s
[1] == 'S' ) &&
528 ( s
[2] == 'o' || s
[2] == 'O' ) )
531 if ( !ft_strcmp( s
, "10646" ) ||
532 ( !ft_strcmp( s
, "8859" ) &&
533 !ft_strcmp( face
->charset_encoding
, "1" ) ) )
538 FT_CharMapRec charmap
;
541 charmap
.face
= FT_FACE( face
);
542 charmap
.encoding
= FT_ENCODING_NONE
;
543 charmap
.platform_id
= 0;
544 charmap
.encoding_id
= 0;
546 if ( unicode_charmap
)
548 charmap
.encoding
= FT_ENCODING_UNICODE
;
549 charmap
.platform_id
= 3;
550 charmap
.encoding_id
= 1;
553 error
= FT_CMap_New( &bdf_cmap_class
, NULL
, &charmap
, NULL
);
556 /* Select default charmap */
557 if ( bdfface
->num_charmaps
)
558 bdfface
->charmap
= bdfface
->charmaps
[0];
566 /* otherwise assume Adobe standard encoding */
569 FT_CharMapRec charmap
;
572 charmap
.face
= FT_FACE( face
);
573 charmap
.encoding
= FT_ENCODING_ADOBE_STANDARD
;
574 charmap
.platform_id
= 7;
575 charmap
.encoding_id
= 0;
577 error
= FT_CMap_New( &bdf_cmap_class
, NULL
, &charmap
, NULL
);
579 /* Select default charmap */
580 if ( bdfface
->num_charmaps
)
581 bdfface
->charmap
= bdfface
->charmaps
[0];
590 BDF_Face_Done( bdfface
);
591 return BDF_Err_Unknown_File_Format
;
595 FT_CALLBACK_DEF( FT_Error
)
596 BDF_Size_Select( FT_Size size
,
597 FT_ULong strike_index
)
599 bdf_font_t
* bdffont
= ( (BDF_Face
)size
->face
)->bdffont
;
602 FT_Select_Metrics( size
->face
, strike_index
);
604 size
->metrics
.ascender
= bdffont
->font_ascent
<< 6;
605 size
->metrics
.descender
= -bdffont
->font_descent
<< 6;
606 size
->metrics
.max_advance
= bdffont
->bbx
.width
<< 6;
612 FT_CALLBACK_DEF( FT_Error
)
613 BDF_Size_Request( FT_Size size
,
614 FT_Size_Request req
)
616 FT_Face face
= size
->face
;
617 FT_Bitmap_Size
* bsize
= face
->available_sizes
;
618 bdf_font_t
* bdffont
= ( (BDF_Face
)face
)->bdffont
;
619 FT_Error error
= BDF_Err_Invalid_Pixel_Size
;
623 height
= FT_REQUEST_HEIGHT( req
);
624 height
= ( height
+ 32 ) >> 6;
628 case FT_SIZE_REQUEST_TYPE_NOMINAL
:
629 if ( height
== ( ( bsize
->y_ppem
+ 32 ) >> 6 ) )
633 case FT_SIZE_REQUEST_TYPE_REAL_DIM
:
634 if ( height
== ( bdffont
->font_ascent
+
635 bdffont
->font_descent
) )
640 error
= BDF_Err_Unimplemented_Feature
;
647 return BDF_Size_Select( size
, 0 );
652 FT_CALLBACK_DEF( FT_Error
)
653 BDF_Glyph_Load( FT_GlyphSlot slot
,
656 FT_Int32 load_flags
)
658 BDF_Face bdf
= (BDF_Face
)FT_SIZE_FACE( size
);
659 FT_Face face
= FT_FACE( bdf
);
660 FT_Error error
= BDF_Err_Ok
;
661 FT_Bitmap
* bitmap
= &slot
->bitmap
;
663 int bpp
= bdf
->bdffont
->bpp
;
665 FT_UNUSED( load_flags
);
668 if ( !face
|| glyph_index
>= (FT_UInt
)face
->num_glyphs
)
670 error
= BDF_Err_Invalid_Argument
;
674 /* index 0 is the undefined glyph */
675 if ( glyph_index
== 0 )
676 glyph_index
= bdf
->default_glyph
;
680 /* slot, bitmap => freetype, glyph => bdflib */
681 glyph
= bdf
->bdffont
->glyphs
[glyph_index
];
683 bitmap
->rows
= glyph
.bbx
.height
;
684 bitmap
->width
= glyph
.bbx
.width
;
685 if ( glyph
.bpr
> INT_MAX
)
686 FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
688 bitmap
->pitch
= (int)glyph
.bpr
; /* same as FT_Bitmap.pitch */
690 /* note: we don't allocate a new array to hold the bitmap; */
691 /* we can simply point to it */
692 ft_glyphslot_set_bitmap( slot
, glyph
.bitmap
);
697 bitmap
->pixel_mode
= FT_PIXEL_MODE_MONO
;
700 bitmap
->pixel_mode
= FT_PIXEL_MODE_GRAY2
;
703 bitmap
->pixel_mode
= FT_PIXEL_MODE_GRAY4
;
706 bitmap
->pixel_mode
= FT_PIXEL_MODE_GRAY
;
707 bitmap
->num_grays
= 256;
711 slot
->format
= FT_GLYPH_FORMAT_BITMAP
;
712 slot
->bitmap_left
= glyph
.bbx
.x_offset
;
713 slot
->bitmap_top
= glyph
.bbx
.ascent
;
715 slot
->metrics
.horiAdvance
= glyph
.dwidth
<< 6;
716 slot
->metrics
.horiBearingX
= glyph
.bbx
.x_offset
<< 6;
717 slot
->metrics
.horiBearingY
= glyph
.bbx
.ascent
<< 6;
718 slot
->metrics
.width
= bitmap
->width
<< 6;
719 slot
->metrics
.height
= bitmap
->rows
<< 6;
722 * XXX DWIDTH1 and VVECTOR should be parsed and
723 * used here, provided such fonts do exist.
725 ft_synthesize_vertical_metrics( &slot
->metrics
,
726 bdf
->bdffont
->bbx
.height
<< 6 );
740 bdf_get_bdf_property( BDF_Face face
,
741 const char* prop_name
,
742 BDF_PropertyRec
*aproperty
)
744 bdf_property_t
* prop
;
747 FT_ASSERT( face
&& face
->bdffont
);
749 prop
= bdf_get_font_property( face
->bdffont
, prop_name
);
752 switch ( prop
->format
)
755 aproperty
->type
= BDF_PROPERTY_TYPE_ATOM
;
756 aproperty
->u
.atom
= prop
->value
.atom
;
760 if ( prop
->value
.l
> 0x7FFFFFFFL
|| prop
->value
.l
< ( -1 - 0x7FFFFFFFL
) )
762 FT_TRACE1(( "bdf_get_bdf_property: " ));
763 FT_TRACE1(( "too large integer 0x%x is truncated\n" ));
765 aproperty
->type
= BDF_PROPERTY_TYPE_INTEGER
;
766 aproperty
->u
.integer
= (FT_Int32
)prop
->value
.l
;
770 if ( prop
->value
.ul
> 0xFFFFFFFFUL
)
772 FT_TRACE1(( "bdf_get_bdf_property: " ));
773 FT_TRACE1(( "too large cardinal 0x%x is truncated\n" ));
775 aproperty
->type
= BDF_PROPERTY_TYPE_CARDINAL
;
776 aproperty
->u
.cardinal
= (FT_UInt32
)prop
->value
.ul
;
786 return BDF_Err_Invalid_Argument
;
791 bdf_get_charset_id( BDF_Face face
,
792 const char* *acharset_encoding
,
793 const char* *acharset_registry
)
795 *acharset_encoding
= face
->charset_encoding
;
796 *acharset_registry
= face
->charset_registry
;
802 static const FT_Service_BDFRec bdf_service_bdf
=
804 (FT_BDF_GetCharsetIdFunc
)bdf_get_charset_id
,
805 (FT_BDF_GetPropertyFunc
) bdf_get_bdf_property
815 static const FT_ServiceDescRec bdf_services
[] =
817 { FT_SERVICE_ID_BDF
, &bdf_service_bdf
},
818 { FT_SERVICE_ID_XF86_NAME
, FT_XF86_FORMAT_BDF
},
823 FT_CALLBACK_DEF( FT_Module_Interface
)
824 bdf_driver_requester( FT_Module module
,
829 return ft_service_list_lookup( bdf_services
, name
);
834 FT_CALLBACK_TABLE_DEF
835 const FT_Driver_ClassRec bdf_driver_class
=
838 FT_MODULE_FONT_DRIVER
|
839 FT_MODULE_DRIVER_NO_OUTLINES
,
840 sizeof ( FT_DriverRec
),
848 (FT_Module_Constructor
)0,
849 (FT_Module_Destructor
) 0,
850 (FT_Module_Requester
) bdf_driver_requester
853 sizeof ( BDF_FaceRec
),
854 sizeof ( FT_SizeRec
),
855 sizeof ( FT_GlyphSlotRec
),
859 0, /* FT_Size_InitFunc */
860 0, /* FT_Size_DoneFunc */
861 0, /* FT_Slot_InitFunc */
862 0, /* FT_Slot_DoneFunc */
864 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
865 ft_stub_set_char_sizes
,
866 ft_stub_set_pixel_sizes
,
870 0, /* FT_Face_GetKerningFunc */
871 0, /* FT_Face_AttachFunc */
872 0, /* FT_Face_GetAdvancesFunc */