am 0c30ba13: Merge "improve compatibility"

* commit '0c30ba1342318e73197db7dd52dcca4b6d4bf06d':
  improve compatibility
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index 22056e1..c6d1974 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -503,13 +503,10 @@
   /*                                                                       */
   /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version  */
   /* of the TrueType bytecode interpreter is used that doesn't implement   */
-  /* any of the patented opcodes and algorithms.  The patents related to   */
-  /* TrueType hinting have expired worldwide since May 2010; this option   */
-  /* is now deprecated.                                                    */
-  /*                                                                       */
-  /* Note that the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored*  */
-  /* if you define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words,  */
-  /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or                */
+  /* any of the patented opcodes and algorithms.  Note that the            */
+  /* TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* if you define  */
+  /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words, either define  */
+  /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER or                              */
   /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time.    */
   /*                                                                       */
   /* This macro is only useful for a small number of font files (mostly    */
diff --git a/src/base/ftbase.h b/src/base/ftbase.h
index 1dc49f3..6375613 100644
--- a/src/base/ftbase.h
+++ b/src/base/ftbase.h
@@ -49,6 +49,17 @@
                          FT_Face     *aface );
 
 
+#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
+  /* Mac OS X/Darwin kernel often changes recommended method to access */
+  /* the resource fork and older methods makes the kernel issue the    */
+  /* warning of deprecated method.  To calm it down, the methods based */
+  /* on Darwin VFS should be grouped and skip the rest methods after   */
+  /* the case the resource is opened but found to lack a font in it.   */
+  FT_LOCAL( FT_Bool )
+  raccess_rule_by_darwin_vfs( FT_UInt  rule_index );
+#endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
+
+
 FT_END_HEADER
 
 #endif /* __FTBASE_H__ */
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 160269d..12fed04 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -47,7 +47,7 @@
   typedef struct FT_MemTableRec_*   FT_MemTable;
 
 
-#define FT_MEM_VAL( addr )  ((FT_ULong)(FT_Pointer)( addr ))
+#define FT_MEM_VAL( addr )  ((FT_PtrDist)(FT_Pointer)( addr ))
 
   /*
    *  This structure holds statistics for a single allocation/release
@@ -275,7 +275,7 @@
       for ( i = 0; i < table->size; i++ )
       {
         FT_MemNode  node, next, *pnode;
-        FT_ULong    hash;
+        FT_PtrDist  hash;
 
 
         node = table->buckets[i];
@@ -430,7 +430,7 @@
   ft_mem_table_get_nodep( FT_MemTable  table,
                           FT_Byte*     address )
   {
-    FT_ULong     hash;
+    FT_PtrDist   hash;
     FT_MemNode  *pnode, node;
 
 
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 7f38df0..cb44b8c 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -1062,6 +1062,7 @@
       if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE    &&
            cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
            FT_Get_CMap_Format( cur[0] ) == 14                  )
+      {
 #ifdef FT_MAX_CHARMAP_CACHEABLE
         if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
         {
@@ -1071,6 +1072,7 @@
         }
 #endif
         return cur[0];
+      }
     }
 
     return NULL;
@@ -1849,6 +1851,7 @@
     char *     file_names[FT_RACCESS_N_RULES];
     FT_Long    offsets[FT_RACCESS_N_RULES];
     FT_Error   errors[FT_RACCESS_N_RULES];
+    FT_Bool    is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */
 
     FT_Open_Args  args2;
     FT_Stream     stream2 = 0;
@@ -1859,6 +1862,15 @@
 
     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
     {
+      is_darwin_vfs = raccess_rule_by_darwin_vfs( i );
+      if ( is_darwin_vfs && vfs_rfork_has_no_font )
+      {
+        FT_TRACE3(( "Skip rule %d: darwin vfs resource fork"
+                    " is already checked and"
+                    " no font is found\n", i ));
+        continue;
+      }  
+
       if ( errors[i] )
       {
         FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
@@ -1872,6 +1884,9 @@
                   i, args2.pathname, offsets[i] ));
 
       error = FT_Stream_New( library, &args2, &stream2 );
+      if ( is_darwin_vfs && error == FT_Err_Cannot_Open_Stream )
+        vfs_rfork_has_no_font = TRUE;
+
       if ( error )
       {
         FT_TRACE3(( "failed\n" ));
@@ -1886,6 +1901,8 @@
 
       if ( !error )
           break;
+      else if ( is_darwin_vfs )
+          vfs_rfork_has_no_font = TRUE;
     }
 
     for (i = 0; i < FT_RACCESS_N_RULES; i++)
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index f64d28b..6df2def 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -349,6 +349,42 @@
                           const char  *insertion );
 
 
+  typedef enum  FT_RFork_Rule_ {
+    FT_RFork_Rule_invalid = -2,
+    FT_RFork_Rule_uknown, /* -1 */
+    FT_RFork_Rule_apple_double,
+    FT_RFork_Rule_apple_single,
+    FT_RFork_Rule_darwin_ufs_export,
+    FT_RFork_Rule_darwin_newvfs,
+    FT_RFork_Rule_darwin_hfsplus,
+    FT_RFork_Rule_vfat,
+    FT_RFork_Rule_linux_cap,
+    FT_RFork_Rule_linux_double,
+    FT_RFork_Rule_linux_netatalk
+  } FT_RFork_Rule;
+
+  /* For fast translation between rule index and rule type,
+   * the macros FT_RFORK_xxx should be kept consistent with
+   * the raccess_guess_funcs table
+   */
+  typedef struct raccess_guess_rec_ {
+    raccess_guess_func  func;
+    FT_RFork_Rule       type;
+  } raccess_guess_rec;
+
+  static raccess_guess_rec  raccess_guess_table[FT_RACCESS_N_RULES] =
+  {
+    { raccess_guess_apple_double,	FT_RFork_Rule_apple_double, },
+    { raccess_guess_apple_single,	FT_RFork_Rule_apple_single, },
+    { raccess_guess_darwin_ufs_export,	FT_RFork_Rule_darwin_ufs_export, },
+    { raccess_guess_darwin_newvfs,	FT_RFork_Rule_darwin_newvfs, },
+    { raccess_guess_darwin_hfsplus,	FT_RFork_Rule_darwin_hfsplus, },
+    { raccess_guess_vfat,		FT_RFork_Rule_vfat, },
+    { raccess_guess_linux_cap,		FT_RFork_Rule_linux_cap, },
+    { raccess_guess_linux_double,	FT_RFork_Rule_linux_double, },
+    { raccess_guess_linux_netatalk,	FT_RFork_Rule_linux_netatalk, },
+  };
+
   FT_BASE_DEF( void )
   FT_Raccess_Guess( FT_Library  library,
                     FT_Stream   stream,
@@ -360,19 +396,6 @@
     FT_Long  i;
 
 
-    raccess_guess_func  funcs[FT_RACCESS_N_RULES] =
-    {
-      raccess_guess_apple_double,
-      raccess_guess_apple_single,
-      raccess_guess_darwin_ufs_export,
-      raccess_guess_darwin_newvfs,
-      raccess_guess_darwin_hfsplus,
-      raccess_guess_vfat,
-      raccess_guess_linux_cap,
-      raccess_guess_linux_double,
-      raccess_guess_linux_netatalk,
-    };
-
     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
     {
       new_names[i] = NULL;
@@ -384,14 +407,41 @@
       if ( errors[i] )
         continue ;
 
-      errors[i] = (funcs[i])( library, stream, base_name,
-                              &(new_names[i]), &(offsets[i]) );
+      errors[i] = (raccess_guess_table[i].func)( library,
+                                                 stream, base_name,
+                                                 &(new_names[i]),
+                                                 &(offsets[i]) );
     }
 
     return;
   }
 
 
+  static FT_RFork_Rule
+  raccess_get_rule_type_from_rule_index( FT_UInt  rule_index )
+  {
+    if ( rule_index >= FT_RACCESS_N_RULES )
+      return FT_RFork_Rule_invalid;
+
+    return raccess_guess_table[rule_index].type;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  raccess_rule_by_darwin_vfs( FT_UInt  rule_index )
+  {
+    switch( raccess_get_rule_type_from_rule_index( rule_index ) )
+    {
+      case FT_RFork_Rule_darwin_newvfs:
+      case FT_RFork_Rule_darwin_hfsplus:
+        return TRUE;
+
+      default:
+        return FALSE;
+    }
+  }
+
+
   static FT_Error
   raccess_guess_apple_double( FT_Library  library,
                               FT_Stream   stream,
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index ba3c633..d4ec0da 100644
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -90,7 +90,7 @@
 
 
     if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
-         slot->format != FT_GLYPH_FORMAT_BITMAP )
+         slot->format != FT_GLYPH_FORMAT_BITMAP  )
       return;
 
     /* some reasonable strength */
@@ -108,7 +108,7 @@
       xstr = xstr * 2;
       ystr = xstr;
     }
-    else if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
+    else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
     {
       /* round to full pixels */
       xstr &= ~63;
diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c
index ba86005..66c5d76 100644
--- a/src/base/ftsystem.c
+++ b/src/base/ftsystem.c
@@ -229,6 +229,13 @@
     if ( !stream )
       return FT_Err_Invalid_Stream_Handle;
 
+    stream->descriptor.pointer = NULL;
+    stream->pathname.pointer   = (char*)filepathname;
+    stream->base               = 0;
+    stream->pos                = 0;
+    stream->read               = NULL;
+    stream->close              = NULL;
+
     file = ft_fopen( filepathname, "rb" );
     if ( !file )
     {
@@ -240,12 +247,16 @@
 
     ft_fseek( file, 0, SEEK_END );
     stream->size = ft_ftell( file );
+    if ( !stream->size )
+    {
+      FT_ERROR(( "FT_Stream_Open:" ));
+      FT_ERROR(( " opened `%s' but zero-sized\n", filepathname ));
+      ft_fclose( file );
+      return FT_Err_Cannot_Open_Stream;
+    }
     ft_fseek( file, 0, SEEK_SET );
 
     stream->descriptor.pointer = file;
-    stream->pathname.pointer   = (char*)filepathname;
-    stream->pos                = 0;
-
     stream->read  = ft_ansi_stream_io;
     stream->close = ft_ansi_stream_close;
 
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 42e7730..000cbe3 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -519,6 +519,18 @@
         }
       }
 
+      /* XXX: should check off2 does not exceed the end of this entry; */
+      /*      at present, only truncate off2 at the end of this stream */
+      if ( off2 > stream->size + 1                    ||
+           idx->data_offset > stream->size - off2 + 1 )
+      {
+        FT_ERROR(( "cff_index_access_element:"
+                   " offset to next entry (%d)"
+                   " exceeds the end of stream (%d)\n",
+                   off2, stream->size - idx->data_offset + 1 ));
+        off2 = stream->size - idx->data_offset + 1;
+      }
+
       /* access element */
       if ( off1 && off2 > off1 )
       {
@@ -779,11 +791,12 @@
       goto Exit;
 
     for ( i = 0; i < num_glyphs; i++ )
+    {
       if ( charset->sids[i] > max_cid )
         max_cid = charset->sids[i];
-    max_cid++;
+    }
 
-    if ( FT_NEW_ARRAY( charset->cids, max_cid ) )
+    if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
       goto Exit;
 
     /* When multiple GIDs map to the same CID, we choose the lowest */
@@ -807,7 +820,7 @@
     FT_UInt  result = 0;
 
 
-    if ( cid < charset->max_cid )
+    if ( cid <= charset->max_cid )
       result = charset->cids[cid];
 
     return result;
@@ -881,20 +894,7 @@
             goto Exit;
 
           for ( j = 1; j < num_glyphs; j++ )
-          {
-            FT_UShort sid = FT_GET_USHORT();
-
-
-            /* this constant is given in the CFF specification */
-            if ( sid < 65000L )
-              charset->sids[j] = sid;
-            else
-            {
-              FT_TRACE0(( "cff_charset_load:"
-                          " invalid SID value %d set to zero\n", sid ));
-              charset->sids[j] = 0;
-            }
-          }
+            charset->sids[j] = FT_GET_USHORT();
 
           FT_FRAME_EXIT();
         }
@@ -927,20 +927,12 @@
                 goto Exit;
             }
 
-            /* check whether the range contains at least one valid glyph; */
-            /* the constant is given in the CFF specification             */
-            if ( glyph_sid >= 65000L )
-            {
-              FT_ERROR(( "cff_charset_load: invalid SID range\n" ));
-              error = CFF_Err_Invalid_File_Format;
-              goto Exit;
-            }
-
             /* try to rescue some of the SIDs if `nleft' is too large */
-            if ( nleft > 65000L - 1L || glyph_sid >= 65000L - nleft )
+            if ( glyph_sid > 0xFFFFL - nleft )
             {
-              FT_ERROR(( "cff_charset_load: invalid SID range trimmed\n" ));
-              nleft = ( FT_UInt )( 65000L - 1L - glyph_sid );
+              FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
+                         " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
+              nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
             }
 
             /* Fill in the range of sids -- `nleft + 1' glyphs. */
@@ -1277,9 +1269,7 @@
           if ( gid != 0 )
           {
             encoding->codes[j] = (FT_UShort)gid;
-
-            if ( encoding->count < j + 1 )
-              encoding->count = j + 1;
+            encoding->count    = j + 1;
           }
           else
           {
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index f8b07c3..1cd35c9 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -677,7 +677,7 @@
 
         /* compute number of glyphs */
         if ( dict->cid_registry != 0xFFFFU )
-          cffface->num_glyphs = cff->charset.max_cid;
+          cffface->num_glyphs = cff->charset.max_cid + 1;
         else
           cffface->num_glyphs = cff->charstrings_index.count;
 
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index babf3ba..ea31c51 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -373,15 +373,6 @@
 #endif
 
 
-    /* we don't want to touch the source code -- use macro trick */
-#define start_point    t1_builder_start_point
-#define check_points   t1_builder_check_points
-#define add_point      t1_builder_add_point
-#define add_point1     t1_builder_add_point1
-#define add_contour    t1_builder_add_contour
-#define close_contour  t1_builder_close_contour
-
-
     /* compute random seed from stack address of parameter */
     seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed              ^
                          (FT_PtrDist)(char*)&decoder           ^
@@ -739,8 +730,10 @@
 
           decoder->flex_state        = 1;
           decoder->num_flex_vectors  = 0;
-          if ( start_point( builder, x, y ) ||
-               check_points( builder, 6 )   )
+          if ( ( error = t1_builder_start_point( builder, x, y ) )
+                 != PSaux_Err_Ok                                   ||
+               ( error = t1_builder_check_points( builder, 6 ) )
+                 != PSaux_Err_Ok                                   )
             goto Fail;
           break;
 
@@ -757,10 +750,10 @@
             /* point without adding any point to the outline    */
             idx = decoder->num_flex_vectors++;
             if ( idx > 0 && idx < 7 )
-              add_point( builder,
-                         x,
-                         y,
-                         (FT_Byte)( idx == 3 || idx == 6 ) );
+              t1_builder_add_point( builder,
+                                    x,
+                                    y,
+                                    (FT_Byte)( idx == 3 || idx == 6 ) );
           }
           break;
 
@@ -1077,7 +1070,7 @@
         case op_endchar:
           FT_TRACE4(( " endchar\n" ));
 
-          close_contour( builder );
+          t1_builder_close_contour( builder );
 
           /* close hints recording session */
           if ( hinter )
@@ -1176,7 +1169,7 @@
           /* if there is no path, `closepath' is a no-op */
           if ( builder->parse_state == T1_Parse_Have_Path   ||
                builder->parse_state == T1_Parse_Have_Moveto )
-            close_contour( builder );
+            t1_builder_close_contour( builder );
 
           builder->parse_state = T1_Parse_Have_Width;
           break;
@@ -1184,7 +1177,8 @@
         case op_hlineto:
           FT_TRACE4(( " hlineto" ));
 
-          if ( start_point( builder, x, y ) )
+          if ( ( error = t1_builder_start_point( builder, x, y ) )
+                 != PSaux_Err_Ok )
             goto Fail;
 
           x += top[0];
@@ -1205,30 +1199,34 @@
         case op_hvcurveto:
           FT_TRACE4(( " hvcurveto" ));
 
-          if ( start_point( builder, x, y ) ||
-               check_points( builder, 3 )   )
+          if ( ( error = t1_builder_start_point( builder, x, y ) )
+                 != PSaux_Err_Ok                                   ||
+               ( error = t1_builder_check_points( builder, 3 ) )
+                 != PSaux_Err_Ok                                   )
             goto Fail;
 
           x += top[0];
-          add_point( builder, x, y, 0 );
+          t1_builder_add_point( builder, x, y, 0 );
           x += top[1];
           y += top[2];
-          add_point( builder, x, y, 0 );
+          t1_builder_add_point( builder, x, y, 0 );
           y += top[3];
-          add_point( builder, x, y, 1 );
+          t1_builder_add_point( builder, x, y, 1 );
           break;
 
         case op_rlineto:
           FT_TRACE4(( " rlineto" ));
 
-          if ( start_point( builder, x, y ) )
+          if ( ( error = t1_builder_start_point( builder, x, y ) )
+                 != PSaux_Err_Ok )
             goto Fail;
 
           x += top[0];
           y += top[1];
 
         Add_Line:
-          if ( add_point1( builder, x, y ) )
+          if ( ( error = t1_builder_add_point1( builder, x, y ) )
+                 != PSaux_Err_Ok )
             goto Fail;
           break;
 
@@ -1248,43 +1246,48 @@
         case op_rrcurveto:
           FT_TRACE4(( " rrcurveto" ));
 
-          if ( start_point( builder, x, y ) ||
-               check_points( builder, 3 )   )
+          if ( ( error = t1_builder_start_point( builder, x, y ) )
+                 != PSaux_Err_Ok                                   ||
+               ( error = t1_builder_check_points( builder, 3 ) )
+                 != PSaux_Err_Ok                                   )
             goto Fail;
 
           x += top[0];
           y += top[1];
-          add_point( builder, x, y, 0 );
+          t1_builder_add_point( builder, x, y, 0 );
 
           x += top[2];
           y += top[3];
-          add_point( builder, x, y, 0 );
+          t1_builder_add_point( builder, x, y, 0 );
 
           x += top[4];
           y += top[5];
-          add_point( builder, x, y, 1 );
+          t1_builder_add_point( builder, x, y, 1 );
           break;
 
         case op_vhcurveto:
           FT_TRACE4(( " vhcurveto" ));
 
-          if ( start_point( builder, x, y ) ||
-               check_points( builder, 3 )   )
+          if ( ( error = t1_builder_start_point( builder, x, y ) )
+                 != PSaux_Err_Ok                                   ||
+               ( error = t1_builder_check_points( builder, 3 ) )
+                 != PSaux_Err_Ok                                   )
             goto Fail;
 
           y += top[0];
-          add_point( builder, x, y, 0 );
+          t1_builder_add_point( builder, x, y, 0 );
           x += top[1];
           y += top[2];
-          add_point( builder, x, y, 0 );
+          t1_builder_add_point( builder, x, y, 0 );
           x += top[3];
-          add_point( builder, x, y, 1 );
+          t1_builder_add_point( builder, x, y, 1 );
           break;
 
         case op_vlineto:
           FT_TRACE4(( " vlineto" ));
 
-          if ( start_point( builder, x, y ) )
+          if ( ( error = t1_builder_start_point( builder, x, y ) )
+                 != PSaux_Err_Ok )
             goto Fail;
 
           y += top[0];
diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c
index 4b08785..d798978 100644
--- a/src/pshinter/pshalgo.c
+++ b/src/pshinter/pshalgo.c
@@ -1862,12 +1862,10 @@
             point->cur_u = hint->cur_pos + hint->cur_len +
                              FT_MulFix( delta - hint->org_len, scale );
 
-          else if ( hint->org_len > 0 )
+          else /* hint->org_len > 0 */
             point->cur_u = hint->cur_pos +
                              FT_MulDiv( delta, hint->cur_len,
                                         hint->org_len );
-          else
-            point->cur_u = hint->cur_pos;
         }
         psh_point_set_fitted( point );
       }
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index ce6fdfe..9638dfb 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -302,7 +302,6 @@
   typedef short           Short;
   typedef unsigned short  UShort, *PUShort;
   typedef long            Long, *PLong;
-  typedef unsigned long   ULong;
 
   typedef unsigned char   Byte, *PByte;
   typedef char            Bool;
@@ -448,7 +447,6 @@
     Int         precision_bits;     /* precision related variables         */
     Int         precision;
     Int         precision_half;
-    Long        precision_mask;
     Int         precision_shift;
     Int         precision_step;
     Int         precision_jitter;
@@ -671,7 +669,6 @@
     ras.precision       = 1 << ras.precision_bits;
     ras.precision_half  = ras.precision / 2;
     ras.precision_shift = ras.precision_bits - Pixel_Bits;
-    ras.precision_mask  = -ras.precision;
   }
 
 
@@ -725,13 +722,13 @@
       if ( overshoot )
         ras.cProfile->flags |= Overshoot_Bottom;
 
-      FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
+      FT_TRACE6(( "New ascending profile = %p\n", ras.cProfile ));
       break;
 
     case Descending_State:
       if ( overshoot )
         ras.cProfile->flags |= Overshoot_Top;
-      FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
+      FT_TRACE6(( "New descending profile = %p\n", ras.cProfile ));
       break;
 
     default:
@@ -784,8 +781,8 @@
 
     if ( h > 0 )
     {
-      FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
-                  (long)ras.cProfile, ras.cProfile->start, h ));
+      FT_TRACE6(( "Ending profile %p, start = %ld, height = %ld\n",
+                  ras.cProfile, ras.cProfile->start, h ));
 
       ras.cProfile->height = h;
       if ( overshoot )
@@ -1094,7 +1091,7 @@
         return SUCCESS;
       else
       {
-        x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+        x1 += SMulDiv( Dx, ras.precision - f1, Dy );
         e1 += 1;
       }
     }
@@ -1122,13 +1119,13 @@
 
     if ( Dx > 0 )
     {
-      Ix = SMulDiv( ras.precision, Dx,  Dy);
+      Ix = SMulDiv( ras.precision, Dx, Dy);
       Rx = ( ras.precision * Dx ) % Dy;
       Dx = 1;
     }
     else
     {
-      Ix = SMulDiv( ras.precision, -Dx,  Dy) * -1;
+      Ix = SMulDiv( ras.precision, -Dx, Dy) * -1;
       Rx =    ( ras.precision * -Dx ) % Dy;
       Dx = -1;
     }
@@ -3385,6 +3382,7 @@
                 FT_Raster  *araster )
   {
      static TRaster  the_raster;
+     FT_UNUSED( memory );
 
 
      *araster = (FT_Raster)&the_raster;
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 6e35e2d..5a1d003 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -691,9 +691,7 @@
       LOAD_( os2 );
       if ( error )
       {
-        if ( error != SFNT_Err_Table_Missing )
-          goto Exit;
-
+        /* we treat the table as missing if there are any errors */
         face->os2.version = 0xFFFFU;
       }
     }
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index 1c174af..20bac73 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -384,6 +384,10 @@
 
     entry = face->dir_tables;
 
+    FT_TRACE2(( "\n"
+                "  tag    offset    length   checksum\n"
+                "  ----------------------------------\n" ));
+
     for ( nn = 0; nn < sfnt.num_tables; nn++ )
     {
       entry->Tag      = FT_GET_TAG4();
@@ -396,13 +400,14 @@
         continue;
       else
       {
-        FT_TRACE2(( "  %c%c%c%c  -  %08lx  -  %08lx\n",
+        FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx\n",
                     (FT_Char)( entry->Tag >> 24 ),
                     (FT_Char)( entry->Tag >> 16 ),
                     (FT_Char)( entry->Tag >> 8  ),
                     (FT_Char)( entry->Tag       ),
                     entry->Offset,
-                    entry->Length ));
+                    entry->Length,
+                    entry->CheckSum ));
         entry++;
       }
     }
@@ -680,9 +685,9 @@
       /*      broken fonts like `Keystrokes MT' :-(           */
       /*                                                      */
       /*   We allocate 64 function entries by default when    */
-      /*   the maxFunctionDefs field is null.                 */
+      /*   the maxFunctionDefs value is smaller.              */
 
-      if ( maxProfile->maxFunctionDefs == 0 )
+      if ( maxProfile->maxFunctionDefs < 64 )
         maxProfile->maxFunctionDefs = 64;
 
       /* we add 4 phantom points later */
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index aa0bf1e..6f4bb1d 100644
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
 /*    Postcript name table processing for TrueType and OpenType fonts      */
 /*    (body).                                                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2009 by             */
+/*  Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 by       */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -26,6 +26,7 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_STREAM_H
 #include FT_TRUETYPE_TAGS_H
 #include "ttpost.h"
@@ -153,7 +154,8 @@
 
   static FT_Error
   load_format_20( TT_Face    face,
-                  FT_Stream  stream )
+                  FT_Stream  stream,
+                  FT_Long    post_limit )
   {
     FT_Memory   memory = stream->memory;
     FT_Error    error;
@@ -230,13 +232,46 @@
         FT_UInt  len;
 
 
-        if ( FT_READ_BYTE  ( len )                    ||
-             FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
-             FT_STREAM_READ  ( name_strings[n], len ) )
+        if ( FT_STREAM_POS() >= post_limit )
+          break;
+        else
+        {
+          FT_TRACE6(( "load_format_20: %d byte left in post table\n",
+                      post_limit - FT_STREAM_POS() ));
+
+          if ( FT_READ_BYTE( len ) )
+            goto Fail1;
+        }
+
+        if ( (FT_Int)len > post_limit                   ||
+             FT_STREAM_POS() > post_limit - (FT_Int)len )
+        {
+          FT_ERROR(( "load_format_20:"
+                     " exceeding string length (%d),"
+                     " truncating at end of post table (%d byte left)\n",
+                     len, post_limit - FT_STREAM_POS() ));
+          len = FT_MAX( 0, post_limit - FT_STREAM_POS() );
+        }
+
+        if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
+             FT_STREAM_READ( name_strings[n], len   ) )
           goto Fail1;
 
         name_strings[n][len] = '\0';
       }
+
+      if ( n < num_names )
+      {
+        FT_ERROR(( "load_format_20:"
+                   " all entries in post table are already parsed,"
+                   " using NULL names for gid %d - %d\n",
+                    n, num_names - 1 ));
+        for ( ; n < num_names; n++ )
+          if ( FT_NEW_ARRAY( name_strings[n], 1 ) )
+            goto Fail1;
+          else
+            name_strings[n][0] = '\0';
+      }
     }
 
     /* all right, set table fields and exit successfully */
@@ -271,7 +306,8 @@
 
   static FT_Error
   load_format_25( TT_Face    face,
-                  FT_Stream  stream )
+                  FT_Stream  stream,
+                  FT_Long    post_limit )
   {
     FT_Memory  memory = stream->memory;
     FT_Error   error;
@@ -279,6 +315,8 @@
     FT_Int     num_glyphs;
     FT_Char*   offset_table = 0;
 
+    FT_UNUSED( post_limit );
+
 
     /* UNDOCUMENTED!  This value appears only in the Apple TT specs. */
     if ( FT_READ_USHORT( num_glyphs ) )
@@ -338,16 +376,20 @@
     FT_Stream  stream;
     FT_Error   error;
     FT_Fixed   format;
+    FT_ULong   post_len;
+    FT_Long    post_limit;
 
 
     /* get a stream for the face's resource */
     stream = face->root.stream;
 
     /* seek to the beginning of the PS names table */
-    error = face->goto_table( face, TTAG_post, stream, 0 );
+    error = face->goto_table( face, TTAG_post, stream, &post_len );
     if ( error )
       goto Exit;
 
+    post_limit = FT_STREAM_POS() + post_len;
+
     format = face->postscript.FormatType;
 
     /* go to beginning of subtable */
@@ -356,9 +398,9 @@
 
     /* now read postscript table */
     if ( format == 0x00020000L )
-      error = load_format_20( face, stream );
+      error = load_format_20( face, stream, post_limit );
     else if ( format == 0x00028000L )
-      error = load_format_25( face, stream );
+      error = load_format_25( face, stream, post_limit );
     else
       error = SFNT_Err_Invalid_File_Format;
 
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 0b94143..a85e160 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -187,7 +187,7 @@
             shift_,                                    \
             delta_                                     \
          };
-                                          
+
 #define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_,            \
                                 raster_new_, raster_reset_,       \
                                 raster_set_mode_, raster_render_, \
@@ -354,8 +354,6 @@
 
     int  band_size;
     int  band_shoot;
-    int  conic_level;
-    int  cubic_level;
 
     ft_jmp_buf  jump_buffer;
 
@@ -879,47 +877,7 @@
     FT_Vector*  arc;
 
 
-    dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
-    if ( dx < 0 )
-      dx = -dx;
-    dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
-    if ( dy < 0 )
-      dy = -dy;
-    if ( dx < dy )
-      dx = dy;
-
-    level = 1;
-    dx = dx / ras.conic_level;
-    while ( dx > 0 )
-    {
-      dx >>= 2;
-      level++;
-    }
-
-    /* a shortcut to speed things up */
-    if ( level <= 1 )
-    {
-      /* we compute the mid-point directly in order to avoid */
-      /* calling gray_split_conic()                          */
-      TPos  to_x, to_y, mid_x, mid_y;
-
-
-      to_x  = UPSCALE( to->x );
-      to_y  = UPSCALE( to->y );
-      mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
-      mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
-
-      gray_render_line( RAS_VAR_ mid_x, mid_y );
-      gray_render_line( RAS_VAR_ to_x, to_y );
-
-      return;
-    }
-
-    arc       = ras.bez_stack;
-    levels    = ras.lev_stack;
-    top       = 0;
-    levels[0] = level;
-
+    arc      = ras.bez_stack;
     arc[0].x = UPSCALE( to->x );
     arc[0].y = UPSCALE( to->y );
     arc[1].x = UPSCALE( control->x );
@@ -927,6 +885,28 @@
     arc[2].x = ras.x;
     arc[2].y = ras.y;
 
+    dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
+    dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
+    if ( dx < dy )
+      dx = dy;
+
+    if ( dx <= ONE_PIXEL / 4 )
+    {
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+      return;
+    }
+
+    level = 0;
+    while ( dx > ONE_PIXEL / 4 )
+    {
+      dx >>= 2;
+      level++;
+    }
+
+    levels    = ras.lev_stack;
+    levels[0] = level;
+    top       = 0;
+
     while ( top >= 0 )
     {
       level = levels[top];
@@ -957,21 +937,9 @@
       }
 
     Draw:
-      {
-        TPos  to_x, to_y, mid_x, mid_y;
-
-
-        to_x  = arc[0].x;
-        to_y  = arc[0].y;
-        mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
-        mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
-
-        gray_render_line( RAS_VAR_ mid_x, mid_y );
-        gray_render_line( RAS_VAR_ to_x, to_y );
-
-        top--;
-        arc -= 2;
-      }
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+      top--;
+      arc -= 2;
     }
 
     return;
@@ -1011,56 +979,9 @@
                               const FT_Vector*  control2,
                               const FT_Vector*  to )
   {
-    int         top, level;
-    int*        levels;
     FT_Vector*  arc;
-    int         mid_x = ( DOWNSCALE( ras.x ) + to->x +
-                          3 * (control1->x + control2->x ) ) / 8;
-    int         mid_y = ( DOWNSCALE( ras.y ) + to->y +
-                          3 * (control1->y + control2->y ) ) / 8;
-    TPos        dx = DOWNSCALE( ras.x ) + to->x - ( mid_x << 1 );
-    TPos        dy = DOWNSCALE( ras.y ) + to->y - ( mid_y << 1 );
 
 
-    if ( dx < 0 )
-      dx = -dx;
-    if ( dy < 0 )
-      dy = -dy;
-    if ( dx < dy )
-      dx = dy;
-
-    level = 1;
-    dx /= ras.cubic_level;
-    while ( dx > 0 )
-    {
-      dx >>= 2;
-      level++;
-    }
-
-    if ( level <= 1 )
-    {
-      TPos  to_x, to_y;
-
-
-      to_x  = UPSCALE( to->x );
-      to_y  = UPSCALE( to->y );
-
-      /* Recalculation of midpoint is needed only if */
-      /* UPSCALE and DOWNSCALE have any effect.      */
-
-#if ( PIXEL_BITS != 6 )
-      mid_x = ( ras.x + to_x +
-                3 * UPSCALE( control1->x + control2->x ) ) / 8;
-      mid_y = ( ras.y + to_y +
-                3 * UPSCALE( control1->y + control2->y ) ) / 8;
-#endif
-
-      gray_render_line( RAS_VAR_ mid_x, mid_y );
-      gray_render_line( RAS_VAR_ to_x, to_y );
-
-      return;
-    }
-
     arc      = ras.bez_stack;
     arc[0].x = UPSCALE( to->x );
     arc[0].y = UPSCALE( to->y );
@@ -1071,60 +992,129 @@
     arc[3].x = ras.x;
     arc[3].y = ras.y;
 
-    levels    = ras.lev_stack;
-    top       = 0;
-    levels[0] = level;
-
-    while ( top >= 0 )
+    for (;;)
     {
-      level = levels[top];
-      if ( level > 1 )
+      /* Check that the arc crosses the current band. */
+      TPos  min, max, y;
+
+
+      min = max = arc[0].y;
+
+      y = arc[1].y;
+      if ( y < min )
+        min = y;
+      if ( y > max )
+        max = y;
+
+      y = arc[2].y;
+      if ( y < min )
+        min = y;
+      if ( y > max )
+        max = y;
+
+      y = arc[3].y;
+      if ( y < min )
+        min = y;
+      if ( y > max )
+        max = y;
+
+      if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
+        goto Draw;
+
+      /* Decide whether to split or draw. See `Rapid Termination          */
+      /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
+      /* F. Hain, at                                                      */
+      /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
+
       {
-        /* check that the arc crosses the current band */
-        TPos  min, max, y;
+        TPos  dx, dy, dx_, dy_;
+        TPos  dx1, dy1, dx2, dy2;
+        TPos  L, s, s_limit;
 
 
-        min = max = arc[0].y;
-        y = arc[1].y;
-        if ( y < min ) min = y;
-        if ( y > max ) max = y;
-        y = arc[2].y;
-        if ( y < min ) min = y;
-        if ( y > max ) max = y;
-        y = arc[3].y;
-        if ( y < min ) min = y;
-        if ( y > max ) max = y;
-        if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
-          goto Draw;
-        gray_split_cubic( arc );
-        arc += 3;
-        top ++;
-        levels[top] = levels[top - 1] = level - 1;
-        continue;
+        /* dx and dy are x and y components of the P0-P3 chord vector. */
+        dx = arc[3].x - arc[0].x;
+        dy = arc[3].y - arc[0].y;
+
+        /* L is an (under)estimate of the Euclidean distance P0-P3.       */
+        /*                                                                */
+        /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated   */
+        /* with least maximum error by                                    */
+        /*                                                                */
+        /*   r_upperbound = dx + (sqrt(2) - 1) * dy  ,                    */
+        /*                                                                */
+        /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */
+        /* error of no more than 8.4%.                                    */
+        /*                                                                */
+        /* Similarly, some elementary calculus shows that r can be        */
+        /* underestimated with least maximum error by                     */
+        /*                                                                */
+        /*   r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx                    */
+        /*                  + sqrt(2 - sqrt(2)) / 2 * dy  .               */
+        /*                                                                */
+        /* 236/256 and 97/256 are (under)estimates of the two algebraic   */
+        /* numbers, giving an error of no more than 8.1%.                 */
+
+        dx_ = FT_ABS( dx );
+        dy_ = FT_ABS( dy );
+
+        /* This is the same as                     */
+        /*                                         */
+        /*   L = ( 236 * FT_MAX( dx_, dy_ )        */
+        /*       + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */
+        L = ( dx_ > dy_ ? 236 * dx_ +  97 * dy_
+                        :  97 * dx_ + 236 * dy_ ) >> 8;
+
+        /* Avoid possible arithmetic overflow below by splitting. */
+        if ( L > 32767 )
+          goto Split;
+
+        /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
+        s_limit = L * (TPos)( ONE_PIXEL / 6 );
+
+        /* s is L * the perpendicular distance from P1 to the line P0-P3. */
+        dx1 = arc[1].x - arc[0].x;
+        dy1 = arc[1].y - arc[0].y;
+        s = FT_ABS( dy * dx1 - dx * dy1 );
+
+        if ( s > s_limit )
+          goto Split;
+
+        /* s is L * the perpendicular distance from P2 to the line P0-P3. */
+        dx2 = arc[2].x - arc[0].x;
+        dy2 = arc[2].y - arc[0].y;
+        s = FT_ABS( dy * dx2 - dx * dy2 );
+
+        if ( s > s_limit )
+          goto Split;
+
+        /* If P1 or P2 is outside P0-P3, split the curve. */
+        if ( dy * dy1 + dx * dx1 < 0                                     ||
+             dy * dy2 + dx * dx2 < 0                                     ||
+             dy * (arc[3].y - arc[1].y) + dx * (arc[3].x - arc[1].x) < 0 ||
+             dy * (arc[3].y - arc[2].y) + dx * (arc[3].x - arc[2].x) < 0 )
+          goto Split;
+
+        /* No reason to split. */
+        goto Draw;
       }
 
+    Split:
+      gray_split_cubic( arc );
+      arc += 3;
+      continue;
+
     Draw:
-      {
-        TPos  to_x, to_y;
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
 
+      if ( arc == ras.bez_stack )
+        return;
 
-        to_x  = arc[0].x;
-        to_y  = arc[0].y;
-        mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
-        mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
-
-        gray_render_line( RAS_VAR_ mid_x, mid_y );
-        gray_render_line( RAS_VAR_ to_x, to_y );
-        top --;
-        arc -= 3;
-      }
+      arc -= 3;
     }
-
-    return;
   }
 
 
-
   static int
   gray_move_to( const FT_Vector*  to,
                 PWorker           worker )
@@ -1760,25 +1750,6 @@
     ras.count_ex = ras.max_ex - ras.min_ex;
     ras.count_ey = ras.max_ey - ras.min_ey;
 
-    /* simple heuristic used to speed up the bezier decomposition -- see */
-    /* the code in gray_render_conic() and gray_render_cubic() for more  */
-    /* details                                                           */
-    ras.conic_level = 32;
-    ras.cubic_level = 16;
-
-    {
-      int  level = 0;
-
-
-      if ( ras.count_ex > 24 || ras.count_ey > 24 )
-        level++;
-      if ( ras.count_ex > 120 || ras.count_ey > 120 )
-        level++;
-
-      ras.conic_level <<= level;
-      ras.cubic_level <<= level;
-    }
-
     /* set up vertical bands */
     num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
     if ( num_bands == 0 )
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 7d16b94..eb12f18 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -140,8 +140,26 @@
     cbox.xMax = FT_PIX_CEIL( cbox.xMax );
     cbox.yMax = FT_PIX_CEIL( cbox.yMax );
 
-    width  = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
-    height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+    if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
+    {
+      FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
+                 " xMin = %d, xMax = %d\n",
+                 cbox.xMin >> 6, cbox.xMax >> 6 ));
+      return Smooth_Err_Raster_Overflow;
+    }
+    else
+      width  = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
+
+    if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
+    {
+      FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
+                 " yMin = %d, yMax = %d\n",
+                 cbox.yMin >> 6, cbox.yMax >> 6 ));
+      return Smooth_Err_Raster_Overflow;
+    }
+    else
+      height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+
     bitmap = &slot->bitmap;
     memory = render->root.memory;
 
@@ -202,7 +220,7 @@
     /* but we care realistic cases only. Always pitch <= width. */
     if ( width > 0x7FFFU || height > 0x7FFFU )
     {
-      FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n",
+      FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
                  width, height ));
       return Smooth_Err_Raster_Overflow;
     }
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 1b496c0..3a69b7b 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -1910,6 +1910,9 @@
         FT_UInt  i;
 
 
+        FT_TRACE4(( "tt_loader_init: grayscale change,"
+                    " re-executing `prep' table\n" ));
+
         exec->grayscale = grayscale;
 
         for ( i = 0; i < size->cvt_size; i++ )
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 653d9d5..47bb9fc 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -130,7 +130,7 @@
     FT_Int     j;
     FT_Int     first;
     FT_Memory  memory = stream->memory;
-    FT_Error   error = TT_Err_Ok;
+    FT_Error   error  = TT_Err_Ok;
 
     FT_UNUSED( error );
 
@@ -154,7 +154,7 @@
         runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
         first  = points[i++] = FT_GET_USHORT();
 
-        if ( runcnt < 1 )
+        if ( runcnt < 1 || i + runcnt >= n )
           goto Exit;
 
         /* first point not included in runcount */
@@ -165,7 +165,7 @@
       {
         first = points[i++] = FT_GET_BYTE();
 
-        if ( runcnt < 1 )
+        if ( runcnt < 1 || i + runcnt >= n )
           goto Exit;
 
         for ( j = 0; j < runcnt; ++j )
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index d22e94f..f55b8ee 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -478,8 +478,7 @@
     return TT_Err_Ok;
 
   Fail_Memory:
-    FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
-               (FT_Long)exec ));
+    FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
     TT_Done_Context( exec );
 
     return error;
@@ -596,6 +595,12 @@
       exec->storage   = size->storage;
 
       exec->twilight  = size->twilight;
+
+      /* In case of multi-threading it can happen that the old size object */
+      /* no longer exists, thus we must clear all glyph zone references.   */
+      ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
+      exec->zp1 = exec->zp0;
+      exec->zp2 = exec->zp0;
     }
 
     /* XXX: We reserve a little more elements on the stack to deal safely */
@@ -5795,7 +5800,16 @@
     if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
       last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
     else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
+    {
       last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
+
+      if ( BOUNDS( last_point, CUR.zp2.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+          CUR.error = TT_Err_Invalid_Reference;
+        return;
+      }
+    }
     else
       last_point = 0;
 
@@ -6773,12 +6787,11 @@
         {
           if ( ( CUR.pts.tags[point] & mask ) != 0 )
           {
-            if ( point > 0 )
-              _iup_worker_interpolate( &V,
-                                       cur_touched + 1,
-                                       point - 1,
-                                       cur_touched,
-                                       point );
+            _iup_worker_interpolate( &V,
+                                     cur_touched + 1,
+                                     point - 1,
+                                     cur_touched,
+                                     point );
             cur_touched = point;
           }
 
@@ -8128,6 +8141,15 @@
     *exc = cur;
 #endif
 
+    /* If any errors have occurred, function tables may be broken. */
+    /* Force a re-execution of `prep' and `fpgm' tables if no      */
+    /* bytecode debugger is run.                                   */
+    if ( CUR.error && !CUR.instruction_trap )
+    {
+      FT_TRACE1(( "  The interpreter returned error 0x%x\n", CUR.error ));
+      exc->size->cvt_ready      = FALSE;  
+    }
+
     return CUR.error;
   }
 
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 11d662d..8fe86ad 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    Objects manager (body).                                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
+/*            2010 by                                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -146,28 +147,28 @@
   /* This list shall be expanded as we find more of them.       */
 
   static FT_Bool
-  tt_check_trickyness( FT_String*  name )
+  tt_check_trickyness_family( FT_String*  name )
   {
+
 #define TRICK_NAMES_MAX_CHARACTERS  16
-#define TRICK_NAMES_COUNT 7
-    static const char trick_names[TRICK_NAMES_COUNT][TRICK_NAMES_MAX_CHARACTERS+1] =
+#define TRICK_NAMES_COUNT            8
+
+    static const char trick_names[TRICK_NAMES_COUNT]
+                                 [TRICK_NAMES_MAX_CHARACTERS + 1] =
     {
       "DFKaiSho-SB",     /* dfkaisb.ttf */
       "DFKaiShu",
       "DFKai-SB",        /* kaiu.ttf */
+      "HuaTianKaiTi?",   /* htkt2.ttf */
       "HuaTianSongTi?",  /* htst3.ttf */
       "MingLiU",         /* mingliu.ttf & mingliu.ttc */
       "PMingLiU",        /* mingliu.ttc */
       "MingLi43",        /* mingli.ttf */
     };
+
     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; nn < TRICK_NAMES_COUNT; nn++ )
       if ( ft_strstr( name, trick_names[nn] ) )
         return TRUE;
@@ -176,6 +177,181 @@
   }
 
 
+  /* XXX: This function should be in the `sfnt' module. */
+
+  /* Some PDF generators clear the checksums in the TrueType header table. */
+  /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF     */
+  /* Printer clears the entries for subsetted subtables.  We thus have to  */
+  /* recalculate the checksums  where necessary.                           */
+
+  static FT_UInt32
+  tt_synth_sfnt_checksum( FT_Stream  stream,
+                          FT_ULong   length )
+  {
+    FT_Error   error;
+    FT_UInt32  checksum = 0;
+    int        i;
+
+
+    if ( FT_FRAME_ENTER( length ) )
+      return 0;
+
+    for ( ; length > 3; length -= 4 )
+      checksum += (FT_UInt32)FT_GET_ULONG();
+
+    for ( i = 3; length > 0; length --, i-- )
+      checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) );
+
+    FT_FRAME_EXIT();
+
+    return checksum;
+  }
+
+
+  /* XXX: This function should be in the `sfnt' module. */
+
+  static FT_ULong
+  tt_get_sfnt_checksum( TT_Face    face,
+                        FT_UShort  i )
+  {
+    if ( face->dir_tables[i].CheckSum )
+      return face->dir_tables[i].CheckSum;
+
+    else if ( !face->goto_table )
+      return 0;
+
+    else if ( !face->goto_table( face,
+                                 face->dir_tables[i].Tag,
+                                 face->root.stream,
+                                 NULL ) )
+      return 0;
+
+    return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
+                                             face->dir_tables[i].Length );
+  }
+
+
+  typedef struct tt_sfnt_id_rec_
+  {
+    FT_ULong  CheckSum;
+    FT_ULong  Length;
+
+  } tt_sfnt_id_rec;
+
+
+  static FT_Bool
+  tt_check_trickyness_sfnt_ids( TT_Face  face )
+  {
+#define TRICK_SFNT_IDS_PER_FACE   3
+#define TRICK_SFNT_IDS_NUM_FACES  5
+
+    static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
+                                       [TRICK_SFNT_IDS_PER_FACE] = {
+
+#define TRICK_SFNT_ID_cvt   0
+#define TRICK_SFNT_ID_fpgm  1
+#define TRICK_SFNT_ID_prep  2
+
+      { /* MingLiU 1995 */
+        { 0x05bcf058, 0x000002e4 }, /* cvt  */
+        { 0x28233bf1, 0x000087c4 }, /* fpgm */
+        { 0xa344a1ea, 0x000001e1 }  /* prep */
+      },
+      { /* MingLiU 1996- */
+        { 0x05bcf058, 0x000002e4 }, /* cvt  */
+        { 0x28233bf1, 0x000087c4 }, /* fpgm */
+        { 0xa344a1eb, 0x000001e1 }  /* prep */
+      },
+      { /* DFKaiShu */
+        { 0x11e5ead4, 0x00000350 }, /* cvt  */
+        { 0x5a30ca3b, 0x00009063 }, /* fpgm */
+        { 0x13a42602, 0x0000007e }  /* prep */
+      },
+      { /* HuaTianKaiTi */
+        { 0xfffbfffc, 0x00000008 }, /* cvt  */
+        { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */
+        { 0x70020112, 0x00000008 }  /* prep */
+      },
+      { /* HuaTianSongTi */
+        { 0xfffbfffc, 0x00000008 }, /* cvt  */
+        { 0x0a5a0483, 0x00017c39 }, /* fpgm */
+        { 0x70020112, 0x00000008 }  /* prep */
+      }
+    };
+
+    FT_ULong  checksum;
+    int       num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
+    int       i, j, k;
+
+
+    FT_MEM_SET( num_matched_ids, 0,
+                sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES );
+
+    for ( i = 0; i < face->num_tables; i++ )
+    {
+      checksum = 0;
+
+      switch( face->dir_tables[i].Tag )
+      {
+      case TTAG_cvt:
+        k = TRICK_SFNT_ID_cvt;
+        break;
+
+      case TTAG_fpgm:
+        k = TRICK_SFNT_ID_fpgm;
+        break;
+
+      case TTAG_prep:
+        k = TRICK_SFNT_ID_prep;
+        break;
+
+      default:
+        continue;
+      }
+
+      for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
+        if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
+        {
+          if ( !checksum )
+            checksum = tt_get_sfnt_checksum( face, i );
+
+          if ( sfnt_id[j][k].CheckSum == checksum )
+            num_matched_ids[j]++;
+
+          if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+  }
+
+
+  static FT_Bool
+  tt_check_trickyness( FT_Face  face )
+  {
+    if ( !face )
+      return FALSE;
+
+    /* First, check the face name. */
+    if ( face->family_name )
+    {
+      if ( tt_check_trickyness_family( face->family_name ) )
+        return TRUE;
+      else
+        return FALSE;
+    }
+
+    /* Type42 fonts may lack `name' tables, we thus try to identify */
+    /* tricky fonts by checking the checksums of Type42-persistent  */
+    /* sfnt tables (`cvt', `fpgm', and `prep').                     */
+    if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
+      return TRUE;
+
+    return FALSE;
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -250,7 +426,7 @@
     if ( error )
       goto Exit;
 
-    if ( tt_check_trickyness( ttface->family_name ) )
+    if ( tt_check_trickyness( ttface ) )
       ttface->face_flags |= FT_FACE_FLAG_TRICKY;
 
     error = tt_face_load_hdmx( face, stream );
@@ -458,7 +634,11 @@
       error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
 
       if ( !error )
+      {
+        FT_TRACE4(( "Executing `fpgm' table.\n" ));
+
         error = face->interpreter( exec );
+      }
     }
     else
       error = TT_Err_Ok;
@@ -520,7 +700,11 @@
       error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
 
       if ( !error && !size->debug )
+      {
+        FT_TRACE4(( "Executing `prep' table.\n" ));
+
         error = face->interpreter( exec );
+      }
     }
     else
       error = TT_Err_Ok;
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index a311b03..68a5453 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType-specific tables loader (body).                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 by       */
+/*  Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -137,6 +137,12 @@
             dist = diff;
         }
 
+        if ( entry == limit )
+        {
+          /* `loca' is the last table */
+          dist = stream->size - pos;
+        }
+
         if ( new_loca_len <= dist )
         {
           face->num_locations = face->root.num_glyphs;
@@ -203,6 +209,26 @@
       }
     }
 
+    /* Check broken location data */
+    if ( pos1 >= face->glyf_len )
+    {
+      FT_TRACE1(( "tt_face_get_location:"
+                 " too large offset=0x%08lx found for gid=0x%04lx,"
+                 " exceeding the end of glyf table (0x%08lx)\n",
+                 pos1, gindex, face->glyf_len ));
+      *asize = 0;
+      return 0;
+    }
+
+    if ( pos2 >= face->glyf_len )
+    {
+      FT_TRACE1(( "tt_face_get_location:"
+                 " too large offset=0x%08lx found for gid=0x%04lx,"
+                 " truncate at the end of glyf table (0x%08lx)\n",
+                 pos2, gindex + 1, face->glyf_len ));
+      pos2 = face->glyf_len;
+    }
+
     /* The `loca' table must be ordered; it refers to the length of */
     /* an entry as the difference between the current and the next  */
     /* position.  However, there do exist (malformed) fonts which   */
@@ -287,7 +313,7 @@
       FT_Short*  limit = cur + face->cvt_size;
 
 
-      for ( ; cur <  limit; cur++ )
+      for ( ; cur < limit; cur++ )
         *cur = FT_GET_SHORT();
     }