diff --git a/ChangeLog b/ChangeLog index fa65c7c6e..714132ad3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2008-12-10 Werner Lemberg + + 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 Really fix Savannah bug #25010: An SFNT font with neither outlines diff --git a/docs/CHANGES b/docs/CHANGES index 3adbd8ff0..4e45e5c3b 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -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. + ====================================================================== diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index f91cc5473..23ff88b5d 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -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 ) + + /*************************************************************************/ /* */ /* */ @@ -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 /* */ /* */ /* 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. */ /* */ /* */ diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index cb5ed42f3..fb750fb6c 100644 --- 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; } } diff --git a/src/base/ftpatent.c b/src/base/ftpatent.c index d63f191c3..9f129d8f0 100644 --- 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 ) && \ diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index 9e9133b0b..b2430ba54 100644 --- 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 */ diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index d70da2323..06fd76a5c 100644 --- 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; + } + + /*************************************************************************/ /* */ /* */ @@ -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. */