shithub: freetype+ttf2subf

Download patch

ref: 22ad9ef0248f4f45e32e2d7c489a73cbec588460
parent: 43ebad42076190ea2328a05186268a6ffd75d0a1
author: Werner Lemberg <[email protected]>
date: Mon May 9 18:11:36 EDT 2005

Handle unsorted SFNT type 4 cmaps correctly (reported by Dirck
Blaskey).

* src/sfnt/ttcmap.h (TT_CMap): Add member `unsorted'.
* src/sfnt/ttcmac.c: Use SFNT_Err_Ok where appropriate.

(tt_cmap0_validate, tt_cmap2_validate, tt_cmap6_validate,
tt_cmap8_validate, tt_cmap10_validate, tt_cmap12_validate): Use
`FT_Error' as return type.
(tt_cmap4_validate): Use `FT_Error' as return type.
Return error code for unsorted cmap.
(tt_cmap4_char_index, tt_cmap4_char_next): Use old code for unsorted
cmaps.
(tt_face_build_cmaps): Set `unsorted' variable in cmap.


Minor formatting.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
 2005-05-07  Werner Lemberg  <[email protected]>
 
+	Handle unsorted SFNT type 4 cmaps correctly (reported by Dirck
+	Blaskey).
+
+	* src/sfnt/ttcmap.h (TT_CMap): Add member `unsorted'.
+	* src/sfnt/ttcmac.c: Use SFNT_Err_Ok where appropriate.
+
+	(tt_cmap0_validate, tt_cmap2_validate, tt_cmap6_validate,
+	tt_cmap8_validate, tt_cmap10_validate, tt_cmap12_validate): Use
+	`FT_Error' as return type.
+	(tt_cmap4_validate): Use `FT_Error' as return type.
+	Return error code for unsorted cmap.
+	(tt_cmap4_char_index, tt_cmap4_char_next): Use old code for unsorted
+	cmaps.
+	(tt_face_build_cmaps): Set `unsorted' variable in cmap.
+
+2005-05-07  Werner Lemberg  <[email protected]>
+
 	* src/truetype/ttpload.c (tt_face_get_location): Fix typo.
 
 2005-05-06  Werner Lemberg  <[email protected]>
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -688,7 +688,7 @@
           {
             /* we are just leaving an edge; record a new segment! */
             segment->last = point;
-            segment->pos  = (FT_Short)(( min_pos + max_pos ) >> 1);
+            segment->pos  = (FT_Short)( ( min_pos + max_pos ) >> 1 );
 
             /* a segment is round if either its first or last point */
             /* is a control point                                   */
@@ -705,8 +705,8 @@
             if ( v > max_pos )
               max_pos = v;
 
-            segment->min_coord = (FT_Short) min_pos;
-            segment->max_coord = (FT_Short) max_pos;
+            segment->min_coord = (FT_Short)min_pos;
+            segment->max_coord = (FT_Short)max_pos;
 
             on_edge = 0;
             segment = NULL;
@@ -732,7 +732,7 @@
           if ( error )
             goto Exit;
 
-          segment->dir      = (FT_Char) segment_dir;
+          segment->dir      = (FT_Char)segment_dir;
           segment->flags    = AF_EDGE_NORMAL;
           min_pos = max_pos = point->u;
           segment->first    = point;
@@ -1150,10 +1150,10 @@
         edge->dir = AF_DIR_NONE;
 
         if ( ups > downs )
-          edge->dir = (FT_Char) up_dir;
+          edge->dir = (FT_Char)up_dir;
 
         else if ( ups < downs )
-          edge->dir = (FT_Char) -up_dir;
+          edge->dir = (FT_Char)-up_dir;
 
         else if ( ups == downs )
           edge->dir = 0;  /* both up and down! */
@@ -1232,7 +1232,7 @@
         /* zone, check for left edges                                      */
         /*                                                                 */
         /* of course, that's for TrueType                                  */
-        is_top_blue  = (FT_Byte)(( blue->flags & AF_LATIN_BLUE_TOP ) != 0);
+        is_top_blue  = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
         is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
 
         /* if it is a top zone, the edge must be against the major    */
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (body).                                        */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004 by                                          */
+/*  Copyright 2002, 2003, 2004, 2005 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -1425,7 +1425,7 @@
             dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END;
           else
           {
-            FT_Byte  ttag = (FT_Byte)(dst_tag[0] & FT_STROKE_TAG_BEGIN_END);
+            FT_Byte  ttag = (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
 
 
             /* switch begin/end tags if necessary */
--- a/src/bdf/bdfdrivr.c
+++ b/src/bdf/bdfdrivr.c
@@ -2,7 +2,7 @@
 
     FreeType font driver for bdf files
 
-    Copyright (C) 2001, 2002, 2003, 2004 by
+    Copyright (C) 2001, 2002, 2003, 2004, 2005 by
     Francesco Zappa Nardelli
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
--- a/src/cache/ftcbasic.c
+++ b/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType basic cache interface (body).                           */
 /*                                                                         */
-/*  Copyright 2003, 2004 by                                                */
+/*  Copyright 2003, 2004, 2005 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -38,8 +38,8 @@
 
   } FTC_BasicAttrRec, *FTC_BasicAttrs;
 
-#define FTC_BASIC_ATTR_COMPARE( a, b )                           \
-          FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) &&  \
+#define FTC_BASIC_ATTR_COMPARE( a, b )                                 \
+          FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
                    (a)->load_flags == (b)->load_flags               )
 
 #define FTC_BASIC_ATTR_HASH( a )                                   \
--- a/src/cache/ftccmap.c
+++ b/src/cache/ftccmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType CharMap cache (body)                                        */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2004 by                               */
+/*  Copyright 2000-2001, 2002, 2003, 2004, 2005 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
--- a/src/cache/ftcmanag.c
+++ b/src/cache/ftcmanag.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Cache Manager (body).                                       */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2004 by                               */
+/*  Copyright 2000-2001, 2002, 2003, 2004, 2005 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -164,7 +164,7 @@
     FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
 
 
-    return FT_BOOL(node->scaler.face_id == face_id);
+    return FT_BOOL( node->scaler.face_id == face_id );
   }
 
 
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType and CFF data/program tables loader (body).                  */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004 by                               */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
--- a/src/cid/cidload.c
+++ b/src/cid/cidload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CID-keyed Type1 font loader (body).                                  */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004 by                               */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -536,11 +536,11 @@
       }
 
       if ( ft_isdigit( *p ) )
-        val = (FT_Byte)(*p - '0');
+        val = (FT_Byte)( *p - '0' );
       else if ( *p >= 'a' && *p <= 'f' )
-        val = (FT_Byte)(*p - 'a');
+        val = (FT_Byte)( *p - 'a' );
       else if ( *p >= 'A' && *p <= 'F' )
-        val = (FT_Byte)(*p - 'A' + 10);
+        val = (FT_Byte)( *p - 'A' + 10 );
       else if ( *p == ' '  ||
                 *p == '\t' ||
                 *p == '\r' ||
@@ -563,14 +563,14 @@
       }
 
       if ( upper_nibble )
-        *d = (FT_Byte)(val << 4);
+        *d = (FT_Byte)( val << 4 );
       else
       {
-        *d = (FT_Byte)(*d + val);
+        *d = (FT_Byte)( *d + val );
         d++;
       }
 
-      upper_nibble = (FT_Byte)(1 - upper_nibble);
+      upper_nibble = (FT_Byte)( 1 - upper_nibble );
 
       if ( done )
         break;
--- a/src/lzw/zopen.c
+++ b/src/lzw/zopen.c
@@ -35,7 +35,7 @@
 
 /*-
  *
- * Copyright (c) 2004
+ * Copyright (c) 2004, 2005
  *	Albert Chin-A-Young.
  *
  * Modified to work with FreeType's PCF driver.
@@ -276,8 +276,8 @@
 
 		/* Generate the new entry. */
 		if ((code = free_ent) < maxmaxcode) {
-			tab_prefixof(code) = (unsigned short) oldcode;
-			tab_suffixof(code) = (unsigned char)  finchar;
+			tab_prefixof(code) = (unsigned short)oldcode;
+			tab_suffixof(code) = (unsigned char)finchar;
 			free_ent = code + 1;
 		}
 
--- a/src/otvalid/otvgdef.c
+++ b/src/otvalid/otvgdef.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType GDEF table validation (body).                               */
 /*                                                                         */
-/*  Copyright 2004 by                                                      */
+/*  Copyright 2004, 2005 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -208,7 +208,7 @@
             case TT_MS_ID_SYMBOL_CS:
             case TT_MS_ID_UNICODE_CS:
             case TT_MS_ID_UCS_4:
-              is_english = FT_BOOL(( rec->languageID & 0x3FF ) == 0x009);
+              is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
               found_win  = n;
               break;
 
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -53,7 +53,7 @@
                 FT_Byte*  table )
   {
     cmap->data = table;
-    return 0;
+    return SFNT_Err_Ok;
   }
 
 
@@ -81,7 +81,7 @@
 
 #ifdef TT_CONFIG_CMAP_FORMAT_0
 
-  FT_CALLBACK_DEF( void )
+  FT_CALLBACK_DEF( FT_Error )
   tt_cmap0_validate( FT_Byte*      table,
                      FT_Validator  valid )
   {
@@ -106,6 +106,8 @@
           FT_INVALID_GLYPH_ID;
       }
     }
+
+    return SFNT_Err_Ok;
   }
 
 
@@ -266,7 +268,7 @@
 
 #ifdef TT_CONFIG_CMAP_FORMAT_2
 
-  FT_CALLBACK_DEF( void )
+  FT_CALLBACK_DEF( FT_Error )
   tt_cmap2_validate( FT_Byte*      table,
                      FT_Validator  valid )
   {
@@ -355,6 +357,8 @@
         }
       }
     }
+
+    return SFNT_Err_Ok;
   }
 
 
@@ -625,7 +629,7 @@
 
 #ifdef OPT_CMAP4
 
-  typedef struct TT_CMap4Rec_
+  typedef struct  TT_CMap4Rec_
   {
     TT_CMapRec  cmap;
     FT_UInt32   old_charcode;   /* old charcode */
@@ -650,7 +654,7 @@
     FT_Byte*  p;
 
 
-    cmap->cmap.data = table;
+    cmap->cmap.data    = table;
 
     p                  = table + 2;
     cmap->table_length = FT_PEEK_USHORT( p );
@@ -662,7 +666,7 @@
     cmap->cur_charcode = 0;
     cmap->cur_gindex   = 0;
 
-    return 0;
+    return SFNT_Err_Ok;
   }
 
 
@@ -792,7 +796,7 @@
 
 
 
-  FT_CALLBACK_DEF( void )
+  FT_CALLBACK_DEF( FT_Error )
   tt_cmap4_validate( FT_Byte*      table,
                      FT_Validator  valid )
   {
@@ -800,6 +804,7 @@
     FT_UInt   length = TT_NEXT_USHORT( p );
     FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
     FT_UInt   num_segs;
+    FT_Error  error = SFNT_Err_Ok;
 
 
     /* in certain fonts, the `length' field is invalid and goes */
@@ -894,10 +899,12 @@
         /* unfortunately, some popular Asian fonts present overlapping */
         /* ranges in their charmaps                                    */
         /*                                                             */
-        if ( valid->level >= FT_VALIDATE_TIGHT )
+        if ( n > 0 && start <= last )
         {
-          if ( n > 0 && start <= last )
+          if ( valid->level >= FT_VALIDATE_TIGHT )
             FT_INVALID_DATA;
+          else
+            error = SFNT_Err_Invalid_CharMap_Format;
         }
 
         if ( offset && offset != 0xFFFFU )
@@ -951,6 +958,8 @@
         last = end;
       }
     }
+
+    return error;
   }
 
 
@@ -972,11 +981,11 @@
       p         = table + 6;
       num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );  /* be paranoid! */
 
-#if 1
-      /* Some fonts have more than 170 segments in their charmaps! */
-      /* We changed this function to use a more efficient binary   */
-      /* search for improving performance                          */
+      if ( !cmap->unsorted )
       {
+        /* Some fonts have more than 170 segments in their charmaps! */
+        /* We changed this function to use a more efficient binary   */
+        /* search for improving performance                          */
         FT_UInt  min = 0;
         FT_UInt  max = num_segs2 >> 1;
         FT_UInt  mid, start, end, offset;
@@ -1021,9 +1030,7 @@
           }
         }
       }
-
-#else /* 0 - old code */
-
+      else
       {
         FT_UInt   n;
         FT_Byte*  q;
@@ -1066,9 +1073,6 @@
           }
         }
       }
-
-#endif /* 0 */
-
     }
 
   Exit:
@@ -1111,174 +1115,173 @@
 
     code      = (FT_UInt)char_code + 1;
     p         = table + 6;
-    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT(p), 2 );  /* ensure even-ness */
+    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* ensure even-ness */
 
-#if 1
-
-    for (;;)
+    if ( !cmap->unsorted )
     {
-      /* Some fonts have more than 170 segments in their charmaps! */
-      /* We changed this function to use a more efficient binary   */
-      /* search                                                    */
-      FT_UInt  offset;
-      FT_Int   delta;
-      FT_UInt  min = 0;
-      FT_UInt  max = num_segs2 >> 1;
-      FT_UInt  mid, start, end;
-      FT_UInt  hi;
+      for (;;)
+      {
+        /* Some fonts have more than 170 segments in their charmaps! */
+        /* We changed this function to use a more efficient binary   */
+        /* search                                                    */
+        FT_UInt  offset;
+        FT_Int   delta;
+        FT_UInt  min = 0;
+        FT_UInt  max = num_segs2 >> 1;
+        FT_UInt  mid, start, end;
+        FT_UInt  hi;
 
 
-      /* we begin by finding the segment which end is
-         closer to our code point */
-      hi = max + 1;
-      while ( min < max )
-      {
-        mid = ( min + max ) >> 1;
-        p   = table + 14 + mid * 2;
-        end = TT_PEEK_USHORT( p );
+        /* we begin by finding the segment which end is
+           closer to our code point */
+        hi = max + 1;
+        while ( min < max )
+        {
+          mid = ( min + max ) >> 1;
+          p   = table + 14 + mid * 2;
+          end = TT_PEEK_USHORT( p );
 
-        if ( end < code )
-          min = mid + 1;
-        else
+          if ( end < code )
+            min = mid + 1;
+          else
+          {
+            hi  = mid;
+            max = mid;
+          }
+        }
+
+        if ( hi > max )
         {
-          hi  = mid;
-          max = mid;
+          /* the point is behind the last segment;
+             we will exit right now */
+          goto Exit;
         }
-      }
 
-      if ( hi > max )
-      {
-        /* the point is behind the last segment;
-           we will exit right now */
-        goto Exit;
-      }
+        p   = table + 14 + hi * 2;
+        end = TT_PEEK_USHORT( p );
 
-      p   = table + 14 + hi * 2;
-      end = TT_PEEK_USHORT( p );
+        p    += 2 + num_segs2;
+        start = TT_PEEK_USHORT( p );
 
-      p    += 2 + num_segs2;
-      start = TT_PEEK_USHORT( p );
+        if ( code < start )
+          code = start;
 
-      if ( code < start )
-        code = start;
+        p    += num_segs2;
+        delta = TT_PEEK_USHORT( p );
 
-      p    += num_segs2;
-      delta = TT_PEEK_USHORT( p );
+        p     += num_segs2;
+        offset = TT_PEEK_USHORT( p );
 
-      p     += num_segs2;
-      offset = TT_PEEK_USHORT( p );
-
-      if ( offset != 0 && offset != 0xFFFFU )
-      {
-        /* parse the glyph ids array for non-zero index */
-        p += offset + ( code - start ) * 2;
-        while ( code <= end )
+        if ( offset != 0 && offset != 0xFFFFU )
         {
-          gindex = TT_NEXT_USHORT( p );
-          if ( gindex != 0 )
+          /* parse the glyph ids array for non-zero index */
+          p += offset + ( code - start ) * 2;
+          while ( code <= end )
           {
-            gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
+            gindex = TT_NEXT_USHORT( p );
             if ( gindex != 0 )
             {
-              result = code;
+              gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
+              if ( gindex != 0 )
+              {
+                result = code;
 #ifdef OPT_CMAP4
-              tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
+                tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
 #endif
-              goto Exit;
+                goto Exit;
+              }
             }
+            code++;
           }
-          code++;
         }
-      }
-      else if ( offset == 0xFFFFU )
-      {
-        /* an offset of 0xFFFF means an empty segment in certain fonts! */
-        code = end + 1;
-      }
-      else  /* offset == 0 */
-      {
-        gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
-        if ( gindex != 0 )
+        else if ( offset == 0xFFFFU )
         {
-          result = code;
+          /* an offset of 0xFFFF means an empty segment in certain fonts! */
+          code = end + 1;
+        }
+        else  /* offset == 0 */
+        {
+          gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
+          if ( gindex != 0 )
+          {
+            result = code;
 #ifdef OPT_CMAP4
-          tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
+            tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
 #endif
-          goto Exit;
+            goto Exit;
+          }
+          code++;
         }
-        code++;
       }
     }
-
-#else   /* old code -- kept for reference */
-
-    for ( ;; )
+    else
     {
-      FT_UInt   offset, n;
-      FT_Int    delta;
-      FT_Byte*  q;
-
-
-      p = table + 14;              /* ends table  */
-      q = table + 16 + num_segs2;  /* starts table */
-
-      for ( n = 0; n < num_segs2; n += 2 )
+      for ( ;; )
       {
-        FT_UInt  end   = TT_NEXT_USHORT( p );
-        FT_UInt  start = TT_NEXT_USHORT( q );
+        FT_UInt   offset, n;
+        FT_Int    delta;
+        FT_Byte*  q;
 
 
-        if ( code < start )
-          code = start;
+        p = table + 14;              /* ends table  */
+        q = table + 16 + num_segs2;  /* starts table */
 
-        if ( code <= end )
+        for ( n = 0; n < num_segs2; n += 2 )
         {
-          p = q + num_segs2 - 2;
-          delta = TT_PEEK_SHORT( p );
-          p += num_segs2;
-          offset = TT_PEEK_USHORT( p );
+          FT_UInt  end   = TT_NEXT_USHORT( p );
+          FT_UInt  start = TT_NEXT_USHORT( q );
 
-          if ( offset != 0 && offset != 0xFFFFU )
+
+          if ( code < start )
+            code = start;
+
+          if ( code <= end )
           {
-            /* parse the glyph ids array for non-0 index */
-            p += offset + ( code - start ) * 2;
-            while ( code <= end )
+            p = q + num_segs2 - 2;
+            delta = TT_PEEK_SHORT( p );
+            p += num_segs2;
+            offset = TT_PEEK_USHORT( p );
+
+            if ( offset != 0 && offset != 0xFFFFU )
             {
-              gindex = TT_NEXT_USHORT( p );
-              if ( gindex != 0 )
+              /* parse the glyph ids array for non-0 index */
+              p += offset + ( code - start ) * 2;
+              while ( code <= end )
               {
-                gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
+                gindex = TT_NEXT_USHORT( p );
                 if ( gindex != 0 )
-                  break;
+                {
+                  gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
+                  if ( gindex != 0 )
+                    break;
+                }
+                code++;
               }
-              code++;
             }
-          }
-          else if ( offset == 0xFFFFU )
-          {
-            /* an offset of 0xFFFF means an empty glyph in certain fonts! */
-            code = end;
-            break;
-          }
-          else
-            gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
+            else if ( offset == 0xFFFFU )
+            {
+              /* an offset of 0xFFFF means an empty glyph in certain fonts! */
+              code = end;
+              break;
+            }
+            else
+              gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
 
-          if ( gindex == 0 )
-            break;
+            if ( gindex == 0 )
+              break;
 
-          result = code;
-          goto Exit;
+            result = code;
+            goto Exit;
+          }
         }
-      }
-      /* loop to next trial charcode */
-      if ( code >= 0xFFFFU )
-        break;
+        /* loop to next trial charcode */
+        if ( code >= 0xFFFFU )
+          break;
 
-      code++;
+        code++;
+      }
     }
 
-#endif /* !1 */
-
   Exit:
     *pchar_code = result;
     return gindex;
@@ -1349,7 +1352,7 @@
 
 #ifdef TT_CONFIG_CMAP_FORMAT_6
 
-  FT_CALLBACK_DEF( void )
+  FT_CALLBACK_DEF( FT_Error )
   tt_cmap6_validate( FT_Byte*      table,
                      FT_Validator  valid )
   {
@@ -1382,6 +1385,8 @@
           FT_INVALID_GLYPH_ID;
       }
     }
+
+    return SFNT_Err_Ok;
   }
 
 
@@ -1535,7 +1540,7 @@
 
 #ifdef TT_CONFIG_CMAP_FORMAT_8
 
-  FT_CALLBACK_DEF( void )
+  FT_CALLBACK_DEF( FT_Error )
   tt_cmap8_validate( FT_Byte*      table,
                      FT_Validator  valid )
   {
@@ -1624,6 +1629,8 @@
         last = end;
       }
     }
+
+    return SFNT_Err_Ok;
   }
 
 
@@ -1757,7 +1764,7 @@
 
 #ifdef TT_CONFIG_CMAP_FORMAT_10
 
-  FT_CALLBACK_DEF( void )
+  FT_CALLBACK_DEF( FT_Error )
   tt_cmap10_validate( FT_Byte*      table,
                       FT_Validator  valid )
   {
@@ -1788,6 +1795,8 @@
           FT_INVALID_GLYPH_ID;
       }
     }
+
+    return SFNT_Err_Ok;
   }
 
 
@@ -1907,7 +1916,7 @@
 
 #ifdef TT_CONFIG_CMAP_FORMAT_12
 
-  FT_CALLBACK_DEF( void )
+  FT_CALLBACK_DEF( FT_Error )
   tt_cmap12_validate( FT_Byte*      table,
                       FT_Validator  valid )
   {
@@ -1954,6 +1963,8 @@
         last = end;
       }
     }
+
+    return SFNT_Err_Ok;
   }
 
 
@@ -2149,6 +2160,7 @@
           if ( clazz->format == format )
           {
             volatile TT_ValidatorRec  valid;
+            FT_Error                  error = SFNT_Err_Ok;
 
 
             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
@@ -2159,11 +2171,19 @@
             if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 )
             {
               /* validate this cmap sub-table */
-              clazz->validate( cmap, FT_VALIDATOR( &valid ) );
+              error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
             }
 
             if ( valid.validator.error == 0 )
+            {
               (void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL );
+
+              /* it is simpler to directly set the `unsorted' flag instead */
+              /* of adding a parameter to FT_CMap_New                      */
+              ((TT_CMap)(face->root.charmaps
+                          [face->root.num_charmaps - 1]))->unsorted =
+                FT_BOOL( error );
+            }
             else
             {
               FT_ERROR(( "tt_face_build_cmaps:" ));
@@ -2175,7 +2195,7 @@
       }
     }
 
-    return 0;
+    return SFNT_Err_Ok;
   }
 
 
--- a/src/sfnt/ttcmap.h
+++ b/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType character mapping table (cmap) support (specification).     */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004 by                                          */
+/*  Copyright 2002, 2003, 2004, 2005 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -31,6 +31,7 @@
   {
     FT_CMapRec  cmap;
     FT_Byte*    data;           /* pointer to in-memory cmap table */
+    FT_Bool     unsorted;       /* for format 4 only               */
 
   } TT_CMapRec, *TT_CMap;
 
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -134,22 +134,22 @@
   }
 
 
- /* In theory, we should check the values of `search_range',               */
- /* `entry_selector', and `range_shift' to detect non-SFNT based files     */
- /* whose header might also start with 0x100000L (yes, these exist).       */
- /*                                                                        */
- /* Very unfortunately, many TrueType fonts don't have these fields        */
- /* set correctly and we must ignore them to support them.  An alternative */
- /* way to check the font file is thus to:                                 */
- /*                                                                        */
- /* - check that `num_tables' is valid                                     */
- /* - look for a "head" table, check its size, and parse it to             */
- /*   see if its "magic" field is correctly set                            */
- /*                                                                        */
- /* When checking directory entries, ignore the tables `glyx' and `locx'   */
- /* which are hacked-out versions of `glyf' and `loca' in some PostScript  */
- /* Type 42 fonts, and will generally be invalid.                          */
- /*                                                                        */
+  /* In theory, we should check the values of `search_range',              */
+  /* `entry_selector', and `range_shift' to detect non-SFNT based files    */
+  /* whose header might also start with 0x100000L (yes, these exist).      */
+  /*                                                                       */
+  /* Very unfortunately, many TrueType fonts don't have these fields       */
+  /* set correctly and we must ignore them to support them.  An            */
+  /* alternative way to check the font file is thus to:                    */
+  /*                                                                       */
+  /* - check that `num_tables' is valid                                    */
+  /* - look for a "head" table, check its size, and parse it to            */
+  /*   see if its "magic" field is correctly set                           */
+  /*                                                                       */
+  /* When checking directory entries, ignore the tables `glyx' and `locx'  */
+  /* which are hacked-out versions of `glyf' and `loca' in some PostScript */
+  /* Type 42 fonts, and will generally be invalid.                         */
+  /*                                                                       */
   static FT_Error
   sfnt_dir_check( FT_Stream  stream,
                   FT_ULong   offset,
@@ -239,7 +239,7 @@
       goto Bad_Format;
 
   Exit:
-    return  error;
+    return error;
 
   Bad_Format:
     error = SFNT_Err_Unknown_File_Format;
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType GX Font Variation loader                                    */
 /*                                                                         */
-/*  Copyright 2004 by                                                      */
+/*  Copyright 2004, 2005 by                                                */
 /*  David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.     */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -92,7 +92,7 @@
   /* indicates that there is a delta for every point without needing to    */
   /* enumerate all of them.                                                */
   /*                                                                       */
-#define ALL_POINTS  (FT_UShort*)(-1)
+#define ALL_POINTS  (FT_UShort*)( -1 )
 
 
   enum
@@ -1209,7 +1209,7 @@
       }
 
       apply = ft_var_apply_tuple( blend,
-                                  (FT_UShort) tupleIndex,
+                                  (FT_UShort)tupleIndex,
                                   tuple_coords,
                                   im_start_coords,
                                   im_end_coords );
@@ -1238,8 +1238,8 @@
       {
         /* this means that there are deltas for every entry in cvt */
         for ( j = 0; j < face->cvt_size; ++j )
-          face->cvt[j] = (FT_Short)( face->cvt[j] + FT_MulFix( deltas[j],
-                                                               apply ) );
+          face->cvt[j] = (FT_Short)( face->cvt[j] +
+                                     FT_MulFix( deltas[j], apply ) );
       }
 
       else
@@ -1404,7 +1404,7 @@
       }
 
       apply = ft_var_apply_tuple( blend,
-                                  (FT_UShort) tupleIndex,
+                                  (FT_UShort)tupleIndex,
                                   tuple_coords,
                                   im_start_coords,
                                   im_end_coords );