freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Git][freetype/freetype][gsoc-craig-2023] WIP GSUB handling


From: Craig White (@gerzytet)
Subject: [Git][freetype/freetype][gsoc-craig-2023] WIP GSUB handling
Date: Mon, 25 Sep 2023 05:31:14 +0000

Craig White pushed to branch gsoc-craig-2023 at FreeType / FreeType

Commits:

  • 2c473abb
    by Craig White at 2023-09-25T01:30:28-04:00
    WIP GSUB handling
    

2 changed files:

Changes:

  • src/autofit/afadjust.c
    ... ... @@ -21,7 +21,7 @@
    21 21
     FT_LOCAL_ARRAY_DEF( AF_AdjustmentDatabaseEntry )
    
    22 22
     adjustment_database[] =
    
    23 23
     {
    
    24
    -    {0x21,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* ! */
    
    24
    +    {0x21,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* !
    
    25 25
         {0x69,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* i */
    
    26 26
         {0x6A,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* j */
    
    27 27
         {0xA1,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*Inverted Exclamation Mark*/
    
    ... ... @@ -138,11 +138,11 @@ adjustment_database[] =
    138 138
         {0x17E, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}
    
    139 139
     };
    
    140 140
     
    
    141
    -FT_LOCAL_DEF( FT_Bool )
    
    141
    +/*FT_LOCAL_DEF( FT_Bool )
    
    142 142
     af_adjustment_database_entry_equals( const AF_AdjustmentDatabaseEntry* a, const AF_AdjustmentDatabaseEntry* b )
    
    143 143
     {
    
    144 144
         return a->codepoint == b->codepoint && a->vertical_separation_adjustment_type == b->vertical_separation_adjustment_type;
    
    145
    -}
    
    145
    +}*/
    
    146 146
     
    
    147 147
     /*Helper function: get the adjustment database entry for a codepoint*/
    
    148 148
     FT_LOCAL_DEF( const AF_AdjustmentDatabaseEntry* )
    
    ... ... @@ -282,6 +282,174 @@ af_reverse_character_map_entry_compare( const void *a, const void *b ) {
    282 282
         return entry_a.glyph_index < entry_b.glyph_index ? -1 : entry_a.glyph_index > entry_b.glyph_index ? 1 : 0;
    
    283 283
     }
    
    284 284
     
    
    285
    +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
    
    286
    +FT_LOCAL_DEF( FT_Error )
    
    287
    +af_all_glyph_variants_helper( hb_font_t *font,
    
    288
    +                              hb_buffer_t *buffer,
    
    289
    +                              hb_set_t *feature_tag_pool,
    
    290
    +                              hb_feature_t *current_features,
    
    291
    +                              FT_UInt32 num_features,
    
    292
    +                              hb_set_t* result )
    
    293
    +{
    
    294
    +    hb_set_t *baseline_glyphs = hb_set_create();
    
    295
    +    if ( !hb_set_allocation_successful( baseline_glyphs ) )
    
    296
    +    {
    
    297
    +        return FT_Err_Out_Of_Memory;
    
    298
    +    }
    
    299
    +
    
    300
    +    hb_ot_shape_glyphs_closure ( font,
    
    301
    +                                 buffer,
    
    302
    +                                 current_features,
    
    303
    +                                 num_features,
    
    304
    +                                 baseline_glyphs );
    
    305
    +
    
    306
    +    hb_set_union( result, baseline_glyphs );
    
    307
    +    if ( !hb_set_allocation_successful( result ) )
    
    308
    +    {
    
    309
    +        return FT_Err_Out_Of_Memory;
    
    310
    +    }
    
    311
    +    if ( hb_set_get_population( feature_tag_pool ) == 0 )
    
    312
    +    {
    
    313
    +        return FT_Err_Ok;
    
    314
    +    }
    
    315
    +
    
    316
    +    /*set the feature to apply to the entire input buffer*/
    
    317
    +    current_features[num_features].start = HB_FEATURE_GLOBAL_START;
    
    318
    +    current_features[num_features].end = HB_FEATURE_GLOBAL_END;
    
    319
    +    current_features[num_features].value = 1; /*set the feature to enabled*/
    
    320
    +    /*quote from docs about value attribute:
    
    321
    +    0 disables the feature, non-zero (usually 1) enables the feature. For features implemented as lookup type 3 (like 'salt') the value is a one based index into the alternates.
    
    322
    +    this does not handle these lookup type 3 cases fully*/
    
    323
    +
    
    324
    +    /*feature tag will be determined by trying all feature tags, looking for anything that affects the result of the lookup*/
    
    325
    +    hb_set_t *new_glyphs = hb_set_create();
    
    326
    +    if ( !hb_set_allocation_successful( new_glyphs ) )
    
    327
    +    {
    
    328
    +        return FT_Err_Out_Of_Memory;
    
    329
    +    }
    
    330
    +    hb_tag_t feature_tag = HB_SET_VALUE_INVALID;
    
    331
    +    while ( hb_set_next( feature_tag_pool, &feature_tag ) )
    
    332
    +    {
    
    333
    +        hb_set_clear( new_glyphs );
    
    334
    +        current_features[num_features].tag = feature_tag;
    
    335
    +        FT_TRACE4(("P3. num: %d\n", num_features));
    
    336
    +        hb_ot_shape_glyphs_closure ( font,
    
    337
    +                                     buffer,
    
    338
    +                                     current_features,
    
    339
    +                                     num_features + 1,
    
    340
    +                                     new_glyphs );
    
    341
    +        if ( !hb_set_allocation_successful( new_glyphs ) )
    
    342
    +        {
    
    343
    +            return FT_Err_Out_Of_Memory;
    
    344
    +        }
    
    345
    +
    
    346
    +        hb_set_subtract( new_glyphs, baseline_glyphs );
    
    347
    +        /*glyphs now contains all glyphs that were added to the*/
    
    348
    +        /*closure as a result of adding this feature*/
    
    349
    +        /*If this is not a subset of result, this feature is relevant*/
    
    350
    +        /*and we should recurse*/
    
    351
    +        if ( !hb_set_is_subset( new_glyphs, result ) )
    
    352
    +        {
    
    353
    +            /*remove this feature from the feature pool so that
    
    354
    +            the later recursion won't try it*/
    
    355
    +            hb_set_del( feature_tag_pool, feature_tag );
    
    356
    +            FT_Error error = af_all_glyph_variants_helper( font,
    
    357
    +                                                           buffer,
    
    358
    +                                                           feature_tag_pool,
    
    359
    +                                                           current_features,
    
    360
    +                                                           num_features + 1,
    
    361
    +                                                           result );
    
    362
    +            if ( error )
    
    363
    +            {
    
    364
    +                return error;
    
    365
    +            }
    
    366
    +            /*add back the feature we removed*/
    
    367
    +            hb_set_add( feature_tag_pool, feature_tag );
    
    368
    +            if ( !hb_set_allocation_successful( feature_tag_pool ) ) {
    
    369
    +                return FT_Err_Out_Of_Memory;
    
    370
    +            }
    
    371
    +        } /* if( !hb_set_is_subset( glyphs, result ) ) */
    
    372
    +
    
    373
    +    } /*while ( hb_set_next( feature_tag_pool, &feature_tag ) )*/
    
    374
    +
    
    375
    +    hb_set_destroy( baseline_glyphs );
    
    376
    +    hb_set_destroy( new_glyphs );
    
    377
    +    return FT_Err_Ok;
    
    378
    +}
    
    379
    +
    
    380
    +FT_LOCAL_DEF( FT_Error )
    
    381
    +af_all_glyph_variants( FT_Face face,
    
    382
    +                       hb_font_t *hb_font,
    
    383
    +                       FT_UInt32 codepoint,
    
    384
    +                       hb_set_t* result )
    
    385
    +{
    
    386
    +    FT_Memory memory = face->memory;
    
    387
    +    FT_Error error;
    
    388
    +    hb_face_t *hb_face = hb_font_get_face( hb_font );
    
    389
    +    hb_set_t  *feature_tags = hb_set_create();
    
    390
    +    if ( !hb_set_allocation_successful( feature_tags ) )
    
    391
    +    {
    
    392
    +        return FT_Err_Out_Of_Memory;
    
    393
    +    }
    
    394
    +
    
    395
    +    FT_Bool feature_list_done = 0;
    
    396
    +    unsigned int start_offset = 0;
    
    397
    +    while ( !feature_list_done ) {
    
    398
    +        unsigned int feature_count = 20;
    
    399
    +        hb_tag_t tags[20];
    
    400
    +        hb_ot_layout_table_get_feature_tags ( hb_face,
    
    401
    +                                              HB_OT_TAG_GSUB,
    
    402
    +                                              start_offset,
    
    403
    +                                              &feature_count,
    
    404
    +                                              tags );
    
    405
    +        start_offset += 20;
    
    406
    +        if ( feature_count < 20 )
    
    407
    +        {
    
    408
    +            feature_list_done = 1;
    
    409
    +        }
    
    410
    +        for ( int i = 0; i < feature_count; i++ )
    
    411
    +        {
    
    412
    +            hb_set_add( feature_tags, tags[i] );
    
    413
    +        }
    
    414
    +        if ( !hb_set_allocation_successful( feature_tags ) )
    
    415
    +        {
    
    416
    +            return FT_Err_Out_Of_Memory;
    
    417
    +        }
    
    418
    +    }
    
    419
    +
    
    420
    +    hb_buffer_t *codepoint_buffer = hb_buffer_create();
    
    421
    +    if ( !hb_buffer_allocation_successful( codepoint_buffer ) )
    
    422
    +    {
    
    423
    +        return FT_Err_Out_Of_Memory;
    
    424
    +    }
    
    425
    +    if ( !hb_buffer_pre_allocate( codepoint_buffer, 1 ) )
    
    426
    +    {
    
    427
    +        return FT_Err_Out_Of_Memory;
    
    428
    +    }
    
    429
    +    hb_buffer_set_direction (codepoint_buffer,
    
    430
    +                             HB_DIRECTION_LTR);
    
    431
    +    hb_buffer_add( codepoint_buffer, codepoint, 0 );
    
    432
    +
    
    433
    +    hb_feature_t *feature_buffer;
    
    434
    +    if ( FT_NEW_ARRAY( feature_buffer, hb_set_get_population( feature_tags ) ) ) {
    
    435
    +        return error;
    
    436
    +    }
    
    437
    +
    
    438
    +    /*hb_codepoint_t and hb_tag_t are both uint32_t, so we can put feature tags inside hb_set*/
    
    439
    +    error = af_all_glyph_variants_helper( hb_font,
    
    440
    +                                          codepoint_buffer,
    
    441
    +                                          feature_tags,
    
    442
    +                                          feature_buffer,
    
    443
    +                                          0,
    
    444
    +                                          result );
    
    445
    +
    
    446
    +    hb_set_destroy( feature_tags );
    
    447
    +    hb_buffer_destroy( codepoint_buffer );
    
    448
    +    FT_FREE( feature_buffer );
    
    449
    +    return FT_Err_Ok;
    
    450
    +}
    
    451
    +#endif /*FT_CONFIG_OPTION_USE_HARFBUZZ*/
    
    452
    +
    
    285 453
     FT_LOCAL_DEF( FT_Error )
    
    286 454
     af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals globals )
    
    287 455
     {
    
    ... ... @@ -290,8 +458,6 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global
    290 458
         /* Search for a unicode charmap */
    
    291 459
         /* If there isn't one, create a blank map */
    
    292 460
     
    
    293
    -
    
    294
    -    /*TODO: use GSUB lookups    */
    
    295 461
         FT_TRACE4(( "af_reverse_character_map_new: building reverse character map\n" ));
    
    296 462
     
    
    297 463
         FT_Error error;
    
    ... ... @@ -314,6 +480,60 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global
    314 480
         {
    
    315 481
             goto Exit;
    
    316 482
         }
    
    483
    +
    
    484
    +
    
    485
    +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
    
    486
    +    hb_font_t *hb_font = globals->hb_font;
    
    487
    +    /*hb_face_t *hb_face = hb_font_get_face( hb_font );*/
    
    488
    +    hb_set_t *result_set = hb_set_create();
    
    489
    +    if ( !hb_set_allocation_successful( result_set ) )
    
    490
    +    {
    
    491
    +        error = FT_Err_Out_Of_Memory;
    
    492
    +        goto harfbuzz_path_Exit;
    
    493
    +    }
    
    494
    +
    
    495
    +
    
    496
    +    /*
    
    497
    +    af_all_glyph_variants( FT_Face face,
    
    498
    +                       hb_font_t *hb_font,
    
    499
    +                       FT_UInt32 codepoint,
    
    500
    +                       hb_set_t* result )*/
    
    501
    +
    
    502
    +    for ( FT_Long i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ )
    
    503
    +    {
    
    504
    +        FT_UInt32 codepoint = adjustment_database[i].codepoint;
    
    505
    +        error = af_all_glyph_variants( face,
    
    506
    +                                       hb_font,
    
    507
    +                                       codepoint,
    
    508
    +                                       result_set );
    
    509
    +        if ( error ) {
    
    510
    +            goto harfbuzz_path_Exit;
    
    511
    +        }
    
    512
    +
    
    513
    +        hb_codepoint_t glyph = HB_SET_VALUE_INVALID;
    
    514
    +        while ( hb_set_next( result_set, &glyph ) )
    
    515
    +        {
    
    516
    +            error = af_reverse_character_map_expand( *map, &capacity, memory );
    
    517
    +            if ( error ) {
    
    518
    +                goto harfbuzz_path_Exit;
    
    519
    +            }
    
    520
    +
    
    521
    +            ( *map )->length++;
    
    522
    +            ( *map )->entries[i].glyph_index = glyph;
    
    523
    +            ( *map )->entries[i].codepoint = codepoint;
    
    524
    +
    
    525
    +        }
    
    526
    +
    
    527
    +        hb_set_clear( result_set );
    
    528
    +
    
    529
    +    }
    
    530
    +harfbuzz_path_Exit:
    
    531
    +    hb_set_destroy( result_set );
    
    532
    +    if ( error )
    
    533
    +    {
    
    534
    +        goto Exit;
    
    535
    +    }
    
    536
    +#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
    
    317 537
     #ifdef FT_DEBUG_LEVEL_TRACE
    
    318 538
         int failed_lookups = 0;
    
    319 539
     #endif
    
    ... ... @@ -338,6 +558,8 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global
    338 558
             ( *map )->entries[i].codepoint = codepoint;
    
    339 559
         }
    
    340 560
     
    
    561
    +#endif /*FT_CONFIG_OPTION_USE_HARFBUZZ*/
    
    562
    +
    
    341 563
         ft_qsort(
    
    342 564
             ( *map )->entries,
    
    343 565
             ( *map )->length,
    
    ... ... @@ -345,120 +567,13 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global
    345 567
             af_reverse_character_map_entry_compare
    
    346 568
         );
    
    347 569
     
    
    348
    -#if 0
    
    349
    -/*#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ*/
    
    350
    -    hb_font_t *hb_font = globals->hb_font;
    
    351
    -    hb_face_t *hb_face = hb_font_get_face( hb_font );
    
    352
    -    hb_set_t  *feature_indicies = hb_set_create();
    
    353
    -    FT_Long oldlength = ( *map )->length;
    
    354
    -    hb_ot_layout_collect_lookups(
    
    355
    -        hb_face,
    
    356
    -        HB_OT_TAG_GSUB,
    
    357
    -        NULL, /*all scripts*/
    
    358
    -        NULL, /*all languages*/
    
    359
    -        NULL, /*all features*/
    
    360
    -        feature_indicies
    
    361
    -    );
    
    362
    -    hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
    
    363
    -    while ( hb_set_next(feature_indicies, &feature_index) )
    
    570
    +    for ( FT_Long i = 0; i < ( *map )->length; i++ )
    
    364 571
         {
    
    365
    -        hb_codepoint_t output_glyph_index;
    
    366
    -        /*TODO: find out whether I can reuse set instances instead of recreating*/
    
    367
    -        hb_set_t *glyphs_before = hb_set_create();
    
    368
    -        hb_set_t *glyphs_input = hb_set_create();
    
    369
    -        hb_set_t *glyphs_after = hb_set_create();
    
    370
    -        hb_set_t *glyphs_output = hb_set_create();
    
    371
    -        hb_ot_layout_lookup_collect_glyphs( hb_face, HB_OT_TAG_GSUB,
    
    372
    -                                            feature_index, glyphs_before,
    
    373
    -                                            glyphs_input, glyphs_after,
    
    374
    -                                            glyphs_output);
    
    375
    -        /*Don't consider anything involving context.  Just do the
    
    376
    -          simple cases*/
    
    377
    -        FT_TRACE4(("num inputs: %d\n", hb_set_get_population( glyphs_input )));
    
    378
    -        FT_TRACE4(("num outputs: %d\n", hb_set_get_population( glyphs_output )));
    
    379
    -        FT_TRACE4(("num before: %d\n", hb_set_get_population( glyphs_before )));
    
    380
    -        FT_TRACE4(("num after: %d\n", hb_set_get_population( glyphs_after )));
    
    381
    -        hb_codepoint_t input = HB_SET_VALUE_INVALID;
    
    382
    -        while ( hb_set_next( glyphs_input, &input ) )
    
    383
    -        {
    
    384
    -            FT_TRACE4(("input: %d\n", input));
    
    385
    -        }
    
    386
    -        hb_codepoint_t output = HB_SET_VALUE_INVALID;
    
    387
    -        while ( hb_set_next( glyphs_output, &output ) )
    
    388
    -        {
    
    389
    -            FT_TRACE4(("output: %d\n", output));
    
    390
    -        }
    
    391
    -        if ( hb_set_get_population( glyphs_before ) > 0 ||
    
    392
    -             hb_set_get_population( glyphs_after ) > 0 )
    
    393
    -        {
    
    394
    -            continue;
    
    395
    -        }
    
    396
    -        if ( hb_set_get_population( glyphs_output ) != 1 )
    
    397
    -        {
    
    398
    -            continue;
    
    399
    -        }
    
    400
    -
    
    401
    -        hb_codepoint_t input_glyph_index = HB_SET_VALUE_INVALID;
    
    402
    -        const AF_AdjustmentDatabaseEntry* input_entry = NULL;
    
    403
    -        FT_UInt32 input_codepoint = 0;
    
    404
    -        while ( hb_set_next( glyphs_input, &input_glyph_index ) ) {
    
    405
    -            FT_TRACE4(("input glyph: %d\n", input_glyph_index));
    
    406
    -            FT_UInt32 inner_codepoint = af_reverse_character_map_lookup_( *map, input_glyph_index, oldlength );
    
    407
    -            if ( inner_codepoint == 0 )
    
    408
    -            {
    
    409
    -                continue;
    
    410
    -            }
    
    411
    -            const AF_AdjustmentDatabaseEntry* entry = af_adjustment_database_lookup( inner_codepoint );
    
    412
    -            if ( entry == NULL )
    
    413
    -            {
    
    414
    -                continue;
    
    415
    -            }
    
    416
    -            if ( input_codepoint == 0 ) {
    
    417
    -                input_codepoint = inner_codepoint;
    
    418
    -            }
    
    419
    -
    
    420
    -            if ( input_entry == NULL )
    
    421
    -            {
    
    422
    -                input_entry = entry;
    
    423
    -            }
    
    424
    -            else
    
    425
    -            {
    
    426
    -                if ( !af_adjustment_database_entry_equals( input_entry, entry ) )
    
    427
    -                {
    
    428
    -                    goto end;
    
    429
    -                }
    
    430
    -            }
    
    431
    -        }
    
    432
    -
    
    433
    -        if ( input_codepoint == 0 )
    
    434
    -        {
    
    435
    -            continue;
    
    436
    -        }
    
    437
    -
    
    438
    -        output_glyph_index = HB_SET_VALUE_INVALID;
    
    439
    -        hb_set_next( glyphs_output, &output_glyph_index );
    
    440
    -
    
    441
    -        /*Make pair output glyph index -> input unicode*/
    
    442
    -        error = af_reverse_character_map_expand( *map, &capacity, memory );
    
    443
    -        if ( error ) {
    
    444
    -            goto Exit;
    
    445
    -        }
    
    446
    -
    
    447
    -        FT_Long index = ( *map )->length++;
    
    448
    -        ( *map )->entries[index].glyph_index = output_glyph_index;
    
    449
    -        ( *map )->entries[index].codepoint = input_codepoint;
    
    450
    -
    
    451
    -        end: ;
    
    572
    +        FT_TRACE4(("char: %c, glyph: %d\n", ( *map )->entries[i].codepoint, ( *map )->entries[i].glyph_index ) );
    
    452 573
         }
    
    453 574
     
    
    454
    -    ft_qsort(
    
    455
    -        ( *map )->entries,
    
    456
    -        ( *map )->length,
    
    457
    -        sizeof( AF_ReverseMapEntry ),
    
    458
    -        af_reverse_character_map_entry_compare
    
    459
    -    );
    
    460
    -
    
    461
    -#endif /*FT_CONFIG_OPTION_USE_HARFBUZZ*/
    
    575
    +    FT_TRACE4(( "    reverse character map built successfully"\
    
    576
    +                " with %d entries\n", (*map)->length ));
    
    462 577
     
    
    463 578
     Exit:
    
    464 579
         face->charmap = old_charmap;
    
    ... ... @@ -472,10 +587,7 @@ Exit:
    472 587
             FT_FREE( *map );
    
    473 588
             return error;
    
    474 589
         }
    
    475
    -#ifdef FT_DEBUG_LEVEL_TRACE
    
    476
    -    FT_TRACE4(( "    reverse character map built successfully"\
    
    477
    -                " with %d entries and %d failed lookups.\n", (*map)->length, failed_lookups ));
    
    478
    -#endif
    
    590
    +
    
    479 591
         return FT_Err_Ok;
    
    480 592
     }
    
    481 593
     
    

  • src/autofit/aflatin.c
    ... ... @@ -2804,7 +2804,6 @@ af_remove_segments_containing_point(AF_GlyphHints hints, AF_Point point)
    2804 2804
     {
    
    2805 2805
       AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT];
    
    2806 2806
       AF_Segment segments = axis->segments;
    
    2807
    -  AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments );
    
    2808 2807
       for ( FT_Int i = 0; i < axis->num_segments; i++ )
    
    2809 2808
       {
    
    2810 2809
         AF_Segment seg = &segments[i];
    


  • reply via email to

    [Prev in Thread] Current Thread [Next in Thread]