freetype-commit
[Top][All Lists]
Advanced

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

[Git][freetype/freetype][gsoc-craig-2023-final] [autofit] Implement vert


From: Craig White (@gerzytet)
Subject: [Git][freetype/freetype][gsoc-craig-2023-final] [autofit] Implement vertical separation adjustment
Date: Fri, 03 Nov 2023 03:42:18 +0000

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

Commits:

  • 41bb41de
    by Craig White at 2023-11-02T23:41:40-04:00
    [autofit] Implement vertical separation adjustment
    * include/freetype/internal/fttrace.h add "afadjust" trace function
    definition, to be used for all adjustment database code.
    * src/autofit/afadjust.c fix null derefence when reverse character map
    is null.
    * src/autofit/aflatin.c contour positions are now adjusted vertically
    based on the entries in the adjustment database and reverse character map
    src/autofit/aftypes.h add reverse character map to AF_StyleMetricsRec
    

4 changed files:

Changes:

  • include/freetype/internal/fttrace.h
    ... ... @@ -164,6 +164,7 @@ FT_TRACE_DEF( afhints )
    164 164
     FT_TRACE_DEF( afmodule )
    
    165 165
     FT_TRACE_DEF( aflatin )
    
    166 166
     FT_TRACE_DEF( afshaper )
    
    167
    +FT_TRACE_DEF( afadjust )
    
    167 168
     
    
    168 169
       /* SDF components */
    
    169 170
     FT_TRACE_DEF( sdf )       /* signed distance raster for outlines (ftsdf.c) */
    

  • src/autofit/afadjust.c
    ... ... @@ -242,7 +242,10 @@ af_reverse_character_map_lookup_( AF_ReverseCharacterMap map, FT_Int glyph_index
    242 242
     FT_LOCAL_DEF( FT_UInt32 )
    
    243 243
     af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index )
    
    244 244
     {
    
    245
    -    return af_reverse_character_map_lookup_( map, glyph_index, map->length );
    
    245
    +  if ( map == NULL ) {
    
    246
    +    return 0;
    
    247
    +  }
    
    248
    +  return af_reverse_character_map_lookup_( map, glyph_index, map->length );
    
    246 249
     }
    
    247 250
     
    
    248 251
     /*prepare to add one more entry to the reverse character map
    
    ... ... @@ -271,6 +274,7 @@ af_reverse_character_map_expand( AF_ReverseCharacterMap map, FT_Long *capacity,
    271 274
     FT_LOCAL_DEF( FT_Error )
    
    272 275
     af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals globals )
    
    273 276
     {
    
    277
    +    *map = NULL;
    
    274 278
         FT_Face face = globals->face;
    
    275 279
         FT_Memory memory = face->memory;
    
    276 280
         /* Search for a unicode charmap */
    
    ... ... @@ -344,6 +348,7 @@ Exit:
    344 348
                 FT_FREE( ( *map )->entries );
    
    345 349
             }
    
    346 350
             FT_FREE( *map );
    
    351
    +        *map = NULL;
    
    347 352
             return error;
    
    348 353
         }
    
    349 354
     
    
    ... ... @@ -352,6 +357,9 @@ Exit:
    352 357
     
    
    353 358
     FT_LOCAL_DEF( FT_Error )
    
    354 359
     af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory ) {
    
    355
    -    FT_FREE( map->entries );
    
    360
    +    if ( map != NULL ) {
    
    361
    +      FT_FREE( map->entries );
    
    362
    +    }
    
    363
    +    FT_FREE( map );
    
    356 364
         return FT_Err_Ok;
    
    357 365
     }

  • src/autofit/aflatin.c
    ... ... @@ -22,7 +22,7 @@
    22 22
     #include "afglobal.h"
    
    23 23
     #include "aflatin.h"
    
    24 24
     #include "aferrors.h"
    
    25
    -
    
    25
    +#include "afadjust.h"
    
    26 26
     
    
    27 27
       /**************************************************************************
    
    28 28
        *
    
    ... ... @@ -1155,6 +1155,8 @@
    1155 1155
           af_latin_metrics_check_digits( metrics, face );
    
    1156 1156
         }
    
    1157 1157
     
    
    1158
    +    af_reverse_character_map_new( &metrics->root.reverse_charmap, metrics->root.globals );
    
    1159
    +
    
    1158 1160
       Exit:
    
    1159 1161
         face->charmap = oldmap;
    
    1160 1162
         return error;
    
    ... ... @@ -1484,6 +1486,11 @@
    1484 1486
         }
    
    1485 1487
       }
    
    1486 1488
     
    
    1489
    +  FT_CALLBACK_DEF( void )
    
    1490
    +  af_latin_metrics_done( AF_StyleMetrics metrics_ ) {
    
    1491
    +    AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_;
    
    1492
    +    af_reverse_character_map_done( metrics->root.reverse_charmap, metrics->root.globals->face->memory );
    
    1493
    +  }
    
    1487 1494
     
    
    1488 1495
       /* Scale global values in both directions. */
    
    1489 1496
     
    
    ... ... @@ -2737,6 +2744,303 @@
    2737 2744
         return width;
    
    2738 2745
       }
    
    2739 2746
     
    
    2747
    +#undef  FT_COMPONENT
    
    2748
    +#define FT_COMPONENT  afadjust
    
    2749
    +
    
    2750
    +static void
    
    2751
    +af_move_contour_vertically( AF_Point contour,
    
    2752
    +                            FT_Int movement )
    
    2753
    +{
    
    2754
    +  AF_Point point = contour;
    
    2755
    +  AF_Point first_point = point;
    
    2756
    +  if ( point != NULL )
    
    2757
    +  {
    
    2758
    +    do
    
    2759
    +    {
    
    2760
    +      point->y += movement;
    
    2761
    +      point = point->next;
    
    2762
    +    } while ( point != first_point );
    
    2763
    +  }
    
    2764
    +}
    
    2765
    +
    
    2766
    +static FT_Int
    
    2767
    +af_find_highest_contour( AF_GlyphHints hints ) {
    
    2768
    +  FT_Int highest_contour = -1;
    
    2769
    +  FT_Pos highest_min_y = 0;
    
    2770
    +  FT_Pos current_min_y = 0;
    
    2771
    +
    
    2772
    +  for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    2773
    +  {
    
    2774
    +    AF_Point point = hints->contours[contour];
    
    2775
    +    AF_Point first_point = point;
    
    2776
    +    if ( point == NULL )
    
    2777
    +    {
    
    2778
    +      continue;
    
    2779
    +    }
    
    2780
    +    current_min_y = point->y;
    
    2781
    +
    
    2782
    +    do
    
    2783
    +    {
    
    2784
    +      if ( point->y < current_min_y )
    
    2785
    +      {
    
    2786
    +        current_min_y = point->y;
    
    2787
    +      }
    
    2788
    +      point = point->next;
    
    2789
    +    } while ( point != first_point );
    
    2790
    +
    
    2791
    +    if ( highest_contour == -1 || current_min_y > highest_min_y )
    
    2792
    +    {
    
    2793
    +      highest_min_y = current_min_y;
    
    2794
    +      highest_contour = contour;
    
    2795
    +    }
    
    2796
    +  }
    
    2797
    +
    
    2798
    +  return highest_contour;
    
    2799
    +}
    
    2800
    +
    
    2801
    +/*True if the given contour overlaps horizontally with the bounding box
    
    2802
    +  Of all other contours combined.
    
    2803
    +  This is a helper for af_glyph_hints_apply_vertical_separation_adjustments */
    
    2804
    +FT_Bool
    
    2805
    +af_check_contour_horizontal_overlap( AF_GlyphHints hints,
    
    2806
    +                                     FT_Int contour_index )
    
    2807
    +{
    
    2808
    +  FT_Pos contour_max_x = -32000;
    
    2809
    +  FT_Pos contour_min_x = 32000;
    
    2810
    +  FT_Pos others_max_x = -32000;
    
    2811
    +  FT_Pos others_min_x = 32000;
    
    2812
    +
    
    2813
    +  for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    2814
    +  {
    
    2815
    +    AF_Point first_point = hints->contours[contour];
    
    2816
    +    AF_Point p = first_point;
    
    2817
    +
    
    2818
    +    do
    
    2819
    +    {
    
    2820
    +      p = p->next;
    
    2821
    +      if ( contour == contour_index )
    
    2822
    +      {
    
    2823
    +        if ( p->x < contour_min_x )
    
    2824
    +        {
    
    2825
    +          contour_min_x = p->x;
    
    2826
    +        }
    
    2827
    +        if ( p->x > contour_max_x )
    
    2828
    +        {
    
    2829
    +          contour_max_x = p->x;
    
    2830
    +        }
    
    2831
    +      }
    
    2832
    +      else /* ( contour != contour_index ) */
    
    2833
    +      {
    
    2834
    +        if ( p->x < others_min_x )
    
    2835
    +        {
    
    2836
    +          others_min_x = p->x;
    
    2837
    +        }
    
    2838
    +        if ( p->x > others_max_x )
    
    2839
    +        {
    
    2840
    +          others_max_x = p->x;
    
    2841
    +        }
    
    2842
    +      }
    
    2843
    +    }
    
    2844
    +    while (p != first_point);
    
    2845
    +  }
    
    2846
    +
    
    2847
    +  FT_Bool horizontal_overlap =
    
    2848
    +    (others_min_x <= contour_max_x && contour_max_x <= others_max_x) ||
    
    2849
    +    (others_min_x <= contour_min_x && contour_min_x <= others_max_x) ||
    
    2850
    +    (contour_max_x >= others_max_x && contour_min_x <= others_min_x);
    
    2851
    +
    
    2852
    +  return horizontal_overlap;
    
    2853
    +}
    
    2854
    +
    
    2855
    +void
    
    2856
    +af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
    
    2857
    +                                                      AF_Dimension dim,
    
    2858
    +                                                      FT_Int glyph_index,
    
    2859
    +                                                      AF_ReverseCharacterMap reverse_charmap )
    
    2860
    +{
    
    2861
    +  FT_TRACE4(("Enter af_glyph_hints_apply_vertical_separation_adjustments\n"));
    
    2862
    +  if ( dim != AF_DIMENSION_VERT )
    
    2863
    +  {
    
    2864
    +    return;
    
    2865
    +  }
    
    2866
    +
    
    2867
    +  if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) == AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP
    
    2868
    +       && hints->num_contours >= 2 )
    
    2869
    +  {
    
    2870
    +    FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments: Applying vertical adjustment: AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP\n" ));
    
    2871
    +
    
    2872
    +    /* Figure out which contout is the higher one by finding the one */
    
    2873
    +    /* with the highest minimum y value */
    
    2874
    +
    
    2875
    +    FT_Int highest_contour = -1;
    
    2876
    +    FT_Pos highest_min_y = 0;
    
    2877
    +    FT_Pos current_min_y = 0;
    
    2878
    +
    
    2879
    +    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    2880
    +    {
    
    2881
    +      AF_Point point = hints->contours[contour];
    
    2882
    +      AF_Point first_point = point;
    
    2883
    +      if ( point == NULL )
    
    2884
    +      {
    
    2885
    +        continue;
    
    2886
    +      }
    
    2887
    +      current_min_y = point->y;
    
    2888
    +
    
    2889
    +      do
    
    2890
    +      {
    
    2891
    +        if ( point->y < current_min_y )
    
    2892
    +        {
    
    2893
    +          current_min_y = point->y;
    
    2894
    +        }
    
    2895
    +        point = point->next;
    
    2896
    +      } while ( point != first_point );
    
    2897
    +
    
    2898
    +      if ( highest_contour == -1 || current_min_y > highest_min_y )
    
    2899
    +      {
    
    2900
    +        highest_min_y = current_min_y;
    
    2901
    +        highest_contour = contour;
    
    2902
    +      }
    
    2903
    +    }
    
    2904
    +
    
    2905
    +    /* check for a horizontal overtap between the top contour and the rest */
    
    2906
    +    /* if there is no overlap, do not adjust. */
    
    2907
    +
    
    2908
    +    FT_Bool horizontal_overlap = af_check_contour_horizontal_overlap( hints, highest_contour );
    
    2909
    +    if (!horizontal_overlap) {
    
    2910
    +      FT_TRACE4(( "    Top contour does not horizontally overlap with other contours.  Skipping adjustment.\n" ));
    
    2911
    +      return;
    
    2912
    +    }
    
    2913
    +
    
    2914
    +    /* If there are any contours that have a maximum y coordinate */
    
    2915
    +    /* greater or equal to the minimum y coordinate of the previously found highest*/
    
    2916
    +    /* contour, bump the high contour up until the distance is one pixel */
    
    2917
    +
    
    2918
    +    FT_Int adjustment_amount = 0;
    
    2919
    +    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    2920
    +    {
    
    2921
    +      if ( contour == highest_contour )
    
    2922
    +      {
    
    2923
    +        continue;
    
    2924
    +      }
    
    2925
    +      AF_Point point = hints->contours[contour];
    
    2926
    +      AF_Point first_point = point;
    
    2927
    +      if ( point == NULL )
    
    2928
    +      {
    
    2929
    +        continue;
    
    2930
    +      }
    
    2931
    +      FT_Pos max_y = point->y;
    
    2932
    +
    
    2933
    +      do
    
    2934
    +      {
    
    2935
    +        if ( point->y > max_y )
    
    2936
    +        {
    
    2937
    +          max_y = point->y;
    
    2938
    +        }
    
    2939
    +        point = point->next;
    
    2940
    +      } while ( point != first_point );
    
    2941
    +
    
    2942
    +      if ( max_y >= highest_min_y - 64 )
    
    2943
    +      {
    
    2944
    +        adjustment_amount = 64 - ( highest_min_y - max_y );
    
    2945
    +      }
    
    2946
    +    }
    
    2947
    +
    
    2948
    +    if ( adjustment_amount > 64 )
    
    2949
    +    {
    
    2950
    +      FT_TRACE4(( "    Calculated adjustment amount %d was more than threshold of 64.  Not adjusting\n", adjustment_amount ));
    
    2951
    +    }
    
    2952
    +    else if ( adjustment_amount > 0 )
    
    2953
    +    {
    
    2954
    +      FT_TRACE4(( "    Pushing top contour %d units up\n", adjustment_amount ));
    
    2955
    +      af_move_contour_vertically(hints->contours[highest_contour], adjustment_amount);
    
    2956
    +    }
    
    2957
    +  } else if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) == AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN
    
    2958
    +       && hints->num_contours >= 2 )
    
    2959
    +  {
    
    2960
    +    FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments: Applying vertical adjustment: AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN\n" ));
    
    2961
    +
    
    2962
    +    /*Find lowest contour*/
    
    2963
    +    FT_Int lowest_contour = -1;
    
    2964
    +    FT_Pos lowest_max_y = 0;
    
    2965
    +    FT_Pos current_max_y = 0;
    
    2966
    +
    
    2967
    +    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    2968
    +    {
    
    2969
    +      AF_Point point = hints->contours[contour];
    
    2970
    +      AF_Point first_point = point;
    
    2971
    +      if ( point == NULL )
    
    2972
    +      {
    
    2973
    +        continue;
    
    2974
    +      }
    
    2975
    +      current_max_y = point->y;
    
    2976
    +
    
    2977
    +      do
    
    2978
    +      {
    
    2979
    +        if ( point->y > current_max_y )
    
    2980
    +        {
    
    2981
    +          current_max_y = point->y;
    
    2982
    +        }
    
    2983
    +        point = point->next;
    
    2984
    +      } while ( point != first_point );
    
    2985
    +
    
    2986
    +      if ( lowest_contour == -1 || current_max_y < lowest_max_y )
    
    2987
    +      {
    
    2988
    +        lowest_max_y = current_max_y;
    
    2989
    +        lowest_contour = contour;
    
    2990
    +      }
    
    2991
    +    }
    
    2992
    +
    
    2993
    +    FT_Int adjustment_amount = 0;
    
    2994
    +    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    2995
    +    {
    
    2996
    +      if ( contour == lowest_contour )
    
    2997
    +      {
    
    2998
    +        continue;
    
    2999
    +      }
    
    3000
    +      AF_Point point = hints->contours[contour];
    
    3001
    +      AF_Point first_point = point;
    
    3002
    +      if ( point == NULL )
    
    3003
    +      {
    
    3004
    +        continue;
    
    3005
    +      }
    
    3006
    +      FT_Pos min_y = point->y;
    
    3007
    +
    
    3008
    +      do
    
    3009
    +      {
    
    3010
    +        if ( point->y < min_y )
    
    3011
    +        {
    
    3012
    +          min_y = point->y;
    
    3013
    +        }
    
    3014
    +        point = point->next;
    
    3015
    +      } while ( point != first_point );
    
    3016
    +
    
    3017
    +      if ( min_y <= lowest_max_y - 64 )
    
    3018
    +      {
    
    3019
    +        adjustment_amount = 64 - ( min_y - lowest_max_y );
    
    3020
    +      }
    
    3021
    +
    
    3022
    +      if ( adjustment_amount > 64 )
    
    3023
    +      {
    
    3024
    +        FT_TRACE4(( "    Calculated adjustment amount %d was more than threshold of 64.  Not adjusting\n", adjustment_amount ));
    
    3025
    +      }
    
    3026
    +      else if ( adjustment_amount > 0 )
    
    3027
    +      {
    
    3028
    +        FT_TRACE4(( "    Pushing bottom contour %d units down\n", adjustment_amount ));
    
    3029
    +        af_move_contour_vertically(hints->contours[lowest_contour], -adjustment_amount);
    
    3030
    +      }
    
    3031
    +    }
    
    3032
    +  }
    
    3033
    +  else
    
    3034
    +  {
    
    3035
    +    FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments: No vertical adjustment needed\n" ));
    
    3036
    +  }
    
    3037
    +
    
    3038
    +  FT_TRACE4(("Exit af_glyph_hints_apply_vertical_separation_adjustments\n"));
    
    3039
    +}
    
    3040
    +
    
    3041
    +#undef  FT_COMPONENT
    
    3042
    +#define FT_COMPONENT  aflatin
    
    3043
    +
    
    2740 3044
     
    
    2741 3045
       /* Compute the snapped width of a given stem, ignoring very thin ones. */
    
    2742 3046
       /* There is a lot of voodoo in this function; changing the hard-coded  */
    
    ... ... @@ -3605,6 +3909,7 @@
    3605 3909
             af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
    
    3606 3910
             af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
    
    3607 3911
             af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
    
    3912
    +        af_glyph_hints_apply_vertical_separation_adjustments(hints, (AF_Dimension) dim, glyph_index, metrics->root.reverse_charmap);
    
    3608 3913
           }
    
    3609 3914
         }
    
    3610 3915
     
    
    ... ... @@ -3633,7 +3938,7 @@
    3633 3938
     
    
    3634 3939
         (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init,        /* style_metrics_init    */
    
    3635 3940
         (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale,       /* style_metrics_scale   */
    
    3636
    -    (AF_WritingSystem_DoneMetricsFunc) NULL,                         /* style_metrics_done    */
    
    3941
    +    (AF_WritingSystem_DoneMetricsFunc) af_latin_metrics_done,                         /* style_metrics_done    */
    
    3637 3942
         (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths, /* style_metrics_getstdw */
    
    3638 3943
     
    
    3639 3944
         (AF_WritingSystem_InitHintsFunc)   af_latin_hints_init,          /* style_hints_init      */
    

  • src/autofit/aftypes.h
    ... ... @@ -423,6 +423,7 @@ extern void* af_debug_hints_;
    423 423
         FT_Bool         digits_have_same_width;
    
    424 424
     
    
    425 425
         AF_FaceGlobals  globals;    /* to access properties */
    
    426
    +    AF_ReverseCharacterMap  reverse_charmap;
    
    426 427
     
    
    427 428
       } AF_StyleMetricsRec;
    
    428 429
     
    


  • reply via email to

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