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.
This commit is contained in:
Werner Lemberg 2008-12-11 08:55:48 +00:00
parent 1474f439b5
commit b972a2a294
7 changed files with 162 additions and 63 deletions

View File

@ -1,3 +1,33 @@
2008-12-10 Werner Lemberg <wl@gnu.org>
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 <wl@gnu.org>
Really fix Savannah bug #25010: An SFNT font with neither outlines

View File

@ -10,9 +10,9 @@ CHANGES BETWEEN 2.3.8 and 2.3.7
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
@ -35,6 +35,22 @@ CHANGES BETWEEN 2.3.8 and 2.3.7
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.
======================================================================

View File

@ -1042,6 +1042,22 @@ FT_BEGIN_HEADER
/* 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 @@ FT_BEGIN_HEADER
#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 @@ FT_BEGIN_HEADER
( 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_BEGIN_HEADER
* @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 @@ FT_BEGIN_HEADER
/* */
/* <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> */

View File

@ -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;
}
}

View File

@ -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 ) && \

View File

@ -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 */

View File

@ -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. */