freetype-commit
[Top][All Lists]
Advanced

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

[Git][freetype/freetype][gsoc-craig-2023] Add a vertical adjustment mode


From: Craig White (@gerzytet)
Subject: [Git][freetype/freetype][gsoc-craig-2023] Add a vertical adjustment mode for pushing the bottom contour down and add a...
Date: Wed, 02 Aug 2023 22:53:47 +0000

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

Commits:

  • 9a813d0c
    by Craig White at 2023-08-02T18:52:29-04:00
    Add a vertical adjustment mode for pushing the bottom contour down and add a WIP tilde correction algorithm
    

4 changed files:

Changes:

  • include/freetype/config/ftoption.h
    ... ... @@ -431,7 +431,7 @@ FT_BEGIN_HEADER
    431 431
        *   them for certain configurations only.
    
    432 432
        */
    
    433 433
     /* #define FT_DEBUG_LEVEL_ERROR */
    
    434
    -/* #define FT_DEBUG_LEVEL_TRACE */
    
    434
    +#define FT_DEBUG_LEVEL_TRACE
    
    435 435
     
    
    436 436
     
    
    437 437
       /**************************************************************************
    

  • src/autofit/afadjust.c
    ... ... @@ -168,6 +168,17 @@ af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int glyph_ind
    168 168
         return entry->vertical_separation_adjustment_type;
    
    169 169
     }
    
    170 170
     
    
    171
    +/*TODO: this is a testing placeholder
    
    172
    +  it only returns 1 for n with tilde*/
    
    173
    +FT_LOCAL_DEF( FT_Int )
    
    174
    +af_lookup_tilde_correction_type( AF_ReverseCharacterMap map, FT_Int glyph_index ) {
    
    175
    +    FT_UInt32 codepoint = af_reverse_character_map_lookup( map, glyph_index );
    
    176
    +    if ( codepoint == 0xF1 ) {
    
    177
    +        return 1;
    
    178
    +    }
    
    179
    +    return 0;
    
    180
    +}
    
    181
    +
    
    171 182
     typedef struct AF_ReverseMapEntry_
    
    172 183
     {
    
    173 184
         FT_Int glyph_index;
    

  • src/autofit/afadjust.h
    ... ... @@ -35,6 +35,9 @@ typedef struct AF_ReverseCharacterMap_ *AF_ReverseCharacterMap;
    35 35
     FT_LOCAL(AF_VerticalSeparationAdjustmentType)
    
    36 36
     af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int glyph_index );
    
    37 37
     
    
    38
    +FT_LOCAL( FT_Int )
    
    39
    +af_lookup_tilde_correction_type( AF_ReverseCharacterMap map, FT_Int glyph_index );
    
    40
    +
    
    38 41
     FT_LOCAL( FT_UInt32 )
    
    39 42
     af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index );
    
    40 43
     
    

  • src/autofit/aflatin.c
    ... ... @@ -2748,6 +2748,170 @@
    2748 2748
     #undef  FT_COMPONENT
    
    2749 2749
     #define FT_COMPONENT  afadjust
    
    2750 2750
     
    
    2751
    +static void
    
    2752
    +af_move_contour_vertically( AF_Point contour,
    
    2753
    +                            FT_Int movement )
    
    2754
    +{
    
    2755
    +  AF_Point point = contour;
    
    2756
    +  AF_Point first_point = point;
    
    2757
    +  if ( point != NULL )
    
    2758
    +  {
    
    2759
    +    do
    
    2760
    +    {
    
    2761
    +      point->y += movement;
    
    2762
    +      point = point->next;
    
    2763
    +    } while ( point != first_point );
    
    2764
    +  }
    
    2765
    +}
    
    2766
    +
    
    2767
    +static FT_Int
    
    2768
    +af_find_highest_contour( AF_GlyphHints hints ) {
    
    2769
    +  FT_Int highest_contour = -1;
    
    2770
    +  FT_Pos highest_min_y = 0;
    
    2771
    +  FT_Pos current_min_y = 0;
    
    2772
    +
    
    2773
    +  for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    2774
    +  {
    
    2775
    +    AF_Point point = hints->contours[contour];
    
    2776
    +    AF_Point first_point = point;
    
    2777
    +    if ( point == NULL )
    
    2778
    +    {
    
    2779
    +      continue;
    
    2780
    +    }
    
    2781
    +    current_min_y = point->y;
    
    2782
    +
    
    2783
    +    do
    
    2784
    +    {
    
    2785
    +      if ( point->y < current_min_y )
    
    2786
    +      {
    
    2787
    +        current_min_y = point->y;
    
    2788
    +      }
    
    2789
    +      point = point->next;
    
    2790
    +    } while ( point != first_point );
    
    2791
    +
    
    2792
    +    if ( highest_contour == -1 || current_min_y > highest_min_y )
    
    2793
    +    {
    
    2794
    +      highest_min_y = current_min_y;
    
    2795
    +      highest_contour = contour;
    
    2796
    +    }
    
    2797
    +  }
    
    2798
    +
    
    2799
    +  return highest_contour;
    
    2800
    +}
    
    2801
    +
    
    2802
    +void
    
    2803
    +af_latin_stretch_tildes( AF_GlyphHints hints,
    
    2804
    +                         FT_Int glyph_index,
    
    2805
    +                         AF_ReverseCharacterMap reverse_charmap ) {
    
    2806
    +  if ( af_lookup_tilde_correction_type( reverse_charmap, glyph_index ) ) {
    
    2807
    +    FT_Int highest_contour = af_find_highest_contour( hints );
    
    2808
    +    AF_Point p = hints->contours[highest_contour];
    
    2809
    +    AF_Point first_point = p;
    
    2810
    +
    
    2811
    +    FT_Pos min_y, max_y;
    
    2812
    +    min_y = max_y = p->y;
    
    2813
    +
    
    2814
    +    FT_Short min_fy, max_fy;
    
    2815
    +    min_fy = max_fy = p->fy;
    
    2816
    +
    
    2817
    +    do {
    
    2818
    +      p = p->next;
    
    2819
    +      if ( p->y < min_y ) {
    
    2820
    +        min_y = p->y;
    
    2821
    +      }
    
    2822
    +      if ( p->y > max_y ) {
    
    2823
    +        max_y = p->y;
    
    2824
    +      }
    
    2825
    +
    
    2826
    +      if ( p->fy < min_fy ) {
    
    2827
    +        min_fy = p->fy;
    
    2828
    +      }
    
    2829
    +
    
    2830
    +      if ( p->fy > max_fy ) {
    
    2831
    +        max_fy = p->fy;
    
    2832
    +      }
    
    2833
    +
    
    2834
    +    } while ( p != first_point );
    
    2835
    +
    
    2836
    +    FT_Pos min_measurement = 32000;
    
    2837
    +    FT_UInt measurements_taken = 0;
    
    2838
    +
    
    2839
    +    do {
    
    2840
    +      p = p->next;
    
    2841
    +      if ( !(p->flags & AF_FLAG_CONTROL)
    
    2842
    +           && p->prev->y == p->y && p->next->y == p->y
    
    2843
    +           && p->y != min_y && p->y != max_y
    
    2844
    +           && p->prev->flags & AF_FLAG_CONTROL
    
    2845
    +           && p->next->flags & AF_FLAG_CONTROL ) {
    
    2846
    +        /* This point could be a candidate.  Find the next and previous on-curve */
    
    2847
    +        /* points, and make sure they are both either above or below the point, */
    
    2848
    +        /* Then make the measurement */
    
    2849
    +        AF_Point prevOn = p->prev;
    
    2850
    +        AF_Point nextOn = p->next;
    
    2851
    +        while ( prevOn->flags & AF_FLAG_CONTROL ) {
    
    2852
    +          prevOn = prevOn->prev;
    
    2853
    +        }
    
    2854
    +        while ( nextOn->flags & AF_FLAG_CONTROL ) {
    
    2855
    +          nextOn = nextOn->next;
    
    2856
    +        }
    
    2857
    +        FT_Pos measurement;
    
    2858
    +        if ( nextOn->y > p->y && prevOn->y > p->y ) {
    
    2859
    +          measurement = p->y - min_y;
    
    2860
    +        } else if ( nextOn->y < p->y && prevOn->y < p->y ) {
    
    2861
    +          measurement = max_y - p->y;
    
    2862
    +        } else {
    
    2863
    +          continue;
    
    2864
    +        }
    
    2865
    +
    
    2866
    +        if (measurement < min_measurement) {
    
    2867
    +          min_measurement = measurement;
    
    2868
    +        }
    
    2869
    +        measurements_taken++;
    
    2870
    +      }
    
    2871
    +
    
    2872
    +    } while ( p != first_point );
    
    2873
    +
    
    2874
    +    FT_Pos height = max_y - min_y;
    
    2875
    +
    
    2876
    +    FT_Pos target_height = min_measurement + 64;
    
    2877
    +    if ( height >= target_height ) {
    
    2878
    +      return;
    
    2879
    +    }
    
    2880
    +
    
    2881
    +    p = first_point;
    
    2882
    +    do {
    
    2883
    +      p = p->next;
    
    2884
    +      /*if ( p->flags & AF_FLAG_CONTROL ) {
    
    2885
    +        continue;
    
    2886
    +      }*/
    
    2887
    +      p->y = ((p->y - min_y) * target_height / height) + min_y;
    
    2888
    +      p->fy = ((p->fy - min_fy) * target_height / height) + min_fy;
    
    2889
    +      p->oy = p->y;
    
    2890
    +      if ( !(p->flags & AF_FLAG_CONTROL) )
    
    2891
    +        p->flags |= AF_FLAG_TOUCH_Y;
    
    2892
    +    } while ( p != first_point );
    
    2893
    +
    
    2894
    +    FT_TRACE4(( "af_latin_stretch_tildes: Height: %d, measurement: %d, measurements taken: %d\n", height, min_measurement, measurements_taken ));
    
    2895
    +
    
    2896
    +    FT_Pos new_min_y, new_max_y;
    
    2897
    +    new_min_y = new_max_y = first_point->y;
    
    2898
    +    p = first_point;
    
    2899
    +    do {
    
    2900
    +      p = p->next;
    
    2901
    +      if ( p->y < new_min_y ) {
    
    2902
    +        new_min_y = p->y;
    
    2903
    +      }
    
    2904
    +      if ( p->y > new_max_y ) {
    
    2905
    +        new_max_y = p->y;
    
    2906
    +      }
    
    2907
    +    } while ( p != first_point );
    
    2908
    +
    
    2909
    +    FT_TRACE4(( "af_latin_stretch_tildes_merp: New height: %d\n, miny: %d, maxy: %d", new_max_y - new_min_y, new_min_y, new_max_y));
    
    2910
    +  }
    
    2911
    +
    
    2912
    +
    
    2913
    +}
    
    2914
    +
    
    2751 2915
     void
    
    2752 2916
     af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
    
    2753 2917
                                                           AF_Dimension dim,
    
    ... ... @@ -2776,7 +2940,7 @@ af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
    2776 2940
           AF_Point point = hints->contours[contour];
    
    2777 2941
           AF_Point first_point = point;
    
    2778 2942
           if ( point == NULL )
    
    2779
    -      { /*TODO: is this necessary?*/
    
    2943
    +      {
    
    2780 2944
             continue;
    
    2781 2945
           }
    
    2782 2946
           current_min_y = point->y;
    
    ... ... @@ -2834,15 +2998,77 @@ af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
    2834 2998
         FT_TRACE4(( "    Pushing top contour %d units up\n", adjustment_amount ));
    
    2835 2999
         if ( adjustment_amount > 0 )
    
    2836 3000
         {
    
    2837
    -      AF_Point point = hints->contours[highest_contour];
    
    3001
    +      af_move_contour_vertically(hints->contours[highest_contour], adjustment_amount);
    
    3002
    +    }
    
    3003
    +  } else if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index ) == AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN
    
    3004
    +       && hints->num_contours >= 2 )
    
    3005
    +  {
    
    3006
    +    FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments: Applying vertical adjustment: AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN\n" ));
    
    3007
    +
    
    3008
    +    /*Find lowest contour*/
    
    3009
    +    FT_Int lowest_contour = -1;
    
    3010
    +    FT_Pos lowest_max_y = 0;
    
    3011
    +    FT_Pos current_max_y = 0;
    
    3012
    +
    
    3013
    +    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    3014
    +    {
    
    3015
    +      AF_Point point = hints->contours[contour];
    
    2838 3016
           AF_Point first_point = point;
    
    2839
    -      if ( point != NULL )
    
    3017
    +      if ( point == NULL )
    
    2840 3018
           {
    
    2841
    -        do
    
    3019
    +        continue;
    
    3020
    +      }
    
    3021
    +      current_max_y = point->y;
    
    3022
    +
    
    3023
    +      do
    
    3024
    +      {
    
    3025
    +        if ( point->y > current_max_y )
    
    3026
    +        {
    
    3027
    +          current_max_y = point->y;
    
    3028
    +        }
    
    3029
    +        point = point->next;
    
    3030
    +      } while ( point != first_point );
    
    3031
    +
    
    3032
    +      if ( lowest_contour == -1 || current_max_y < lowest_max_y )
    
    3033
    +      {
    
    3034
    +        lowest_max_y = current_max_y;
    
    3035
    +        lowest_contour = contour;
    
    3036
    +      }
    
    3037
    +    }
    
    3038
    +
    
    3039
    +    FT_Int adjustment_amount = 0;
    
    3040
    +    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
    
    3041
    +    {
    
    3042
    +      if ( contour == lowest_contour )
    
    3043
    +      {
    
    3044
    +        continue;
    
    3045
    +      }
    
    3046
    +      AF_Point point = hints->contours[contour];
    
    3047
    +      AF_Point first_point = point;
    
    3048
    +      if ( point == NULL )
    
    3049
    +      {
    
    3050
    +        continue;
    
    3051
    +      }
    
    3052
    +      FT_Pos min_y = point->y;
    
    3053
    +
    
    3054
    +      do
    
    3055
    +      {
    
    3056
    +        if ( point->y < min_y )
    
    2842 3057
             {
    
    2843
    -          point->y += adjustment_amount;
    
    2844
    -          point = point->next;
    
    2845
    -        } while ( point != first_point );
    
    3058
    +          min_y = point->y;
    
    3059
    +        }
    
    3060
    +        point = point->next;
    
    3061
    +      } while ( point != first_point );
    
    3062
    +
    
    3063
    +      if ( min_y <= lowest_max_y - 64 )
    
    3064
    +      {
    
    3065
    +        adjustment_amount = 64 - ( min_y - lowest_max_y );
    
    3066
    +      }
    
    3067
    +
    
    3068
    +      FT_TRACE4(( "    Pushing bottom contour %d units down\n", adjustment_amount ));
    
    3069
    +      if ( adjustment_amount > 0 )
    
    3070
    +      {
    
    3071
    +        af_move_contour_vertically(hints->contours[lowest_contour], -adjustment_amount);
    
    2846 3072
           }
    
    2847 3073
         }
    
    2848 3074
       }
    
    ... ... @@ -3666,6 +3892,31 @@ af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
    3666 3892
     #endif
    
    3667 3893
       }
    
    3668 3894
     
    
    3895
    +/*Print the height of the topmost contour for debugging purposes.
    
    3896
    +  TODO: remove this once the tilde unflattening works.*/
    
    3897
    +static void traceheight(FT_UInt num, AF_GlyphHints hints) {
    
    3898
    +  AF_Point p = hints->contours[af_find_highest_contour(hints)];
    
    3899
    +  AF_Point first_point = p;
    
    3900
    +
    
    3901
    +  FT_Pos min_y, max_y;
    
    3902
    +  min_y = max_y = p->y;
    
    3903
    +  FT_UInt candidates = 0;
    
    3904
    +
    
    3905
    +  do {
    
    3906
    +    p = p->next;
    
    3907
    +    if ( !(p->flags & AF_FLAG_CONTROL) ) {
    
    3908
    +      if ( p->y < min_y ) {
    
    3909
    +        min_y = p->y;
    
    3910
    +      }
    
    3911
    +      if ( p->y > max_y ) {
    
    3912
    +        max_y = p->y;
    
    3913
    +      }
    
    3914
    +    }
    
    3915
    +  } while ( p != first_point );
    
    3916
    +
    
    3917
    +  FT_Pos height = max_y - min_y;
    
    3918
    +  FT_TRACE4(( "height %d: %d\n", num, height ));
    
    3919
    +}
    
    3669 3920
     
    
    3670 3921
       /* Apply the complete hinting algorithm to a latin glyph. */
    
    3671 3922
     
    
    ... ... @@ -3701,6 +3952,7 @@ af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
    3701 3952
     
    
    3702 3953
         if ( AF_HINTS_DO_VERTICAL( hints ) )
    
    3703 3954
         {
    
    3955
    +      af_latin_stretch_tildes( hints, glyph_index, metrics->root.reverse_charmap );
    
    3704 3956
           axis  = &metrics->axis[AF_DIMENSION_VERT];
    
    3705 3957
           error = af_latin_hints_detect_features( hints,
    
    3706 3958
                                                   axis->width_count,
    


  • reply via email to

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