shithub: freetype+ttf2subf

Download patch

ref: cf432dbf2273c084b011162ea6b8350a33dfd3da
parent: 9a966b7d1bbc9e35eddb68136b73cbe006dff675
author: David Turner <[email protected]>
date: Fri Oct 19 08:36:40 EDT 2007

* include/freetype/freetype.h, src/base/ftobjs.c: renamed
        cmap14-related new APIs to the FT_Object_ActionName scheme.
        update the documentation for these APIs

        * src/sfnt/ttcmap.c: stronger cmap 14 validation, make the
        code a little more consistent with FreeType coding conventions
        and modify the cmap14 functions that returned a newly allocated
        array to use a persistent vector from the TT_CMap14 object
        instead.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2007-10-18  David Turner  <[email protected]>
+
+	* include/freetype/freetype.h, src/base/ftobjs.c: renamed
+	cmap14-related new APIs to the FT_Object_ActionName scheme.
+	update the documentation for these APIs
+
+	* src/sfnt/ttcmap.c: stronger cmap 14 validation, make the
+	code a little more consistent with FreeType coding conventions
+	and modify the cmap14 functions that returned a newly allocated
+	array to use a persistent vector from the TT_CMap14 object
+	instead.
+
 2007-10-15  George Williams  <[email protected]>
 
 	Add support for cmap type 14.
@@ -46,7 +58,7 @@
 2007-10-01  Werner Lemberg  <[email protected]>
 
 	* src/base/ftobjs.c (find_unicode_charmap): If search for a UCS-4
-	charmap fails, do the loop again while searching a UCS-2 charmap. 
+	charmap fails, do the loop again while searching a UCS-2 charmap.
 	This favours MS charmaps over Apple ones.
 
 2007-08-29  suzuki toshiya  <[email protected]>
@@ -121,7 +133,7 @@
 
 2007-08-04  Werner Lemberg  <[email protected]>
 
-	* builds/unix/configure.raw: Add call to AC_LIBTOOL_WIN32_DLL. 
+	* builds/unix/configure.raw: Add call to AC_LIBTOOL_WIN32_DLL.
 	Fixes Savannah bug #20686.
 
 2007-08-03  Werner Lemberg  <[email protected]>
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -2995,7 +2995,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    FT_Get_Char_Variant_Index                                          */
+  /*    FT_Face_GetCharVariantIndex                                        */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Return the glyph index of a given character code as modified by    */
@@ -3029,15 +3029,15 @@
   /*      b) the current charmap has a Unicode encoding                    */
   /*                                                                       */
   FT_EXPORT( FT_UInt )
-  FT_Get_Char_Variant_Index( FT_Face   face,
-                             FT_ULong  charcode,
-                             FT_ULong  variantSelector );
+  FT_Face_GetCharVariantIndex( FT_Face   face,
+                               FT_ULong  charcode,
+                               FT_ULong  variantSelector );
 
 
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    FT_Get_Char_Variant_IsDefault                                      */
+  /*    FT_Face_GetCharVariantIsDefault                                    */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Check whether this variant of this Unicode character is the one to */
@@ -3062,15 +3062,15 @@
   /*    selector cmap subtable.                                            */
   /*                                                                       */
   FT_EXPORT( FT_Int )
-  FT_Get_Char_Variant_IsDefault( FT_Face   face,
-                                 FT_ULong  charcode,
-                                 FT_ULong  variantSelector );
+  FT_Face_GetCharVariantIsDefault( FT_Face   face,
+                                   FT_ULong  charcode,
+                                   FT_ULong  variantSelector );
 
 
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    FT_Get_Variant_Selectors                                           */
+  /*    FT_Face_GetVariantSelectors                                        */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Return a zero-terminated list of Unicode variant selectors found   */
@@ -3080,20 +3080,22 @@
   /*    face :: A handle to the source face object.                        */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    A list of all the variant selector code points in the cmap         */
-  /*    or NULL if there is no valid variant selector cmap subtable.       */
+  /*    A pointer to an array of selector code points, or NULL if there is */
+  /*    no valid variant selector cmap subtable.                           */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    User is responsible for deallocating the returned list.            */
+  /*    the last item in the array is 0. the array is owned by the FT_Face */
+  /*    but can be overwritten or released on the next call to a FreeType  */
+  /*    function.                                                          */
   /*                                                                       */
   FT_EXPORT( FT_UInt32* )
-  FT_Get_Variant_Selectors( FT_Face  face );
+  FT_Face_GetVariantSelectors( FT_Face  face );
 
 
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    FT_Get_Variants_Of_Char                                            */
+  /*    FT_Face_GetVariantsOfChar                                          */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Return a zero-terminated list of Unicode variant selectors found   */
@@ -3107,22 +3109,24 @@
   /*      The character codepoint in Unicode.                              */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    A list of all the variant selector code points which are active    */
-  /*    for the given character or NULL if there is no valid variant       */
-  /*    selector cmap subtable (or if if this character has no variants).  */
+  /*    A pointer to an array of variant selector code points which are    */
+  /*    active for the given character, or NULL if the corresponding list  */
+  /*    is empty.                                                          */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    User is responsible for deallocating the returned list.            */
+  /*    the last item in the array is 0. the array is owned by the FT_Face */
+  /*    but can be overwritten or released on the next call to a FreeType  */
+  /*    function.                                                          */
   /*                                                                       */
   FT_EXPORT( FT_UInt32* )
-  FT_Get_Variants_Of_Char( FT_Face   face,
-                           FT_ULong  charcode );
+  FT_Face_GetVariantsOfChar( FT_Face   face,
+                             FT_ULong  charcode );
 
 
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    FT_Get_Chars_Of_Variant                                            */
+  /*    FT_Face_GetCharsOfVariant                                          */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Return a zero-terminated list of Unicode character codes found for */
@@ -3141,11 +3145,13 @@
   /*    is no valid cmap or the variant selector is invalid.               */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    User is responsible for deallocating the returned list.            */
+  /*    the last item in the array is 0. the array is owned by the FT_Face */
+  /*    but can be overwritten or released on the next call to a FreeType  */
+  /*    function.                                                          */
   /*                                                                       */
   FT_EXPORT( FT_UInt32* )
-  FT_Get_Chars_Of_Variant( FT_Face   face,
-                           FT_ULong  variantSelector );
+  FT_Face_GetCharsOfVariant( FT_Face   face,
+                             FT_ULong  variantSelector );
 
 
   /*************************************************************************/
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2893,9 +2893,9 @@
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_UInt )
-  FT_Get_Char_Variant_Index( FT_Face   face,
-                             FT_ULong  charcode,
-                             FT_ULong  variantSelector )
+  FT_Face_GetCharVariantIndex( FT_Face   face,
+                               FT_ULong  charcode,
+                               FT_ULong  variantSelector )
   {
     FT_UInt  result = 0;
 
@@ -2924,9 +2924,9 @@
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Int )
-  FT_Get_Char_Variant_IsDefault( FT_Face   face,
-                                 FT_ULong  charcode,
-                                 FT_ULong  variantSelector )
+  FT_Face_GetCharVariantIsDefault( FT_Face   face,
+                                   FT_ULong  charcode,
+                                   FT_ULong  variantSelector )
   {
     FT_Int  result = -1;
 
@@ -2953,7 +2953,7 @@
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_UInt32* )
-  FT_Get_Variant_Selectors( FT_Face  face )
+  FT_Face_GetVariantSelectors( FT_Face  face )
   {
     FT_UInt32  *result = NULL;
 
@@ -2980,8 +2980,8 @@
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_UInt32* )
-  FT_Get_Variants_Of_Char( FT_Face   face,
-                           FT_ULong  charcode )
+  FT_Face_GetVariantsOfChar( FT_Face   face,
+                             FT_ULong  charcode )
   {
     FT_UInt32  *result = NULL;
 
@@ -3007,8 +3007,8 @@
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_UInt32* )
-  FT_Get_Chars_Of_Variant( FT_Face   face,
-                           FT_ULong  variantSelector )
+  FT_Face_GetCharsOfVariant( FT_Face   face,
+                             FT_ULong  variantSelector )
   {
     FT_UInt32  *result = NULL;
 
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -2287,7 +2287,7 @@
   /*   GID            3     USHORT  and its GID                            */
   /*                                                                       */
   /* Ranges are sorted by `uniStart'.                                      */
-  
+
 #ifdef TT_CONFIG_CMAP_FORMAT_14
 
   typedef struct  TT_CMap14Rec_
@@ -2295,9 +2295,50 @@
     TT_CMapRec  cmap;
     FT_ULong    num_selectors;
 
+   /* this array is used to store the results of various
+    * cmap 14 query functions. its content is overwritten
+    * on each call to these functions
+    */
+    FT_UInt     max_results;
+    FT_UInt32*  results;
+    FT_Memory   memory;
+
   } TT_CMap14Rec, *TT_CMap14;
 
 
+  FT_CALLBACK_DEF( void )
+  tt_cmap14_done( TT_CMap14  cmap )
+  {
+    FT_Memory  memory = cmap->memory;
+
+    cmap->max_results = 0;
+    if (memory != NULL && cmap->results != NULL)
+      FT_FREE( cmap->results );
+  }
+
+
+  static FT_Error
+  tt_cmap14_ensure( TT_CMap14  cmap,
+                    FT_UInt    num_results,
+                    FT_Memory  memory )
+  {
+    FT_UInt   old_max = cmap->max_results;
+    FT_Error  error   = 0;
+
+
+    if (num_results > cmap->max_results)
+    {
+       cmap->memory = memory;
+
+       if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
+         return error;
+
+       cmap->max_results = num_results;
+    }
+    return error;
+  }
+
+
   FT_CALLBACK_DEF( FT_Error )
   tt_cmap14_init( TT_CMap14  cmap,
                   FT_Byte*   table )
@@ -2306,6 +2347,8 @@
 
     table               += 6;
     cmap->num_selectors = FT_PEEK_ULONG( table );
+    cmap->max_results   = 0;
+    cmap->results       = NULL;
 
     return SFNT_Err_Ok;
   }
@@ -2325,22 +2368,27 @@
 
     /* check selectors, they must be in increasing order */
     {
-      FT_ULong  n, varSel, defOff, nondefOff, last = 0;
+     /* we start lastVarSel at 1 because a variant selector value of 0
+      * isn't legal.
+      */
+      FT_ULong  n, lastVarSel = 1;
 
 
       for ( n = 0; n < num_selectors; n++ )
       {
-        varSel    = TT_NEXT_UINT24( p );
-        defOff    = TT_NEXT_ULONG( p );
-        nondefOff = TT_NEXT_ULONG( p );
+        FT_ULong  varSel    = TT_NEXT_UINT24( p );
+        FT_ULong  defOff    = TT_NEXT_ULONG( p );
+        FT_ULong  nondefOff = TT_NEXT_ULONG( p );
 
+
         if ( defOff >= length || nondefOff >= length )
           FT_INVALID_TOO_SHORT;
 
-        if ( n > 0 && varSel <= last )
+        if ( varSel < lastVarSel )
           FT_INVALID_DATA;
-        last = varSel;
 
+        lastVarSel = varSel + 1;
+
         /* check the default table (these glyphs should be reached     */
         /* through the normal Unicode cmap, no GIDs, just check order) */
         if ( defOff != 0 )
@@ -2347,20 +2395,25 @@
         {
           FT_Byte*  defp      = table + defOff;
           FT_ULong  numRanges = TT_NEXT_ULONG( defp );
-          FT_ULong  i, base, cnt;
+          FT_ULong  i;
+          FT_ULong  lastBase  = 0;
 
+          if ( defp + numRanges*4 > valid->limit )
+            FT_INVALID_TOO_SHORT;
 
           for ( i = 0; i < numRanges; ++i )
           {
-            base = TT_NEXT_UINT24( defp );
-            cnt  = FT_NEXT_BYTE( defp );
+            FT_ULong  base = TT_NEXT_UINT24( defp );
+            FT_ULong  cnt  = FT_NEXT_BYTE( defp );
 
+
             if ( base + cnt >= 0x110000UL )              /* end of Unicode */
               FT_INVALID_DATA;
 
-            if ( i > 0 && base <= last )
+            if ( base < lastBase )
               FT_INVALID_DATA;
-            last = base + cnt;
+
+            lastBase = base + cnt + 1U;
           }
         }
 
@@ -2368,21 +2421,26 @@
         if ( nondefOff != 0 ) {
           FT_Byte*  ndp         = table + nondefOff;
           FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
-          FT_ULong  i, uni, gid;
+          FT_ULong  i, lastUni = 0;
 
 
+          if ( ndp + numMappings*4 > valid->limit )
+            FT_INVALID_TOO_SHORT;
+
           for ( i = 0; i < numMappings; ++i )
           {
-            uni = TT_NEXT_UINT24( ndp );
-            gid = TT_NEXT_USHORT( ndp );
+            FT_ULong  uni = TT_NEXT_UINT24( ndp );
+            FT_ULong  gid = TT_NEXT_USHORT( ndp );
 
+
             if ( uni >= 0x110000UL )                     /* end of Unicode */
               FT_INVALID_DATA;
 
-            if ( i > 0 && uni <= last )
+            if ( uni < lastUni )
               FT_INVALID_DATA;
-            last = uni;
 
+            lastUni = uni + 1U;
+
             if ( valid->level >= FT_VALIDATE_TIGHT    &&
                  gid >= TT_VALID_GLYPH_COUNT( valid ) )
               FT_INVALID_GLYPH_ID;
@@ -2437,29 +2495,23 @@
   tt_cmap14_char_map_def_binary( FT_Byte    *base,
                                  FT_UInt32   char_code )
   {
-    FT_Byte*   p;
     FT_UInt32  numRanges = TT_PEEK_ULONG( base );
-    FT_UInt32  start, cnt;
-    FT_UInt32  max, min, mid;
+    FT_UInt32  max, min;
 
 
-    if ( !numRanges )
-      return FALSE;
-
-    /* make compiler happy */
-    mid = numRanges;
-
     min = 0;
     max = numRanges;
 
+    base += 4;
+
     /* binary search */
     while ( min < max )
     {
-      mid = ( min + max ) >> 1;
-      p   = base + 4 + 4 * mid;
+      FT_UInt32  mid   = ( min + max ) >> 1;
+      FT_Byte*   p     = base + 4 * mid;
+      FT_ULong   start = TT_NEXT_UINT24( p );
+      FT_UInt    cnt   = FT_NEXT_BYTE( p );
 
-      start = TT_NEXT_UINT24( p );
-      cnt   = FT_NEXT_BYTE( p );
 
       if ( char_code < start )
         max = mid;
@@ -2477,29 +2529,22 @@
   tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
                                     FT_UInt32   char_code )
   {
-    FT_Byte*   p;
     FT_UInt32  numMappings = TT_PEEK_ULONG( base );
-    FT_UInt32  uni, gid;
-    FT_UInt32  max, min, mid;
+    FT_UInt32  max, min;
 
 
-    if ( !numMappings )
-      return 0;
-
-    /* make compiler happy */
-    mid = numMappings;
-
     min = 0;
     max = numMappings;
 
+    base += 4;
+
     /* binary search */
     while ( min < max )
     {
-      mid = ( min + max ) >> 1;
-      p   = base + 4 + 5 * mid;
+      FT_UInt32  mid = ( min + max ) >> 1;
+      FT_Byte*   p   = base + 5 * mid;
+      FT_UInt32  uni = TT_PEEK_UINT24( p );
 
-      uni = TT_NEXT_UINT24( p );
-      gid = TT_NEXT_USHORT( p );
 
       if ( char_code < uni )
         max = mid;
@@ -2506,9 +2551,8 @@
       else if ( char_code > uni )
         min = mid + 1;
       else
-        return gid;
+        return TT_PEEK_USHORT( p );
     }
-
     return 0;
   }
 
@@ -2517,28 +2561,22 @@
   tt_cmap14_find_variant( FT_Byte    *base,
                           FT_UInt32   variantCode )
   {
-    FT_Byte*   p;
     FT_UInt32  numVar = TT_PEEK_ULONG( base );
-    FT_ULong   varSel;
-    FT_UInt32  max, min, mid;
+    FT_UInt32  max, min;
 
 
-    if ( !numVar )
-      return NULL;
-
-    /* make compiler happy */
-    mid = numVar;
-
     min = 0;
     max = numVar;
 
+    base += 4;
+
     /* binary search */
     while ( min < max )
     {
-      mid = ( min + max ) >> 1;
-      p   = base + 4 + 11 * mid;
+      FT_UInt32  mid    = ( min + max ) >> 1;
+      FT_Byte*   p      = base + 11 * mid;
+      FT_ULong   varSel = TT_PEEK_UINT24( p );
 
-      varSel = TT_NEXT_UINT24( p );
 
       if ( variantCode < varSel )
         max = mid;
@@ -2558,7 +2596,7 @@
                             FT_ULong  charcode,
                             FT_ULong  variantSelector)
   {
-    FT_Byte   *p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
+    FT_Byte*   p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
     FT_ULong   defOff;
     FT_ULong   nondefOff;
 
@@ -2567,7 +2605,7 @@
       return 0;
 
     defOff    = TT_NEXT_ULONG( p );
-    nondefOff = TT_NEXT_ULONG( p );
+    nondefOff = TT_PEEK_ULONG( p );
 
     if ( defOff != 0                                                    &&
          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
@@ -2590,7 +2628,7 @@
                                 FT_ULong  charcode,
                                 FT_ULong  variantSelector )
   {
-    FT_Byte   *p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
+    FT_Byte*   p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
     FT_ULong   defOff;
     FT_ULong   nondefOff;
 
@@ -2619,24 +2657,23 @@
                       FT_Memory  memory )
   {
     TT_CMap14   cmap14 = (TT_CMap14)cmap;
+    FT_UInt     count  = cmap14->num_selectors;
     FT_Byte*    p      = cmap->data + 10;
-    FT_UInt32*  ret;
+    FT_UInt32*  result;
     FT_UInt     i;
-    FT_Error    error;
 
-
-    if ( FT_ALLOC( ret,
-                   ( cmap14->num_selectors + 1 ) * sizeof ( FT_UInt32 ) ) )
+    if ( tt_cmap14_ensure( cmap14, (count + 1), memory ) )
       return NULL;
 
-    for ( i = 0; i < cmap14->num_selectors; ++i )
+    result = cmap14->results;
+    for ( i = 0; i < count; ++i )
     {
-      ret[i] = TT_NEXT_UINT24( p );
-      p += 8;
+      result[i] = TT_NEXT_UINT24( p );
+      p        += 8;
     }
-    ret[i] = 0;
+    result[i] = 0;
 
-    return ret;
+    return result;
   }
 
 
@@ -2646,24 +2683,21 @@
                            FT_ULong   charCode )
   {
     TT_CMap14   cmap14 = (TT_CMap14)  cmap;
-    FT_Byte*    p = cmap->data + 10;
-    FT_UInt32  *ret;
-    FT_UInt     i, j;
-    FT_UInt32   varSel;
-    FT_ULong    defOff;
-    FT_ULong    nondefOff;
-    FT_Error    error;
+    FT_UInt     count  = cmap14->num_selectors;
+    FT_Byte*    p      = cmap->data + 10;
+    FT_UInt32*  q;
 
 
-    if ( FT_ALLOC( ret,
-                   ( cmap14->num_selectors + 1 ) * sizeof ( FT_UInt32 ) ) )
+    if ( tt_cmap14_ensure( cmap14, (count + 1), memory ) )
       return NULL;
 
-    for ( i = j = 0; i < cmap14->num_selectors; ++i )
+    for ( q = cmap14->results; count > 0; --count )
     {
-      varSel    = TT_NEXT_UINT24( p );
-      defOff    = TT_NEXT_ULONG( p );
-      nondefOff = TT_NEXT_ULONG( p );
+      FT_UInt32  varSel    = TT_NEXT_UINT24( p );
+      FT_ULong   defOff    = TT_NEXT_ULONG( p );
+      FT_ULong   nondefOff = TT_NEXT_ULONG( p );
+
+
       if ( ( defOff != 0                                               &&
              tt_cmap14_char_map_def_binary( cmap->data + defOff,
                                             charCode )                 ) ||
@@ -2670,11 +2704,14 @@
            ( nondefOff != 0                                            &&
              tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
                                                charCode ) != 0         ) )
-        ret[j++] = varSel;
+      {
+        q[0] = varSel;
+        q++;
+      }
     }
-    ret[j] = 0;
+    q[0] = 0;
 
-    return ret;
+    return cmap14->results;
   }
 
 
@@ -2681,20 +2718,15 @@
   static FT_UInt
   tt_cmap14_def_char_count( FT_Byte  *p )
   {
-    FT_UInt32  numRanges;
-    FT_UInt    tot;
-    FT_UInt    cnt;
-    FT_UInt    i;
+    FT_UInt32  numRanges = TT_NEXT_ULONG( p );
+    FT_UInt    tot       = 0;
 
 
-    numRanges = TT_NEXT_ULONG( p );
-
-    tot = 0;
-    for ( i = 0; i < numRanges; ++i )
+    p += 3;  /* point to the first 'cnt' field */
+    for ( ; numRanges > 0; numRanges-- )
     {
-      p += 3;
-      cnt = FT_NEXT_BYTE( p );
-      tot += cnt + 1;
+      tot += 1 + p[0];
+      p   += 4;
     }
 
     return tot;
@@ -2701,53 +2733,59 @@
   }
 
 
-  static FT_UInt*
-  tt_cmap14_get_def_chars( FT_Byte    *p,
+  static FT_UInt32*
+  tt_cmap14_get_def_chars( TT_CMap     cmap,
+                           FT_Byte*    p,
                            FT_Memory   memory )
   {
+    TT_CMap14   cmap14 = (TT_CMap14) cmap;
     FT_UInt32   numRanges;
-    FT_UInt     uni;
     FT_UInt     cnt;
-    FT_UInt     i, j, k;
-    FT_UInt32  *ret;
-    FT_Error    error;
+    FT_UInt32*  q;
 
 
     cnt       = tt_cmap14_def_char_count( p );
     numRanges = TT_NEXT_ULONG( p );
 
-    if ( FT_ALLOC( ret , ( cnt + 1 ) * sizeof ( FT_UInt32 ) ) )
+    if ( tt_cmap14_ensure( cmap14, (cnt + 1), memory ) )
       return NULL;
 
-    for ( i = j = 0; i < numRanges; ++i )
+    for ( q = cmap14->results; numRanges > 0; --numRanges )
     {
-      uni = TT_NEXT_UINT24( p );
-      cnt = FT_NEXT_BYTE( p );
+      FT_UInt  uni = TT_NEXT_UINT24( p );
+      FT_UInt  cnt = FT_NEXT_BYTE( p ) + 1;
 
-      for ( k = 0; k <= cnt; ++k )
-        ret[j++] = uni + k;
+      do
+      {
+        q[0]  = uni;
+        uni  += 1;
+        q    += 1;
+      }
+      while ( --cnt != 0 );
     }
-    ret[j] = 0;
+    q[0] = 0;
 
-    return ret;
+    return cmap14->results;
   }
-    
 
+
   static FT_UInt*
-  tt_cmap14_get_nondef_chars( FT_Byte    *p,
+  tt_cmap14_get_nondef_chars( TT_CMap     cmap,
+                              FT_Byte    *p,
                               FT_Memory   memory )
   {
+    TT_CMap14   cmap14 = (TT_CMap14) cmap;
     FT_UInt32   numMappings;
     FT_UInt     i;
     FT_UInt32  *ret;
-    FT_Error    error;
 
 
     numMappings = TT_NEXT_ULONG( p );
 
-    if ( FT_ALLOC( ret, ( numMappings + 1 ) * sizeof ( FT_UInt32 ) ) )
+    if ( tt_cmap14_ensure( cmap14, (numMappings + 1), memory ) )
       return NULL;
 
+    ret = cmap14->results;
     for ( i = 0; i < numMappings; ++i )
     {
       ret[i] = TT_NEXT_UINT24( p );
@@ -2755,10 +2793,10 @@
     }
     ret[i] = 0;
 
-    return( ret );
+    return ret;
   }
-  
 
+
   FT_CALLBACK_DEF( FT_UInt32 * )
   tt_cmap14_variant_chars( TT_CMap    cmap,
                            FT_Memory  memory,
@@ -2782,13 +2820,14 @@
       return NULL;
 
     if ( defOff == 0 )
-      return tt_cmap14_get_nondef_chars( cmap->data + nondefOff, memory );
+      return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, memory );
     else if ( nondefOff == 0 )
-      return tt_cmap14_get_def_chars( cmap->data + defOff, memory );
+      return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, memory );
     else
     {
       /* Both a default and a non-default glyph set?  That's probably not */
       /* good font design, but the spec allows for it...                  */
+      TT_CMap14  cmap14 = (TT_CMap14) cmap;
       FT_UInt32  numRanges;
       FT_UInt32  numMappings;
       FT_UInt32  duni;
@@ -2796,7 +2835,6 @@
       FT_UInt32  nuni;
       FT_Byte*   dp;
       FT_UInt    di, ni, k;
-      FT_Error   error;
 
 
       p  = cmap->data + nondefOff;
@@ -2807,14 +2845,14 @@
       numRanges   = TT_NEXT_ULONG( dp );
 
       if ( numMappings == 0 )
-        return tt_cmap14_get_def_chars( cmap->data + defOff, memory );
+        return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, memory );
       if ( dcnt == 0 )
-        return tt_cmap14_get_nondef_chars( cmap->data + nondefOff, memory );
+        return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, memory );
 
-      if ( FT_ALLOC( ret,
-           ( dcnt + numMappings + 1 ) * sizeof ( FT_UInt32 ) ) )
+      if ( tt_cmap14_ensure( cmap14, (dcnt + numMappings + 1), memory ) )
         return NULL;
 
+      ret  = cmap14->results;
       duni = TT_NEXT_UINT24( dp );
       dcnt = FT_NEXT_BYTE( dp );
       di   = 1;
@@ -2832,13 +2870,11 @@
 
           ++di;
 
-          if ( di <= numRanges )
-          {
-            duni = TT_NEXT_UINT24( dp );
-            dcnt = FT_NEXT_BYTE( dp );
-          }
-          else
+          if ( di > numRanges )
             break;
+
+          duni = TT_NEXT_UINT24( dp );
+          dcnt = FT_NEXT_BYTE( dp );
         }
         else
         {
@@ -2847,13 +2883,11 @@
           /* If it is within the default range then ignore it -- */
           /* that should not have happened                       */
           ++ni;
-          if ( ni <= numMappings )
-          {
-            nuni = TT_NEXT_UINT24( p );
-            p += 2;
-          }
-          else
+          if ( ni > numMappings )
             break;
+
+          nuni = TT_NEXT_UINT24( p );
+          p += 2;
         }
       }
 
@@ -2903,7 +2937,7 @@
       sizeof ( TT_CMap14Rec ),
 
       (FT_CMap_InitFunc)     tt_cmap14_init,
-      (FT_CMap_DoneFunc)     NULL,
+      (FT_CMap_DoneFunc)     tt_cmap14_done,
       (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
       (FT_CMap_CharNextFunc) tt_cmap14_char_next,
       /* Format 14 extension functions */