Add type 3 lookup handling

This commit is contained in:
Craig White 2023-10-27 01:30:32 -04:00
parent 23daa69048
commit 99f56eed57
1 changed files with 91 additions and 16 deletions

View File

@ -55,7 +55,7 @@ adjustment_database[] =
{0xEC, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}, {0xEC, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
{0xED, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}, {0xED, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
{0xEE, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}, {0xEE, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
{0xF1, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 1}, /*n with tilde*/ {0xF1, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}, /*n with tilde*/
{0xF2, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}, {0xF2, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
{0xF3, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}, {0xF3, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
{0xF4, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}, {0xF4, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
@ -446,16 +446,31 @@ af_all_glyph_variants( FT_Face face,
hb_face_t *hb_face = hb_font_get_face( hb_font ); hb_face_t *hb_face = hb_font_get_face( hb_font );
/*The set of all feature tags in the font*/ /*The set of all feature tags in the font*/
hb_set_t *feature_tags = hb_set_create(); hb_set_t *feature_tags = hb_set_create();
hb_set_t *type_3_lookup_indicies = hb_set_create();
hb_buffer_t *codepoint_buffer = hb_buffer_create();
hb_codepoint_t *type_3_alternate_glyphs_buffer;
if ( !hb_set_allocation_successful( feature_tags ) ) if ( !hb_set_allocation_successful( feature_tags ) )
{ {
return FT_Err_Out_Of_Memory; error = FT_Err_Out_Of_Memory;
goto Exit;
}
if ( !hb_buffer_allocation_successful( codepoint_buffer ) )
{
error = FT_Err_Out_Of_Memory;
goto Exit;
}
if ( !hb_set_allocation_successful ( type_3_lookup_indicies ) )
{
error = FT_Err_Out_Of_Memory;
goto Exit;
} }
/*populate feature_tags using the output of hb_ot_layout_table_get_feature_tags*/ /*populate feature_tags using the output of hb_ot_layout_table_get_feature_tags*/
FT_Bool feature_list_done = 0; FT_Bool feature_list_done = 0;
unsigned int start_offset = 0; unsigned int start_offset = 0;
while ( !feature_list_done ) { while ( !feature_list_done )
{
unsigned int feature_count = 20; unsigned int feature_count = 20;
hb_tag_t tags[20]; hb_tag_t tags[20];
hb_ot_layout_table_get_feature_tags ( hb_face, hb_ot_layout_table_get_feature_tags ( hb_face,
@ -474,31 +489,28 @@ af_all_glyph_variants( FT_Face face,
} }
if ( !hb_set_allocation_successful( feature_tags ) ) if ( !hb_set_allocation_successful( feature_tags ) )
{ {
return FT_Err_Out_Of_Memory; error = FT_Err_Out_Of_Memory;
goto Exit;
} }
} }
/*make a buffer only consisting of the given codepoint*/ /*make a buffer only consisting of the given codepoint*/
hb_buffer_t *codepoint_buffer = hb_buffer_create();
if ( !hb_buffer_allocation_successful( codepoint_buffer ) )
{
return FT_Err_Out_Of_Memory;
}
if ( !hb_buffer_pre_allocate( codepoint_buffer, 1 ) ) if ( !hb_buffer_pre_allocate( codepoint_buffer, 1 ) )
{ {
return FT_Err_Out_Of_Memory; error = FT_Err_Out_Of_Memory;
goto Exit;
} }
hb_buffer_set_direction (codepoint_buffer, hb_buffer_set_direction ( codepoint_buffer,
HB_DIRECTION_LTR); HB_DIRECTION_LTR );
hb_buffer_add( codepoint_buffer, codepoint, 0 ); hb_buffer_add( codepoint_buffer, codepoint, 0 );
/*The array of features that will be used by the recursive part /*The array of features that will be used by the recursive part
it will have at most as many entries as there are features, so it will have at most as many entries as there are features, so
make the length = length of feature_tags*/ make the length = length of feature_tags*/
hb_feature_t *feature_buffer; hb_feature_t *feature_buffer;
if ( FT_NEW_ARRAY( feature_buffer, hb_set_get_population( feature_tags ) ) ) if (( error = FT_NEW_ARRAY( feature_buffer, hb_set_get_population( feature_tags ) ) ))
{ {
return error; goto Exit;
} }
error = af_all_glyph_variants_helper( hb_font, error = af_all_glyph_variants_helper( hb_font,
@ -507,10 +519,72 @@ af_all_glyph_variants( FT_Face face,
feature_buffer, feature_buffer,
0, 0,
result ); result );
if ( error )
{
goto Exit;
}
/*
Add the alternative glyph forms that come from features using
type 3 lookups.
This file from gtk was very useful in figuring out my approach:
https://github.com/val-verde/gtk/blob/212e85e92628eda9f9650e5cc8d88c44062642ae/gtk/gtkfontchooserwidget.c#L2085
*/
/*list of features containing type 3 lookups:*/
hb_tag_t feature_list[] = {
HB_TAG('s','a','l','t'),
HB_TAG('s','w','s','h'),
HB_TAG('n','a','l','t'),
HB_TAG_NONE
};
hb_ot_layout_collect_lookups ( hb_face,
HB_OT_TAG_GSUB,
NULL,
NULL,
feature_list,
type_3_lookup_indicies);
if ( !hb_set_allocation_successful( type_3_lookup_indicies ) )
{
error = FT_Err_Out_Of_Memory;
goto Exit;
}
if (( error = FT_NEW_ARRAY( type_3_alternate_glyphs_buffer, 100 ) ))
{
goto Exit;
}
hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID;
FT_UInt base_glyph_index = FT_Get_Char_Index( face, codepoint );
if ( base_glyph_index != 0 ) {
while ( hb_set_next( type_3_lookup_indicies, &lookup_index ) )
{
unsigned alternate_count = 100;
hb_ot_layout_lookup_get_glyph_alternates
( hb_face,
lookup_index,
base_glyph_index,
0,
&alternate_count,
type_3_alternate_glyphs_buffer );
for ( unsigned i = 0; i < alternate_count; i++ )
{
hb_set_add( result, type_3_alternate_glyphs_buffer[i] );
}
}
}
Exit:
hb_set_destroy( feature_tags ); hb_set_destroy( feature_tags );
hb_buffer_destroy( codepoint_buffer ); hb_buffer_destroy( codepoint_buffer );
FT_FREE( feature_buffer ); FT_FREE( feature_buffer );
FT_FREE( type_3_alternate_glyphs_buffer );
return error; return error;
} }
#endif /*FT_CONFIG_OPTION_USE_HARFBUZZ*/ #endif /*FT_CONFIG_OPTION_USE_HARFBUZZ*/
@ -528,7 +602,8 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global
FT_Error error; FT_Error error;
/* backup face->charmap because find_unicode_charmap sets it */ /* backup face->charmap because find_unicode_charmap sets it */
FT_CharMap old_charmap = face->charmap; FT_CharMap old_charmap = face->charmap;
if ( ( error = find_unicode_charmap( face ) ) ) { if ( ( error = find_unicode_charmap( face ) ) )
{
*map = NULL; *map = NULL;
goto Exit; goto Exit;
} }