Commit 73cc8330ede27c73f39706bae2e403b40df1ef63

Werner Lemberg 2014-01-01T07:10:36

[autofit] Implement and use `af_get_char_index' with HarfBuzz. * src/autofit/hbshim.c (COVERAGE) [FT_CONFIG_OPTION_USE_HARFBUZZ]: Redefine to construct HarfBuzz features. (af_get_char_index) [FT_CONFIG_OPTION_USE_HARFBUZZ]: Rewritten. * src/autofit/aflatin.c (af_latin_metrics_init_blues): Use `y_offset' to adjust `best_y'.

diff --git a/ChangeLog b/ChangeLog
index 2580884..a6f3390 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2014-01-01  Werner Lemberg  <wl@gnu.org>
+
+	[autofit] Implement and use `af_get_char_index' with HarfBuzz.
+
+	* src/autofit/hbshim.c (COVERAGE) [FT_CONFIG_OPTION_USE_HARFBUZZ]:
+	Redefine to construct HarfBuzz features.
+	(af_get_char_index) [FT_CONFIG_OPTION_USE_HARFBUZZ]: Rewritten.
+
+	* src/autofit/aflatin.c (af_latin_metrics_init_blues): Use
+	`y_offset' to adjust `best_y'.
+
 2013-12-31  Werner Lemberg  <wl@gnu.org>
 
 	[autofit] s/AF_STYLE_...._DEFAULT/AF_STYLE_...._DFLT/i.
@@ -2595,7 +2606,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright 2013 by
+Copyright 2013-2014 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index fc1d443..8841d94 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin writing system (body).        */
 /*                                                                         */
-/*  Copyright 2003-2013 by                                                 */
+/*  Copyright 2003-2014 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -620,6 +620,12 @@
             }
           }
 
+          /* for computing blue zones, we add the y offset as returned */
+          /* by the currently used OpenType feature -- for example,    */
+          /* superscript glyphs might be identical to subscript glyphs */
+          /* with a vertical shift                                     */
+          best_y += y_offset;
+
           FT_TRACE5(( "  U+%04lX: best_y = %5ld", ch, best_y ));
 
           /* now set the `round' flag depending on the segment's kind: */
diff --git a/src/autofit/hbshim.c b/src/autofit/hbshim.c
index d280e55..7dae08f 100644
--- a/src/autofit/hbshim.c
+++ b/src/autofit/hbshim.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    HarfBuzz interface for accessing OpenType features (body).           */
 /*                                                                         */
-/*  Copyright 2013 by                                                      */
+/*  Copyright 2013, 2014 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -230,22 +230,96 @@
   }
 
 
+  /* construct HarfBuzz features */
+#undef  COVERAGE
+#define COVERAGE( name, NAME, description,                \
+                  tag1, tag2, tag3, tag4 )                \
+          static const hb_feature_t  name ## _feature[] = \
+          {                                               \
+            {                                             \
+              HB_TAG( tag1, tag2, tag3, tag4 ),           \
+              1, 0, -1                                    \
+            }                                             \
+          };
+
+
+#include "afcover.h"
+
+
+  /* define mapping between HarfBuzz features and AF_Coverage */
+#undef  COVERAGE
+#define COVERAGE( name, NAME, description, \
+                  tag1, tag2, tag3, tag4 ) \
+          name ## _feature,
+
+
+  static const hb_feature_t*  features[] =
+  {
+#include "afcover.h"
+
+    NULL /* AF_COVERAGE_DEFAULT */
+  };
+
+
   FT_Error
   af_get_char_index( AF_StyleMetrics  metrics,
                      FT_ULong         charcode,
                      FT_ULong        *codepoint,
                      FT_Long         *y_offset )
   {
-    FT_Face  face;
+    AF_StyleClass  style_class;
+
+    const hb_feature_t*  feature;
 
 
     if ( !metrics )
       return FT_THROW( Invalid_Argument );
 
-    face = metrics->globals->face;
+    style_class = metrics->style_class;
 
-    *codepoint = FT_Get_Char_Index( face, charcode );
-    *y_offset  = 0;
+    feature = features[style_class->coverage];
+
+    if ( feature )
+    {
+      hb_font_t*    font = metrics->globals->hb_font;
+      hb_buffer_t*  buf  = hb_buffer_create();
+
+      uint32_t  c = (uint32_t)charcode;
+
+      hb_glyph_info_t*      ginfo;
+      hb_glyph_position_t*  gpos;
+      unsigned int          gcount;
+
+
+      /* XXX: is this sufficient for a single character of any script? */
+      hb_buffer_set_direction( buf, HB_DIRECTION_LTR );
+      hb_buffer_set_script( buf, scripts[style_class->script] );
+
+      /* we add one character to `buf' ... */
+      hb_buffer_add_utf32( buf, &c, 1, 0, 1 );
+
+      /* ... and apply one feature */
+      hb_shape( font, buf, feature, 1 );
+
+      ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
+      gpos  = hb_buffer_get_glyph_positions( buf, &gcount );
+
+      *codepoint = ginfo[0].codepoint;
+      *y_offset  = gpos[0].y_offset;
+
+      hb_buffer_destroy( buf );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+      if ( gcount > 1 )
+        FT_TRACE1(( "af_get_char_index:"
+                    " input character mapped to multiple glyphs\n" ));
+#endif
+    }
+    else
+    {
+      *codepoint = FT_Get_Char_Index( metrics->globals->face, charcode );
+      *y_offset  = 0;
+    }
 
     return FT_Err_Ok;
   }