--- freetype2-2.2.0-rc3/src/psaux/psobjs.c	2006-01-16 23:35:33.000000000 +0100
+++ freetype2-2.2.0-rc3/src/psaux/psobjs.c	2006-02-28 16:18:31.000000000 +0100
@@ -325,7 +325,11 @@
     while ( cur < limit )
     {
       if ( *cur == '\\' )
+      {
         cur++;
+        if ( cur == limit )
+          break; /* XXX this is an error */
+      }
       else if ( *cur == '(' )
         embed++;
       else if ( *cur == ')' )
@@ -340,18 +344,21 @@
       cur++;
     }
 
+    if ( embed != 0 )
+      ; /* XXX this is an error */
+
     *acur = cur;
   }
 
 
   /* first character must be `<' */
 
-  static void
-  skip_string( PS_Parser  parser )
+  static FT_Error
+  skip_string( FT_Byte* *acur,
+               FT_Byte*  limit )
   {
-    FT_Byte*  cur   = parser->cursor;
-    FT_Byte*  limit = parser->limit;
-
+    FT_Byte*  cur   = *acur;
+    FT_Error  err   = PSaux_Err_Ok;
 
     while ( ++cur < limit )
     {
@@ -367,12 +374,71 @@
     if ( cur < limit && *cur != '>' )
     {
       FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
-      parser->error = PSaux_Err_Invalid_File_Format;
+      err = PSaux_Err_Invalid_File_Format;
     }
     else
       cur++;
 
-    parser->cursor = cur;
+    *acur = cur;
+    return err;
+  }
+
+
+  /* first character must be `{'                    */
+
+  /* NB: [ and ] need not match:                    */
+  /* "/foo {[} def" is a valid PostScript fragment, */
+  /* even within a Type1 font                       */
+
+  static FT_Error
+  skip_procedure( FT_Byte*  *acur,
+                  FT_Byte*   limit )
+  {
+    FT_Byte*  cur;
+    FT_Int    embed = 0;
+    FT_Error  err = PSaux_Err_Ok;
+
+
+    for ( cur = *acur; cur < limit; ++cur )
+    {
+      switch ( *cur )
+      {
+        case '{':
+          ++embed;
+          break;
+
+        case '}':
+          --embed;
+          if ( embed == 0 )
+          {
+            ++cur;
+            goto end;
+          }
+          break;
+
+        case '(':
+          /* err = */ skip_literal_string( &cur, limit );
+          break;
+
+        case '<':
+          err = skip_string( &cur, limit );
+          if ( err != PSaux_Err_Ok )
+            goto end;
+          break;
+
+        case '%':
+          skip_comment( &cur, limit );
+          break;
+      }
+    }
+
+  end:
+    if ( embed != 0 )
+      ; /* XXX this is an error */
+	
+    *acur = cur;
+
+   return err;
   }
 
 
@@ -400,13 +466,19 @@
       goto Exit;
 
     /* self-delimiting, single-character tokens */
-    if ( *cur == '[' || *cur == ']' ||
-         *cur == '{' || *cur == '}' )
+    if ( *cur == '[' || *cur == ']' /*||
+         *cur == '{' || *cur == '}' */)
     {
       cur++;
       goto Exit;
     }
 
+    if ( *cur == '{' )                              /* {...} */
+    {
+      skip_procedure( &cur, limit );
+      goto Exit;
+    }
+
     if ( *cur == '(' )                              /* (...) */
     {
       skip_literal_string( &cur, limit );
@@ -415,6 +487,8 @@
 
     if ( *cur == '<' )                              /* <...> */
     {
+      FT_Error err;
+
       if ( cur + 1 < limit && *(cur + 1) == '<' )   /* << */
       {
         cur++;
@@ -422,7 +496,10 @@
         goto Exit;
       }
       parser->cursor = cur;
-      skip_string( parser );
+      err = skip_string( &parser->cursor, parser->limit );
+
+      if ( err != PSaux_Err_Ok )
+        parser->error = err;
       return;
     }
 
@@ -504,15 +581,18 @@
       token->type  = T1_TOKEN_TYPE_STRING;
       token->start = cur;
       skip_literal_string( &cur, limit );
-      if ( cur < limit )
+      if ( cur <= limit )
         token->limit = cur;
       break;
 
       /************* check for programs/array *****************/
     case '{':
-      token->type = T1_TOKEN_TYPE_ARRAY;
-      ender = '}';
-      goto Lookup_Ender;
+      token->type  = T1_TOKEN_TYPE_ARRAY;
+      token->start = cur;
+      skip_procedure( &cur, limit );
+      if ( cur <= limit )
+        token->limit = cur;
+      break;
 
       /************* check for table/array ********************/
     case '[':
@@ -520,7 +600,7 @@
       ender = ']';
       /* fall through */
 
-    Lookup_Ender:
+   /* Lookup_Ender: */
       embed        = 1;
       starter      = *cur;
       token->start = cur++;
@@ -532,6 +612,8 @@
 
       while ( cur < limit && !parser->error )
       {
+        /* XXX this is wrong because it does not */
+        /* skip comments and procedures          */
         if ( *cur == starter )
           embed++;
         else if ( *cur == ender )
@@ -607,7 +689,7 @@
         if ( !token.type )
           break;
 
-        if ( cur < limit )
+        if ( tokens != NULL && cur < limit )
           *cur = token;
 
         cur++;
@@ -654,22 +736,25 @@
     /* now, read the coordinates */
     while ( cur < limit )
     {
+      FT_Short dummy;
+
       /* skip whitespace in front of data */
       skip_spaces( &cur, limit );
       if ( cur >= limit )
         goto Exit;
 
-      if ( count >= max_coords )
+      if ( coords != NULL && count >= max_coords )
         break;
 
-      if ( c == ender )
+      if ( *cur == ender )
       {
         cur++;
         break;
       }
 
-      coords[count] =
-        (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
+      *( coords != NULL ? &coords[count] : &dummy )
+        = (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
+
       count++;
 
       if ( !ender )
@@ -716,21 +801,25 @@
     /* now, read the values */
     while ( cur < limit )
     {
+      FT_Fixed dummy;
+
       /* skip whitespace in front of data */
       skip_spaces( &cur, limit );
       if ( cur >= limit )
         goto Exit;
 
-      if ( count >= max_values )
+      if ( values != NULL && count >= max_values )
         break;
 
-      if ( c == ender )
+      if ( *cur == ender )
       {
         cur++;
         break;
       }
 
-      values[count] = PS_Conv_ToFixed( &cur, limit, power_ten );
+      *(values != NULL ? &values[count] : &dummy)
+        = PS_Conv_ToFixed( &cur, limit, power_ten );
+
       count++;
 
       if ( !ender )
@@ -1038,11 +1127,10 @@
     T1_FieldRec  fieldrec = *(T1_Field)field;
 
 
-#if 1
     fieldrec.type = T1_FIELD_TYPE_INTEGER;
-    if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY )
-      fieldrec.type = T1_FIELD_TYPE_FIXED;
-#endif
+    if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
+         field->type == T1_FIELD_TYPE_BBOX )
+        fieldrec.type = T1_FIELD_TYPE_FIXED;
 
     ps_parser_to_token_array( parser, elements,
                               T1_MAX_TABLE_ELEMENTS, &num_elements );
@@ -1057,9 +1145,12 @@
     old_cursor = parser->cursor;
     old_limit  = parser->limit;
 
-    /* we store the elements count */
-    *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
-      (FT_Byte)num_elements;
+    /* we store the elements count if necessary */
+    if ( field->type != T1_FIELD_TYPE_BBOX )
+    {
+      *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
+          (FT_Byte)num_elements;
+    }
 
     /* we now load each element, adjusting the field.offset on each one */
     token = elements;
@@ -1294,6 +1385,8 @@
     builder->advance.x      = 0;
     builder->advance.y      = 0;
 
+    builder->shift          = TRUE;
+
     builder->funcs = t1_builder_funcs;
   }
 
@@ -1349,6 +1442,7 @@
 
       if ( builder->shift )
       {
+        /* XXX this throws away the extra precision */
         x >>= 16;
         y >>= 16;
       }
--- freetype2-2.2.0-rc3/src/psaux/t1decode.c	2005-02-10 09:18:27.000000000 +0100
+++ freetype2-2.2.0-rc3/src/psaux/t1decode.c	2006-02-28 16:53:30.000000000 +0100
@@ -323,6 +323,8 @@
     FT_Byte*         limit;
     T1_Builder       builder = &decoder->builder;
     FT_Pos           x, y, orig_x, orig_y;
+    FT_Int           known_othersubr_result_cnt   = 0;
+    FT_Int           unknown_othersubr_result_cnt = 0;
 
     T1_Hints_Funcs   hinter;
 
@@ -357,14 +359,19 @@
     if ( hinter )
       hinter->open( hinter->hints );
 
+    FT_TRACE4(( "\nStart charstring\n" ));
+
     /* now, execute loop */
     while ( ip < limit )
     {
-      FT_Long*     top   = decoder->top;
+      FT_Fixed*    top   = decoder->top;
       T1_Operator  op    = op_none;
-      FT_Long      value = 0;
+      FT_Fixed     value = 0;
 
+      FT_ASSERT( known_othersubr_result_cnt == 0
+                 || unknown_othersubr_result_cnt == 0 );
 
+      FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
       /*********************************************************************/
       /*                                                                   */
       /* Decode operator or operand                                        */
@@ -415,7 +422,7 @@
 
       case 15:          /* undocumented, obsolete operator */
         op = op_none;
-        break;
+        continue;
 
       case 21:
         op = op_rmoveto;
@@ -520,6 +527,23 @@
         }
       }
 
+      if ( unknown_othersubr_result_cnt > 0 )
+      {
+        switch ( op )
+        {
+        case op_callsubr:
+        case op_return:
+        case op_none:
+        case op_pop:
+          break;
+
+        default:
+          /* all operands have been transferred by previous pops */
+          unknown_othersubr_result_cnt = 0;
+          break;
+        }
+      }
+
       /*********************************************************************/
       /*                                                                   */
       /*  Push value on stack, or process operator                         */
@@ -535,21 +559,49 @@
 
         FT_TRACE4(( " %ld", value ));
 
-        *top++       = value;
+        /* Shifting is only correct when using two's complement notation, */
+        /* and for negative values only if the shift is arithmetic (not   */
+        /* logical), but if everyone else is doing it, why can't I ?      */
+        *top++       = value << 16; /* XXX handle overflow */
         decoder->top = top;
       }
       else if ( op == op_callothersubr )  /* callothersubr */
       {
+        int subr_no;
+        int arg_cnt;
+
         FT_TRACE4(( " callothersubr" ));
 
         if ( top - decoder->stack < 2 )
           goto Stack_Underflow;
 
         top -= 2;
-        switch ( (FT_Int)top[1] )
+
+        subr_no = top[1] >> 16;
+        arg_cnt = top[0] >> 16;
+
+        if ( arg_cnt > top - decoder->stack )
+          goto Stack_Underflow;
+
+        /***********************************************************/
+        /*                                                         */
+        /* remove all operands to callsubr from the stack          */
+        /*                                                         */
+        /* for handled othersubrs we will increase the stack       */
+        /* by the value of known_othersubr_result_cnt              */
+        /*                                                         */
+        /* for unhandled othersubrs the following pops will adjust */
+        /* the stack pointer as necessary                          */
+
+        top -= arg_cnt;
+
+        known_othersubr_result_cnt   = 0;
+        unknown_othersubr_result_cnt = 0;
+
+        switch ( subr_no )
         {
         case 1:                     /* start flex feature */
-          if ( top[0] != 0 )
+          if ( arg_cnt != 0 )
             goto Unexpected_OtherSubr;
 
           decoder->flex_state        = 1;
@@ -564,7 +616,7 @@
             FT_Int  idx;
 
 
-            if ( top[0] != 0 )
+            if ( arg_cnt != 0 )
               goto Unexpected_OtherSubr;
 
             /* note that we should not add a point for index 0; */
@@ -580,7 +632,7 @@
           break;
 
         case 0:                     /* end flex feature */
-          if ( top[0] != 3 )
+          if ( arg_cnt != 3 )
             goto Unexpected_OtherSubr;
 
           if ( decoder->flex_state       == 0 ||
@@ -591,40 +643,15 @@
             goto Syntax_Error;
           }
 
-          /* now consume the remaining `pop pop setcurpoint' */
-          if ( ip + 6 > limit ||
-               ip[0] != 12 || ip[1] != 17 || /* pop */
-               ip[2] != 12 || ip[3] != 17 || /* pop */
-               ip[4] != 12 || ip[5] != 33 )  /* setcurpoint */
-          {
-            FT_ERROR(( "t1_decoder_parse_charstrings: "
-                       "invalid flex charstring\n" ));
-            goto Syntax_Error;
-          }
-
-          ip += 6;
-          decoder->flex_state = 0;
+          /* the two `results' are popped by the following setcurrentpoint */
+          known_othersubr_result_cnt = 2;
           break;
 
         case 3:                     /* change hints */
-          if ( top[0] != 1 )
+          if ( arg_cnt != 1 )
             goto Unexpected_OtherSubr;
 
-          /* eat the following `pop' */
-          if ( ip + 2 > limit )
-          {
-            FT_ERROR(( "t1_decoder_parse_charstrings: "
-                       "invalid escape (12+%d)\n", ip[-1] ));
-            goto Syntax_Error;
-          }
-
-          if ( ip[0] != 12 || ip[1] != 17 )
-          {
-            FT_ERROR(( "t1_decoder_parse_charstrings: " ));
-            FT_ERROR(( "`pop' expected, found (%d %d)\n", ip[0], ip[1] ));
-            goto Syntax_Error;
-          }
-          ip += 2;
+          known_othersubr_result_cnt = 1;
 
           if ( hinter )
             hinter->reset( hinter->hints, builder->current->n_points );
@@ -656,18 +683,14 @@
               goto Syntax_Error;
             }
 
-            num_points = (FT_UInt)top[1] - 13 + ( top[1] == 18 );
-            if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
+            num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
+            if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
             {
               FT_ERROR(( "t1_decoder_parse_charstrings: " ));
               FT_ERROR(( "incorrect number of mm arguments\n" ));
               goto Syntax_Error;
             }
 
-            top -= blend->num_designs * num_points;
-            if ( top < decoder->stack )
-              goto Stack_Underflow;
-
             /* we want to compute:                                   */
             /*                                                       */
             /*  a0*w0 + a1*w1 + ... + ak*wk                          */
@@ -695,16 +718,169 @@
 
               *values++ = tmp;
             }
-            /* note that `top' will be incremented later by calls to `pop' */
+
+            known_othersubr_result_cnt = num_points;
             break;
           }
 
+        case 19:
+          /* <idx> 1 19 callothersubr                        */
+          /* => replace elements starting from index [<idx>] */
+          /*    of BuildCharArray with WeightVector          */
+          {
+            FT_Int    idx;
+            PS_Blend  blend = decoder->blend;
+
+            if ( arg_cnt != 1 )
+              goto Unexpected_OtherSubr;
+
+            idx = top[0] >> 16;
+
+            if ( idx < 0 || idx + blend->num_designs > blend->len_buildchar )
+              goto Unexpected_OtherSubr;
+
+            memcpy( &blend->buildchar[idx],
+                    blend->weight_vector,
+                    blend->num_designs * sizeof( blend->weight_vector[ 0 ] ) );
+          }
+          break;
+
+        case 20:
+          /* <arg1> <arg2> 2 20 callothersubr pop   */
+          /* ==> push <arg1> + <arg2> onto T1 stack */
+          if ( arg_cnt != 2 )
+            goto Unexpected_OtherSubr;
+
+          top[0] += top[1]; /* XXX (over|under)flow */
+
+          known_othersubr_result_cnt = 1;
+          break;
+
+        case 21:
+          /* <arg1> <arg2> 2 21 callothersubr pop   */
+          /* ==> push <arg1> - <arg2> onto T1 stack */
+          if ( arg_cnt != 2 )
+            goto Unexpected_OtherSubr;
+
+          top[0] -= top[1]; /* XXX (over|under)flow */
+
+          known_othersubr_result_cnt = 1;
+          break;
+
+        case 22:
+          /* <arg1> <arg2> 2 22 callothersubr pop   */
+          /* ==> push <arg1> * <arg2> onto T1 stack */
+          if ( arg_cnt != 2 )
+            goto Unexpected_OtherSubr;
+
+          top[0] *= top[1]; /* XXX (over|under)flow */
+
+          known_othersubr_result_cnt = 1;
+          break;
+
+        case 23:
+          /* <arg1> <arg2> 2 23 callothersubr pop   */
+          /* ==> push <arg1> / <arg2> onto T1 stack */
+          if ( arg_cnt != 2 || top[1] == 0 )
+            goto Unexpected_OtherSubr;
+
+          top[0] = FT_DivFix( top[0], top[1] ); /* XXX (over|under)flow */
+
+          known_othersubr_result_cnt = 1;
+          break;
+
+        case 24:
+          /* <val> <idx> 2 24 callothersubr                  */
+          /* => put <val> at index [<idx>] of BuildCharArray */
+          {
+            FT_Int    idx;
+            PS_Blend  blend = decoder->blend;
+
+            if ( arg_cnt != 2 )
+              goto Unexpected_OtherSubr;
+
+            idx = top[1] >> 16;
+
+            if ( idx < 0 || (FT_UInt) idx >= blend->len_buildchar )
+              goto Unexpected_OtherSubr;
+
+            blend->buildchar[idx] = top[0];
+          }
+          break;
+
+        case 25:
+          /* <idx> 1 25 callothersubr pop                      */
+          /* => put element at index [<idx>] of BuildCharArray */
+          /*    onto T1 stack                                  */
+          {
+            FT_Int    idx;
+            PS_Blend  blend = decoder->blend;
+
+            if ( arg_cnt != 1 )
+              goto Unexpected_OtherSubr;
+
+            idx = top[0] >> 16;
+
+            if ( idx < 0 || (FT_UInt) idx >= blend->len_buildchar )
+              goto Unexpected_OtherSubr;
+
+            top[0] = blend->buildchar[idx];
+          }
+
+          known_othersubr_result_cnt = 1;
+          break;
+
+#if 0
+        case 26:
+          /* <idx> <val1> <val2> 3 26 callothersubr                     */
+          /* => if <val1> is a mark: BuildCharArray[ [<idx>] ] = <val2> */
+          /*    otherwise:           BuildCharArray[ [<idx>] ] = <val1> */
+          XXX how can we push a mark onto the stack ???;
+          break;
+#endif
+
+        case 27:
+          /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
+          /* ==> push <res1> onto T1 stack if <val1> <= <val2>,  */
+          /*     otherwise push <res2>                          */
+          if ( arg_cnt != 4 )
+            goto Unexpected_OtherSubr;
+
+          if ( top[2] > top[3] )
+            top[0] = top[1];
+
+          known_othersubr_result_cnt = 1;
+          break;
+
+        case 28:
+          /* 0 28 callothersubr pop                               */
+          /* => push random value from interval [0, 1) onto stack */
+          if ( arg_cnt != 0 )
+            goto Unexpected_OtherSubr;
+
+          /* hahaha, random (but not worse what the type2 decoder does) */
+          top[0] = (FT_UInt16) ( (unsigned long) ip
+                                 ^ (unsigned long) limit
+                                 ^ (unsigned long) top
+                                 ^ (unsigned long) &top );
+          known_othersubr_result_cnt = 1;
+          break;
+
         default:
+          FT_ERROR(( "t1_decoder_parse_charstrings: "
+                     "unknown othersubr [%d %d], wish me luck!\n",
+                     arg_cnt, subr_no ));
+          unknown_othersubr_result_cnt = arg_cnt;
+          break;
+
         Unexpected_OtherSubr:
           FT_ERROR(( "t1_decoder_parse_charstrings: "
-                     "invalid othersubr [%d %d]!\n", top[0], top[1] ));
+                     "invalid othersubr [%d %d]!\n",
+                     arg_cnt, subr_no ));
           goto Syntax_Error;
         }
+
+        top += known_othersubr_result_cnt;
         decoder->top = top;
       }
       else  /* general operator */
@@ -712,9 +888,35 @@
         FT_Int  num_args = t1_args_count[op];
 
 
+        FT_ASSERT( num_args >= 0 );
+
         if ( top - decoder->stack < num_args )
           goto Stack_Underflow;
 
+        /* XXX Operators usually take their operands from the        */
+        /*     bottom of the stack, i.e., the operands are           */
+        /*     decoder->stack[0], ..., decoder->stack[num_args - 1]; */
+        /*     only div, callsubr, and callothersubr are different.  */
+        /*     In practice it doesn't matter (?).                    */
+#ifdef FT_DEBUG_LEVEL_TRACE
+        switch ( op )
+        {
+        case op_callsubr:
+        case op_div:
+        case op_callothersubr:
+        case op_pop:
+        case op_return:
+          break;
+
+        default:
+          if ( top - decoder->stack != num_args )
+            FT_TRACE0(( "\nMore operands on the stack than expected "
+                        "(have %d, expected %d)\n",
+                        top - decoder->stack, num_args ));
+            break;
+        }
+#endif
+
         top -= num_args;
 
         switch ( op )
@@ -750,7 +952,7 @@
           builder->parse_state = T1_Parse_Have_Width;
 
           builder->left_bearing.x += top[0];
-          builder->advance.x       = top[1];
+          builder->advance.x       = top[1] >> 16;
           builder->advance.y       = 0;
 
           orig_x = builder->last.x = x = builder->pos_x + top[0];
@@ -769,7 +971,7 @@
         case op_seac:
           /* return immediately after the processing */
           return t1operator_seac( decoder, top[0], top[1], top[2],
-                                           (FT_Int)top[3], (FT_Int)top[4] );
+                                           top[3] >> 16, top[4] >> 16 );
 
         case op_sbw:
           FT_TRACE4(( " sbw" ));
@@ -778,8 +980,8 @@
 
           builder->left_bearing.x += top[0];
           builder->left_bearing.y += top[1];
-          builder->advance.x       = top[2];
-          builder->advance.y       = top[3];
+          builder->advance.x       = top[2] >> 16;
+          builder->advance.y       = top[3] >> 16;
 
           builder->last.x = x = builder->pos_x + top[0];
           builder->last.y = y = builder->pos_y + top[1];
@@ -928,7 +1130,7 @@
 
           if ( top[1] )
           {
-            *top = top[0] / top[1];
+            *top = FT_DivFix( top[0], top[1] );
             ++top;
           }
           else
@@ -945,11 +1147,11 @@
 
             FT_TRACE4(( " callsubr" ));
 
-            idx = (FT_Int)top[0];
+            idx = (FT_Int)(top[0] >> 16);
             if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
             {
               FT_ERROR(( "t1_decoder_parse_charstrings: "
-                         "invalid subrs index\n" ));
+                         "invalid subrs index %d\n", idx ));
               goto Syntax_Error;
             }
 
@@ -997,8 +1199,22 @@
         case op_pop:
           FT_TRACE4(( " pop" ));
 
-          /* theoretically, the arguments are already on the stack */
-          top++;
+          if ( known_othersubr_result_cnt > 0 )
+          {
+            --known_othersubr_result_cnt;
+            /* ignore, we pushed the operands ourselves */
+            break;
+          }
+
+          if ( unknown_othersubr_result_cnt == 0 )
+          {
+              FT_ERROR(( "t1_decoder_parse_charstrings: "
+                         "no more operands for othersubr!\n" ));
+              goto Syntax_Error;
+          }
+
+          --unknown_othersubr_result_cnt;
+          top++; /* `push' the operand to callothersubr onto the stack */
           break;
 
         case op_return:
@@ -1073,9 +1289,20 @@
         case op_setcurrentpoint:
           FT_TRACE4(( " setcurrentpoint" ));
 
-          FT_ERROR(( "t1_decoder_parse_charstrings: " ));
-          FT_ERROR(( "unexpected `setcurrentpoint'\n" ));
-          goto Syntax_Error;
+          /* <q>The setcurrentpoint command is used only in                */
+          /* conjunction with results from OtherSubrs procedures.</q>      */
+
+          /* known_othersubr_result_cnt != 0 is already handled above      */
+          if ( decoder->flex_state != 1 )
+          {
+            FT_ERROR(( "t1_decoder_parse_charstrings: " ));
+            FT_ERROR(( "unexpected `setcurrentpoint'\n" ));
+
+            goto Syntax_Error;
+          }
+          else
+            decoder->flex_state = 0;
+          break;
 
         default:
           FT_ERROR(( "t1_decoder_parse_charstrings: "
@@ -1083,6 +1310,10 @@
           goto Syntax_Error;
         }
 
+        /* XXX Operators usually clear the operand stack;  */
+        /*     only div, callsubr, callothersubr, pop, and */
+        /*     return are different.                       */
+        /*     In practice it doesn't matter (?).          */
         decoder->top = top;
 
       } /* general operator processing */
--- freetype2-2.2.0-rc3/src/type1/t1load.c	2006-02-15 07:05:52.000000000 +0100
+++ freetype2-2.2.0-rc3/src/type1/t1load.c	2006-02-28 16:08:57.000000000 +0100
@@ -168,6 +168,13 @@
         blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
     }
 
+    /* blend->blend_bitflags = ???; */
+    blend->len_buildchar = 0;
+    blend->buildchar     = NULL;
+
+    blend->ndv_idx = -1;
+    blend->cdv_idx = -1;
+
   Exit:
     return error;
 
@@ -364,6 +371,8 @@
   }
 
 
+  /* XXX why doesn't this function recompute face->type1->font_bbox, */
+  /* face->type1->private->(blue_values|standard_width|...) ???      */
   FT_LOCAL_DEF( FT_Error )
   T1_Set_MM_Blend( T1_Face    face,
                    FT_UInt    num_coords,
@@ -877,6 +886,47 @@
   }
 
 
+  static void
+  parse_blend( T1_Face    face,
+               T1_Loader  loader )
+  {
+    loader->blend_encountered = 1;
+  }
+
+
+  static void
+  parse_buildchar( T1_Face    face,
+                   T1_Loader  loader )
+  {
+    /* XXX wish I had a better solution */
+    FT_Byte*   old_cursor = loader->parser.root.cursor;
+    FT_Memory  memory     = face->root.memory;
+    FT_Error   error      = T1_Err_Ok;
+
+    if ( face->blend == NULL )
+    {
+      FT_ERROR(( "parse_buildchar: have not allocated blend\n" ));
+      return;
+    }
+
+    face->blend->len_buildchar = T1_ToFixedArray( &loader->parser, 0, NULL, 0 );
+
+    if ( FT_NEW_ARRAY( face->blend->buildchar, face->blend->len_buildchar ) )
+      /* nothing we can do about it here; will fail later */
+      face->blend->len_buildchar = 0;
+    else
+    {
+      loader->parser.root.cursor = old_cursor;
+
+      T1_ToFixedArray( &loader->parser,
+                       face->blend->len_buildchar,
+                       face->blend->buildchar,
+                       0 );
+    }
+
+    return;
+  }
+
 #endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
 
 
@@ -915,39 +965,51 @@
     switch ( field->location )
     {
     case T1_FIELD_LOCATION_FONT_INFO:
-      dummy_object = &face->type1.font_info;
-      objects      = &dummy_object;
-      max_objects  = 0;
-
-      if ( blend )
+      if ( loader->blend_encountered )
       {
         objects     = (void**)blend->font_infos;
         max_objects = blend->num_designs;
       }
+      else
+      {
+        dummy_object = &face->type1.font_info;
+        objects      = &dummy_object;
+        max_objects  = 0;
+      }
       break;
 
     case T1_FIELD_LOCATION_PRIVATE:
-      dummy_object = &face->type1.private_dict;
-      objects      = &dummy_object;
-      max_objects  = 0;
-
-      if ( blend )
+      if ( loader->blend_encountered )
       {
         objects     = (void**)blend->privates;
         max_objects = blend->num_designs;
       }
+      else
+      {
+        dummy_object = &face->type1.private_dict;
+        objects      = &dummy_object;
+        max_objects  = 0;
+      }
       break;
 
     case T1_FIELD_LOCATION_BBOX:
-      dummy_object = &face->type1.font_bbox;
-      objects      = &dummy_object;
-      max_objects  = 0;
-
-      if ( blend )
+      if ( loader->blend_encountered )
       {
         objects     = (void**)blend->bboxes;
         max_objects = blend->num_designs;
       }
+      else
+      {
+        dummy_object = &face->type1.font_bbox;
+        objects      = &dummy_object;
+        max_objects  = 0;
+      }
+      break;
+
+    case T1_FIELD_LOCATION_BLEND:
+      dummy_object = face->blend;
+      objects      = &dummy_object;
+      max_objects  = 0;
       break;
 
     default:
@@ -957,7 +1019,8 @@
     }
 
     if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
-         field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
+         field->type == T1_FIELD_TYPE_FIXED_ARRAY   ||
+         ( field->type == T1_FIELD_TYPE_BBOX && loader->blend_encountered ) )
       error = T1_Load_Field_Table( &loader->parser, field,
                                    objects, max_objects, 0 );
     else
@@ -1028,8 +1091,8 @@
     FT_Matrix*  matrix = &face->type1.font_matrix;
     FT_Vector*  offset = &face->type1.font_offset;
     FT_Face     root   = (FT_Face)&face->root;
-    FT_Fixed    temp[6];
-    FT_Fixed    temp_scale;
+    FT_Fixed    temp[6];        /* 16.16 */
+    FT_Fixed    temp_scale;     /* 16.16 */
 
 
     (void)T1_ToFixedArray( parser, 6, temp, 3 );
@@ -1662,6 +1725,14 @@
   }
 
 
+  static void
+  parse_private( T1_Face    face,
+                 T1_Loader  loader )
+  {
+    loader->private_encountered = 1;
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* Define the token field static variables.  This is a set of            */
@@ -1681,12 +1752,15 @@
     T1_FIELD_CALLBACK( "Encoding", parse_encoding )
     T1_FIELD_CALLBACK( "Subrs", parse_subrs )
     T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
+    T1_FIELD_CALLBACK( "Private", parse_private )
 
 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
     T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
     T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
     T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
     T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
+    T1_FIELD_CALLBACK( "Blend", parse_blend )
+    T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar )
 #endif
 
     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
@@ -1701,8 +1775,7 @@
   parse_dict( T1_Face    face,
               T1_Loader  loader,
               FT_Byte*   base,
-              FT_Long    size,
-              FT_Byte*   keyword_flags )
+              FT_Long    size )
   {
     T1_Parser  parser = &loader->parser;
     FT_Byte   *limit, *start_binary = NULL;
@@ -1724,55 +1797,25 @@
 
       cur = parser->root.cursor;
 
-      /* look for `FontDirectory' which causes problems for some fonts */
-      if ( *cur == 'F' && cur + 25 < limit                    &&
-           ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
-      {
-        FT_Byte*  cur2;
-
-
-        /* skip the `FontDirectory' keyword */
-        T1_Skip_PS_Token( parser );
-        T1_Skip_Spaces  ( parser );
-        cur = cur2 = parser->root.cursor;
-
-        /* look up the `known' keyword */
-        while ( cur < limit )
-        {
-          if ( *cur == 'k' && cur + 5 < limit            &&
-               ft_strncmp( (char*)cur, "known", 5 ) == 0 )
-            break;
-
-          T1_Skip_PS_Token( parser );
-          if ( parser->root.error )
-            goto Exit;
-          T1_Skip_Spaces( parser );
-          cur = parser->root.cursor;
-        }
-
-        if ( cur < limit )
-        {
-          T1_TokenRec  token;
-
+      /* look for `eexec' */
+      /* XXX cur[5] must be a token delimiter */
+      if ( *cur == 'e' && cur + 5 < limit &&
+           ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
+        break;
 
-          /* skip the `known' keyword and the token following it */
-          T1_Skip_PS_Token( parser );
-          T1_ToToken( parser, &token );
+      /* look for `FontDirectory' */
+      /* XXX cur[13] must be a token delimiter */
+      else if ( cur + sizeof( "FontDirectory" ) - 1 < limit
+                && ft_strncmp( (char*)cur, "FontDirectory", sizeof( "FontDirectory") - 1 ) == 0 )
+      {
+          if ( loader->private_encountered )
+               loader->fontdir_after_private = 1;
 
-          /* if the last token was an array, skip it! */
-          if ( token.type == T1_TOKEN_TYPE_ARRAY )
-            cur2 = parser->root.cursor;
-        }
-        parser->root.cursor = cur2;
-        have_integer = 0;
+          parser->root.cursor += sizeof( "FontDirectory" ) - 1;
       }
 
-      /* look for `eexec' */
-      else if ( *cur == 'e' && cur + 5 < limit &&
-                ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
-        break;
-
       /* look for `closefile' which ends the eexec section */
+      /* XXX cur[9] must be a token delimiter */
       else if ( *cur == 'c' && cur + 9 < limit &&
                 ft_strncmp( (char*)cur, "closefile", 9 ) == 0 )
         break;
@@ -1834,8 +1877,7 @@
         if ( len > 0 && len < 22 && parser->root.cursor < limit )
         {
           /* now compare the immediate name to the keyword table */
-          T1_Field  keyword      = (T1_Field)t1_keywords;
-          FT_Byte*  keyword_flag = keyword_flags;
+          T1_Field  keyword = (T1_Field)t1_keywords;
 
 
           for (;;)
@@ -1852,20 +1894,22 @@
                  ft_memcmp( cur, name, len ) == 0                   )
             {
               /* We found it -- run the parsing callback! */
-              /* We only record the first instance of any */
-              /* field to deal adequately with synthetic  */
-              /* fonts; /Subrs and /CharStrings are       */
-              /* handled specially.                       */
-              if ( keyword_flag[0] == 0                               ||
-                   ft_strcmp( (const char*)name, "Subrs" ) == 0       ||
-                   ft_strcmp( (const char*)name, "CharStrings" ) == 0 )
+              /* We record every instance of every field  */
+              /* (until we reach the base font of a       */
+              /* synthetic font) to deal adequately with  */
+              /* multiple master fonts; this is also      */
+              /* necessary because later PostScript       */
+              /* definitions override earlier ones        */
+
+              /* XXX does this work for hybrid fonts ?    */
+
+              if ( ! loader->fontdir_after_private
+                   || ft_strcmp((const char*)name, "CharStrings") == 0 )
               {
                 parser->root.error = t1_load_keyword( face,
                                                       loader,
                                                       keyword );
-                if ( parser->root.error == T1_Err_Ok )
-                  keyword_flag[0] = 1;
-                else
+                if ( parser->root.error != T1_Err_Ok )
                 {
                   if ( FT_ERROR_BASE( parser->root.error ) == FT_Err_Ignore )
                     parser->root.error = T1_Err_Ok;
@@ -1877,7 +1921,6 @@
             }
 
             keyword++;
-            keyword_flag++;
           }
         }
 
@@ -1910,12 +1953,16 @@
     loader->num_chars  = 0;
 
     /* initialize the tables -- simply set their `init' field to 0 */
-    loader->encoding_table.init = 0;
-    loader->charstrings.init    = 0;
-    loader->glyph_names.init    = 0;
-    loader->subrs.init          = 0;
-    loader->swap_table.init     = 0;
-    loader->fontdata            = 0;
+    loader->encoding_table.init    = 0;
+    loader->charstrings.init       = 0;
+    loader->glyph_names.init       = 0;
+    loader->subrs.init             = 0;
+    loader->swap_table.init        = 0;
+    loader->fontdata               = 0;
+    loader->private_encountered    = 0;
+    loader->blend_encountered      = 0;
+    loader->fontdir_after_private  = 0;
+
   }
 
 
@@ -1945,7 +1992,6 @@
     T1_Font        type1 = &face->type1;
     PS_Private     priv  = &type1->private_dict;
     FT_Error       error;
-    FT_Byte        keyword_flags[T1_FIELD_COUNT];
 
     PSAux_Service  psaux = (PSAux_Service)face->psaux;
 
@@ -1967,16 +2013,7 @@
     if ( error )
       goto Exit;
 
-    {
-      FT_UInt  n;
-      
-
-      for ( n = 0; n < T1_FIELD_COUNT; n++ )
-        keyword_flags[n] = 0;
-    }
-
-    error = parse_dict( face, &loader, parser->base_dict, parser->base_len,
-                        keyword_flags );
+    error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
     if ( error )
       goto Exit;
 
@@ -1985,8 +2022,7 @@
       goto Exit;
 
     error = parse_dict( face, &loader, parser->private_dict,
-                        parser->private_len,
-                        keyword_flags );
+                        parser->private_len );
     if ( error )
       goto Exit;
 
--- freetype2-2.2.0-rc3/src/type1/t1load.h	2004-04-25 22:15:11.000000000 +0200
+++ freetype2-2.2.0-rc3/src/type1/t1load.h	2006-02-27 19:33:54.000000000 +0100
@@ -47,7 +47,9 @@
     FT_Int        num_subrs;
     PS_TableRec   subrs;
     FT_Bool       fontdata;
-
+    FT_Bool       private_encountered;
+    FT_Bool       blend_encountered;
+    FT_Bool       fontdir_after_private;
   } T1_LoaderRec, *T1_Loader;
 
 
--- freetype2-2.2.0-rc3/include/freetype/t1tables.h	2004-11-12 08:02:45.000000000 +0100
+++ freetype2-2.2.0-rc3/include/freetype/t1tables.h	2006-02-28 15:35:53.000000000 +0100
@@ -250,10 +250,15 @@
     PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
     PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
 
-    FT_ULong         blend_bitflags;
+    FT_ULong         blend_bitflags; /* unused */
 
     FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
 
+    FT_UInt          len_buildchar;
+    FT_Fixed*        buildchar;
+
+    FT_Int           ndv_idx;
+    FT_Int           cdv_idx;
   } PS_BlendRec, *PS_Blend;
 
 
--- freetype2-2.2.0-rc3/include/freetype/internal/psaux.h	2006-02-17 09:07:09.000000000 +0100
+++ freetype2-2.2.0-rc3/include/freetype/internal/psaux.h	2006-02-28 15:11:51.000000000 +0100
@@ -199,6 +199,9 @@
     T1_FIELD_LOCATION_FONT_INFO,
     T1_FIELD_LOCATION_PRIVATE,
     T1_FIELD_LOCATION_BBOX,
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+    T1_FIELD_LOCATION_BLEND,
+#endif
 
     /* do not remove */
     T1_FIELD_LOCATION_MAX
@@ -653,8 +656,11 @@
   {
     T1_BuilderRec        builder;
 
-    FT_Long              stack[T1_MAX_CHARSTRINGS_OPERANDS];
-    FT_Long*             top;
+
+    /* operators need not be integers, */
+    /* e.g., 9 2 div hlineto           */
+    FT_Fixed             stack[T1_MAX_CHARSTRINGS_OPERANDS];
+    FT_Fixed*            top;
 
     T1_Decoder_ZoneRec   zones[T1_MAX_SUBRS_CALLS + 1];
     T1_Decoder_Zone      zone;
--- freetype2-2.2.0-rc3/include/freetype/internal/t1types.h	2006-02-28 13:27:52.000000000 +0100
+++ freetype2-2.2.0-rc3/include/freetype/internal/t1types.h	2006-02-28 13:28:42.000000000 +0100
@@ -111,9 +111,9 @@
 
     FT_Byte          paint_type;
     FT_Byte          font_type;
-    FT_Matrix        font_matrix;
-    FT_Vector        font_offset;
-    FT_BBox          font_bbox;
+    FT_Matrix        font_matrix;       /* 16.16   */
+    FT_Vector        font_offset;       /* 16.16 ? */
+    FT_BBox          font_bbox;         /* 16.16   */
     FT_Long          font_id;
 
     FT_Fixed         stroke_width;
