shithub: freetype+ttf2subf

Download patch

ref: 19241347101203f873b47ddc0c17f7144373a986
parent: b337fa25cf1ae602a9ba8ac11d2896cc004caa17
author: Werner Lemberg <[email protected]>
date: Sat Dec 21 16:31:38 EST 2013

Introduce `coverages'.

Coverages are the interface to the HarfBuzz library to access
OpenType features for handling glyphs not addressable by the cmap.

Right now, compilation of HarfBuzz is only added to the development
build.  A solution for standard build mode will be delayed until
HarfBuzz gets split into two libraries to avoid mutual dependencies
between FreeType and HarfBuzz.

Note that this is only a first step in handling coverages, basically
providing the framework only.  Code for handling selected OpenType
features (this is, actually using the data in `afcover.h') will
follow.

* devel/ftoption.h, include/config/ftoption.h
(FT_CONFIG_OPTION_USE_HARFBUZZ): New macro.

* src/autofit/hbshim.c, src/autofit/hbshim.h, src/autofit/afcover.h:
New files.

* src/autofit/afscript.h: Add HarfBuzz script name tags.

* src/autofit/afstyles.h: Add default coverage enumeration values.

* src/autofit/aftypes.h: Update use of `SCRIPT' and `STYLE' macros.
(AF_Coverage): New enumeration (generated by `afcover.h').
(AF_StyleClassRec): New member `coverage'.
(AF_DEFINE_STYLE_CLASS): Updated.

* include/internal/fttrace.h: Add `afharfbuzz' for tracing coverage
data.

* src/autofit/afglobal.h: Update use of `SCRIPT' and `STYLE' macros.
(AF_SCRIPT_FALLBACK): Renamed to ...
(AF_STYLE_FALLBACK): ... this.

* src/autofit/afglobal.c: Include `hbshim.c'.
Update use of `SCRIPT' and `STYLE' macros.
(af_face_globals_compute_style_coverage)
[FT_CONFIG_OPTION_USE_HARFBUZZ]: Call `af_get_coverage'.
Update.

* src/autofit/afmodule.h (AF_ModuleRec):
s/fallback_script/fallback_style/.

* src/autofit/afmodule.c (af_property_set): Adapt handling of
`fallback-script' property to set a fallback style.
(af_property_get, af_autofitter_init): Updated.

* src/autofit/afpic.c: Update use of `SCRIPT' and `STYLE' macros.

* src/autofit/afranges.h: Update use of `SCRIPT' macro.

* src/autofit/autofit.c [FT_CONFIG_OPTION_USE_HARFBUZZ]: Include
`hbshim.c'.

* src/autofit/rules.mk (AUTOF_DRV_SRC): Add `hbshim.c'.
(AUTOF_DRV_H): Add `afcover.h'.

* builds/freetype.mk (INCLUDE_FLAGS) [DEVEL_DIR]: Use pkg-config for
all libraries needed by FreeType.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,70 @@
 2013-12-21  Werner Lemberg  <[email protected]>
 
+	[autofit] Introduce `coverages'.
+
+	Coverages are the interface to the HarfBuzz library to acces
+	OpenType features for handling glyphs not addressable by the cmap.
+
+	Right now, compilation of HarfBuzz is only added to the development
+	build.  A solution for standard build mode will be delayed until
+	HarfBuzz gets split into two libraries to avoid mutual dependencies
+	between FreeType and HarfBuzz.
+
+	Note that this is only a first step in handling coverages, basically
+	providing the framework only.  Code for handling selected OpenType
+	features (this is, actually using the data in `afcover.h') will
+	follow.
+
+	* devel/ftoption.h, include/config/ftoption.h
+	(FT_CONFIG_OPTION_USE_HARFBUZZ): New macro.
+
+	* src/autofit/hbshim.c, src/autofit/hbshim.h, src/autofit/afcover.h:
+	New files.
+
+	* src/autofit/afscript.h: Add HarfBuzz script name tags.
+
+	* src/autofit/afstyles.h: Add default coverage enumeration values.
+
+	* src/autofit/aftypes.h: Update use of `SCRIPT' and `STYLE' macros.
+	(AF_Coverage): New enumeration (generated by `afcover.h').
+	(AF_StyleClassRec): New member `coverage'.
+	(AF_DEFINE_STYLE_CLASS): Updated.
+
+	* include/internal/fttrace.h: Add `afharfbuzz' for tracing coverage
+	data.
+
+	* src/autofit/afglobal.h: Update use of `SCRIPT' and `STYLE' macros.
+	(AF_SCRIPT_FALLBACK): Renamed to ...
+	(AF_STYLE_FALLBACK): ... this.
+
+	* src/autofit/afglobal.c: Include `hbshim.c'.
+	Update use of `SCRIPT' and `STYLE' macros.
+	(af_face_globals_compute_style_coverage)
+	[FT_CONFIG_OPTION_USE_HARFBUZZ]: Call `af_get_coverage'.
+	Update.
+
+	* src/autofit/afmodule.h (AF_ModuleRec):
+	s/fallback_script/fallback_style/.
+
+	* src/autofit/afmodule.c (af_property_set): Adapt handling of
+	`fallback-script' property to set a fallback style.
+	(af_property_get, af_autofitter_init): Updated.
+
+	* src/autofit/afpic.c: Update use of `SCRIPT' and `STYLE' macros.
+
+	* src/autofit/afranges.h: Update use of `SCRIPT' macro.
+
+	* src/autofit/autofit.c [FT_CONFIG_OPTION_USE_HARFBUZZ]: Include
+	`hbshim.c'.
+
+	* src/autofit/rules.mk (AUTOF_DRV_SRC): Add `hbshim.c'.
+	(AUTOF_DRV_H): Add `afcover.h'.
+
+	* builds/freetype.mk (INCLUDE_FLAGS) [DEVEL_DIR]: Use pkg-config for
+	all libraries needed by FreeType.
+
+2013-12-21  Werner Lemberg  <[email protected]>
+
 	Fix Savannah bug #40975 (sort of).
 
 	* src/truetype/ttinterp.c (Ins_IP): Fix sign typo to make FreeType
--- a/builds/freetype.mk
+++ b/builds/freetype.mk
@@ -126,6 +126,15 @@
 
 INCLUDE_FLAGS := $(INCLUDES:%=$I%)
 
+ifdef DEVEL_DIR
+  # We assume that all library dependencies for FreeType are fulfilled for a
+  # development build, so we directly access the necessary include directory
+  # information using `pkg-config'.
+  INCLUDE_FLAGS += $(shell pkg-config --cflags bzip2 \
+                                               libpng \
+                                               harfbuzz )
+endif
+
 
 # C flags used for the compilation of an object file.  This must include at
 # least the paths for the `base' and `builds/<system>' directories;
--- a/devel/ftoption.h
+++ b/devel/ftoption.h
@@ -219,6 +219,19 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /*  HarfBuzz support.                                                    */
+  /*                                                                       */
+  /*   FreeType uses the HarfBuzz library to improve auto-hinting of       */
+  /*   OpenType fonts.  If available, many glyphs not directly addressable */
+  /*   by a font's character map will be hinted also.                      */
+  /*                                                                       */
+  /*   Define this macro if you want to enable this `feature'.             */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_USE_HARFBUZZ
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* Define to disable the use of file stream functions and types, FILE,   */
   /* fopen() etc.  Enables the use of smaller system libraries on embedded */
   /* systems that have multiple system libraries, some with or without     */
--- a/include/config/ftoption.h
+++ b/include/config/ftoption.h
@@ -230,6 +230,19 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /*  HarfBuzz support.                                                    */
+  /*                                                                       */
+  /*   FreeType uses the HarfBuzz library to improve auto-hinting of       */
+  /*   OpenType fonts.  If available, many glyphs not directly addressable */
+  /*   by a font's character map will be hinted also.                      */
+  /*                                                                       */
+  /*   Define this macro if you want to enable this `feature'.             */
+  /*                                                                       */
+/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* DLL export compilation                                                */
   /*                                                                       */
   /*   When compiling FreeType as a DLL, some systems/compilers need a     */
--- a/include/internal/fttrace.h
+++ b/include/internal/fttrace.h
@@ -148,5 +148,6 @@
 FT_TRACE_DEF( aflatin )
 FT_TRACE_DEF( aflatin2 )
 FT_TRACE_DEF( afwarp )
+FT_TRACE_DEF( afharfbuzz )
 
 /* END */
--- /dev/null
+++ b/src/autofit/afcover.h
@@ -1,0 +1,66 @@
+/***************************************************************************/
+/*                                                                         */
+/*  afcover.h                                                              */
+/*                                                                         */
+/*    Auto-fitter coverages (specification only).                          */
+/*                                                                         */
+/*  Copyright 2013 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /* This header file can be included multiple times. */
+  /* Define `COVERAGE_{1,2,3}' as needed.             */
+
+
+  /* Add new coverages here.  The first and second arguments are the   */
+  /* coverage name in lowercase and uppercase, respectively, followed  */
+  /* by a description string.  The remaining arguments the             */
+  /* corresponding OpenType features (with four characters a feature). */
+
+  COVERAGE_1( oldstyle_figures, OLDSTYLE_FIGURES,
+              "oldstyle figures",
+              'o', 'n', 'u', 'm' ) /* Oldstyle Figures */
+
+  COVERAGE_2( petite_capitals, PETITE_CAPITALS,
+              "petite capitals",
+              'c', '2', 'c', 'p',  /* Petite Capitals from Capitals */
+              'p', 'c', 'a', 'p' ) /* Petite Capitals               */
+
+  COVERAGE_2( small_capitals, SMALL_CAPITALS,
+              "small capitals",
+              'c', '2', 's', 'c',  /* Small Capitals from Capitals */
+              's', 'm', 'c', 'p' ) /* Small Capitals               */
+
+  COVERAGE_1( titling, TITLING,
+              "titling",
+              't', 'i', 't', 'l' ) /* Titling */
+
+  COVERAGE_2( sub_superscript_1, SUB_SUPERSCRIPT_1,
+              "sub- and superscripts group 1",
+              's', 'u', 'b', 's',  /* Subscript   */
+              's', 'u', 'p', 's' ) /* Superscript */
+
+  COVERAGE_2( sub_superscript_2, SUB_SUPERSCRIPT_2,
+              "sub- and superscripts group 2",
+              'o', 'r', 'd', 'n',  /* Ordinals             */
+              's', 'i', 'n', 'f' ) /* Scientific Inferiors */
+
+  COVERAGE_3( fractions, FRACTIONS,
+              "fractions",
+              'd', 'n', 'o', 'm',  /* Denominators */
+              'f', 'r', 'a', 'c',  /* Fractions    */
+              'n', 'u', 'm', 'r' ) /* Numerators   */
+
+  COVERAGE_1( alternative_fractions, ALTERNATIVE_FRACTIONS,
+              "alternative fractions",
+              'a', 'f', 'r', 'c' ) /* Alternative Fractions */
+
+/* END */
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -18,6 +18,7 @@
 
 #include "afglobal.h"
 #include "afranges.h"
+#include "hbshim.h"
 
   /* get writing system specific header files */
 #undef  WRITING_SYSTEM
@@ -29,7 +30,7 @@
 
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, dc )          \
+#define SCRIPT( s, S, d, h, dc )       \
           AF_DEFINE_SCRIPT_CLASS(      \
             af_ ## s ## _script_class, \
             AF_SCRIPT_ ## S,           \
@@ -40,13 +41,14 @@
 
 
 #undef  STYLE
-#define STYLE( s, S, d, ws, sc, ss )  \
-          AF_DEFINE_STYLE_CLASS(      \
-            af_ ## s ## _style_class, \
-            AF_STYLE_ ## S,           \
-            ws,                       \
-            sc,                       \
-            ss )
+#define STYLE( s, S, d, ws, sc, ss, c )  \
+          AF_DEFINE_STYLE_CLASS(         \
+            af_ ## s ## _style_class,    \
+            AF_STYLE_ ## S,              \
+            ws,                          \
+            sc,                          \
+            ss,                          \
+            c )
 
 #include "afstyles.h"
 
@@ -68,7 +70,7 @@
 
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, dc )         \
+#define SCRIPT( s, S, d, h, dc )      \
           &af_ ## s ## _script_class,
 
   FT_LOCAL_ARRAY_DEF( AF_ScriptClass )
@@ -82,7 +84,7 @@
 
 
 #undef  STYLE
-#define STYLE( s, S, d, ws, sc, ss ) \
+#define STYLE( s, S, d, ws, sc, ss, c ) \
           &af_ ## s ## _style_class,
 
   FT_LOCAL_ARRAY_DEF( AF_StyleClass )
@@ -100,7 +102,7 @@
 #ifdef FT_DEBUG_LEVEL_TRACE
 
 #undef  STYLE
-#define STYLE( s, S, d, ws, sc, ss )  #s,
+#define STYLE( s, S, d, ws, sc, ss, c )  #s,
 
   FT_LOCAL_ARRAY_DEF( char* )
   af_style_names[] =
@@ -135,7 +137,7 @@
     if ( error )
     {
      /*
-      *  Ignore this error; we simply use the fallback script.
+      *  Ignore this error; we simply use the fallback style.
       *  XXX: Shouldn't we rather disable hinting?
       */
       error = FT_Err_Ok;
@@ -186,6 +188,11 @@
             gstyles[gindex] = (FT_Byte)ss;
         }
       }
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+      /* get glyphs not directly addressable by cmap */
+      af_get_coverage( face, style_class, gstyles );
+#endif
     }
 
     /* mark ASCII digits */
@@ -200,10 +207,10 @@
 
   Exit:
     /*
-     *  By default, all uncovered glyphs are set to the fallback script.
+     *  By default, all uncovered glyphs are set to the fallback style.
      *  XXX: Shouldn't we disable hinting or do something similar?
      */
-    if ( globals->module->fallback_script != AF_STYLE_UNASSIGNED )
+    if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED )
     {
       FT_Long  nn;
 
@@ -213,7 +220,7 @@
         if ( ( gstyles[nn] & ~AF_DIGIT ) == AF_STYLE_UNASSIGNED )
         {
           gstyles[nn] &= ~AF_STYLE_UNASSIGNED;
-          gstyles[nn] |= globals->module->fallback_script;
+          gstyles[nn] |= globals->module->fallback_style;
         }
       }
     }
--- a/src/autofit/afglobal.h
+++ b/src/autofit/afglobal.h
@@ -33,7 +33,7 @@
 
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, dc )                                  \
+#define SCRIPT( s, S, d, h, dc )                               \
           AF_DECLARE_SCRIPT_CLASS( af_ ## s ## _script_class )
 
 #include "afscript.h"
@@ -43,7 +43,7 @@
 
 
 #undef  STYLE
-#define STYLE( s, S, d, ws, sc, ss )                         \
+#define STYLE( s, S, d, ws, sc, ss, c )                      \
           AF_DECLARE_STYLE_CLASS( af_ ## s ## _style_class )
 
 #include "afstyles.h"
@@ -63,11 +63,11 @@
    *  AF_ModuleRec) and face globals (in AF_FaceGlobalsRec).
    */
 
-  /* index of fallback script in `af_style_classes' */
+  /* index of fallback style in `af_style_classes' */
 #ifdef AF_CONFIG_OPTION_CJK
-#define AF_SCRIPT_FALLBACK  AF_STYLE_HANI_DEFAULT
+#define AF_STYLE_FALLBACK  AF_STYLE_HANI_DEFAULT
 #else
-#define AF_SCRIPT_FALLBACK  AF_STYLE_NONE_DEFAULT
+#define AF_STYLE_FALLBACK  AF_STYLE_NONE_DEFAULT
 #endif
   /* a bit mask indicating an uncovered glyph        */
 #define AF_STYLE_UNASSIGNED  0x7F
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -92,9 +92,32 @@
     {
       FT_UInt*  fallback_script = (FT_UInt*)value;
 
+      FT_UInt  ss;
 
-      module->fallback_script = *fallback_script;
 
+      /* We translate the fallback script to a fallback style that uses */
+      /* `fallback-script' as its script and `AF_COVERAGE_NONE' as its  */
+      /* coverage value.                                                */
+      for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
+      {
+        AF_StyleClass  style_class = AF_STYLE_CLASSES_GET[ss];
+
+
+        if ( style_class->script == *fallback_script      &&
+             style_class->coverage == AF_COVERAGE_DEFAULT )
+        {
+          module->fallback_style = ss;
+          break;
+        }
+      }
+
+      if ( !AF_STYLE_CLASSES_GET[ss] )
+      {
+        FT_TRACE0(( "af_property_set: Invalid value %d for property `%s'\n",
+                    fallback_script, property_name ));
+        return FT_THROW( Invalid_Argument );
+      }
+
       return error;
     }
     else if ( !ft_strcmp( property_name, "increase-x-height" ) )
@@ -121,9 +144,9 @@
                    const char*  property_name,
                    void*        value )
   {
-    FT_Error   error           = FT_Err_Ok;
-    AF_Module  module          = (AF_Module)ft_module;
-    FT_UInt    fallback_script = module->fallback_script;
+    FT_Error   error          = FT_Err_Ok;
+    AF_Module  module         = (AF_Module)ft_module;
+    FT_UInt    fallback_style = module->fallback_style;
 
 
     if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
@@ -142,9 +165,11 @@
     {
       FT_UInt*  val = (FT_UInt*)value;
 
+      AF_StyleClass  style_class = AF_STYLE_CLASSES_GET[fallback_style];
 
-      *val = fallback_script;
 
+      *val = style_class->script;
+
       return error;
     }
     else if ( !ft_strcmp( property_name, "increase-x-height" ) )
@@ -206,7 +231,7 @@
     AF_Module  module = (AF_Module)ft_module;
 
 
-    module->fallback_script = AF_SCRIPT_FALLBACK;
+    module->fallback_style = AF_STYLE_FALLBACK;
 
     return af_loader_init( module );
   }
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -40,7 +40,7 @@
   {
     FT_ModuleRec  root;
 
-    FT_UInt       fallback_script;
+    FT_UInt       fallback_style;
 
     AF_LoaderRec  loader[1];
 
--- a/src/autofit/afpic.c
+++ b/src/autofit/afpic.c
@@ -122,7 +122,7 @@
 #include "afwrtsys.h"
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, dc )                        \
+#define SCRIPT( s, S, d, h, dc )                     \
         FT_Init_Class_af_ ## s ## _script_class(     \
           &container->af_script_classes_rec[ss++] );
 
@@ -130,7 +130,7 @@
 #include "afscript.h"
 
 #undef  STYLE
-#define STYLE( s, S, d, ws, sc, bss )               \
+#define STYLE( s, S, d, ws, sc, bss, c )            \
         FT_Init_Class_af_ ## s ## _style_class(     \
           &container->af_style_classes_rec[ss++] );
 
--- a/src/autofit/afranges.h
+++ b/src/autofit/afranges.h
@@ -26,7 +26,7 @@
 FT_BEGIN_HEADER
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, dc )                                           \
+#define SCRIPT( s, S, d, h, dc )                                        \
           extern const AF_Script_UniRangeRec  af_ ## s ## _uniranges[];
 
 #include "afscript.h"
--- a/src/autofit/afscript.h
+++ b/src/autofit/afscript.h
@@ -20,34 +20,45 @@
   /* Define `SCRIPT' as needed.                         */
 
 
-  /* Add new scripts here. */
+  /* Add new scripts here.  The first and second arguments are the   */
+  /* script name in lowercase and uppercase, respectively, followed  */
+  /* by a description string.  Then comes the corresponding HarfBuzz */
+  /* script name tag, followed by the default character (to derive   */
+  /* the standard width and height of stems).                        */
 
   SCRIPT( cyrl, CYRL,
           "Cyrillic",
+          HB_SCRIPT_CYRILLIC,
           0x43E ) /* о */
 
   SCRIPT( deva, DEVA,
           "Indic scripts",
+          HB_SCRIPT_DEVANAGARI,
           'o' ) /* XXX */
 
   SCRIPT( none, NONE,
           "no script",
+          HB_SCRIPT_INVALID,
           '\0' )
 
   SCRIPT( grek, GREK,
           "Greek",
+          HB_SCRIPT_GREEK,
           0x3BF ) /* ο */
 
   SCRIPT( hani, HANI,
           "CJKV ideographs",
+          HB_SCRIPT_HAN,
           0x7530 ) /* 田 */
 
   SCRIPT( hebr, HEBR,
           "Hebrew",
+          HB_SCRIPT_HEBREW,
           0x5DD ) /* ם */
 
   SCRIPT( latn, LATN,
           "Latin",
+          HB_SCRIPT_LATIN,
           'o' )
 
 
--- a/src/autofit/afstyles.h
+++ b/src/autofit/afstyles.h
@@ -20,49 +20,53 @@
   /* Define `STYLE' as needed.                          */
 
 
-  /* Add new styles here. */
+  /* Add new styles here.  The first and second arguments are the  */
+  /* style name in lowercase and uppercase, respectively, followed */
+  /* by a description string.  The next arguments are the          */
+  /* corresponding writing system, script, blue stringset, and     */
+  /* coverage.                                                     */
 
   STYLE( cyrl_default, CYRL_DEFAULT,
          "Cyrillic default style",
          AF_WRITING_SYSTEM_LATIN,
          AF_SCRIPT_CYRL,
-         AF_BLUE_STRINGSET_CYRL )
+         AF_BLUE_STRINGSET_CYRL,
+         AF_COVERAGE_DEFAULT )
 
   STYLE( deva_default, DEVA_DEFAULT,
          "Indic scripts default style",
          AF_WRITING_SYSTEM_INDIC,
          AF_SCRIPT_DEVA,
-         (AF_Blue_Stringset)0 ) /* XXX */
+         (AF_Blue_Stringset)0, /* XXX */
+         AF_COVERAGE_DEFAULT )
 
-  STYLE( none_default, NONE_DEFAULT,
-         "no style",
-         AF_WRITING_SYSTEM_DUMMY,
-         AF_SCRIPT_NONE,
-         (AF_Blue_Stringset)0 )
-
   STYLE( grek_default, GREK_DEFAULT,
          "Greek default style",
          AF_WRITING_SYSTEM_LATIN,
          AF_SCRIPT_GREK,
-         AF_BLUE_STRINGSET_GREK )
+         AF_BLUE_STRINGSET_GREK,
+         AF_COVERAGE_DEFAULT )
 
   STYLE( hani_default, HANI_DEFAULT,
          "CJKV ideographs default style",
          AF_WRITING_SYSTEM_CJK,
          AF_SCRIPT_HANI,
-         AF_BLUE_STRINGSET_HANI )
+         AF_BLUE_STRINGSET_HANI,
+         AF_COVERAGE_DEFAULT )
 
   STYLE( hebr_default, HEBR_DEFAULT,
          "Hebrew default style",
          AF_WRITING_SYSTEM_LATIN,
          AF_SCRIPT_HEBR,
-         AF_BLUE_STRINGSET_HEBR )
+         AF_BLUE_STRINGSET_HEBR,
+         AF_COVERAGE_DEFAULT )
 
   STYLE( latn_default, LATN_DEFAULT,
          "Latin default style",
          AF_WRITING_SYSTEM_LATIN,
          AF_SCRIPT_LATN,
-         AF_BLUE_STRINGSET_LATN )
+         AF_BLUE_STRINGSET_LATN,
+         AF_COVERAGE_DEFAULT )
 
 #ifdef FT_OPTION_AUTOFIT2
   STYLE( ltn2_default, LTN2_DEFAULT,
@@ -69,8 +73,16 @@
          "Latin 2 default style",
          AF_WRITING_SYSTEM_LATIN2,
          AF_SCRIPT_LATN,
-         AF_BLUE_STRINGSET_LATN )
+         AF_BLUE_STRINGSET_LATN,
+         AF_COVERAGE_DEFAULT )
 #endif
+
+  STYLE( none_default, NONE_DEFAULT,
+         "no style",
+         AF_WRITING_SYSTEM_DUMMY,
+         AF_SCRIPT_NONE,
+         (AF_Blue_Stringset)0,
+         AF_COVERAGE_DEFAULT )
 
 
 /* END */
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -303,7 +303,7 @@
    */
 
 #undef  SCRIPT
-#define SCRIPT( s, S, d, dc ) \
+#define SCRIPT( s, S, d, h, dc ) \
           AF_SCRIPT_ ## S,
 
   /* The list of known scripts. */
@@ -344,6 +344,82 @@
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
+  /*****                      C O V E R A G E S                        *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*
+   *  Usually, a font contains more glyphs than can be addressed by its
+   *  character map.
+   *
+   *  In the PostScript font world, encoding vectors specific to a given
+   *  task are used to select such glyphs, and these glyphs can be often
+   *  recognized by having a suffix in its glyph names.  For example, a
+   *  superscript glyph `A' might be called `A.sup'.  Unfortunately, this
+   *  naming scheme is not standardized and thus unusable for us.
+   *
+   *  In the OpenType world, a better solution was invented, namely
+   *  `features', which cleanly separate a character's input encoding from
+   *  the corresponding glyph's appearance, and which don't use glyph names
+   *  at all.  For our purposes, and slightly generalized, an OpenType
+   *  feature is a name of a mapping that maps character codes to
+   *  non-standard glyph indices (features get used for other things also).
+   *  For example, the `sups' feature provides superscript glyphs, thus
+   *  mapping character codes like `A' or `B' to superscript glyph
+   *  representation forms.  How this mapping happens is completely
+   *  uninteresting to us.
+   *
+   *  For the auto-hinter, a `coverage' represents all glyphs of one or more
+   *  OpenType features collected in a set (as listed below) that can be
+   *  hinted together.  To continue the above example, superscript glyphs
+   *  must not be hinted together with normal glyphs because the blue zones
+   *  completely differ.  On the other hand, superscripts and subscripts
+   *  don't overlap, so they can be combined into a single set.
+   *
+   *  Note that FreeType itself doesn't compute coverages; it only provides
+   *  the glyphs addressable by the default Unicode character map.  Instead,
+   *  we use the HarfBuzz library (if available), which has many functions
+   *  exactly for this purpose.
+   *
+   *  AF_COVERAGE_DEFAULT is special: It should cover everything that isn't
+   *  listed separately (including the glyphs addressable by the character
+   *  map).  In case HarfBuzz isn't available, it exactly covers the glyphs
+   *  addressable by the character map.
+   *
+   */
+
+#undef  COVERAGE_1
+#define COVERAGE_1( name, NAME, description,         \
+                    tag_a1, tag_a2, tag_a3, tag_a4 ) \
+          AF_COVERAGE_ ## NAME,
+
+#undef  COVERAGE_2
+#define COVERAGE_2( name, NAME, description,         \
+                    tag_a1, tag_a2, tag_a3, tag_a4,  \
+                    tag_b1, tag_b2, tag_b3, tag_b4 ) \
+          AF_COVERAGE_ ## NAME,
+
+#undef  COVERAGE_3
+#define COVERAGE_3( name, NAME, description,         \
+                    tag_a1, tag_a2, tag_a3, tag_a4,  \
+                    tag_b1, tag_b2, tag_b3, tag_b4,  \
+                    tag_c1, tag_c2, tag_c3, tag_c4 ) \
+          AF_COVERAGE_ ## NAME,
+
+
+  typedef enum  AF_Coverage_
+  {
+#include "afcover.h"
+
+    AF_COVERAGE_DEFAULT
+
+  } AF_Coverage;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
   /*****                         S T Y L E S                           *****/
   /*****                                                               *****/
   /*************************************************************************/
@@ -355,7 +431,7 @@
    */
 
 #undef  STYLE
-#define STYLE( s, S, d, ws, sc, ss ) \
+#define STYLE( s, S, d, ws, sc, ss, c ) \
           AF_STYLE_ ## S,
 
   /* The list of known styles. */
@@ -376,6 +452,7 @@
     AF_WritingSystem   writing_system;
     AF_Script          script;
     AF_Blue_Stringset  blue_stringset;
+    AF_Coverage        coverage;
 
   } AF_StyleClassRec;
 
@@ -466,7 +543,8 @@
           style,                        \
           writing_system,               \
           script,                       \
-          blue_stringset )              \
+          blue_stringset,               \
+          coverage )                    \
   FT_CALLBACK_TABLE_DEF                 \
   const AF_StyleClassRec  style_class = \
   {                                     \
@@ -473,7 +551,8 @@
     style,                              \
     writing_system,                     \
     script,                             \
-    blue_stringset                      \
+    blue_stringset,                     \
+    coverage                            \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
@@ -534,7 +613,8 @@
           style_,                                        \
           writing_system_,                               \
           script_,                                       \
-          blue_stringset_ )                              \
+          blue_stringset_,                               \
+          coverage_ )                                    \
   FT_LOCAL_DEF( void )                                   \
   FT_Init_Class_ ## style_class( AF_StyleClassRec*  ac ) \
   {                                                      \
@@ -542,6 +622,7 @@
     ac->writing_system = writing_system_;                \
     ac->script         = script_;                        \
     ac->blue_stringset = blue_stringset_;                \
+    ac->coverage       = coverage_;                      \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
--- a/src/autofit/afwrtsys.h
+++ b/src/autofit/afwrtsys.h
@@ -37,7 +37,8 @@
   /* Define `WRITING_SYSTEM' as needed.                 */
 
 
-  /* Add new writing systems here. */
+  /* Add new writing systems here.  The arguments are the writing system */
+  /* name in lowercase and uppercase, respectively.                      */
 
   WRITING_SYSTEM( dummy,  DUMMY  )
   WRITING_SYSTEM( latin,  LATIN  )
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -34,6 +34,10 @@
 #include "afcjk.c"
 #include "afindic.c"
 
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+#include "hbshim.c"
+#endif
+
 #include "afloader.c"
 #include "afmodule.c"
 
--- /dev/null
+++ b/src/autofit/hbshim.c
@@ -1,0 +1,269 @@
+/***************************************************************************/
+/*                                                                         */
+/*  hbshim.c                                                               */
+/*                                                                         */
+/*    HarfBuzz interface for accessing OpenType features (body).           */
+/*                                                                         */
+/*  Copyright 2013 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+#include <hb.h>
+#include <hb-ot.h>
+#include <hb-ft.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_afharfbuzz
+
+
+  /*
+   * We use `sets' (in the HarfBuzz sense, which comes quite near to the
+   * usual mathematical meaning) to manage both lookups and glyph indices.
+   *
+   * 1. For each coverage, collect lookup IDs in a set.  Note that an
+   *    auto-hinter `coverage' is represented by one or more `feature's, and
+   *    a feature consists of an arbitrary number of (font specific)
+   *    `lookup's that actually do the mapping job.  Please check the
+   *    OpenType specification for more details on features and lookups.
+   *
+   * 2. Create glyph ID sets from the corresponding lookup sets.
+   *
+   * 3. The glyph set corresponding to AF_COVERAGE_DEFAULT is computed
+   *    with all lookups specific to the OpenType script activated.  It
+   *    relies on the order of AF_DEFINE_STYLE_CLASS entries so that
+   *    special coverages (like `oldstyle figures') don't get overwritten.
+   *
+   */
+
+
+  /* load coverage tags */
+#undef  COVERAGE_1
+#define COVERAGE_1( name, NAME, description,           \
+                    tag_a1, tag_a2, tag_a3, tag_a4 )   \
+          static const hb_tag_t  name ## _coverage[] = \
+          {                                            \
+            HB_TAG( tag_a1, tag_a2, tag_a3, tag_a4 ),  \
+            HB_TAG_NONE                                \
+          };
+
+#undef  COVERAGE_2
+#define COVERAGE_2( name, NAME, description,           \
+                    tag_a1, tag_a2, tag_a3, tag_a4,    \
+                    tag_b1, tag_b2, tag_b3, tag_b4 )   \
+          static const hb_tag_t  name ## _coverage[] = \
+          {                                            \
+            HB_TAG( tag_a1, tag_a2, tag_a3, tag_a4 ),  \
+            HB_TAG( tag_b1, tag_b2, tag_b3, tag_b4 ),  \
+            HB_TAG_NONE                                \
+          };
+
+#undef  COVERAGE_3
+#define COVERAGE_3( name, NAME, description,           \
+                    tag_a1, tag_a2, tag_a3, tag_a4,    \
+                    tag_b1, tag_b2, tag_b3, tag_b4,    \
+                    tag_c1, tag_c2, tag_c3, tag_c4 )   \
+          static const hb_tag_t  name ## _coverage[] = \
+          {                                            \
+            HB_TAG( tag_a1, tag_a2, tag_a3, tag_a4 ),  \
+            HB_TAG( tag_b1, tag_b2, tag_b3, tag_b4 ),  \
+            HB_TAG( tag_c1, tag_c2, tag_c3, tag_c4 ),  \
+            HB_TAG_NONE                                \
+          };
+
+
+#include "afcover.h"
+
+
+  /* define mapping between coverage tags and AF_Coverage */
+#undef  COVERAGE_1
+#define COVERAGE_1( name, NAME, description,           \
+                    tag_a1, tag_a2, tag_a3, tag_a4 )   \
+          name ## _coverage,
+
+#undef  COVERAGE_2
+#define COVERAGE_2( name, NAME, description,           \
+                    tag_a1, tag_a2, tag_a3, tag_a4,    \
+                    tag_b1, tag_b2, tag_b3, tag_b4 )   \
+          name ## _coverage,
+
+#undef  COVERAGE_3
+#define COVERAGE_3( name, NAME, description,           \
+                    tag_a1, tag_a2, tag_a3, tag_a4,    \
+                    tag_b1, tag_b2, tag_b3, tag_b4,    \
+                    tag_c1, tag_c2, tag_c3, tag_c4 )   \
+          name ## _coverage,
+
+
+  static const hb_tag_t*  coverages[] =
+  {
+#include "afcover.h"
+
+    NULL /* AF_COVERAGE_DEFAULT */
+  };
+
+
+  /* load HarfBuzz script tags */
+#undef  SCRIPT
+#define SCRIPT( s, S, d, h, dc )  h,
+
+
+  static const hb_tag_t  scripts[] =
+  {
+#include "afscript.h"
+  };
+
+
+  FT_Error
+  af_get_coverage( FT_Face        ft_face,
+                   AF_StyleClass  style_class,
+                   FT_Byte*       gstyles )
+  {
+    hb_face_t*  face;
+
+    hb_set_t*  lookups;  /* lookups for a given script */
+    hb_set_t*  glyphs;   /* glyphs covered by lookups  */
+
+    hb_tag_t         script;
+    const hb_tag_t*  coverage_tags;
+    hb_tag_t         script_tags[] = { HB_TAG_NONE,
+                                       HB_TAG_NONE,
+                                       HB_TAG_NONE };
+
+    hb_codepoint_t  idx;
+#ifdef FT_DEBUG_LEVEL_TRACE
+    int             count;
+#endif
+
+
+    if ( !ft_face || !style_class || !gstyles )
+      return FT_THROW( Invalid_Argument );
+
+    face = hb_ft_face_create( ft_face, NULL );
+
+    lookups = hb_set_create();
+    glyphs  = hb_set_create();
+
+    coverage_tags = coverages[style_class->coverage];
+    script        = scripts[style_class->script];
+
+    /* Convert a HarfBuzz script tag into the corresponding OpenType */
+    /* tag or tags -- some Indic scripts like Devanagari have an old */
+    /* and a new set of features.                                    */
+    hb_ot_tags_from_script( script,
+                            &script_tags[0],
+                            &script_tags[1] );
+
+    /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */
+    /* as the second tag.  We change that to HB_TAG_NONE since the       */
+    /* default script gets handled later on.                             */
+    if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT )
+      script_tags[1] = HB_TAG_NONE;
+
+    hb_ot_layout_collect_lookups( face,
+                                  HB_OT_TAG_GSUB,
+                                  script_tags,
+                                  NULL,
+                                  coverage_tags,
+                                  lookups );
+
+    FT_TRACE4(( "lookups (style `%s'):\n"
+                " ",
+                af_style_names[style_class->style] ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    count = 0;
+#endif
+
+    for ( idx = -1; hb_set_next( lookups, &idx ); )
+    {
+#ifdef FT_DEBUG_LEVEL_TRACE
+      FT_TRACE4(( " %d", idx ));
+      count++;
+#endif
+
+      hb_ot_layout_lookup_collect_glyphs( face,
+                                          HB_OT_TAG_GSUB,
+                                          idx,
+                                          NULL,
+                                          NULL,
+                                          NULL,
+                                          glyphs );
+    }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( !count )
+      FT_TRACE4(( " (none)" ));
+    FT_TRACE4(( "\n\n" ));
+
+    FT_TRACE4(( "  glyphs (`*' means already assigned)" ));
+
+    count = 0;
+#endif
+
+    for ( idx = -1; hb_set_next( glyphs, &idx ); )
+    {
+#ifdef FT_DEBUG_LEVEL_TRACE
+      if ( !( count % 10 ) )
+        FT_TRACE4(( "\n"
+                    "   " ));
+
+      FT_TRACE4(( " %d", idx ));
+      count++;
+#endif
+
+      if ( gstyles[idx] == AF_STYLE_UNASSIGNED )
+        gstyles[idx] = (FT_Byte)style_class->style;
+#ifdef FT_DEBUG_LEVEL_TRACE
+      else
+        FT_TRACE4(( "*" ));
+#endif
+    }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( !count )
+      FT_TRACE4(( "\n"
+                  "    (none)" ));
+    FT_TRACE4(( "\n\n" ));
+#endif
+
+    hb_set_destroy( lookups );
+    hb_set_destroy( glyphs  );
+
+    hb_face_destroy( face );
+
+    return FT_Err_Ok;
+  }
+
+
+#if 0
+  /* to be always excluded */
+  COVERAGE(nalt, 'n', 'a', 'l', 't'); /* Alternate Annotation Forms (?) */
+  COVERAGE(ornm, 'o', 'r', 'n', 'm'); /* Ornaments (?) */
+  /* COVERAGE(ruby, 'r', 'u', 'b', 'y') */ /* (only for Japanese) */
+#endif
+
+#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+/* END */
--- /dev/null
+++ b/src/autofit/hbshim.h
@@ -1,0 +1,47 @@
+/***************************************************************************/
+/*                                                                         */
+/*  hbshim.h                                                               */
+/*                                                                         */
+/*    HarfBuzz interface for accessing OpenType features (specification).  */
+/*                                                                         */
+/*  Copyright 2013 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __HBSHIM_H__
+#define __HBSHIM_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+
+FT_BEGIN_HEADER
+
+  FT_Error
+  af_get_coverage( FT_Face        face,
+                   AF_StyleClass  style_class,
+                   FT_Byte*       gstyles );
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+#endif /* __HBSHIM_H__ */
+
+
+/* END */
--- a/src/autofit/rules.mk
+++ b/src/autofit/rules.mk
@@ -37,11 +37,13 @@
                  $(AUTOF_DIR)/afmodule.c \
                  $(AUTOF_DIR)/afpic.c    \
                  $(AUTOF_DIR)/afranges.c \
-                 $(AUTOF_DIR)/afwarp.c
+                 $(AUTOF_DIR)/afwarp.c   \
+                 $(AUTOF_DIR)/hbshim.c
 
 # AUTOF driver headers
 #
 AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h)  \
+               $(AUTOF_DIR)/afcover.h  \
                $(AUTOF_DIR)/aferrors.h \
                $(AUTOF_DIR)/afscript.h \
                $(AUTOF_DIR)/afstyles.h \