shithub: freetype+ttf2subf

Download patch

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.

git/fs: mount .git/fs: mount/attach disallowed
--- 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.          */