1 /***************************************************************************/
5 /* High-level SFNT driver interface (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_SFNT_H
22 #include FT_INTERNAL_OBJECTS_H
31 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
35 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
39 #ifdef TT_CONFIG_OPTION_BDF
41 #include FT_SERVICE_BDF_H
48 #include FT_SERVICE_GLYPH_DICT_H
49 #include FT_SERVICE_POSTSCRIPT_NAME_H
50 #include FT_SERVICE_SFNT_H
51 #include FT_SERVICE_TT_CMAP_H
53 /*************************************************************************/
55 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
56 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
57 /* messages during execution. */
60 #define FT_COMPONENT trace_sfdriver
69 get_sfnt_table( TT_Face face
,
78 table
= &face
->header
;
82 table
= &face
->horizontal
;
86 table
= face
->vertical_info
? &face
->vertical
: 0;
90 table
= face
->os2
.version
== 0xFFFFU
? 0 : &face
->os2
;
94 table
= &face
->postscript
;
98 table
= &face
->max_profile
;
102 table
= face
->pclt
.Version
? &face
->pclt
: 0;
114 sfnt_table_info( TT_Face face
,
120 if ( !tag
|| !offset
|| !length
)
121 return SFNT_Err_Invalid_Argument
;
123 if ( idx
>= face
->num_tables
)
124 return SFNT_Err_Table_Missing
;
126 *tag
= face
->dir_tables
[idx
].Tag
;
127 *offset
= face
->dir_tables
[idx
].Offset
;
128 *length
= face
->dir_tables
[idx
].Length
;
134 FT_DEFINE_SERVICE_SFNT_TABLEREC(sfnt_service_sfnt_table
,
135 (FT_SFNT_TableLoadFunc
)tt_face_load_any
,
136 (FT_SFNT_TableGetFunc
) get_sfnt_table
,
137 (FT_SFNT_TableInfoFunc
)sfnt_table_info
141 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
149 sfnt_get_glyph_name( TT_Face face
,
158 error
= tt_face_get_ps_name( face
, glyph_index
, &gname
);
160 FT_STRCPYN( buffer
, gname
, buffer_max
);
167 sfnt_get_name_index( TT_Face face
,
168 FT_String
* glyph_name
)
170 FT_Face root
= &face
->root
;
171 FT_UInt i
, max_gid
= FT_UINT_MAX
;
174 if ( root
->num_glyphs
< 0 )
176 else if ( ( FT_ULong
) root
->num_glyphs
< FT_UINT_MAX
)
177 max_gid
= ( FT_UInt
) root
->num_glyphs
;
179 FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",
180 FT_UINT_MAX
, root
->num_glyphs
));
182 for ( i
= 0; i
< max_gid
; i
++ )
185 FT_Error error
= tt_face_get_ps_name( face
, i
, &gname
);
191 if ( !ft_strcmp( glyph_name
, gname
) )
199 FT_DEFINE_SERVICE_GLYPHDICTREC(sfnt_service_glyph_dict
,
200 (FT_GlyphDict_GetNameFunc
) sfnt_get_glyph_name
,
201 (FT_GlyphDict_NameIndexFunc
)sfnt_get_name_index
204 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
208 * POSTSCRIPT NAME SERVICE
213 sfnt_get_ps_name( TT_Face face
)
215 FT_Int n
, found_win
, found_apple
;
216 const char* result
= NULL
;
219 /* shouldn't happen, but just in case to avoid memory leaks */
220 if ( face
->postscript_name
)
221 return face
->postscript_name
;
223 /* scan the name table to see whether we have a Postscript name here, */
224 /* either in Macintosh or Windows platform encodings */
228 for ( n
= 0; n
< face
->num_names
; n
++ )
230 TT_NameEntryRec
* name
= face
->name_table
.names
+ n
;
233 if ( name
->nameID
== 6 && name
->stringLength
> 0 )
235 if ( name
->platformID
== 3 &&
236 name
->encodingID
== 1 &&
237 name
->languageID
== 0x409 )
240 if ( name
->platformID
== 1 &&
241 name
->encodingID
== 0 &&
242 name
->languageID
== 0 )
247 if ( found_win
!= -1 )
249 FT_Memory memory
= face
->root
.memory
;
250 TT_NameEntryRec
* name
= face
->name_table
.names
+ found_win
;
251 FT_UInt len
= name
->stringLength
/ 2;
252 FT_Error error
= SFNT_Err_Ok
;
257 if ( !FT_ALLOC( result
, name
->stringLength
+ 1 ) )
259 FT_Stream stream
= face
->name_table
.stream
;
260 FT_String
* r
= (FT_String
*)result
;
261 FT_Byte
* p
= (FT_Byte
*)name
->string
;
264 if ( FT_STREAM_SEEK( name
->stringOffset
) ||
265 FT_FRAME_ENTER( name
->stringLength
) )
268 name
->stringLength
= 0;
269 name
->stringOffset
= 0;
270 FT_FREE( name
->string
);
275 p
= (FT_Byte
*)stream
->cursor
;
277 for ( ; len
> 0; len
--, p
+= 2 )
279 if ( p
[0] == 0 && p
[1] >= 32 && p
[1] < 128 )
289 if ( found_apple
!= -1 )
291 FT_Memory memory
= face
->root
.memory
;
292 TT_NameEntryRec
* name
= face
->name_table
.names
+ found_apple
;
293 FT_UInt len
= name
->stringLength
;
294 FT_Error error
= SFNT_Err_Ok
;
299 if ( !FT_ALLOC( result
, len
+ 1 ) )
301 FT_Stream stream
= face
->name_table
.stream
;
304 if ( FT_STREAM_SEEK( name
->stringOffset
) ||
305 FT_STREAM_READ( result
, len
) )
307 name
->stringOffset
= 0;
308 name
->stringLength
= 0;
309 FT_FREE( name
->string
);
313 ((char*)result
)[len
] = '\0';
318 face
->postscript_name
= result
;
322 FT_DEFINE_SERVICE_PSFONTNAMEREC(sfnt_service_ps_name
,
323 (FT_PsName_GetFunc
)sfnt_get_ps_name
330 FT_DEFINE_SERVICE_TTCMAPSREC(tt_service_get_cmap_info
,
331 (TT_CMap_Info_GetFunc
)tt_get_cmap_info
335 #ifdef TT_CONFIG_OPTION_BDF
338 sfnt_get_charset_id( TT_Face face
,
339 const char* *acharset_encoding
,
340 const char* *acharset_registry
)
342 BDF_PropertyRec encoding
, registry
;
346 /* XXX: I don't know whether this is correct, since
347 * tt_face_find_bdf_prop only returns something correct if we have
348 * previously selected a size that is listed in the BDF table.
349 * Should we change the BDF table format to include single offsets
350 * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
352 error
= tt_face_find_bdf_prop( face
, "CHARSET_REGISTRY", ®istry
);
355 error
= tt_face_find_bdf_prop( face
, "CHARSET_ENCODING", &encoding
);
358 if ( registry
.type
== BDF_PROPERTY_TYPE_ATOM
&&
359 encoding
.type
== BDF_PROPERTY_TYPE_ATOM
)
361 *acharset_encoding
= encoding
.u
.atom
;
362 *acharset_registry
= registry
.u
.atom
;
365 error
= FT_Err_Invalid_Argument
;
373 FT_DEFINE_SERVICE_BDFRec(sfnt_service_bdf
,
374 (FT_BDF_GetCharsetIdFunc
) sfnt_get_charset_id
,
375 (FT_BDF_GetPropertyFunc
) tt_face_find_bdf_prop
378 #endif /* TT_CONFIG_OPTION_BDF */
385 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
386 FT_DEFINE_SERVICEDESCREC5(sfnt_services
,
387 FT_SERVICE_ID_SFNT_TABLE
, &FT_SFNT_SERVICE_SFNT_TABLE_GET
,
388 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME
, &FT_SFNT_SERVICE_PS_NAME_GET
,
389 FT_SERVICE_ID_GLYPH_DICT
, &FT_SFNT_SERVICE_GLYPH_DICT_GET
,
390 FT_SERVICE_ID_BDF
, &FT_SFNT_SERVICE_BDF_GET
,
391 FT_SERVICE_ID_TT_CMAP
, &FT_TT_SERVICE_GET_CMAP_INFO_GET
393 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
394 FT_DEFINE_SERVICEDESCREC4(sfnt_services
,
395 FT_SERVICE_ID_SFNT_TABLE
, &FT_SFNT_SERVICE_SFNT_TABLE_GET
,
396 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME
, &FT_SFNT_SERVICE_PS_NAME_GET
,
397 FT_SERVICE_ID_GLYPH_DICT
, &FT_SFNT_SERVICE_GLYPH_DICT_GET
,
398 FT_SERVICE_ID_TT_CMAP
, &FT_TT_SERVICE_GET_CMAP_INFO_GET
400 #elif defined TT_CONFIG_OPTION_BDF
401 FT_DEFINE_SERVICEDESCREC4(sfnt_services
,
402 FT_SERVICE_ID_SFNT_TABLE
, &FT_SFNT_SERVICE_SFNT_TABLE_GET
,
403 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME
, &FT_SFNT_SERVICE_PS_NAME_GET
,
404 FT_SERVICE_ID_BDF
, &FT_SFNT_SERVICE_BDF_GET
,
405 FT_SERVICE_ID_TT_CMAP
, &FT_TT_SERVICE_GET_CMAP_INFO_GET
408 FT_DEFINE_SERVICEDESCREC3(sfnt_services
,
409 FT_SERVICE_ID_SFNT_TABLE
, &FT_SFNT_SERVICE_SFNT_TABLE_GET
,
410 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME
, &FT_SFNT_SERVICE_PS_NAME_GET
,
411 FT_SERVICE_ID_TT_CMAP
, &FT_TT_SERVICE_GET_CMAP_INFO_GET
416 FT_CALLBACK_DEF( FT_Module_Interface
)
417 sfnt_get_interface( FT_Module module
,
418 const char* module_interface
)
422 return ft_service_list_lookup( FT_SFNT_SERVICES_GET
, module_interface
);
426 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
428 FT_CALLBACK_DEF( FT_Error
)
429 tt_face_load_sfnt_header_stub( TT_Face face
,
436 FT_UNUSED( face_index
);
439 return FT_Err_Unimplemented_Feature
;
443 FT_CALLBACK_DEF( FT_Error
)
444 tt_face_load_directory_stub( TT_Face face
,
452 return FT_Err_Unimplemented_Feature
;
456 FT_CALLBACK_DEF( FT_Error
)
457 tt_face_load_hdmx_stub( TT_Face face
,
463 return FT_Err_Unimplemented_Feature
;
467 FT_CALLBACK_DEF( void )
468 tt_face_free_hdmx_stub( TT_Face face
)
474 FT_CALLBACK_DEF( FT_Error
)
475 tt_face_set_sbit_strike_stub( TT_Face face
,
478 FT_ULong
* astrike_index
)
481 * We simply forge a FT_Size_Request and call the real function
482 * that does all the work.
484 * This stub might be called by libXfont in the X.Org Xserver,
485 * compiled against version 2.1.8 or newer.
488 FT_Size_RequestRec req
;
491 req
.type
= FT_SIZE_REQUEST_TYPE_NOMINAL
;
492 req
.width
= (FT_F26Dot6
)x_ppem
;
493 req
.height
= (FT_F26Dot6
)y_ppem
;
494 req
.horiResolution
= 0;
495 req
.vertResolution
= 0;
497 *astrike_index
= 0x7FFFFFFFUL
;
499 return tt_face_set_sbit_strike( face
, &req
, astrike_index
);
503 FT_CALLBACK_DEF( FT_Error
)
504 tt_face_load_sbit_stub( TT_Face face
,
511 * This function was originally implemented to load the sbit table.
512 * However, it has been replaced by `tt_face_load_eblc', and this stub
513 * is only there for some rogue clients which would want to call it
514 * directly (which doesn't make much sense).
516 return FT_Err_Unimplemented_Feature
;
520 FT_CALLBACK_DEF( void )
521 tt_face_free_sbit_stub( TT_Face face
)
523 /* nothing to do in this stub */
528 FT_CALLBACK_DEF( FT_Error
)
529 tt_face_load_charmap_stub( TT_Face face
,
537 return FT_Err_Unimplemented_Feature
;
541 FT_CALLBACK_DEF( FT_Error
)
542 tt_face_free_charmap_stub( TT_Face face
,
551 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
553 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
554 #define PUT_EMBEDDED_BITMAPS(a) a
556 #define PUT_EMBEDDED_BITMAPS(a) 0
558 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
559 #define PUT_PS_NAMES(a) a
561 #define PUT_PS_NAMES(a) 0
564 FT_DEFINE_SFNT_INTERFACE(sfnt_interface
,
574 tt_face_load_sfnt_header_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
575 tt_face_load_directory_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
587 tt_face_load_hdmx_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
588 tt_face_free_hdmx_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
595 PUT_EMBEDDED_BITMAPS(tt_face_load_bhed
),
597 tt_face_set_sbit_strike_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
598 tt_face_load_sbit_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
600 tt_find_sbit_image
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
601 tt_load_sbit_metrics
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
603 PUT_EMBEDDED_BITMAPS(tt_face_load_sbit_image
),
605 tt_face_free_sbit_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
608 PUT_PS_NAMES(tt_face_get_ps_name
),
609 PUT_PS_NAMES(tt_face_free_ps_names
),
611 tt_face_load_charmap_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
612 tt_face_free_charmap_stub
, /* FT_CONFIG_OPTION_OLD_INTERNALS */
614 /* since version 2.1.8 */
618 /* since version 2.2 */
620 tt_face_load_font_dir
,
623 /* see `ttsbit.h' and `sfnt.h' */
624 PUT_EMBEDDED_BITMAPS(tt_face_load_eblc
),
625 PUT_EMBEDDED_BITMAPS(tt_face_free_eblc
),
627 PUT_EMBEDDED_BITMAPS(tt_face_set_sbit_strike
),
628 PUT_EMBEDDED_BITMAPS(tt_face_load_strike_metrics
),
634 FT_DEFINE_MODULE(sfnt_module_class
,
636 0, /* not a font driver or renderer */
637 sizeof( FT_ModuleRec
),
639 "sfnt", /* driver name */
640 0x10000L
, /* driver version 1.0 */
641 0x20000L
, /* driver requires FreeType 2.0 or higher */
643 (const void*)&FT_SFNT_INTERFACE_GET
, /* module specific interface */
645 (FT_Module_Constructor
)0,
646 (FT_Module_Destructor
) 0,
647 (FT_Module_Requester
) sfnt_get_interface