freetype-commit
[Top][All Lists]
Advanced

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

[freetype2] master 24aa9c6 3/4: [autofit] Rewrite HarfBuzz interface to


From: Werner LEMBERG
Subject: [freetype2] master 24aa9c6 3/4: [autofit] Rewrite HarfBuzz interface to support character clusters.
Date: Sun, 06 Dec 2015 18:36:41 +0000

branch: master
commit 24aa9c665e3a8bbfbc5ae016354ffba7a1377fd3
Author: Werner Lemberg <address@hidden>
Commit: Werner Lemberg <address@hidden>

    [autofit] Rewrite HarfBuzz interface to support character clusters.
    
    Scripts like Khmer have blue zones that can't be directly
    represented by Unicode characters.  Instead, it is necessary to let
    HarfBuzz convert character clusters into proper glyph representation
    forms, then deriving the blue zone information from the resulting
    glyphs.
    
    * src/autofit/hbshim.c, src/autofit/hbshim.h: Replaced by...
    * src/autofit/afshaper.c, src/autofit/afshaper.h: ... these two new
    files, providing a new API to access HarfBuzz.
    
    The new API manages a HarfBuzz buffer with `af_shaper_buf_create'
    and `af_shaper_buf_destroy'.  The buffer receives a UTF8 encoded
    string with function `af_shaper_get_cluster', and the resulting
    glyph data (indices, advance widths, vertical offsets) can be
    iteratively accessed with function `af_shaper_get_elem'.
    
    * src/autofit/afcjk.c (af_cjk_metrics_init_widths,
    af_cjk_metrics_init_blues, af_cjk_metrics_check_digits): Updated.
    
    * src/autofit/aflatin.c (af_latin_metrics_init_widths,
    af_latin_metrics_init_blues, af_latin_metrics_check_digits):
    Updated.
    
    * include/freetype/internal/fttrace.h: s/afharfbuzz/afshaper/.
    
    * src/autofit/afglobal.c: s/hbshim.h/afshaper.h/.
    (af_face_globals_compute_style_coverage): Updated.
    
    * src/autofit/afglocal.h: s/hbshim.h/afshaper.h/.
    
    * src/autofit/autofit.c: s/hbshim.c/afshaper.c/.
    
    * src/autofit/Jamfile, src/autofit/rules.mk (AUTOF_DRV_SRC):
    Updated.
---
 ChangeLog                            |   39 ++++++
 include/freetype/internal/fttrace.h  |    2 +-
 src/autofit/Jamfile                  |    2 +-
 src/autofit/afcjk.c                  |  128 ++++++++++++++----
 src/autofit/afglobal.c               |    8 +-
 src/autofit/afglobal.h               |    2 +-
 src/autofit/aflatin.c                |  171 ++++++++++++++++++-----
 src/autofit/{hbshim.c => afshaper.c} |  247 +++++++++++++++++++++++-----------
 src/autofit/{hbshim.h => afshaper.h} |   39 ++++--
 src/autofit/autofit.c                |    2 +-
 src/autofit/rules.mk                 |    4 +-
 11 files changed, 476 insertions(+), 168 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 90364bb..ec4890f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,44 @@
 2015-12-06  Werner Lemberg  <address@hidden>
 
+       [autofit] Rewrite HarfBuzz interface to support character clusters.
+
+       Scripts like Khmer have blue zones that can't be directly
+       represented by Unicode characters.  Instead, it is necessary to let
+       HarfBuzz convert character clusters into proper glyph representation
+       forms, then deriving the blue zone information from the resulting
+       glyphs.
+
+       * src/autofit/hbshim.c, src/autofit/hbshim.h: Replaced by...
+       * src/autofit/afshaper.c, src/autofit/afshaper.h: ... these two new
+       files, providing a new API to access HarfBuzz.
+
+       The new API manages a HarfBuzz buffer with `af_shaper_buf_create'
+       and `af_shaper_buf_destroy'.  The buffer receives a UTF8 encoded
+       string with function `af_shaper_get_cluster', and the resulting
+       glyph data (indices, advance widths, vertical offsets) can be
+       iteratively accessed with function `af_shaper_get_elem'.
+
+       * src/autofit/afcjk.c (af_cjk_metrics_init_widths,
+       af_cjk_metrics_init_blues, af_cjk_metrics_check_digits): Updated.
+
+       * src/autofit/aflatin.c (af_latin_metrics_init_widths,
+       af_latin_metrics_init_blues, af_latin_metrics_check_digits):
+       Updated.
+
+       * include/freetype/internal/fttrace.h: s/afharfbuzz/afshaper/.
+
+       * src/autofit/afglobal.c: s/hbshim.h/afshaper.h/.
+       (af_face_globals_compute_style_coverage): Updated.
+
+       * src/autofit/afglocal.h: s/hbshim.h/afshaper.h/.
+
+       * src/autofit/autofit.c: s/hbshim.c/afshaper.c/.
+
+       * src/autofit/Jamfile, src/autofit/rules.mk (AUTOF_DRV_SRC):
+       Updated.
+
+2015-12-06  Werner Lemberg  <address@hidden>
+
        [autofit] Prepare forthcoming changes.
 
        This makes it easier to control the commits.
diff --git a/include/freetype/internal/fttrace.h 
b/include/freetype/internal/fttrace.h
index 9d28d21..2b0bf9d 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -148,7 +148,7 @@ FT_TRACE_DEF( afcjk )
 FT_TRACE_DEF( aflatin )
 FT_TRACE_DEF( aflatin2 )
 FT_TRACE_DEF( afwarp )
-FT_TRACE_DEF( afharfbuzz )
+FT_TRACE_DEF( afshaper )
 FT_TRACE_DEF( afglobal )
 
 /* END */
diff --git a/src/autofit/Jamfile b/src/autofit/Jamfile
index 5cd0b46..a7641b4 100644
--- a/src/autofit/Jamfile
+++ b/src/autofit/Jamfile
@@ -33,8 +33,8 @@ SubDir FT2_TOP src autofit ;
                afmodule
                afpic
                afranges
+               afshaper
                afwarp
-               hbshim
                ;
 
     if $(FT2_AUTOFIT2)
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index 089e66d..73d75ae 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -88,7 +88,6 @@
     {
       FT_Error          error;
       FT_ULong          glyph_index;
-      FT_Long           y_offset;
       int               dim;
       AF_CJKMetricsRec  dummy[1];
       AF_Scaler         scaler = &dummy->root.scaler;
@@ -101,31 +100,56 @@
       AF_ScriptClass  script_class = AF_SCRIPT_CLASSES_GET
                                        [style_class->script];
 
+      void*        shaper_buf;
       const char*  p;
 
+#ifdef FT_DEBUG_LEVEL_TRACE
       FT_ULong  ch;
+#endif
 
-
-      p = script_class->standard_charstring;
+      p          = script_class->standard_charstring;
+      shaper_buf = af_shaper_buf_create( face );
 
       /* We check a list of standard characters.  The first match wins. */
 
       glyph_index = 0;
       while ( *p )
       {
+        unsigned int  num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        const char*  p_old;
+#endif
+
+
         while ( *p == ' ' )
           p++;
 
-        GET_UTF8_CHAR( ch, p );
+#ifdef FT_DEBUG_LEVEL_TRACE
+        p_old = p;
+        GET_UTF8_CHAR( ch, p_old );
+#endif
 
-        af_get_char_index( &metrics->root,
-                           ch,
-                           &glyph_index,
-                           &y_offset );
+        /* reject input that maps to more than a single glyph */
+        p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+        if ( num_idx > 1 )
+          continue;
+
+        /* otherwise exit loop if we have a result */
+        glyph_index = af_shaper_get_elem( &metrics->root,
+                                          shaper_buf,
+                                          0,
+                                          NULL,
+                                          NULL );
         if ( glyph_index )
           break;
       }
 
+      af_shaper_buf_destroy( face, shaper_buf );
+
+      if ( !glyph_index )
+        goto Exit;
+
       if ( !glyph_index )
         goto Exit;
 
@@ -168,6 +192,12 @@
         if ( error )
           goto Exit;
 
+        /*
+         *  We assume that the glyphs selected for the stem width
+         *  computation are `featureless' enough so that the linking
+         *  algorithm works fine without adjustments of its scoring
+         *  function.
+         */
         af_latin_hints_link_segments( hints,
                                       0,
                                       NULL,
@@ -266,6 +296,8 @@
     AF_Blue_Stringset         bss = sc->blue_stringset;
     const AF_Blue_StringRec*  bs  = &af_blue_stringsets[bss];
 
+    void*  shaper_buf;
+
 
     /* we walk over the blue character strings as specified in the   */
     /* style's entry in the `af_blue_stringset' array, computing its */
@@ -275,6 +307,8 @@
                 "==========================\n"
                 "\n" ));
 
+    shaper_buf = af_shaper_buf_create( face );
+
     for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
     {
       const char*  p = &af_blue_strings[bs->string];
@@ -313,26 +347,47 @@
 
       while ( *p )
       {
-        FT_ULong    ch;
         FT_ULong    glyph_index;
-        FT_Long     y_offset;
         FT_Pos      best_pos;       /* same as points.y or points.x, resp. */
         FT_Int      best_point;
         FT_Vector*  points;
 
+        unsigned int  num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        const char*  p_old;
+        FT_ULong     ch;
+#endif
+
 
-        GET_UTF8_CHAR( ch, p );
+        while ( *p == ' ' )
+          p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        p_old = p;
+        GET_UTF8_CHAR( ch, p_old );
+#endif
 
         /* switch to characters that define flat values */
-        if ( ch == '|' )
+        if ( *p == '|' )
         {
           fill = 0;
           FT_TRACE5(( "  [reference values]\n" ));
+          p++;
           continue;
         }
 
+        /* reject input that maps to more than a single glyph */
+        p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+        if ( num_idx > 1 )
+          continue;
+
         /* load the character in the face -- skip unknown or empty ones */
-        af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
+        glyph_index = af_shaper_get_elem( &metrics->root,
+                                          shaper_buf,
+                                          0,
+                                          NULL,
+                                          NULL );
         if ( glyph_index == 0 )
         {
           FT_TRACE5(( "  U+%04lX unavailable\n", ch ));
@@ -341,9 +396,9 @@
 
         error   = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
         outline = face->glyph->outline;
-        if ( error || outline.n_points <= 0 )
+        if ( error || outline.n_points <= 2 )
         {
-          FT_TRACE5(( "  U+%04lX contains no outlines\n", ch ));
+          FT_TRACE5(( "  U+%04lX contains no (usable) outlines\n", ch ));
           continue;
         }
 
@@ -422,7 +477,8 @@
           fills[num_fills++] = best_pos;
         else
           flats[num_flats++] = best_pos;
-      }
+
+      } /* end while loop */
 
       if ( num_flats == 0 && num_fills == 0 )
       {
@@ -489,7 +545,10 @@
       FT_TRACE5(( "    -> reference = %ld\n"
                   "       overshoot = %ld\n",
                   *blue_ref, *blue_shoot ));
-    }
+
+    } /* end for loop */
+
+    af_shaper_buf_destroy( face, shaper_buf );
 
     FT_TRACE5(( "\n" ));
 
@@ -503,27 +562,36 @@
   af_cjk_metrics_check_digits( AF_CJKMetrics  metrics,
                                FT_Face        face )
   {
-    FT_UInt   i;
     FT_Bool   started = 0, same_width = 1;
     FT_Fixed  advance, old_advance = 0;
 
+    void*  shaper_buf;
 
-    /* digit `0' is 0x30 in all supported charmaps */
-    for ( i = 0x30; i <= 0x39; i++ )
+    /* in all supported charmaps, digits have character codes 0x30-0x39 */
+    const char   digits[] = "0 1 2 3 4 5 6 7 8 9";
+    const char*  p;
+
+
+    p          = digits;
+    shaper_buf = af_shaper_buf_create( face );
+
+    while ( *p )
     {
-      FT_ULong  glyph_index;
-      FT_Long   y_offset;
+      FT_ULong      glyph_index;
+      unsigned int  num_idx;
 
 
-      af_get_char_index( &metrics->root, i, &glyph_index, &y_offset );
-      if ( glyph_index == 0 )
+      /* reject input that maps to more than a single glyph */
+      p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+      if ( num_idx > 1 )
         continue;
 
-      if ( FT_Get_Advance( face, glyph_index,
-                           FT_LOAD_NO_SCALE         |
-                           FT_LOAD_NO_HINTING       |
-                           FT_LOAD_IGNORE_TRANSFORM,
-                           &advance ) )
+      glyph_index = af_shaper_get_elem( &metrics->root,
+                                        shaper_buf,
+                                        0,
+                                        &advance,
+                                        NULL );
+      if ( !glyph_index )
         continue;
 
       if ( started )
@@ -541,6 +609,8 @@
       }
     }
 
+    af_shaper_buf_destroy( face, shaper_buf );
+
     metrics->root.digits_have_same_width = same_width;
   }
 
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index ecd333e..207b41c 100644
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -18,7 +18,7 @@
 
 #include "afglobal.h"
 #include "afranges.h"
-#include "hbshim.h"
+#include "afshaper.h"
 #include FT_INTERNAL_DEBUG_H
 
 
@@ -240,12 +240,12 @@
       else
       {
         /* get glyphs not directly addressable by cmap */
-        af_get_coverage( globals, style_class, gstyles );
+        af_shaper_get_coverage( globals, style_class, gstyles );
       }
     }
 
     /* handle the default OpenType features of the default script ... */
-    af_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );
+    af_shaper_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );
 
     /* ... and the remaining default OpenType features */
     for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
@@ -254,7 +254,7 @@
 
 
       if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT )
-        af_get_coverage( globals, style_class, gstyles );
+        af_shaper_get_coverage( globals, style_class, gstyles );
     }
 
     /* mark ASCII digits */
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index 0a54a96..c1170d4 100644
--- a/src/autofit/afglobal.h
+++ b/src/autofit/afglobal.h
@@ -23,7 +23,7 @@
 
 #include "aftypes.h"
 #include "afmodule.h"
-#include "hbshim.h"
+#include "afshaper.h"
 
 
 FT_BEGIN_HEADER
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 6089599..495a32a 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -79,7 +79,6 @@
     {
       FT_Error            error;
       FT_ULong            glyph_index;
-      FT_Long             y_offset;
       int                 dim;
       AF_LatinMetricsRec  dummy[1];
       AF_Scaler           scaler = &dummy->root.scaler;
@@ -92,12 +91,15 @@
       AF_ScriptClass  script_class = AF_SCRIPT_CLASSES_GET
                                        [style_class->script];
 
+      void*        shaper_buf;
       const char*  p;
 
+#ifdef FT_DEBUG_LEVEL_TRACE
       FT_ULong  ch;
+#endif
 
-
-      p = script_class->standard_charstring;
+      p          = script_class->standard_charstring;
+      shaper_buf = af_shaper_buf_create( face );
 
       /*
        * We check a list of standard characters to catch features like
@@ -109,19 +111,41 @@
       glyph_index = 0;
       while ( *p )
       {
+        unsigned int  num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        const char*  p_old;
+#endif
+
+
         while ( *p == ' ' )
           p++;
 
-        GET_UTF8_CHAR( ch, p );
+#ifdef FT_DEBUG_LEVEL_TRACE
+        p_old = p;
+        GET_UTF8_CHAR( ch, p_old );
+#endif
+
+        /* reject input that maps to more than a single glyph */
+        p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+        if ( num_idx > 1 )
+          continue;
 
-        af_get_char_index( &metrics->root,
-                           ch,
-                           &glyph_index,
-                           &y_offset );
+        /* otherwise exit loop if we have a result */
+        glyph_index = af_shaper_get_elem( &metrics->root,
+                                          shaper_buf,
+                                          0,
+                                          NULL,
+                                          NULL );
         if ( glyph_index )
           break;
       }
 
+      af_shaper_buf_destroy( face, shaper_buf );
+
+      if ( !glyph_index )
+        goto Exit;
+
       if ( !glyph_index )
         goto Exit;
 
@@ -269,6 +293,8 @@
 
     FT_Pos  flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
 
+    void*  shaper_buf;
+
 
     /* we walk over the blue character strings as specified in the */
     /* style's entry in the `af_blue_stringset' array              */
@@ -277,6 +303,8 @@
                 "============================\n"
                 "\n" ));
 
+    shaper_buf = af_shaper_buf_create( face );
+
     for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
     {
       const char*  p = &af_blue_strings[bs->string];
@@ -340,24 +368,51 @@
 
       while ( *p )
       {
-        FT_ULong    ch;
         FT_ULong    glyph_index;
         FT_Long     y_offset;
-        FT_Pos      best_y;                            /* same as points.y */
         FT_Int      best_point, best_contour_first, best_contour_last;
         FT_Vector*  points;
-        FT_Bool     round = 0;
+
+        FT_Pos   best_y_extremum;                      /* same as points.y */
+        FT_Bool  best_round = 0;
 
         unsigned int  i, num_idx;
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+        const char*  p_old;
+        FT_ULong     ch;
+#endif
+
+
+        while ( *p == ' ' )
+          p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        p_old = p;
+        GET_UTF8_CHAR( ch, p_old );
+#endif
+
+        p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
 
-        GET_UTF8_CHAR( ch, p );
+        if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+          best_y_extremum = FT_INT_MIN;
+        else
+          best_y_extremum = FT_INT_MAX;
 
-        num_idx = 1;
+        /* iterate over all glyph elements of the character cluster */
+        /* and get the data of the `biggest' one                    */
         for ( i = 0; i < num_idx; i++ )
         {
+          FT_Pos   best_y;
+          FT_Bool  round = 0;
+
+
           /* load the character in the face -- skip unknown or empty ones */
-          af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
+          glyph_index = af_shaper_get_elem( &metrics->root,
+                                            shaper_buf,
+                                            i,
+                                            NULL,
+                                            &y_offset );
           if ( glyph_index == 0 )
           {
             FT_TRACE5(( "  U+%04lX unavailable\n", ch ));
@@ -369,7 +424,13 @@
           /* reject glyphs that don't produce any rendering */
           if ( error || outline.n_points <= 2 )
           {
-            FT_TRACE5(( "  U+%04lX contains no (usable) outlines\n", ch ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+            if ( num_idx == 1 )
+              FT_TRACE5(( "  U+%04lX contains no (usable) outlines\n", ch ));
+            else
+              FT_TRACE5(( "  component %d of cluster starting with U+%04lX"
+                          " contains no (usable) outlines\n", i, ch ));
+#endif
             continue;
           }
 
@@ -394,9 +455,10 @@
 
               last = outline.contours[nn];
 
-              /* Avoid single-point contours since they are never rasterized. 
*/
-              /* In some fonts, they correspond to mark attachment points     
*/
-              /* that are way outside of the glyph's real outline.            
*/
+              /* Avoid single-point contours since they are never      */
+              /* rasterized.  In some fonts, they correspond to mark   */
+              /* attachment points that are way outside of the glyph's */
+              /* real outline.                                         */
               if ( last <= first )
                 continue;
 
@@ -648,8 +710,8 @@
                   if ( l2r == left2right     &&
                        d >= length_threshold )
                   {
-                    /* all constraints are met; update segment after finding */
-                    /* its end                                               */
+                    /* all constraints are met; update segment after */
+                    /* finding its end                               */
                     do
                     {
                       if ( last < best_contour_last )
@@ -735,12 +797,31 @@
             FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
           }
 
-          if ( round )
-            rounds[num_rounds++] = best_y;
+          if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+          {
+            if ( best_y > best_y_extremum )
+            {
+              best_y_extremum = best_y;
+              best_round      = round;
+            }
+          }
           else
-            flats[num_flats++]   = best_y;
-        }
-      }
+          {
+            if ( best_y < best_y_extremum )
+            {
+              best_y_extremum = best_y;
+              best_round      = round;
+            }
+          }
+
+        } /* end for loop */
+
+        if ( best_round )
+          rounds[num_rounds++] = best_y_extremum;
+        else
+          flats[num_flats++]   = best_y_extremum;
+
+      } /* end while loop */
 
       if ( num_flats == 0 && num_rounds == 0 )
       {
@@ -820,7 +901,10 @@
       FT_TRACE5(( "    -> reference = %ld\n"
                   "       overshoot = %ld\n",
                   *blue_ref, *blue_shoot ));
-    }
+
+    } /* end for loop */
+
+    af_shaper_buf_destroy( face, shaper_buf );
 
     FT_TRACE5(( "\n" ));
 
@@ -834,27 +918,36 @@
   af_latin_metrics_check_digits( AF_LatinMetrics  metrics,
                                  FT_Face          face )
   {
-    FT_UInt   i;
     FT_Bool   started = 0, same_width = 1;
     FT_Fixed  advance, old_advance = 0;
 
+    void*  shaper_buf;
+
+    /* in all supported charmaps, digits have character codes 0x30-0x39 */
+    const char   digits[] = "0 1 2 3 4 5 6 7 8 9";
+    const char*  p;
+
 
-    /* digit `0' is 0x30 in all supported charmaps */
-    for ( i = 0x30; i <= 0x39; i++ )
+    p          = digits;
+    shaper_buf = af_shaper_buf_create( face );
+
+    while ( *p )
     {
-      FT_ULong  glyph_index;
-      FT_Long   y_offset;
+      FT_ULong      glyph_index;
+      unsigned int  num_idx;
 
 
-      af_get_char_index( &metrics->root, i, &glyph_index, &y_offset );
-      if ( glyph_index == 0 )
+      /* reject input that maps to more than a single glyph */
+      p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+      if ( num_idx > 1 )
         continue;
 
-      if ( FT_Get_Advance( face, glyph_index,
-                           FT_LOAD_NO_SCALE         |
-                           FT_LOAD_NO_HINTING       |
-                           FT_LOAD_IGNORE_TRANSFORM,
-                           &advance ) )
+      glyph_index = af_shaper_get_elem( &metrics->root,
+                                        shaper_buf,
+                                        0,
+                                        &advance,
+                                        NULL );
+      if ( !glyph_index )
         continue;
 
       if ( started )
@@ -872,6 +965,8 @@
       }
     }
 
+    af_shaper_buf_destroy( face, shaper_buf );
+
     metrics->root.digits_have_same_width = same_width;
   }
 
diff --git a/src/autofit/hbshim.c b/src/autofit/afshaper.c
similarity index 75%
rename from src/autofit/hbshim.c
rename to src/autofit/afshaper.c
index 7b05823..f7c518a 100644
--- a/src/autofit/hbshim.c
+++ b/src/autofit/afshaper.c
@@ -1,6 +1,6 @@
 /***************************************************************************/
 /*                                                                         */
-/*  hbshim.c                                                               */
+/*  afshaper.c                                                             */
 /*                                                                         */
 /*    HarfBuzz interface for accessing OpenType features (body).           */
 /*                                                                         */
@@ -20,7 +20,7 @@
 #include FT_FREETYPE_H
 #include "afglobal.h"
 #include "aftypes.h"
-#include "hbshim.h"
+#include "afshaper.h"
 
 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
 
@@ -32,7 +32,7 @@
   /* messages during execution.                                            */
   /*                                                                       */
 #undef  FT_COMPONENT
-#define FT_COMPONENT  trace_afharfbuzz
+#define FT_COMPONENT  trace_afshaper
 
 
   /*
@@ -96,9 +96,9 @@
 
 
   FT_Error
-  af_get_coverage( AF_FaceGlobals  globals,
-                   AF_StyleClass   style_class,
-                   FT_UShort*      gstyles )
+  af_shaper_get_coverage( AF_FaceGlobals  globals,
+                          AF_StyleClass   style_class,
+                          FT_UShort*      gstyles )
   {
     hb_face_t*  face;
 
@@ -418,88 +418,110 @@
   };
 
 
-  FT_Error
-  af_get_char_index( AF_StyleMetrics  metrics,
-                     FT_ULong         charcode,
-                     FT_ULong        *codepoint,
-                     FT_Long         *y_offset )
+  void*
+  af_shaper_buf_create( FT_Face  face )
   {
-    AF_StyleClass  style_class;
-
-    const hb_feature_t*  feature;
+    FT_UNUSED( face );
 
-    FT_ULong  in_idx, out_idx;
+    return (void*)hb_buffer_create();
+  }
 
 
-    if ( !metrics )
-      return FT_THROW( Invalid_Argument );
+  void
+  af_shaper_buf_destroy( FT_Face  face,
+                         void*    buf )
+  {
+    FT_UNUSED( face );
 
-    in_idx = FT_Get_Char_Index( metrics->globals->face, charcode );
+    hb_buffer_destroy( (hb_buffer_t*)buf );
+  }
 
-    style_class = metrics->style_class;
 
-    feature = features[style_class->coverage];
+  const char*
+  af_shaper_get_cluster( const char*      p,
+                         AF_StyleMetrics  metrics,
+                         void*            buf_,
+                         unsigned int*    count )
+  {
+    AF_StyleClass        style_class;
+    const hb_feature_t*  feature;
+    FT_Int               upem;
+    const char*          q;
+    int                  len;
 
-    if ( feature )
-    {
-      FT_Int  upem = (FT_Int)metrics->globals->face->units_per_EM;
+    hb_buffer_t*    buf = (hb_buffer_t*)buf_;
+    hb_font_t*      font;
+    hb_codepoint_t  dummy;
 
-      hb_font_t*    font = metrics->globals->hb_font;
-      hb_buffer_t*  buf  = hb_buffer_create();
 
-      uint32_t  c = (uint32_t)charcode;
+    upem        = (FT_Int)metrics->globals->face->units_per_EM;
+    style_class = metrics->style_class;
+    feature     = features[style_class->coverage];
 
-      hb_glyph_info_t*      ginfo;
-      hb_glyph_position_t*  gpos;
-      unsigned int          gcount;
+    font = metrics->globals->hb_font;
 
+    /* we shape at a size of units per EM; this means font units */
+    hb_font_set_scale( font, upem, upem );
 
-      /* we shape at a size of units per EM; this means font units */
-      hb_font_set_scale( font, upem, upem );
+    while ( *p == ' ' )
+      p++;
 
-      /* 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] );
+    /* count characters up to next space (or end of buffer) */
+    q = p;
+    while ( !( *q == ' ' || *q == '\0' ) )
+      GET_UTF8_CHAR( dummy, q );
+    len = (int)( q - p );
 
-      /* we add one character to `buf' ... */
-      hb_buffer_add_utf32( buf, &c, 1, 0, 1 );
+    /* feed character(s) to the HarfBuzz buffer */
+    hb_buffer_clear_contents( buf );
+    hb_buffer_add_utf8( buf, p, len, 0, len );
 
-      /* ... and apply one feature */
-      hb_shape( font, buf, feature, 1 );
+    /* we let HarfBuzz guess the script and writing direction */
+    hb_buffer_guess_segment_properties( buf );
 
-      ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
-      gpos  = hb_buffer_get_glyph_positions( buf, &gcount );
+    /* shape buffer, which means conversion from character codes to */
+    /* glyph indices, possibly applying a feature                   */
+    hb_shape( font, buf, feature, feature ? 1 : 0 );
 
-      out_idx = ginfo[0].codepoint;
-
-      /* getting the same index indicates no substitution,         */
-      /* which means that the glyph isn't available in the feature */
-      if ( in_idx == out_idx )
-      {
-        *codepoint = 0;
-        *y_offset  = 0;
-      }
-      else
-      {
-        *codepoint = out_idx;
-        *y_offset  = gpos[0].y_offset;
-      }
-
-      hb_buffer_destroy( buf );
+    *count = hb_buffer_get_length( buf );
 
 #ifdef FT_DEBUG_LEVEL_TRACE
-      if ( gcount > 1 )
+      if ( feature && *count > 1 )
         FT_TRACE1(( "af_get_char_index:"
                     " input character mapped to multiple glyphs\n" ));
 #endif
-    }
-    else
-    {
-      *codepoint = in_idx;
-      *y_offset  = 0;
-    }
 
-    return FT_Err_Ok;
+    return q;
+  }
+
+
+  FT_ULong
+  af_shaper_get_elem( AF_StyleMetrics  metrics,
+                      void*            buf_,
+                      unsigned int     idx,
+                      FT_Long*         advance,
+                      FT_Long*         y_offset )
+  {
+    hb_buffer_t*          buf = (hb_buffer_t*)buf_;
+    hb_glyph_info_t*      ginfo;
+    hb_glyph_position_t*  gpos;
+    unsigned int          gcount;
+
+    FT_UNUSED( metrics );
+
+
+    ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
+    gpos  = hb_buffer_get_glyph_positions( buf, &gcount );
+
+    if ( idx >= gcount )
+      return 0;
+
+    if ( advance )
+      *advance = gpos[idx].x_advance;
+    if ( y_offset )
+      *y_offset = gpos[idx].y_offset;
+
+    return ginfo[idx].codepoint;
   }
 
 
@@ -507,9 +529,9 @@
 
 
   FT_Error
-  af_get_coverage( AF_FaceGlobals  globals,
-                   AF_StyleClass   style_class,
-                   FT_UShort*      gstyles )
+  af_shaper_get_coverage( AF_FaceGlobals  globals,
+                          AF_StyleClass   style_class,
+                          FT_UShort*      gstyles )
   {
     FT_UNUSED( globals );
     FT_UNUSED( style_class );
@@ -519,24 +541,91 @@
   }
 
 
-  FT_Error
-  af_get_char_index( AF_StyleMetrics  metrics,
-                     FT_ULong         charcode,
-                     FT_ULong        *codepoint,
-                     FT_Long         *y_offset )
+  void*
+  af_shaper_buf_create( FT_Face  face )
   {
-    FT_Face  face;
+    FT_Memory  memory = face->memory;
+    FT_ULong*  buf;
 
 
-    if ( !metrics )
-      return FT_THROW( Invalid_Argument );
+    FT_ALLOC( buf, sizeof ( FT_ULong ) );
+
+    return (void*)buf;
+  }
+
 
-    face = metrics->globals->face;
+  void
+  af_shaper_buf_destroy( FT_Face  face,
+                         void*    buf )
+  {
+    FT_Memory  memory = face->memory;
 
-    *codepoint = FT_Get_Char_Index( face, charcode );
-    *y_offset  = 0;
 
-    return FT_Err_Ok;
+    FT_FREE( buf );
+  }
+
+
+  const char*
+  af_shaper_get_cluster( const char*      p,
+                         AF_StyleMetrics  metrics,
+                         void*            buf_,
+                         unsigned int*    count )
+  {
+    FT_Face    face      = metrics->globals->face;
+    FT_ULong   ch, dummy = 0;
+    FT_ULong*  buf       = (FT_ULong*)buf_;
+
+
+    while ( *p == ' ' )
+      p++;
+
+    GET_UTF8_CHAR( ch, p );
+
+    /* since we don't have an engine to handle clusters, */
+    /* we scan the characters but return zero            */
+    while ( !( *p == ' ' || *p == '\0' ) )
+      GET_UTF8_CHAR( dummy, p );
+
+    if ( dummy )
+    {
+      *buf   = 0;
+      *count = 0;
+    }
+    else
+    {
+      *buf   = FT_Get_Char_Index( face, ch );
+      *count = 1;
+    }
+
+    return p;
+  }
+
+
+  FT_ULong
+  af_shaper_get_elem( AF_StyleMetrics  metrics,
+                      void*            buf_,
+                      unsigned int     idx,
+                      FT_Long*         advance,
+                      FT_Long*         y_offset )
+  {
+    FT_Face   face        = metrics->globals->face;
+    FT_ULong  glyph_index = *(FT_ULong*)buf_;
+
+    FT_UNUSED( idx );
+
+
+    if ( advance )
+      FT_Get_Advance( face,
+                      glyph_index,
+                      FT_LOAD_NO_SCALE         |
+                      FT_LOAD_NO_HINTING       |
+                      FT_LOAD_IGNORE_TRANSFORM,
+                      advance ) )
+
+    if ( y_offset )
+      *y_offset = 0;
+
+    return glyph_index;
   }
 
 
diff --git a/src/autofit/hbshim.h b/src/autofit/afshaper.h
similarity index 61%
rename from src/autofit/hbshim.h
rename to src/autofit/afshaper.h
index 3824941..db1b4e0 100644
--- a/src/autofit/hbshim.h
+++ b/src/autofit/afshaper.h
@@ -1,6 +1,6 @@
 /***************************************************************************/
 /*                                                                         */
-/*  hbshim.h                                                               */
+/*  afshaper.h                                                             */
 /*                                                                         */
 /*    HarfBuzz interface for accessing OpenType features (specification).  */
 /*                                                                         */
@@ -16,8 +16,8 @@
 /***************************************************************************/
 
 
-#ifndef __HBSHIM_H__
-#define __HBSHIM_H__
+#ifndef __AFSHAPER_H__
+#define __AFSHAPER_H__
 
 
 #include <ft2build.h>
@@ -36,21 +36,36 @@
 FT_BEGIN_HEADER
 
   FT_Error
-  af_get_coverage( AF_FaceGlobals  globals,
-                   AF_StyleClass   style_class,
-                   FT_UShort*      gstyles );
+  af_shaper_get_coverage( AF_FaceGlobals  globals,
+                          AF_StyleClass   style_class,
+                          FT_UShort*      gstyles );
 
-  FT_Error
-  af_get_char_index( AF_StyleMetrics  metrics,
-                     FT_ULong         charcode,
-                     FT_ULong        *codepoint,
-                     FT_Long         *y_offset );
+
+  void*
+  af_shaper_buf_create( FT_Face  face );
+
+  void
+  af_shaper_buf_destroy( FT_Face  face,
+                         void*    buf );
+
+  const char*
+  af_shaper_get_cluster( const char*      p,
+                         AF_StyleMetrics  metrics,
+                         void*            buf_,
+                         unsigned int*    count );
+
+  FT_ULong
+  af_shaper_get_elem( AF_StyleMetrics  metrics,
+                      void*            buf_,
+                      unsigned int     idx,
+                      FT_Long*         x_advance,
+                      FT_Long*         y_offset );
 
  /* */
 
 FT_END_HEADER
 
-#endif /* __HBSHIM_H__ */
+#endif /* __AFSHAPER_H__ */
 
 
 /* END */
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index b6ed4a0..a971a24 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -34,7 +34,7 @@
 #include "afcjk.c"
 #include "afindic.c"
 
-#include "hbshim.c"
+#include "afshaper.c"
 
 #include "afloader.c"
 #include "afmodule.c"
diff --git a/src/autofit/rules.mk b/src/autofit/rules.mk
index 6ef959f..57a24bd 100644
--- a/src/autofit/rules.mk
+++ b/src/autofit/rules.mk
@@ -40,8 +40,8 @@ AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
                  $(AUTOF_DIR)/afmodule.c \
                  $(AUTOF_DIR)/afpic.c    \
                  $(AUTOF_DIR)/afranges.c \
-                 $(AUTOF_DIR)/afwarp.c   \
-                 $(AUTOF_DIR)/hbshim.c
+                 $(AUTOF_DIR)/afshaper.c \
+                 $(AUTOF_DIR)/afwarp.c
 
 # AUTOF driver headers
 #



reply via email to

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