@ -1,6 +1,7 @@
/*
* Copyright © 2009 Red Hat , Inc .
* Copyright © 2009 Keith Stribley
* Copyright © 2015 Google , Inc .
*
* This is part of HarfBuzz , a text shaping library .
*
@ -23,6 +24,7 @@
* PROVIDE MAINTENANCE , SUPPORT , UPDATES , ENHANCEMENTS , OR MODIFICATIONS .
*
* Red Hat Author ( s ) : Behdad Esfahbod
* Google Author ( s ) : Behdad Esfahbod
*/
# include "hb-private.hh"
@ -46,17 +48,15 @@
* In general , this file does a fine job of what it ' s supposed to do .
* There are , however , things that need more work :
*
* - We don ' t handle any load_flags . That definitely has API implications . : (
* I believe hb_ft_font_create ( ) should take load_flags input .
* In particular , FT_Get_Advance ( ) without the NO_HINTING flag seems to be
* buggy .
* - I remember seeing FT_Get_Advance ( ) without the NO_HINTING flag to be buggy .
* Have not investigated .
*
* FreeType works in 26.6 mode . Clients can decide to use that mode , and everything
* - FreeType works in 26.6 mode . Clients can decide to use that mode , and everything
* would work fine . However , we also abuse this API for performing in font - space ,
* but don ' t pass the correct flags to FreeType . We just abuse the no - hinting mode
* for that , such that no rounding etc happens . As such , we don ' t set ppem , and
* pass NO_HINTING around . This seems to work best , until we go ahead and add a full
* load_flags API .
* pass NO_HINTING as load_flags . Would be much better to use NO_SCALE , and scale
* ourselves , like we do in uniscribe , etc .
*
* - We don ' t handle / allow for emboldening / obliqueing .
*
@ -66,6 +66,76 @@
*/
struct hb_ft_font_t
{
FT_Face ft_face ;
int load_flags ;
bool unref ; /* Whether to destroy ft_face when done. */
} ;
static hb_ft_font_t *
_hb_ft_font_create ( FT_Face ft_face , bool unref )
{
hb_ft_font_t * ft_font = ( hb_ft_font_t * ) calloc ( 1 , sizeof ( hb_ft_font_t ) ) ;
if ( unlikely ( ! ft_font ) )
return NULL ;
ft_font - > ft_face = ft_face ;
ft_font - > unref = unref ;
ft_font - > load_flags = FT_LOAD_DEFAULT ;
return ft_font ;
}
static void
_hb_ft_font_destroy ( hb_ft_font_t * ft_font )
{
if ( ft_font - > unref )
FT_Done_Face ( ft_font - > ft_face ) ;
free ( ft_font ) ;
}
void
hb_ft_font_set_load_flags ( hb_font_t * font , int load_flags )
{
if ( font - > immutable )
return ;
if ( font - > destroy ! = ( hb_destroy_func_t ) _hb_ft_font_destroy )
return ;
hb_ft_font_t * ft_font = ( hb_ft_font_t * ) font - > user_data ;
ft_font - > load_flags = load_flags ;
}
int
hb_ft_font_get_load_flags ( hb_font_t * font )
{
if ( font - > destroy ! = ( hb_destroy_func_t ) _hb_ft_font_destroy )
return 0 ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font - > user_data ;
return ft_font - > load_flags ;
}
FT_Face
hb_ft_font_get_face ( hb_font_t * font )
{
if ( font - > destroy ! = ( hb_destroy_func_t ) _hb_ft_font_destroy )
return NULL ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font - > user_data ;
return ft_font - > ft_face ;
}
static hb_bool_t
hb_ft_get_glyph ( hb_font_t * font HB_UNUSED ,
void * font_data ,
@ -75,13 +145,13 @@ hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
void * user_data HB_UNUSED )
{
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
unsigned int g ;
FT_Face ft_face = ( FT_Face ) font_data ;
if ( likely ( ! variation_selector ) )
g = FT_Get_Char_Index ( ft_face , unicode ) ;
g = FT_Get_Char_Index ( ft_font - > ft_f ace , unicode ) ;
else
g = FT_Face_GetCharVariantIndex ( ft_face , unicode , variation_selector ) ;
g = FT_Face_GetCharVariantIndex ( ft_font - > ft_f ace , unicode , variation_selector ) ;
if ( unlikely ( ! g ) )
return false ;
@ -96,11 +166,10 @@ hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
hb_codepoint_t glyph ,
void * user_data HB_UNUSED )
{
FT_Face ft_face = ( FT_Face ) font_data ;
int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
FT_Fixed v ;
if ( unlikely ( FT_Get_Advance ( ft_face , glyph , load_flags , & v ) ) )
if ( unlikely ( FT_Get_Advance ( ft_font - > ft_f ace , glyph , ft_font - > load_flags , & v ) ) )
return 0 ;
if ( font - > x_scale < 0 )
@ -115,11 +184,10 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
hb_codepoint_t glyph ,
void * user_data HB_UNUSED )
{
FT_Face ft_face = ( FT_Face ) font_data ;
int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
FT_Fixed v ;
if ( unlikely ( FT_Get_Advance ( ft_face , glyph , load_flags , & v ) ) )
if ( unlikely ( FT_Get_Advance ( ft_font - > ft_f ace , glyph , ft_font - > load_flags | FT_LOAD_VERTICAL_LAYOUT , & v ) ) )
return 0 ;
if ( font - > y_scale < 0 )
@ -150,10 +218,10 @@ hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
hb_position_t * y ,
void * user_data HB_UNUSED )
{
FT_Face ft_face = ( FT_Face ) font_data ;
int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
FT_Face ft_face = ft_font - > ft_face ;
if ( unlikely ( FT_Load_Glyph ( ft_face , glyph , load_flags ) ) )
if ( unlikely ( FT_Load_Glyph ( ft_face , glyph , ft_font - > load_flags ) ) )
return false ;
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
@ -176,11 +244,11 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
hb_codepoint_t right_glyph ,
void * user_data HB_UNUSED )
{
FT_Face ft_face = ( FT_Face ) font_data ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
FT_Vector kerningv ;
FT_Kerning_Mode mode = font - > x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED ;
if ( FT_Get_Kerning ( ft_face , left_glyph , right_glyph , mode , & kerningv ) )
if ( FT_Get_Kerning ( ft_font - > ft_f ace , left_glyph , right_glyph , mode , & kerningv ) )
return 0 ;
return kerningv . x ;
@ -204,10 +272,10 @@ hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
hb_glyph_extents_t * extents ,
void * user_data HB_UNUSED )
{
FT_Face ft_face = ( FT_Face ) font_data ;
int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
FT_Face ft_face = ft_font - > ft_face ;
if ( unlikely ( FT_Load_Glyph ( ft_face , glyph , load_flags ) ) )
if ( unlikely ( FT_Load_Glyph ( ft_face , glyph , ft_font - > load_flags ) ) )
return false ;
extents - > x_bearing = ft_face - > glyph - > metrics . horiBearingX ;
@ -226,10 +294,10 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
hb_position_t * y ,
void * user_data HB_UNUSED )
{
FT_Face ft_face = ( FT_Face ) font_data ;
int load_flags = FT_LOAD_DEFAULT ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
FT_Face ft_face = ft_font - > ft_face ;
if ( unlikely ( FT_Load_Glyph ( ft_face , glyph , load_flags ) ) )
if ( unlikely ( FT_Load_Glyph ( ft_face , glyph , ft_font - > load_flags ) ) )
return false ;
if ( unlikely ( ft_face - > glyph - > format ! = FT_GLYPH_FORMAT_OUTLINE ) )
@ -251,9 +319,9 @@ hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED,
char * name , unsigned int size ,
void * user_data HB_UNUSED )
{
FT_Face ft_face = ( FT_Face ) font_data ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
hb_bool_t ret = ! FT_Get_Glyph_Name ( ft_face , glyph , name , size ) ;
hb_bool_t ret = ! FT_Get_Glyph_Name ( ft_font - > ft_f ace , glyph , name , size ) ;
if ( ret & & ( size & & ! * name ) )
ret = false ;
@ -267,7 +335,8 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
hb_codepoint_t * glyph ,
void * user_data HB_UNUSED )
{
FT_Face ft_face = ( FT_Face ) font_data ;
const hb_ft_font_t * ft_font = ( const hb_ft_font_t * ) font_data ;
FT_Face ft_face = ft_font - > ft_face ;
if ( len < 0 )
* glyph = FT_Get_Name_Index ( ft_face , ( FT_String * ) name ) ;
@ -293,8 +362,8 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
}
static hb_font_funcs_t *
_hb_ft_get_font_funcs ( void )
static void
_hb_ft_font_set_funcs ( hb_font_t * font , FT_Face ft_face , bool unref )
{
static const hb_font_funcs_t ft_ffuncs = {
HB_OBJECT_HEADER_STATIC ,
@ -308,7 +377,10 @@ _hb_ft_get_font_funcs (void)
}
} ;
return const_cast < hb_font_funcs_t * > ( & ft_ffuncs ) ;
hb_font_set_funcs ( font ,
const_cast < hb_font_funcs_t * > ( & ft_ffuncs ) ,
_hb_ft_font_create ( ft_face , unref ) ,
( hb_destroy_func_t ) _hb_ft_font_destroy ) ;
}
@ -420,11 +492,6 @@ hb_ft_face_create_cached (FT_Face ft_face)
return hb_face_reference ( ( hb_face_t * ) ft_face - > generic . data ) ;
}
static void
_do_nothing ( void )
{
}
/**
* hb_ft_font_create :
@ -446,9 +513,7 @@ hb_ft_font_create (FT_Face ft_face,
face = hb_ft_face_create ( ft_face , destroy ) ;
font = hb_font_create ( face ) ;
hb_face_destroy ( face ) ;
hb_font_set_funcs ( font ,
_hb_ft_get_font_funcs ( ) ,
ft_face , ( hb_destroy_func_t ) _do_nothing ) ;
_hb_ft_font_set_funcs ( font , ft_face , false ) ;
hb_font_set_scale ( font ,
( int ) ( ( ( uint64_t ) ft_face - > size - > metrics . x_scale * ( uint64_t ) ft_face - > units_per_EM + ( 1 < < 15 ) ) > > 16 ) ,
( int ) ( ( ( uint64_t ) ft_face - > size - > metrics . y_scale * ( uint64_t ) ft_face - > units_per_EM + ( 1 < < 15 ) ) > > 16 ) ) ;
@ -562,18 +627,6 @@ hb_ft_font_set_funcs (hb_font_t *font)
ft_face - > generic . data = blob ;
ft_face - > generic . finalizer = ( FT_Generic_Finalizer ) _release_blob ;
hb_font_set_funcs ( font ,
_hb_ft_get_font_funcs ( ) ,
ft_face ,
( hb_destroy_func_t ) FT_Done_Face ) ;
}
FT_Face
hb_ft_font_get_face ( hb_font_t * font )
{
if ( font - > destroy = = ( hb_destroy_func_t ) FT_Done_Face | |
font - > destroy = = ( hb_destroy_func_t ) _do_nothing )
return ( FT_Face ) font - > user_data ;
return NULL ;
_hb_ft_font_set_funcs ( font , ft_face , true ) ;
hb_ft_font_set_load_flags ( font , FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING ) ;
}