freetype-commit
[Top][All Lists]
Advanced

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

[freetype2] gsoc-craig-2023 fa336db62 1/2: Improve validation for vertic


From: Werner Lemberg
Subject: [freetype2] gsoc-craig-2023 fa336db62 1/2: Improve validation for vertical seperation adjustments, and use new approach for tilde unflattening
Date: Sat, 26 Aug 2023 23:00:36 -0400 (EDT)

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

    Improve validation for vertical seperation adjustments, and use new 
approach for tilde unflattening
---
 src/autofit/afadjust.c |   3 +
 src/autofit/aflatin.c  | 232 ++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 204 insertions(+), 31 deletions(-)

diff --git a/src/autofit/afadjust.c b/src/autofit/afadjust.c
index 2858ee88f..9a23da873 100644
--- a/src/autofit/afadjust.c
+++ b/src/autofit/afadjust.c
@@ -10,6 +10,9 @@
 
 /*TODO: find out whether capital u/U with accent entries are needed*/
 /*the accent won't merge with the rest of the glyph because the accent mark is 
sitting above empty space*/
+/*
+  All entries in this list must be sorted by unicode codepoint ascending
+*/
 FT_LOCAL_ARRAY_DEF( AF_AdjustmentDatabaseEntry )
 adjustment_database[] =
 {
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 656ffeb35..690f2ada3 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -2799,6 +2799,87 @@ 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;
+  AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments );
+  for ( FT_Int i = 0; i < axis->num_segments; i++ )
+  {
+    AF_Segment seg = &segments[i];
+    FT_Bool remove = 0;
+    for ( AF_Point p = seg->first; p <= seg->last; p = p->next )
+    {
+      if ( p == point )
+      {
+        remove = 1;
+        break;
+      }
+    }
+
+    if ( remove )
+    {
+      FT_TRACE4(("Removing segment %d\n", i));
+      /* 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 */
+    }
+  }
+}
+
+static void
+af_latin_stretch_tildes_step_2( 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 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 )
+      {
+        af_remove_segments_containing_point( hints, p );
+      }
+    } while ( p != first_point );
+  }
+
+}
+
 void
 af_latin_stretch_tildes( AF_GlyphHints hints,
                          FT_Int glyph_index,
@@ -2814,82 +2895,99 @@ af_latin_stretch_tildes( AF_GlyphHints hints,
     FT_Short min_fy, max_fy;
     min_fy = max_fy = p->fy;
 
-    do {
+    do
+    {
       p = p->next;
-      if ( p->y < min_y ) {
+      if ( p->y < min_y )
+      {
         min_y = p->y;
       }
-      if ( p->y > max_y ) {
+      if ( p->y > max_y )
+      {
         max_y = p->y;
       }
 
-      if ( p->fy < min_fy ) {
+      if ( p->fy < min_fy )
+      {
         min_fy = p->fy;
       }
 
-      if ( p->fy > max_fy ) {
+      if ( p->fy > max_fy )
+      {
         max_fy = p->fy;
       }
 
-    } while ( p != first_point );
+    }
+    while ( p != first_point );
 
     FT_Pos min_measurement = 32000;
     FT_UInt measurements_taken = 0;
 
-    do {
+    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 ) {
+           && 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 ) {
+        while ( prevOn->flags & AF_FLAG_CONTROL )
+        {
           prevOn = prevOn->prev;
         }
-        while ( nextOn->flags & AF_FLAG_CONTROL ) {
+        while ( nextOn->flags & AF_FLAG_CONTROL )
+        {
           nextOn = nextOn->next;
         }
         FT_Pos measurement;
-        if ( nextOn->y > p->y && prevOn->y > p->y ) {
+        if ( nextOn->y > p->y && prevOn->y > p->y )
+        {
           measurement = p->y - min_y;
-        } else if ( nextOn->y < p->y && prevOn->y < p->y ) {
+        }
+        else if ( nextOn->y < p->y && prevOn->y < p->y )
+        {
           measurement = max_y - p->y;
-        } else {
+        }
+        else
+        {
           continue;
         }
 
-        if (measurement < min_measurement) {
+        if (measurement < min_measurement)
+        {
           min_measurement = measurement;
         }
         measurements_taken++;
       }
 
-    } while ( p != first_point );
+    }
+    while ( p != first_point );
 
     FT_Pos height = max_y - min_y;
 
     FT_Pos target_height = min_measurement + 64;
-    if ( height >= target_height ) {
+    if ( height >= target_height )
+    {
       return;
     }
 
     p = first_point;
-    do {
+    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 );
+    }
+    while ( p != first_point );
 
     FT_TRACE4(( "af_latin_stretch_tildes: Height: %d, measurement: %d, 
measurements taken: %d\n", height, min_measurement, measurements_taken ));
 
@@ -2898,18 +2996,73 @@ af_latin_stretch_tildes( AF_GlyphHints hints,
     p = first_point;
     do {
       p = p->next;
-      if ( p->y < new_min_y ) {
+      if ( p->y < new_min_y )
+      {
         new_min_y = p->y;
       }
-      if ( p->y > new_max_y ) {
+      if ( p->y > new_max_y )
+      {
         new_max_y = p->y;
       }
-    } while ( p != first_point );
+    }
+    while ( p != first_point );
+
+    FT_TRACE4(( "af_latin_stretch_tildes: New height: %d\n, miny: %d, maxy: 
%d", new_max_y - new_min_y, new_min_y, new_max_y));
+  }
+}
+
+/*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 */
+FT_Bool
+af_check_contour_horizontal_overlap( AF_GlyphHints hints,
+                                     FT_Int contour_index )
+{
+  FT_Pos contour_max_x = -32000;
+  FT_Pos contour_min_x = 32000;
+  FT_Pos others_max_x = -32000;
+  FT_Pos others_min_x = 32000;
 
-    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));
+  for ( FT_Int contour = 0; contour < hints->num_contours; contour++ )
+  {
+    AF_Point first_point = hints->contours[contour];
+    AF_Point p = first_point;
+
+    do
+    {
+      p = p->next;
+      if ( contour == contour_index )
+      {
+        if ( p->x < contour_min_x )
+        {
+          contour_min_x = p->x;
+        }
+        if ( p->x > contour_max_x )
+        {
+          contour_max_x = p->x;
+        }
+      }
+      else /* ( contour != contour_index ) */
+      {
+        if ( p->x < others_min_x )
+        {
+          others_min_x = p->x;
+        }
+        if ( p->x > others_max_x )
+        {
+          others_max_x = p->x;
+        }
+      }
+    }
+    while (p != first_point);
   }
 
+  FT_Bool horizontal_overlap =
+    (others_min_x <= contour_max_x && contour_max_x <= others_max_x) ||
+    (others_min_x <= contour_min_x && contour_min_x <= others_max_x) ||
+    (contour_max_x >= others_max_x && contour_min_x <= others_min_x);
 
+  return horizontal_overlap;
 }
 
 void
@@ -2961,6 +3114,15 @@ af_glyph_hints_apply_vertical_separation_adjustments( 
AF_GlyphHints hints,
       }
     }
 
+    /* check for a horizontal overtap between the top contour and the rest */
+    /* if there is no overlap, do not adjust. */
+
+    FT_Bool horizontal_overlap = af_check_contour_horizontal_overlap( hints, 
highest_contour );
+    if (!horizontal_overlap) {
+      FT_TRACE4(( "    Top contour does not horizontally overlap with other 
contours.  Skipping adjustment.\n" ));
+      return;
+    }
+
     /* If there are any contours that have a maximum y coordinate */
     /* greater or equal to the minimum y coordinate of the previously found 
highest*/
     /* contour, bump the high contour up until the distance is one pixel */
@@ -2995,9 +3157,13 @@ 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 )
+    if ( adjustment_amount > 64 )
+    {
+      FT_TRACE4(( "    Calculated adjustment amount %d was more than threshold 
of 64.  Not adjusting\n", adjustment_amount ));
+    }
+    else if ( adjustment_amount > 0 )
     {
+      FT_TRACE4(( "    Pushing top contour %d units up\n", adjustment_amount 
));
       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
@@ -3065,9 +3231,13 @@ af_glyph_hints_apply_vertical_separation_adjustments( 
AF_GlyphHints hints,
         adjustment_amount = 64 - ( min_y - lowest_max_y );
       }
 
-      FT_TRACE4(( "    Pushing bottom contour %d units down\n", 
adjustment_amount ));
-      if ( adjustment_amount > 0 )
+      if ( adjustment_amount > 64 )
+      {
+        FT_TRACE4(( "    Calculated adjustment amount %d was more than 
threshold of 64.  Not adjusting\n", adjustment_amount ));
+      }
+      else if ( adjustment_amount > 0 )
       {
+        FT_TRACE4(( "    Pushing bottom contour %d units down\n", 
adjustment_amount ));
         af_move_contour_vertically(hints->contours[lowest_contour], 
-adjustment_amount);
       }
     }
@@ -3900,7 +4070,6 @@ static void traceheight(FT_UInt num, AF_GlyphHints hints) 
{
 
   FT_Pos min_y, max_y;
   min_y = max_y = p->y;
-  FT_UInt candidates = 0;
 
   do {
     p = p->next;
@@ -3952,12 +4121,13 @@ static void traceheight(FT_UInt num, AF_GlyphHints 
hints) {
 
     if ( AF_HINTS_DO_VERTICAL( hints ) )
     {
-      af_latin_stretch_tildes( hints, glyph_index, 
metrics->root.reverse_charmap );
+      /*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,
                                               axis->widths,
                                               AF_DIMENSION_VERT );
+      af_latin_stretch_tildes_step_2( hints, glyph_index, 
metrics->root.reverse_charmap );
       if ( error )
         goto Exit;
 



reply via email to

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