freetype-commit
[Top][All Lists]
Advanced

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

[freetype2] adjust 34c1acfca 4/7: [autofit] Implement vertical separatio


From: Werner Lemberg
Subject: [freetype2] adjust 34c1acfca 4/7: [autofit] Implement vertical separation adjustment.
Date: Sun, 14 Apr 2024 10:04:04 -0400 (EDT)

branch: adjust
commit 34c1acfca3697b8e55701141d0cf6e4c99ad3f8e
Author: Craig White <gerzytet@gmail.com>
Commit: Werner Lemberg <wl@gnu.org>

    [autofit] Implement vertical separation adjustment.
    
    * src/autofit/aflatin.c: Include `afadjust.h`.
    (af_latin_metrics_init): Call `af_reverse_character_map_new`.
    (af_latin_metrics_done): New function.
    
    (af_move_contour_vertically, af_check_contour_horizontal_overlap,
    af_glyph_hints_apply_vertical_separation_adjustments): New functions.
    
    (af_latin_hints_apply): Call
    `af_glyph_hints_apply_vertical_separation_adjustments`.
    
    (af_latin_writing_system_class): Updated.
    
    * src/autofit/aftypes.h (AF_StyleMetricsRec): Add `reverse_charmap` field.
---
 src/autofit/aflatin.c | 320 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/autofit/aftypes.h |   2 +
 2 files changed, 321 insertions(+), 1 deletion(-)

diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 316e7c676..91d369f40 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -22,6 +22,7 @@
 #include "afglobal.h"
 #include "aflatin.h"
 #include "aferrors.h"
+#include "afadjust.h"
 
 
   /**************************************************************************
@@ -1155,6 +1156,9 @@
       af_latin_metrics_check_digits( metrics, face );
     }
 
+    af_reverse_character_map_new( &metrics->root.reverse_charmap,
+                                  metrics->root.globals );
+
   Exit:
     face->charmap = oldmap;
     return error;
@@ -1485,6 +1489,17 @@
   }
 
 
+  FT_CALLBACK_DEF( void )
+  af_latin_metrics_done( AF_StyleMetrics  metrics_ )
+  {
+    AF_LatinMetrics  metrics = (AF_LatinMetrics)metrics_;
+
+
+    af_reverse_character_map_done( metrics->root.reverse_charmap,
+                                   metrics->root.globals->face->memory );
+  }
+
+
   /* Scale global values in both directions. */
 
   FT_LOCAL_DEF( void )
@@ -2738,6 +2753,304 @@
   }
 
 
+#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 )
+    {
+      do
+      {
+        point->y += movement;
+        point     = point->next;
+
+      } while ( point != first_point );
+    }
+  }
+
+
+  /* Return 1 if the given contour overlaps horizontally with the bounding */
+  /* box of all other contours combined.  This is a helper for function    */
+  /* `af_glyph_hints_apply_vertical_separation_adjustments`.               */
+  static 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_Int  contour;
+
+    FT_Bool  horizontal_overlap;
+
+
+    for ( 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
+        {
+          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 );
+    }
+
+    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;
+  }
+
+
+  static void
+  af_glyph_hints_apply_vertical_separation_adjustments(
+    AF_GlyphHints           hints,
+    AF_Dimension            dim,
+    FT_Int                  glyph_index,
+    AF_ReverseCharacterMap  reverse_charmap )
+  {
+    FT_TRACE4(( "Entering"
+                " af_glyph_hints_apply_vertical_separation_adjustments\n" ));
+
+    if ( dim != AF_DIMENSION_VERT )
+      return;
+
+    if ( af_lookup_vertical_separation_type( reverse_charmap,
+                                             glyph_index ) ==
+           AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP              &&
+         hints->num_contours >= 2                             )
+    {
+      FT_Int  highest_contour = -1;
+      FT_Pos  highest_min_y   = 0;
+      FT_Pos  current_min_y   = 0;
+
+      FT_Int   contour;
+      FT_Bool  horizontal_overlap;
+      FT_Int   adjustment_amount;
+
+      FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n"
+                  "  Applying vertical adjustment:"
+                  " AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP\n" ));
+
+      /* Figure out which contour is the higher one by finding the one */
+      /* with the highest minimum y value.                             */
+      for ( contour = 0; contour < hints->num_contours; contour++ )
+      {
+        AF_Point  point       = hints->contours[contour];
+        AF_Point  first_point = point;
+
+
+        if ( !point )
+          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;
+        }
+      }
+
+      /* Check for a horizontal overlap between the top contour and the */
+      /* rest.  If there is no overlap, do not adjust.                  */
+      horizontal_overlap =
+        af_check_contour_horizontal_overlap( hints, highest_contour );
+      if ( !horizontal_overlap )
+      {
+        FT_TRACE4(( "    Top contour does not horizontally overlap"
+                    " with other contours.\n"
+                    "    Skipping adjustment.\n" ));
+        return;
+      }
+
+      /* If there are any contours that have a maximum y coordinate       */
+      /* greater than or equal to the minimum y coordinate of the         */
+      /* previously found highest contour, bump the high contour up until */
+      /* the distance is one pixel.                                       */
+      adjustment_amount = 0;
+
+      for ( contour = 0; contour < hints->num_contours; contour++ )
+      {
+        AF_Point  point;
+        AF_Point  first_point;
+
+        FT_Pos max_y;
+
+
+        if ( contour == highest_contour )
+          continue;
+
+        point       = hints->contours[contour];
+        first_point = point;
+        if ( !point )
+          continue;
+
+        max_y = point->y;
+        do
+        {
+          if ( point->y > max_y )
+            max_y = point->y;
+          point = point->next;
+
+        } while ( point != first_point );
+
+        if ( max_y >= highest_min_y - 64 )
+          adjustment_amount = 64 - ( highest_min_y - max_y );
+      }
+
+      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_separation_type( reverse_charmap,
+                                                  glyph_index ) ==
+                AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN         &&
+              hints->num_contours >= 2                             )
+    {
+      FT_Int  lowest_contour = -1;
+      FT_Pos  lowest_max_y   = 0;
+      FT_Pos  current_max_y  = 0;
+
+      FT_Int  contour;
+      FT_Int  adjustment_amount;
+
+
+      FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n"
+                  "  Applying vertical adjustment:"
+                  " AF_VERTICAL_ADJUSTMENT_BOTTOM_CONTOUR_DOWN\n" ));
+
+      /* Find lowest contour. */
+      for ( contour = 0; contour < hints->num_contours; contour++ )
+      {
+        AF_Point  point       = hints->contours[contour];
+        AF_Point  first_point = point;
+
+
+        if ( !point )
+          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;
+        }
+      }
+
+      adjustment_amount = 0;
+
+      for ( contour = 0; contour < hints->num_contours; contour++ )
+      {
+        AF_Point  point;
+        AF_Point  first_point;
+
+        FT_Pos  min_y;
+
+
+        if ( contour == lowest_contour )
+          continue;
+
+        point       = hints->contours[contour];
+        first_point = point;
+        if ( !point )
+          continue;
+
+        min_y = point->y;
+        do
+        {
+          if ( point->y < min_y )
+            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 );
+      }
+
+      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 );
+      }
+    }
+
+    else
+      FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n"
+                  "  No vertical adjustment needed\n" ));
+
+    FT_TRACE4(( "Exiting"
+                " af_glyph_hints_apply_vertical_separation_adjustments\n" ));
+  }
+
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  aflatin
+
+
   /* Compute the snapped width of a given stem, ignoring very thin ones. */
   /* There is a lot of voodoo in this function; changing the hard-coded  */
   /* parameters influence the whole hinting process.                     */
@@ -3605,6 +3918,11 @@
         af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
         af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
         af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
+        af_glyph_hints_apply_vertical_separation_adjustments(
+          hints,
+          (AF_Dimension)dim,
+          glyph_index,
+          metrics->root.reverse_charmap );
       }
     }
 
@@ -3633,7 +3951,7 @@
 
     (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init,        /* 
style_metrics_init    */
     (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale,       /* 
style_metrics_scale   */
-    (AF_WritingSystem_DoneMetricsFunc) NULL,                         /* 
style_metrics_done    */
+    (AF_WritingSystem_DoneMetricsFunc) af_latin_metrics_done,        /* 
style_metrics_done    */
     (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths, /* 
style_metrics_getstdw */
 
     (AF_WritingSystem_InitHintsFunc)   af_latin_hints_init,          /* 
style_hints_init      */
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 5d4aaa9ba..259b555be 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -439,6 +439,8 @@ extern void*  af_debug_hints_;
 
     AF_FaceGlobals  globals;    /* to access properties */
 
+    AF_ReverseCharacterMap  reverse_charmap;
+
   } AF_StyleMetricsRec;
 
 



reply via email to

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