freetype-commit
[Top][All Lists]
Advanced

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

[freetype2] gsoc-craig-2023-final 5cfdd444d: [autofit] add tilde unflatt


From: Werner Lemberg
Subject: [freetype2] gsoc-craig-2023-final 5cfdd444d: [autofit] add tilde unflattening algorithm
Date: Fri, 3 Nov 2023 01:20:51 -0400 (EDT)

branch: gsoc-craig-2023-final
commit 5cfdd444d4a2056c62dfd966d92ce312cb1fae34
Author: Craig White <gerzytet@gmail.com>
Commit: Craig White <gerzytet@gmail.com>

    [autofit] add tilde unflattening algorithm
    * src/autofit/aflatin.c add tilde unflattening algorithm, applied
    based on adjustment database and reverse character map
    * src/autofit/aflatin.c fix adjustment database entry for n with tilde
---
 src/autofit/afadjust.c |   2 +-
 src/autofit/aflatin.c  | 222 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 223 insertions(+), 1 deletion(-)

diff --git a/src/autofit/afadjust.c b/src/autofit/afadjust.c
index a340716e6..536956eba 100644
--- a/src/autofit/afadjust.c
+++ b/src/autofit/afadjust.c
@@ -52,7 +52,7 @@ adjustment_database[] =
     {0xEC,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
     {0xED,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
     {0xEE,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
-    {0xF1,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}, /*n with tilde*/
+    {0xF1,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 1}, /*n with tilde*/
     {0xF2,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
     {0xF3,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
     {0xF4,  AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 20d49f5fe..208e18570 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -2798,6 +2798,221 @@ af_find_highest_contour( AF_GlyphHints hints ) {
   return highest_contour;
 }
 
+static void
+af_remove_segments_containing_point(AF_GlyphHints hints, AF_Point point)
+{
+  AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT];
+  AF_Segment segments = axis->segments;
+  for ( FT_Int i = 0; i < axis->num_segments; i++ )
+  {
+    AF_Segment seg = &segments[i];
+    FT_Bool remove = 0;
+    AF_Point p = seg->first;
+    while ( 1 )
+    {
+      if ( p == point )
+      {
+        remove = 1;
+        break;
+      }
+      if (p == seg->last) {
+        break;
+      }
+      p = p->next;
+    }
+
+    if ( remove )
+    {
+      /* first, check the first and last fields of the edge */
+      AF_Edge edge = seg->edge;
+      if ( edge->first == seg && edge->last == seg )
+      {
+        /* The edge only consists of the segment to be removed.  remove the 
edge*/
+          *edge = axis->edges[--axis->num_edges];
+      }
+      else
+      {
+        if ( edge->first == seg )
+        {
+          edge->first = seg->edge_next;
+        }
+        if ( edge->last == seg )
+        {
+          edge->last = edge->first;
+          while ( edge->last->edge_next != seg )
+          {
+            edge->last = edge->last->edge_next;
+          }
+        }
+      }
+
+      /* Now, delete the segment */
+      *seg = axis->segments[--axis->num_segments];
+
+      i--; /* we have to check the new segment at this position */
+    }
+  }
+}
+
+/*remove all segments containing points on the tilde contour*/
+static void
+af_latin_remove_tilde_points_from_edges( AF_GlyphHints hints,
+                                         FT_Int glyph_index )
+{
+  FT_Int highest_contour = af_find_highest_contour(hints);
+  AF_Point first_point = hints->contours[highest_contour];
+
+  /* search for any curve tips that are on a y extrema, and delete any
+    segments that contain this point.*/
+  AF_Point p = first_point;
+
+  do
+  {
+    p = p->next;
+    if ( /*!(p->flags & AF_FLAG_CONTROL)
+          && p->prev->y == p->y && p->next->y == p->y
+          && p->prev->flags & AF_FLAG_CONTROL
+          && p->next->flags & AF_FLAG_CONTROL*/ 1 )
+    {
+      FT_TRACE4(("%p", p));
+      af_remove_segments_containing_point( hints, p );
+    }
+  } while ( p != first_point );
+}
+
+/*
+The tilde unflattening algorithm sometimes goes too far and makes an
+unusually high tilde, where decreasing the ppem will increase the height
+instead of a steady decrease in height as less pixels are used.
+
+The n tilde on times new roman with forced autofitting on,
+16.5-18 ppem font size exhibits this behaviour.
+*/
+void
+af_latin_stretch_tildes( AF_GlyphHints hints,
+                         FT_Int 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;
+    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_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 );
+}
+
 /*True if the given contour overlaps horizontally with the bounding box
   Of all other contours combined.
   This is a helper for af_glyph_hints_apply_vertical_separation_adjustments */
@@ -3886,11 +4101,18 @@ af_glyph_hints_apply_vertical_separation_adjustments( 
AF_GlyphHints hints,
 
     if ( AF_HINTS_DO_VERTICAL( hints ) )
     {
+      FT_Bool is_tilde = af_lookup_tilde_correction_type( 
metrics->root.reverse_charmap, glyph_index );
+      if ( is_tilde ) {
+        //af_latin_stretch_tildes( hints, glyph_index );
+      }
       axis  = &metrics->axis[AF_DIMENSION_VERT];
       error = af_latin_hints_detect_features( hints,
                                               axis->width_count,
                                               axis->widths,
                                               AF_DIMENSION_VERT );
+      if ( is_tilde ) {
+        //af_latin_remove_tilde_points_from_edges( hints, glyph_index );
+      }
       if ( error )
         goto Exit;
 



reply via email to

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