freetype-commit
[Top][All Lists]
Advanced

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

[Git][freetype/freetype][gsoc-craig-2023] Prototype adjustment database,


From: Craig White (@gerzytet)
Subject: [Git][freetype/freetype][gsoc-craig-2023] Prototype adjustment database, reverse character lookup, and fixes for a few characters
Date: Sun, 04 Jun 2023 19:32:10 +0000

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

Commits:

  • f8e996bf
    by Craig White at 2023-06-04T15:31:13-04:00
    Prototype adjustment database, reverse character lookup, and fixes for a few characters
    

6 changed files:

Changes:

  • src/autofit/afadjust.c
    1
    +#include "afadjust.h"
    
    2
    +#include <freetype/freetype.h>
    
    3
    +#include <freetype/internal/ftobjs.h>
    
    4
    +#include <freetype/internal/ftmemory.h>
    
    5
    +
    
    6
    +#define AF_ADJUSTMENT_DATABASE_LENGTH 12
    
    7
    +
    
    8
    +/*TODO: find out whether capital u/U with accent entries are needed*/
    
    9
    +/*the accent won't merge with the rest of the glyph because the accent mark is sitting above empty space*/
    
    10
    +FT_LOCAL_ARRAY_DEF( AF_AdjustmentDatabaseEntry )
    
    11
    +adjustment_database[AF_ADJUSTMENT_DATABASE_LENGTH] = {
    
    12
    +    {'i',   AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE},
    
    13
    +    {'j',   AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE},
    
    14
    +    {0xC8,  AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*E with grave*/
    
    15
    +    {0xCC,  AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*I with grave*/
    
    16
    +    {0xD9,  AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*U with grave*/
    
    17
    +    {0xE0,  AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*a with grave*/
    
    18
    +    {0xEC,  AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*i with grave*/
    
    19
    +    {0x114, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*E with macron*/
    
    20
    +    {0x12A, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*I with macron*/
    
    21
    +    {0x12B, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*i with macron*/
    
    22
    +    {0x16A, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}, /*U with macron*/
    
    23
    +    {0x16B, AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE}  /*u with macron*/
    
    24
    +    /*TODO: find out why E won't work, even though it appears to be one-on-one*/
    
    25
    +};
    
    26
    +
    
    27
    +/*Helper function: get the adjustment database entry for a codepoint*/
    
    28
    +FT_LOCAL_DEF( const AF_AdjustmentDatabaseEntry* )
    
    29
    +af_adjustment_database_lookup( FT_UInt32 codepoint ) {
    
    30
    +    for ( FT_Int entry = 0; entry < AF_ADJUSTMENT_DATABASE_LENGTH; entry++ ) {
    
    31
    +        if ( adjustment_database[entry].codepoint == codepoint ) {
    
    32
    +            return &adjustment_database[entry];
    
    33
    +        }
    
    34
    +    }
    
    35
    +
    
    36
    +    return NULL;
    
    37
    +}
    
    38
    +
    
    39
    +FT_LOCAL_DEF( AF_VerticalSeparationAdjustmentType )
    
    40
    +af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int glyph_index ) {
    
    41
    +    FT_UInt32 codepoint = af_reverse_character_map_lookup( map, glyph_index );
    
    42
    +    const AF_AdjustmentDatabaseEntry *entry = af_adjustment_database_lookup( codepoint );
    
    43
    +    if ( entry == NULL ) {
    
    44
    +        return AF_VERTICAL_ADJUSTMENT_NONE;
    
    45
    +    }
    
    46
    +    return entry->vertical_separation_adjustment_type;
    
    47
    +}
    
    48
    +
    
    49
    +typedef struct AF_ReverseMapEntry_ {
    
    50
    +    FT_Int glyph_index;
    
    51
    +    FT_UInt32 codepoint;
    
    52
    +} AF_ReverseMapEntry;
    
    53
    +
    
    54
    +typedef struct AF_ReverseCharacterMap_ {
    
    55
    +    FT_UInt length;
    
    56
    +    AF_ReverseMapEntry *entries;
    
    57
    +} AF_ReverseCharacterMap_Rec;
    
    58
    +
    
    59
    +FT_LOCAL_DEF(FT_UInt32)
    
    60
    +af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index ) {
    
    61
    +    if ( map == NULL ) {
    
    62
    +        return 0;
    
    63
    +    }
    
    64
    +
    
    65
    +    for ( FT_UInt entry = 0; entry < map->length; entry++ ) {
    
    66
    +        if ( map->entries[entry].glyph_index == glyph_index ) {
    
    67
    +            return map->entries[entry].codepoint;
    
    68
    +        }
    
    69
    +    }
    
    70
    +
    
    71
    +    return 0;
    
    72
    +}
    
    73
    +
    
    74
    +FT_LOCAL_DEF( FT_Error )
    
    75
    +af_reverse_character_map_new( FT_Face face, AF_ReverseCharacterMap *map, FT_Memory memory ) {
    
    76
    +    /* Search for a unicode charmap */
    
    77
    +    /* If there isn't one, create a blank map */
    
    78
    +    
    
    79
    +    /*TODO: change this to logic that searches for a "preferred" unicode charmap that maps the most codepoints*/
    
    80
    +    /*see find_unicode_charmap*/
    
    81
    +    /*TODO: use GSUB lookups    */
    
    82
    +    FT_CMap unicode_charmap = NULL;
    
    83
    +    for ( FT_UInt i = 0; i < face->num_charmaps; i++ ) {
    
    84
    +        if ( face->charmaps[i]->encoding == FT_ENCODING_UNICODE ) {
    
    85
    +            unicode_charmap = FT_CMAP( face->charmaps[i] );
    
    86
    +        }
    
    87
    +    }
    
    88
    +    
    
    89
    +    if ( unicode_charmap == NULL ) {
    
    90
    +        *map = NULL;
    
    91
    +        return FT_Err_Ok;
    
    92
    +    }
    
    93
    +
    
    94
    +    FT_Error error;
    
    95
    +
    
    96
    +    if ( FT_NEW( *map ) ) {
    
    97
    +        goto Exit;
    
    98
    +    }
    
    99
    +
    
    100
    +    FT_Int capacity = 10;
    
    101
    +    FT_Int size = 0;
    
    102
    +    
    
    103
    +    if ( FT_NEW_ARRAY((*map)->entries, capacity) ) {
    
    104
    +        goto Exit;
    
    105
    +    }
    
    106
    +    for ( FT_Int i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ ) {
    
    107
    +        FT_UInt32 codepoint = adjustment_database[i].codepoint;
    
    108
    +        FT_Int glyph = unicode_charmap->clazz->char_index(unicode_charmap, codepoint);
    
    109
    +        if ( glyph == 0 ) {
    
    110
    +            continue;
    
    111
    +        }
    
    112
    +        if (size == capacity) {
    
    113
    +            capacity += capacity / 2;
    
    114
    +            if ( FT_RENEW_ARRAY((*map)->entries, size, capacity) ) {
    
    115
    +                goto Exit;
    
    116
    +            }
    
    117
    +        }
    
    118
    +        size++;
    
    119
    +        (*map)->entries[i].glyph_index = glyph;
    
    120
    +        (*map)->entries[i].codepoint = codepoint;
    
    121
    +    }
    
    122
    +    (*map)->length = size;
    
    123
    +
    
    124
    +Exit:
    
    125
    +    if ( error ) {
    
    126
    +        if ( *map ) {
    
    127
    +            FT_FREE( ( *map )->entries );
    
    128
    +        }
    
    129
    +        FT_FREE( *map );
    
    130
    +        return error;
    
    131
    +    }
    
    132
    +
    
    133
    +    return FT_Err_Ok;
    
    134
    +}
    
    135
    +
    
    136
    +FT_LOCAL_DEF( FT_Error )
    
    137
    +af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory ) {
    
    138
    +    FT_FREE( map->entries );
    
    139
    +    return FT_Err_Ok;
    
    140
    +}
    \ No newline at end of file

  • src/autofit/afadjust.h
    1
    +#ifndef AFADJUST_H_
    
    2
    +#define AFADJUST_H_
    
    3
    +
    
    4
    +#include <freetype/fttypes.h>
    
    5
    +
    
    6
    +FT_BEGIN_HEADER
    
    7
    +
    
    8
    +/*The type of adjustment that should be done to prevent cases where 2 parts of a character*/
    
    9
    +/*stacked vertically merge, even though they should be separate*/
    
    10
    +typedef enum AF_VerticalSeparationAdjustmentType_ {
    
    11
    +    AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE,
    
    12
    +    /*"One on one" means that the character is expected to be one contour on top of another, where the contours should not touch*/
    
    13
    +    /*the hinter will force the contours to have a gap of at least 1 pixel between them*/
    
    14
    +    /*by moving the top contour up */
    
    15
    +    AF_VERTICAL_ADJUSTMENT_NONE
    
    16
    +
    
    17
    +    /*others will be needed, such as the case where the lower contour should be moved in the adjustment instead of the upper one*/
    
    18
    +    /*or umlats, where there are 2 contours which should be moved together*/
    
    19
    +    /*and a way of handling A and O, where the letter consists of 2 contours*/
    
    20
    +} AF_VerticalSeparationAdjustmentType;
    
    21
    +
    
    22
    +typedef struct AF_AdjustmentDatabaseEntry_ {
    
    23
    +    FT_UInt32 codepoint;
    
    24
    +    AF_VerticalSeparationAdjustmentType vertical_separation_adjustment_type;
    
    25
    +  } AF_AdjustmentDatabaseEntry;
    
    26
    +
    
    27
    +struct AF_ReverseCharacterMap_;
    
    28
    +
    
    29
    +typedef struct AF_ReverseCharacterMap_ *AF_ReverseCharacterMap;
    
    30
    +
    
    31
    +FT_LOCAL(AF_VerticalSeparationAdjustmentType)
    
    32
    +af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int glyph_index );
    
    33
    +
    
    34
    +FT_LOCAL( FT_UInt32 )
    
    35
    +af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index );
    
    36
    +
    
    37
    +/*allocate and populate the reverse character map, using the character map within the face*/
    
    38
    +FT_LOCAL( FT_Error )
    
    39
    +af_reverse_character_map_new( FT_Face face, AF_ReverseCharacterMap *map, FT_Memory memory );
    
    40
    + 
    
    41
    +/*free the reverse character map*/
    
    42
    +FT_LOCAL( FT_Error )
    
    43
    +af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory );
    
    44
    +
    
    45
    +FT_END_HEADER
    
    46
    +
    
    47
    +#endif
    \ No newline at end of file

  • src/autofit/aflatin.c
    ... ... @@ -22,6 +22,7 @@
    22 22
     #include "afglobal.h"
    
    23 23
     #include "aflatin.h"
    
    24 24
     #include "aferrors.h"
    
    25
    +#include "afadjust.h"
    
    25 26
     
    
    26 27
     
    
    27 28
       /**************************************************************************
    
    ... ... @@ -227,7 +228,6 @@
    227 228
                                          dummy->units_per_em / 100 );
    
    228 229
             axis->width_count = num_widths;
    
    229 230
           }
    
    230
    -
    
    231 231
         Exit:
    
    232 232
           for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
    
    233 233
           {
    
    ... ... @@ -1153,6 +1153,8 @@
    1153 1153
             goto Exit;
    
    1154 1154
           }
    
    1155 1155
           af_latin_metrics_check_digits( metrics, face );
    
    1156
    +      
    
    1157
    +      af_reverse_character_map_new( face, &metrics->root.reverse_charmap, face->memory );
    
    1156 1158
         }
    
    1157 1159
     
    
    1158 1160
       Exit:
    
    ... ... @@ -1502,6 +1504,11 @@
    1502 1504
         af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
    
    1503 1505
       }
    
    1504 1506
     
    
    1507
    +  FT_CALLBACK_DEF( void )
    
    1508
    +  af_latin_metrics_done( AF_StyleMetrics metrics_ ) {
    
    1509
    +    AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_;
    
    1510
    +    af_reverse_character_map_done( metrics->root.reverse_charmap, metrics->root.globals->face->memory );
    
    1511
    +  }
    
    1505 1512
     
    
    1506 1513
       /* Extract standard_width from writing system/script specific */
    
    1507 1514
       /* metrics class.                                             */
    
    ... ... @@ -2738,6 +2745,83 @@
    2738 2745
       }
    
    2739 2746
     
    
    2740 2747
     
    
    2748
    +void af_glyph_hints_apply_adjustments(AF_GlyphHints hints, AF_Dimension dim, FT_Int glyph_index, AF_ReverseCharacterMap reverse_charmap) {
    
    2749
    +  if ( dim != AF_DIMENSION_VERT ) {
    
    2750
    +    return;
    
    2751
    +  }
    
    2752
    +  if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) == AF_VERTICAL_ADJUSTMENT_ONE_ON_ONE &&
    
    2753
    +      hints->num_contours == 2 ) {
    
    2754
    +    
    
    2755
    +    /* Figure out which contout is the higher one by finding the one */
    
    2756
    +    /* with the highest minimum y value */
    
    2757
    +
    
    2758
    +    FT_Int highest_contour = -1;
    
    2759
    +    FT_Pos highest_min_y = 0;
    
    2760
    +    FT_Pos current_min_y = 0;
    
    2761
    +
    
    2762
    +    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ ) {
    
    2763
    +      AF_Point point = hints->contours[contour];
    
    2764
    +      AF_Point first_point = point;
    
    2765
    +      if ( point == NULL ) { /*TODO: is this necessary?*/
    
    2766
    +        continue;
    
    2767
    +      }
    
    2768
    +      current_min_y = point->y;
    
    2769
    +
    
    2770
    +      do {
    
    2771
    +        if ( point->y < current_min_y ) {
    
    2772
    +          current_min_y = point->y;
    
    2773
    +        }
    
    2774
    +        point = point->next;
    
    2775
    +      } while ( point != first_point );
    
    2776
    +
    
    2777
    +      if ( highest_contour == -1 || current_min_y > highest_min_y ) {
    
    2778
    +        highest_min_y = current_min_y;
    
    2779
    +        highest_contour = contour;
    
    2780
    +      }
    
    2781
    +    }
    
    2782
    +
    
    2783
    +    /* If there are any contours that have a maximum y coordinate */
    
    2784
    +    /* greater or equal to the minimum y coordinate of the previously found highest*/
    
    2785
    +    /* contour, bump the high contour up until the distance is one pixel */
    
    2786
    +
    
    2787
    +    FT_Int adjustment_amount = 0;
    
    2788
    +    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ ) {
    
    2789
    +      if (contour == highest_contour) {
    
    2790
    +        continue;
    
    2791
    +      }
    
    2792
    +      AF_Point point = hints->contours[contour];
    
    2793
    +      AF_Point first_point = point;
    
    2794
    +      if ( point == NULL ) {
    
    2795
    +        continue;
    
    2796
    +      }
    
    2797
    +      FT_Pos max_y = point->y;
    
    2798
    +
    
    2799
    +      do {
    
    2800
    +        if ( point->y > max_y ) {
    
    2801
    +          max_y = point->y;
    
    2802
    +        }
    
    2803
    +        point = point->next;
    
    2804
    +      } while ( point != first_point );
    
    2805
    +
    
    2806
    +      if ( max_y >= highest_min_y - 64 ) {
    
    2807
    +        adjustment_amount = 64 - (highest_min_y - max_y);
    
    2808
    +      }
    
    2809
    +    }
    
    2810
    +
    
    2811
    +    if ( adjustment_amount > 0 ) {
    
    2812
    +      AF_Point point = hints->contours[highest_contour];
    
    2813
    +      AF_Point first_point = point;
    
    2814
    +      if ( point != NULL ) {
    
    2815
    +        do {
    
    2816
    +          point->y += adjustment_amount;
    
    2817
    +          point = point->next;
    
    2818
    +        } while ( point != first_point );
    
    2819
    +      }
    
    2820
    +    }
    
    2821
    +  }
    
    2822
    +}
    
    2823
    +
    
    2824
    +
    
    2741 2825
       /* Compute the snapped width of a given stem, ignoring very thin ones. */
    
    2742 2826
       /* There is a lot of voodoo in this function; changing the hard-coded  */
    
    2743 2827
       /* parameters influence the whole hinting process.                     */
    
    ... ... @@ -3605,6 +3689,7 @@
    3605 3689
             af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
    
    3606 3690
             af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
    
    3607 3691
             af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
    
    3692
    +        af_glyph_hints_apply_adjustments(hints, (AF_Dimension) dim, glyph_index, metrics->root.reverse_charmap);
    
    3608 3693
           }
    
    3609 3694
         }
    
    3610 3695
     
    
    ... ... @@ -3633,12 +3718,11 @@
    3633 3718
     
    
    3634 3719
         (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init,        /* style_metrics_init    */
    
    3635 3720
         (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale,       /* style_metrics_scale   */
    
    3636
    -    (AF_WritingSystem_DoneMetricsFunc) NULL,                         /* style_metrics_done    */
    
    3721
    +    (AF_WritingSystem_DoneMetricsFunc) af_latin_metrics_done,        /* style_metrics_done    */
    
    3637 3722
         (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths, /* style_metrics_getstdw */
    
    3638 3723
     
    
    3639 3724
         (AF_WritingSystem_InitHintsFunc)   af_latin_hints_init,          /* style_hints_init      */
    
    3640 3725
         (AF_WritingSystem_ApplyHintsFunc)  af_latin_hints_apply          /* style_hints_apply     */
    
    3641 3726
       )
    
    3642 3727
     
    
    3643
    -
    
    3644 3728
     /* END */

  • src/autofit/aftypes.h
    ... ... @@ -39,6 +39,7 @@
    39 39
     #include <freetype/internal/ftdebug.h>
    
    40 40
     
    
    41 41
     #include "afblue.h"
    
    42
    +#include "afadjust.h"
    
    42 43
     
    
    43 44
     #ifdef FT_DEBUG_AUTOFIT
    
    44 45
     #include FT_CONFIG_STANDARD_LIBRARY_H
    
    ... ... @@ -417,6 +418,7 @@ extern void* af_debug_hints_;
    417 418
         FT_Bool         digits_have_same_width;
    
    418 419
     
    
    419 420
         AF_FaceGlobals  globals;    /* to access properties */
    
    421
    +    AF_ReverseCharacterMap  reverse_charmap;
    
    420 422
     
    
    421 423
       } AF_StyleMetricsRec;
    
    422 424
     
    

  • src/autofit/autofit.c
    ... ... @@ -30,6 +30,7 @@
    30 30
     #include "afmodule.c"
    
    31 31
     #include "afranges.c"
    
    32 32
     #include "afshaper.c"
    
    33
    +#include "afadjust.c"
    
    33 34
     
    
    34 35
     
    
    35 36
     /* END */

  • src/base/ftobjs.c
    ... ... @@ -1358,7 +1358,6 @@
    1358 1358
                           driver );
    
    1359 1359
       }
    
    1360 1360
     
    
    1361
    -
    
    1362 1361
       /**************************************************************************
    
    1363 1362
        *
    
    1364 1363
        * @Function:
    


  • reply via email to

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