freetype-commit
[Top][All Lists]
Advanced

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

[freetype2] gsoc-craig-2023 9a813d0c5: Add a vertical adjustment mode fo


From: Werner Lemberg
Subject: [freetype2] gsoc-craig-2023 9a813d0c5: Add a vertical adjustment mode for pushing the bottom contour down and add a WIP tilde correction algorithm
Date: Wed, 2 Aug 2023 18:53:50 -0400 (EDT)

branch: gsoc-craig-2023
commit 9a813d0c55d6be745e377e3a438e12fea6b00528
Author: Craig White <gerzytet@gmail.com>
Commit: Craig White <gerzytet@gmail.com>

    Add a vertical adjustment mode for pushing the bottom contour down and add 
a WIP tilde correction algorithm
---
 include/freetype/config/ftoption.h |   2 +-
 src/autofit/afadjust.c             |  11 ++
 src/autofit/afadjust.h             |   3 +
 src/autofit/aflatin.c              | 266 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 274 insertions(+), 8 deletions(-)

diff --git a/include/freetype/config/ftoption.h 
b/include/freetype/config/ftoption.h
index 1976b33af..3601dd6ae 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -431,7 +431,7 @@ FT_BEGIN_HEADER
    *   them for certain configurations only.
    */
 /* #define FT_DEBUG_LEVEL_ERROR */
-/* #define FT_DEBUG_LEVEL_TRACE */
+#define FT_DEBUG_LEVEL_TRACE
 
 
   /**************************************************************************
diff --git a/src/autofit/afadjust.c b/src/autofit/afadjust.c
index 9e15746c9..2858ee88f 100644
--- a/src/autofit/afadjust.c
+++ b/src/autofit/afadjust.c
@@ -168,6 +168,17 @@ af_lookup_vertical_seperation_type( AF_ReverseCharacterMap 
map, FT_Int glyph_ind
     return entry->vertical_separation_adjustment_type;
 }
 
+/*TODO: this is a testing placeholder
+  it only returns 1 for n with tilde*/
+FT_LOCAL_DEF( FT_Int )
+af_lookup_tilde_correction_type( AF_ReverseCharacterMap map, FT_Int 
glyph_index ) {
+    FT_UInt32 codepoint = af_reverse_character_map_lookup( map, glyph_index );
+    if ( codepoint == 0xF1 ) {
+        return 1;
+    }
+    return 0;
+}
+
 typedef struct AF_ReverseMapEntry_
 {
     FT_Int glyph_index;
diff --git a/src/autofit/afadjust.h b/src/autofit/afadjust.h
index 797947f42..179f4fd5e 100644
--- a/src/autofit/afadjust.h
+++ b/src/autofit/afadjust.h
@@ -35,6 +35,9 @@ typedef struct AF_ReverseCharacterMap_ 
*AF_ReverseCharacterMap;
 FT_LOCAL(AF_VerticalSeparationAdjustmentType)
 af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int 
glyph_index );
 
+FT_LOCAL( FT_Int )
+af_lookup_tilde_correction_type( AF_ReverseCharacterMap map, FT_Int 
glyph_index );
+
 FT_LOCAL( FT_UInt32 )
 af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int 
glyph_index );
 
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 47ad8b175..656ffeb35 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -2748,6 +2748,170 @@
 #undef  FT_COMPONENT
 #define FT_COMPONENT  afadjust
 
+static void
+af_move_contour_vertically( AF_Point contour,
+                            FT_Int movement )
+{
+  AF_Point point = contour;
+  AF_Point first_point = point;
+  if ( point != NULL )
+  {
+    do
+    {
+      point->y += movement;
+      point = point->next;
+    } while ( point != first_point );
+  }
+}
+
+static FT_Int
+af_find_highest_contour( AF_GlyphHints hints ) {
+  FT_Int highest_contour = -1;
+  FT_Pos highest_min_y = 0;
+  FT_Pos current_min_y = 0;
+
+  for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
+  {
+    AF_Point point = hints->contours[contour];
+    AF_Point first_point = point;
+    if ( point == NULL )
+    {
+      continue;
+    }
+    current_min_y = point->y;
+
+    do
+    {
+      if ( point->y < current_min_y )
+      {
+        current_min_y = point->y;
+      }
+      point = point->next;
+    } while ( point != first_point );
+
+    if ( highest_contour == -1 || current_min_y > highest_min_y )
+    {
+      highest_min_y = current_min_y;
+      highest_contour = contour;
+    }
+  }
+
+  return highest_contour;
+}
+
+void
+af_latin_stretch_tildes( AF_GlyphHints hints,
+                         FT_Int glyph_index,
+                         AF_ReverseCharacterMap reverse_charmap ) {
+  if ( af_lookup_tilde_correction_type( reverse_charmap, glyph_index ) ) {
+    FT_Int highest_contour = af_find_highest_contour( hints );
+    AF_Point p = hints->contours[highest_contour];
+    AF_Point first_point = p;
+
+    FT_Pos min_y, max_y;
+    min_y = max_y = p->y;
+
+    FT_Short min_fy, max_fy;
+    min_fy = max_fy = p->fy;
+
+    do {
+      p = p->next;
+      if ( p->y < min_y ) {
+        min_y = p->y;
+      }
+      if ( p->y > max_y ) {
+        max_y = p->y;
+      }
+
+      if ( p->fy < min_fy ) {
+        min_fy = p->fy;
+      }
+
+      if ( p->fy > max_fy ) {
+        max_fy = p->fy;
+      }
+
+    } while ( p != first_point );
+
+    FT_Pos min_measurement = 32000;
+    FT_UInt measurements_taken = 0;
+
+    do {
+      p = p->next;
+      if ( !(p->flags & AF_FLAG_CONTROL)
+           && p->prev->y == p->y && p->next->y == p->y
+           && p->y != min_y && p->y != max_y
+           && p->prev->flags & AF_FLAG_CONTROL
+           && p->next->flags & AF_FLAG_CONTROL ) {
+        /* This point could be a candidate.  Find the next and previous 
on-curve */
+        /* points, and make sure they are both either above or below the 
point, */
+        /* Then make the measurement */
+        AF_Point prevOn = p->prev;
+        AF_Point nextOn = p->next;
+        while ( prevOn->flags & AF_FLAG_CONTROL ) {
+          prevOn = prevOn->prev;
+        }
+        while ( nextOn->flags & AF_FLAG_CONTROL ) {
+          nextOn = nextOn->next;
+        }
+        FT_Pos measurement;
+        if ( nextOn->y > p->y && prevOn->y > p->y ) {
+          measurement = p->y - min_y;
+        } else if ( nextOn->y < p->y && prevOn->y < p->y ) {
+          measurement = max_y - p->y;
+        } else {
+          continue;
+        }
+
+        if (measurement < min_measurement) {
+          min_measurement = measurement;
+        }
+        measurements_taken++;
+      }
+
+    } while ( p != first_point );
+
+    FT_Pos height = max_y - min_y;
+
+    FT_Pos target_height = min_measurement + 64;
+    if ( height >= target_height ) {
+      return;
+    }
+
+    p = first_point;
+    do {
+      p = p->next;
+      /*if ( p->flags & AF_FLAG_CONTROL ) {
+        continue;
+      }*/
+      p->y = ((p->y - min_y) * target_height / height) + min_y;
+      p->fy = ((p->fy - min_fy) * target_height / height) + min_fy;
+      p->oy = p->y;
+      if ( !(p->flags & AF_FLAG_CONTROL) )
+        p->flags |= AF_FLAG_TOUCH_Y;
+    } while ( p != first_point );
+
+    FT_TRACE4(( "af_latin_stretch_tildes: Height: %d, measurement: %d, 
measurements taken: %d\n", height, min_measurement, measurements_taken ));
+
+    FT_Pos new_min_y, new_max_y;
+    new_min_y = new_max_y = first_point->y;
+    p = first_point;
+    do {
+      p = p->next;
+      if ( p->y < new_min_y ) {
+        new_min_y = p->y;
+      }
+      if ( p->y > new_max_y ) {
+        new_max_y = p->y;
+      }
+    } while ( p != first_point );
+
+    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));
+  }
+
+
+}
+
 void
 af_glyph_hints_apply_vertical_separation_adjustments( AF_GlyphHints hints,
                                                       AF_Dimension dim,
@@ -2776,7 +2940,7 @@ af_glyph_hints_apply_vertical_separation_adjustments( 
AF_GlyphHints hints,
       AF_Point point = hints->contours[contour];
       AF_Point first_point = point;
       if ( point == NULL )
-      { /*TODO: is this necessary?*/
+      {
         continue;
       }
       current_min_y = point->y;
@@ -2834,15 +2998,77 @@ af_glyph_hints_apply_vertical_separation_adjustments( 
AF_GlyphHints hints,
     FT_TRACE4(( "    Pushing top contour %d units up\n", adjustment_amount ));
     if ( adjustment_amount > 0 )
     {
-      AF_Point point = hints->contours[highest_contour];
+      af_move_contour_vertically(hints->contours[highest_contour], 
adjustment_amount);
+    }
+  } else if ( af_lookup_vertical_seperation_type( reverse_charmap, glyph_index 
) == AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN
+       && hints->num_contours >= 2 )
+  {
+    FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments: 
Applying vertical adjustment: AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN\n" ));
+
+    /*Find lowest contour*/
+    FT_Int lowest_contour = -1;
+    FT_Pos lowest_max_y = 0;
+    FT_Pos current_max_y = 0;
+
+    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
+    {
+      AF_Point point = hints->contours[contour];
       AF_Point first_point = point;
-      if ( point != NULL )
+      if ( point == NULL )
       {
-        do
+        continue;
+      }
+      current_max_y = point->y;
+
+      do
+      {
+        if ( point->y > current_max_y )
+        {
+          current_max_y = point->y;
+        }
+        point = point->next;
+      } while ( point != first_point );
+
+      if ( lowest_contour == -1 || current_max_y < lowest_max_y )
+      {
+        lowest_max_y = current_max_y;
+        lowest_contour = contour;
+      }
+    }
+
+    FT_Int adjustment_amount = 0;
+    for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
+    {
+      if ( contour == lowest_contour )
+      {
+        continue;
+      }
+      AF_Point point = hints->contours[contour];
+      AF_Point first_point = point;
+      if ( point == NULL )
+      {
+        continue;
+      }
+      FT_Pos min_y = point->y;
+
+      do
+      {
+        if ( point->y < min_y )
         {
-          point->y += adjustment_amount;
-          point = point->next;
-        } while ( point != first_point );
+          min_y = point->y;
+        }
+        point = point->next;
+      } while ( point != first_point );
+
+      if ( min_y <= lowest_max_y - 64 )
+      {
+        adjustment_amount = 64 - ( min_y - lowest_max_y );
+      }
+
+      FT_TRACE4(( "    Pushing bottom contour %d units down\n", 
adjustment_amount ));
+      if ( adjustment_amount > 0 )
+      {
+        af_move_contour_vertically(hints->contours[lowest_contour], 
-adjustment_amount);
       }
     }
   }
@@ -3666,6 +3892,31 @@ af_glyph_hints_apply_vertical_separation_adjustments( 
AF_GlyphHints hints,
 #endif
   }
 
+/*Print the height of the topmost contour for debugging purposes.
+  TODO: remove this once the tilde unflattening works.*/
+static void traceheight(FT_UInt num, AF_GlyphHints hints) {
+  AF_Point p = hints->contours[af_find_highest_contour(hints)];
+  AF_Point first_point = p;
+
+  FT_Pos min_y, max_y;
+  min_y = max_y = p->y;
+  FT_UInt candidates = 0;
+
+  do {
+    p = p->next;
+    if ( !(p->flags & AF_FLAG_CONTROL) ) {
+      if ( p->y < min_y ) {
+        min_y = p->y;
+      }
+      if ( p->y > max_y ) {
+        max_y = p->y;
+      }
+    }
+  } while ( p != first_point );
+
+  FT_Pos height = max_y - min_y;
+  FT_TRACE4(( "height %d: %d\n", num, height ));
+}
 
   /* Apply the complete hinting algorithm to a latin glyph. */
 
@@ -3701,6 +3952,7 @@ af_glyph_hints_apply_vertical_separation_adjustments( 
AF_GlyphHints hints,
 
     if ( AF_HINTS_DO_VERTICAL( hints ) )
     {
+      af_latin_stretch_tildes( hints, glyph_index, 
metrics->root.reverse_charmap );
       axis  = &metrics->axis[AF_DIMENSION_VERT];
       error = af_latin_hints_detect_features( hints,
                                               axis->width_count,



reply via email to

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