ref: b972a2a294a6d1f53ad403ae2bf0a098a38f0c2b
parent: 1474f439b54ef1553d0aac57ebde6261f1b2ed81
author: Werner Lemberg <[email protected]>
date: Thu Dec 11 03:55:48 EST 2008
Generalize the concept of `tricky' fonts by introducing FT_FACE_FLAG_TRICKY to indicate that the font format's hinting engine is necessary for correct rendering. At the same time, slightly modify the behaviour of tricky fonts: FT_LOAD_NO_HINTING is now ignored. To really force raw loading of tricky fonts (without hinting), both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT must be used. Finally, tricky TrueType fonts always use the bytecode interpreter even if the patented code is used. * include/freetype/freetype.h (FT_FACE_FLAG_TRICKY, FT_IS_TRICKY): New macros. * src/truetype/ttdriver.c (Load_Glyph): Handle new load flags semantics as described above. * src/truetype/ttobjs.c (tt_check_trickyness): New function, using code of ... (tt_face_init): This function, now simplified and updated to new semantics. * src/base/ftobjs.c (FT_Load_Glyph): Don't use autohinter for tricky fonts. * docs/CHANGES: Document it.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2008-12-10 Werner Lemberg <[email protected]>
+
+ Generalize the concept of `tricky' fonts by introducing
+ FT_FACE_FLAG_TRICKY to indicate that the font format's hinting
+ engine is necessary for correct rendering.
+
+ At the same time, slightly modify the behaviour of tricky fonts:
+ FT_LOAD_NO_HINTING is now ignored. To really force raw loading
+ of tricky fonts (without hinting), both FT_LOAD_NO_HINTING and
+ FT_LOAD_NO_AUTOHINT must be used.
+
+ Finally, tricky TrueType fonts always use the bytecode interpreter
+ even if the patented code is used.
+
+ * include/freetype/freetype.h (FT_FACE_FLAG_TRICKY, FT_IS_TRICKY):
+ New macros.
+
+ * src/truetype/ttdriver.c (Load_Glyph): Handle new load flags
+ semantics as described above.
+
+ * src/truetype/ttobjs.c (tt_check_trickyness): New function, using
+ code of ...
+ (tt_face_init): This function, now simplified and updated to new
+ semantics.
+
+ * src/base/ftobjs.c (FT_Load_Glyph): Don't use autohinter for tricky
+ fonts.
+
+ * docs/CHANGES: Document it.
+
2008-12-09 Werner Lemberg <[email protected]>
Really fix Savannah bug #25010: An SFNT font with neither outlines
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -10,9 +10,9 @@
was very noticeable for outlines processed with FT_Glyph_Stroke,
using thick strokes.
- - `FT_Get_TrueType_Engine_Type' returned a wrong value if both
- TT_CONFIG_OPTION_BYTECODE_INTERPRETER and
- TT_CONFIG_OPTION_UNPATENTED_HINTING are defined.
+ - `FT_Get_TrueType_Engine_Type' returned a wrong value if both
+ configuration macros TT_CONFIG_OPTION_BYTECODE_INTERPRETER and
+ TT_CONFIG_OPTION_UNPATENTED_HINTING were defined.
II. IMPORTANT CHANGES
@@ -34,6 +34,22 @@
- FT_MulFix is now an inlined function; by default, assembler code
is provided for x86 and ARM. See FT_CONFIG_OPTION_INLINE_MULFIX
and FT_CONFIG_OPTION_NO_ASSEMBLER (in ftoption.h) for more.
+
+ - The handling of `tricky' fonts (this is, fonts which don't work
+ with the autohinter, needing the font format's hinting engine)
+ has been generalized and changed slightly:
+
+ . A new face flag FT_FACE_FLAG_TRICKY indicates that the font
+ format's hinting engine is necessary for correct rendering.
+ The macro FT_IS_TRICKY can be used to check this flag.
+
+ . FT_LOAD_NO_HINTING is now ignored for tricky fonts. To really
+ force raw loading of such fonts (without hinting), both
+ FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT must be used --
+ this is something which you probably never want to do.
+
+ . Tricky TrueType fonts always use the bytecode interpreter,
+ either the patented or unpatented version.
======================================================================
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -1042,6 +1042,22 @@
/* way (using contiguous indices); the `CID-ness' isn't visible to */
/* the application. */
/* */
+ /* FT_FACE_FLAG_TRICKY :: */
+ /* Set if the font is `tricky', this is, it always needs the */
+ /* font format's native hinting engine to get a reasonable result. */
+ /* A typical example is the Chinese font `mingli.ttf' which uses */
+ /* TrueType bytecode instructions to move and scale all of its */
+ /* subglyphs. */
+ /* */
+ /* It is not possible to autohint such fonts using */
+ /* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */
+ /* @FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING */
+ /* and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */
+ /* probably never want this except for demonstration purposes. */
+ /* */
+ /* Currently, there are six TrueType fonts in the list of tricky */
+ /* fonts; they are hard-coded in file `ttobjs.c'. */
+ /* */
#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 )
@@ -1055,6 +1071,7 @@
#define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 )
#define FT_FACE_FLAG_HINTER ( 1L << 11 )
#define FT_FACE_FLAG_CID_KEYED ( 1L << 12 )
+#define FT_FACE_FLAG_TRICKY ( 1L << 13 )
/*************************************************************************
@@ -1225,6 +1242,20 @@
( face->face_flags & FT_FACE_FLAG_CID_KEYED )
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_IS_TRICKY( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face represents a `tricky' font.
+ * See the discussion of @FT_FACE_FLAG_TRICKY for more details.
+ *
+ */
+#define FT_IS_TRICKY( face ) \
+ ( face->face_flags & FT_FACE_FLAG_TRICKY )
+
+
/*************************************************************************/
/* */
/* <Const> */
@@ -2411,6 +2442,9 @@
* @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be
* used at all.
*
+ * See the description of @FT_FACE_FLAG_TRICKY for a special exception
+ * (affecting only a handful of Asian fonts).
+ *
* Besides deciding which hinter to use, you can also decide which
* hinting algorithm to use. See @FT_LOAD_TARGET_XXX for details.
*/
@@ -3717,7 +3751,7 @@
/* */
/* <Return> */
/* The old setting value. This will always be false if this is not */
- /* a SFNT font, or if the unpatented hinter is not compiled in this */
+ /* an SFNT font, or if the unpatented hinter is not compiled in this */
/* instance of the library. */
/* */
/* <Since> */
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -41,6 +41,7 @@
#define GRID_FIT_METRICS
+
FT_BASE_DEF( FT_Pointer )
ft_service_list_lookup( FT_ServiceDesc service_descriptors,
const char* service_id )
@@ -552,7 +553,7 @@
FT_Driver driver;
FT_GlyphSlot slot;
FT_Library library;
- FT_Bool autohint = 0;
+ FT_Bool autohint = FALSE;
FT_Module hinter;
@@ -596,22 +597,22 @@
*
* - Otherwise, auto-hint for LIGHT hinting mode.
*
- * - Exception: The font requires the unpatented
- * bytecode interpreter to load properly.
+ * - Exception: The font is `tricky' and requires
+ * the native hinter to load properly.
*/
- autohint = 0;
- if ( hinter &&
- ( load_flags & FT_LOAD_NO_HINTING ) == 0 &&
- ( load_flags & FT_LOAD_NO_AUTOHINT ) == 0 &&
- FT_DRIVER_IS_SCALABLE( driver ) &&
- FT_DRIVER_USES_OUTLINES( driver ) &&
- face->internal->transform_matrix.yy > 0 &&
- face->internal->transform_matrix.yx == 0 )
+ if ( hinter &&
+ !( load_flags & FT_LOAD_NO_HINTING ) &&
+ !( load_flags & FT_LOAD_NO_AUTOHINT ) &&
+ FT_DRIVER_IS_SCALABLE( driver ) &&
+ FT_DRIVER_USES_OUTLINES( driver ) &&
+ !FT_IS_TRICKY( face ) &&
+ face->internal->transform_matrix.yy > 0 &&
+ face->internal->transform_matrix.yx == 0 )
{
- if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) != 0 ||
- !FT_DRIVER_HAS_HINTER( driver ) )
- autohint = 1;
+ if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||
+ !FT_DRIVER_HAS_HINTER( driver ) )
+ autohint = TRUE;
else
{
FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
@@ -619,7 +620,7 @@
if ( mode == FT_RENDER_MODE_LIGHT ||
face->internal->ignore_unpatented_hinter )
- autohint = 1;
+ autohint = TRUE;
}
}
--- a/src/base/ftpatent.c
+++ b/src/base/ftpatent.c
@@ -5,7 +5,7 @@
/* FreeType API for checking patented TrueType bytecode instructions */
/* (body). */
/* */
-/* Copyright 2007 by David Turner. */
+/* Copyright 2007, 2008 by David Turner. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
@@ -260,7 +260,7 @@
FT_Face_SetUnpatentedHinting( FT_Face face,
FT_Bool value )
{
- FT_Bool result = 0;
+ FT_Bool result = FALSE;
#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -272,7 +272,7 @@
/* glyph_index :: The index of the glyph in the font file. */
/* */
/* load_flags :: A flag indicating what to load for this glyph. The */
- /* FTLOAD_??? constants can be used to control the */
+ /* FT_LOAD_XXX constants can be used to control the */
/* glyph loading process (e.g., whether the outline */
/* should be scaled, whether to load bitmaps or not, */
/* whether to hint the outline, etc). */
@@ -301,11 +301,24 @@
if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
return TT_Err_Invalid_Argument;
+ if ( load_flags & FT_LOAD_NO_HINTING )
+ {
+ /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT */
+ /* are necessary to disable hinting for tricky fonts */
+
+ if ( FT_IS_TRICKY( face ) )
+ load_flags &= ~FT_LOAD_NO_HINTING;
+
+ if ( load_flags & FT_LOAD_NO_AUTOHINT )
+ load_flags |= FT_LOAD_NO_HINTING;
+ }
+
if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) )
{
- load_flags |= FT_LOAD_NO_HINTING |
- FT_LOAD_NO_BITMAP |
- FT_LOAD_NO_SCALE;
+ load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE;
+
+ if ( !FT_IS_TRICKY( face ) )
+ load_flags |= FT_LOAD_NO_HINTING;
}
/* now load the glyph outline if necessary */
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -144,6 +144,38 @@
#endif /* TT_USE_BYTECODE_INTERPRETER */
+ /* Compare the face with a list of well-known `tricky' fonts. */
+ /* This list shall be expanded as we find more of them. */
+
+ static FT_Bool
+ tt_check_trickyness( FT_String* name )
+ {
+ static const char* const trick_names[] =
+ {
+ "DFKaiSho-SB", /* dfkaisb.ttf */
+ "DFKai-SB", /* kaiu.ttf */
+ "HuaTianSongTi?", /* htst3.ttf */
+ "MingLiU", /* mingliu.ttf & mingliu.ttc */
+ "PMingLiU", /* mingliu.ttc */
+ "MingLi43", /* mingli.ttf */
+ NULL
+ };
+ int nn;
+
+
+ if ( !name )
+ return FALSE;
+
+ /* Note that we only check the face name at the moment; it might */
+ /* be worth to do more checks for a few special cases. */
+ for ( nn = 0; trick_names[nn] != NULL; nn++ )
+ if ( ft_strstr( name, trick_names[nn] ) )
+ return TRUE;
+
+ return FALSE;
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -180,7 +212,7 @@
TT_Face face = (TT_Face)ttface;
- library = face->root.driver->root.library;
+ library = ttface->driver->root.library;
sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
if ( !sfnt )
goto Bad_Format;
@@ -206,7 +238,7 @@
}
#ifdef TT_USE_BYTECODE_INTERPRETER
- face->root.face_flags |= FT_FACE_FLAG_HINTER;
+ ttface->face_flags |= FT_FACE_FLAG_HINTER;
#endif
/* If we are performing a simple font format check, exit immediately. */
@@ -218,16 +250,19 @@
if ( error )
goto Exit;
+ if ( tt_check_trickyness( ttface->family_name ) )
+ ttface->face_flags |= FT_FACE_FLAG_TRICKY;
+
error = tt_face_load_hdmx( face, stream );
if ( error )
goto Exit;
- if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE )
+ if ( FT_IS_SCALABLE( ttface ) )
{
#ifdef FT_CONFIG_OPTION_INCREMENTAL
- if ( !face->root.internal->incremental_interface )
+ if ( !ttface->internal->incremental_interface )
error = tt_face_load_loca( face, stream );
if ( !error )
error = tt_face_load_cvt( face, stream );
@@ -267,38 +302,8 @@
if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING )
unpatented_hinting = TRUE;
- /* Compare the face with a list of well-known `tricky' fonts. */
- /* This list shall be expanded as we find more of them. */
if ( !unpatented_hinting )
- {
- static const char* const trick_names[] =
- {
- "DFKaiSho-SB", /* dfkaisb.ttf */
- "DFKai-SB", /* kaiu.ttf */
- "HuaTianSongTi?", /* htst3.ttf */
- "MingLiU", /* mingliu.ttf & mingliu.ttc */
- "PMingLiU", /* mingliu.ttc */
- "MingLi43", /* mingli.ttf */
- NULL
- };
- int nn;
-
-
- /* Note that we only check the face name at the moment; it might */
- /* be worth to do more checks for a few special cases. */
- for ( nn = 0; trick_names[nn] != NULL; nn++ )
- {
- if ( ttface->family_name &&
- ft_strstr( ttface->family_name, trick_names[nn] ) )
- {
- unpatented_hinting = 1;
- break;
- }
- }
- }
-
- ttface->internal->ignore_unpatented_hinter =
- FT_BOOL( !unpatented_hinting );
+ ttface->internal->ignore_unpatented_hinter = TRUE;
}
#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING &&
@@ -339,8 +344,8 @@
if ( !face )
return;
- memory = face->root.memory;
- stream = face->root.stream;
+ memory = ttface->memory;
+ stream = ttface->stream;
sfnt = (SFNT_Service)face->sfnt;
/* for `extended TrueType formats' (i.e. compressed versions) */
@@ -680,7 +685,7 @@
if ( !size->cvt_ready )
{
FT_UInt i;
- TT_Face face = (TT_Face) size->root.face;
+ TT_Face face = (TT_Face)size->root.face;
/* Scale the cvt values to the new ppem. */