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.
--- 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 \