Common subdirectories: opentypeorig/.deps and opentype/.deps
Binary files opentypeorig/disasm.o and opentype/disasm.o differ
diff -u opentypeorig/ftxgsub.c opentype/ftxgsub.c
--- opentypeorig/ftxgsub.c	2004-07-27 22:58:10.000000000 +0600
+++ opentype/ftxgsub.c	2004-08-09 09:34:44.000000000 +0600
@@ -55,6 +55,11 @@
                                                     (glyph_index), (component), (ligID)  \
                                                   ) ) != TT_Err_Ok )
 
+/* Code for handling LookupType 8 */
+#define ADD_Glyph_ReverseOrder( buffer, glyph_index, component, ligID )             		 	 \
+          ( ( error = otl_buffer_add_output_glyph_reverse( (buffer),                             \
+                                                    (glyph_index), (component), (ligID)  \
+                                                  ) ) != TT_Err_Ok )
 
   static FT_Error  Do_Glyph_Lookup( TTO_GSUBHeader*   gsub,
                                     FT_UShort         lookup_index,
@@ -3638,6 +3643,373 @@
   }
 
 
+  /*New code: Routine for handling GSUB lookup 8 */
+  
+  static FT_Error  Load_ReverseChainContextSubst1(
+                     TTO_ReverseChainContextSubstFormat1*  rccsf1,
+                     FT_Stream                      stream )
+  {
+    FT_Error error;
+    FT_Memory memory = stream->memory;
+
+    FT_UShort                m, count;
+    /*FT_ULong               backtrack_offset, input_offset, lookahead_offset;*/
+
+    FT_UShort               nb = 0,  nl = 0;
+    FT_UShort               backtrack_count, lookahead_count;
+    FT_ULong                cur_offset, new_offset, base_offset;
+
+    TTO_Coverage*           b;
+    TTO_Coverage*           l;
+    FT_UShort*              sub;
+   
+    base_offset = FILE_Pos() - 2;
+
+    if ( ACCESS_Frame( 2L ) )
+      return error;
+
+    new_offset = GET_UShort() + base_offset;
+
+    FORGET_Frame();
+
+    cur_offset = FILE_Pos();
+     
+    if ( FILE_Seek( new_offset ) ||
+         ( error = Load_Coverage( &rccsf1->Coverage, stream ) ) != TT_Err_Ok )
+      return error;
+    (void)FILE_Seek( cur_offset );
+    
+    /* Input coverage loaded */
+    if ( ACCESS_Frame( 2L ) )
+      goto Fail5;
+   
+    
+    rccsf1->BacktrackGlyphCount = GET_UShort();
+    FORGET_Frame();
+
+    rccsf1->BacktrackCoverage = NULL;
+
+    backtrack_count = rccsf1->BacktrackGlyphCount;
+
+    if ( ALLOC_ARRAY( rccsf1->BacktrackCoverage, backtrack_count,
+                      TTO_Coverage ) )
+      return error;
+    
+    b = rccsf1->BacktrackCoverage;
+
+    for ( nb = 0; nb < backtrack_count; nb++ )
+    {
+      if ( ACCESS_Frame( 2L ) )
+        goto Fail4;
+
+      new_offset = GET_UShort() + base_offset;
+
+      FORGET_Frame();
+
+      cur_offset = FILE_Pos();
+      if ( FILE_Seek( new_offset ) ||
+           ( error = Load_Coverage( &b[nb], stream ) ) != TT_Err_Ok )
+        goto Fail4;
+      (void)FILE_Seek( cur_offset );
+    }
+
+    /* Backtrack coverage loaded */
+
+    if ( ACCESS_Frame( 2L ) )
+      goto Fail4;
+
+  
+    rccsf1->LookaheadGlyphCount = GET_UShort();
+    FORGET_Frame();
+
+    rccsf1->LookaheadCoverage = NULL;
+
+    lookahead_count = rccsf1->LookaheadGlyphCount;
+
+    if ( ALLOC_ARRAY( rccsf1->LookaheadCoverage, lookahead_count,
+                      TTO_Coverage ) )
+      goto Fail4;
+
+    l = rccsf1->LookaheadCoverage;
+  
+    for ( nl = 0; nl < lookahead_count; nl++ )
+    {
+      if ( ACCESS_Frame( 2L ) )
+        goto Fail2;
+
+      new_offset = GET_UShort() + base_offset;
+
+      FORGET_Frame();
+
+      cur_offset = FILE_Pos();
+      if ( FILE_Seek( new_offset ) ||
+           ( error = Load_Coverage( &l[nl], stream ) ) != TT_Err_Ok )
+        goto Fail2;
+      (void)FILE_Seek( cur_offset );
+    }
+   
+    if ( ACCESS_Frame( 2L ) )
+      goto Fail2;
+  
+    rccsf1->GlyphCount = GET_UShort();
+    FORGET_Frame();
+
+    rccsf1->Substitute = NULL;
+
+    count = rccsf1->GlyphCount;
+
+    if ( ALLOC_ARRAY( rccsf1->Substitute, count,
+                      FT_UShort ) )
+      goto Fail2;
+
+    sub = rccsf1->Substitute;
+
+    
+    if ( ACCESS_Frame( count * 2L ) )
+      goto Fail1;
+    
+    /* Loading Substitute */
+    int ncount = 0;
+    for(ncount = 0; ncount < count; ncount++)
+      sub[ncount] = GET_UShort();
+      
+      
+    FORGET_Frame();
+
+    return TT_Err_Ok;
+
+     Fail1:
+    FREE( sub );
+    
+  Fail2:
+    for ( m = 0; m < nl; m++ )
+      Free_Coverage( &l[m], memory );
+
+    FREE( l );
+
+ 
+
+  Fail4:
+    for ( m = 0; m < nb; m++ )
+      Free_Coverage( &b[m], memory );
+
+    FREE( b );
+    return error;
+
+ Fail5:
+    Free_Coverage( &rccsf1->Coverage, memory );
+    return error;
+
+
+  }
+  
+ static void  Free_ReverseChainContext1( TTO_ReverseChainContextSubstFormat1*  rccsf1,
+				   FT_Memory                      memory )
+  {
+
+    FT_UShort      n, count;
+
+    TTO_Coverage*  c;
+
+    /* Freeing LookaheadCoverage */
+    if ( rccsf1->LookaheadCoverage )
+    {
+      count = rccsf1->LookaheadGlyphCount;
+      c     = rccsf1->LookaheadCoverage;
+
+      for ( n = 0; n < count; n++ )
+        Free_Coverage( &c[n], memory );
+
+      FREE( c );
+    }
+
+    /* Freeing BacktrackCoverage */
+    if ( rccsf1->BacktrackCoverage )
+    {
+      count = rccsf1->BacktrackGlyphCount;
+      c     = rccsf1->BacktrackCoverage;
+
+      for ( n = 0; n < count; n++ )
+        Free_Coverage( &c[n], memory );
+
+      FREE( c );
+    }
+
+
+    /* Freeing InputCoverage */
+    Free_Coverage( &rccsf1->Coverage, memory );
+
+  }
+  
+  FT_Error  Load_ReverseChainContextSubst( TTO_ReverseChainContextSubst*  rccs,
+                                    FT_Stream               stream )
+  {
+
+    FT_Error error;
+
+
+    if ( ACCESS_Frame( 2L ) )
+      return error;
+    rccs->SubstFormat = GET_UShort();
+
+    FORGET_Frame();
+
+    switch ( rccs->SubstFormat )
+    {
+      case 1:
+	return Load_ReverseChainContextSubst1( &rccs->rccsf.rccsf1, stream );
+
+      default:
+	return TTO_Err_Invalid_GSUB_SubTable_Format;
+    }
+        return TT_Err_Ok;               /* never reached */
+  }
+
+  void  Free_ReverseChainContextSubst( TTO_ReverseChainContextSubst*  rccs,
+				FT_Memory               memory )
+  {
+    switch ( rccs->SubstFormat )
+    {
+
+    case 1:
+      Free_ReverseChainContext1( &rccs->rccsf.rccsf1, memory );
+      break;
+
+    }
+  }
+
+ static FT_Error  Lookup_ReverseChainContextSubst1(
+                     TTO_GSUBHeader*                gsub,
+                     TTO_ReverseChainContextSubstFormat1*  rccsf1,
+		     OTL_Buffer                     buffer,
+                     FT_UShort                      flags,
+                     FT_UShort                      context_length,
+                     int                            nesting_level )
+  {
+    FT_UShort        index,input_index, i, j, property, new_in_pos;
+    FT_UShort        bgc, lgc;
+    FT_Error         error;
+
+    TTO_Coverage*    bc;
+    TTO_Coverage*    lc;
+    TTO_GDEFHeader*  gdef;
+
+
+    gdef = gsub->gdef;
+
+    if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
+      return error;
+
+    bgc = rccsf1->BacktrackGlyphCount;
+    lgc = rccsf1->LookaheadGlyphCount;
+
+    if ( context_length != 0xFFFF && context_length < 1 )
+      return TTO_Err_Not_Covered;
+
+    /* check whether context is too long; it is a first guess only */
+    /*Reverse chaining goes from start to end. 
+      buffer->in_pos should be buffer->in_length - (buffer->in_pos+1)*/
+
+    new_in_pos =  buffer->in_length - ( buffer->in_pos + 1);
+
+    if ( bgc > new_in_pos || buffer->in_length - new_in_pos + lgc > buffer->in_length )
+      return TTO_Err_Not_Covered;
+
+    if ( bgc )
+    {
+      /* Since we don't know in advance the number of glyphs to inspect,
+         we search backwards for matches in the backtrack glyph array    */
+
+      bc       = rccsf1->BacktrackCoverage;
+
+      new_in_pos =  buffer->in_length - ( buffer->in_pos + 1);
+
+      /* For ChainingContextSubst we had 
+      for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )*/
+ 
+      for ( i = 0, j = new_in_pos - 1; i < bgc; i++, j-- )
+      {
+        while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
+        {
+          if ( error && error != TTO_Err_Not_Covered )
+            return error;
+
+	  if ( j + 1 == bgc - i )
+	    return TTO_Err_Not_Covered;
+	  j--;
+        }
+
+        error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
+        if ( error )
+          return error;
+      }
+    }
+
+    j = new_in_pos;
+
+    error = Coverage_Index( &rccsf1->Coverage, IN_GLYPH( j ), &input_index );
+      
+    if ( error )
+        return error;
+
+    /* we are starting for lookahead glyphs right after the last context
+       glyph                                                             */
+
+    j += 1;
+    if( j >= buffer->in_length )
+      return TTO_Err_Not_Covered;
+
+    lc       = rccsf1->LookaheadCoverage;
+
+    for ( i = 0; i < lgc; i++, j++ )
+    {
+      while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
+      {
+        if ( error && error != TTO_Err_Not_Covered )
+          return error;
+
+	if ( j + lgc - i == buffer->in_length )
+	  return TTO_Err_Not_Covered;
+	j++;
+      }
+
+      error = Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
+      if ( error )
+        return error;
+    }
+
+	FT_Short val;
+	    val =  rccsf1->Substitute[input_index];
+
+    if ( ADD_Glyph_ReverseOrder( buffer,val, 0xFFFF, 0xFFFF ) )
+      return error;
+     
+    /* ADD_String_ReverseOrder(buffer, 1, 1,val,0xFFFF,0xFFFF);
+       return 0;*/
+  }
+
+
+ static FT_Error  Lookup_ReverseChainContextSubst(
+                     TTO_GSUBHeader*         gsub,
+                     TTO_ReverseChainContextSubst*  rccs,
+		     OTL_Buffer              buffer,
+                     FT_UShort               flags,
+                     FT_UShort               context_length,
+                     int                     nesting_level )
+  {
+    switch ( rccs->SubstFormat )
+    {
+      case 1:
+	return Lookup_ReverseChainContextSubst1( gsub, &rccs->rccsf.rccsf1,buffer,
+                                        flags, context_length,
+                                        nesting_level );
+
+      default:
+	return TTO_Err_Invalid_GSUB_SubTable_Format;
+    }
+
+    return TT_Err_Ok;               /* never reached */
+  }
 
   /***********
    * GSUB API
@@ -3997,6 +4369,15 @@
                                           flags, context_length,
                                           nesting_level );
         break;
+
+	/*New code: for LookupType 8 */
+      case GSUB_LOOKUP_REVERSE_CHAIN:
+        error = Lookup_ReverseChainContextSubst( gsub,
+                                          &lo->SubTable[i].st.gsub.reverse,
+						 buffer,
+						 flags, context_length,
+						 nesting_level );
+	break;
       }
 
       /* Check whether we have a successful substitution or an error other
@@ -4016,6 +4397,9 @@
 				     OTL_Buffer        buffer )
   {
     FT_Error  error, retError = TTO_Err_Not_Covered;
+    
+    /* Used a mirror for buffer->in_pos in case of LookupType 8 */
+    FT_UShort new_in_pos;
 
     FT_UShort*  properties = gsub->LookupList.Properties;
 
@@ -4041,8 +4425,17 @@
         error = TTO_Err_Not_Covered;
 
       if ( error == TTO_Err_Not_Covered ) 
-        if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ), 0xFFFF, 0xFFFF ) )
-          return error;
+        {
+	  if(gsub->LookupList.Lookup[lookup_index].LookupType == GSUB_LOOKUP_REVERSE_CHAIN)
+	    {
+	      new_in_pos = buffer->in_length - (buffer->in_pos + 1);
+	      if ( ADD_Glyph_ReverseOrder( buffer,IN_GLYPH(new_in_pos), 0xFFFF, 0xFFFF ) )
+		return error;
+	    }
+	  else
+	    if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ), 0xFFFF, 0xFFFF ) )
+	      return error;
+	}
     }
 
     return retError;
Only in opentype: ftxgsub.c~
diff -u opentypeorig/ftxgsub.h opentype/ftxgsub.h
--- opentypeorig/ftxgsub.h	2004-02-29 20:44:50.000000000 +0500
+++ opentype/ftxgsub.h	2004-08-09 09:12:05.000000000 +0600
@@ -39,7 +39,8 @@
 #define GSUB_LOOKUP_CONTEXT    5
 #define GSUB_LOOKUP_CHAIN      6
 #define GSUB_LOOKUP_EXTENSION  7
-
+/* New code*/
+#define GSUB_LOOKUP_REVERSE_CHAIN 8
 
 /* Use this if a feature applies to all glyphs */
 
@@ -466,6 +467,45 @@
 
   typedef struct TTO_ChainContextSubst_  TTO_ChainContextSubst;
 
+  /* New Code for reverse chain GSUB lookup type 8 */
+
+  /* LookupType 8 */
+  struct TTO_ReverseChainContextSubstFormat1_
+  {
+    TTO_Coverage            Coverage;
+                                        /*coverage table for input glyphs*/
+    FT_UShort               BacktrackGlyphCount;
+                                        /* number of backtrack glyphs    */
+    TTO_Coverage*           BacktrackCoverage;
+                                        /* array of backtrack Coverage
+                                           tables                        */
+    FT_UShort               LookaheadGlyphCount;
+                                        /* number of lookahead glyphs    */
+    TTO_Coverage*           LookaheadCoverage;
+                                        /* array of lookahead coverage
+                                           tables                        */
+    FT_UShort               GlyphCount;
+                                        /* number of Glyph ID's          */
+    FT_UShort*              Substitute;
+                                        /* array of substitute Glyph ID  */
+  };
+
+  typedef struct TTO_ReverseChainContextSubstFormat1_  TTO_ReverseChainContextSubstFormat1;
+
+
+  struct  TTO_ReverseChainContextSubst_
+  {
+    FT_UShort  SubstFormat;             /* currently only 1 */
+    
+    union
+    {
+      TTO_ReverseChainContextSubstFormat1  rccsf1;
+      
+    } rccsf;
+  };
+  
+  typedef struct TTO_ReverseChainContextSubst_  TTO_ReverseChainContextSubst;
+  
 
   union  TTO_GSUB_SubTable_
   {
@@ -475,6 +515,9 @@
     TTO_LigatureSubst      ligature;
     TTO_ContextSubst       context;
     TTO_ChainContextSubst  chain;
+
+    /* Table Updated */
+    TTO_ReverseChainContextSubst  reverse;
   };
 
   typedef union TTO_GSUB_SubTable_  TTO_GSUB_SubTable;
Only in opentype: ftxgsub.h~
diff -u opentypeorig/ftxopen.c opentype/ftxopen.c
--- opentypeorig/ftxopen.c	2004-07-27 22:58:10.000000000 +0600
+++ opentype/ftxopen.c	2004-08-09 09:43:18.000000000 +0600
@@ -469,6 +469,10 @@
 
       case GSUB_LOOKUP_CHAIN:
         return Load_ChainContextSubst( &st->st.gsub.chain, stream );
+	
+	/* New entry for reverse chain */
+      case GSUB_LOOKUP_REVERSE_CHAIN:           
+        return Load_ReverseChainContextSubst( &st->st.gsub.reverse, stream );
 
       default:
         return TTO_Err_Invalid_GSUB_SubTable_Format;
@@ -536,6 +540,11 @@
         Free_ContextSubst( &st->st.gsub.context, memory );
         break;
 
+	/* New entry for reverse chain */      
+      case GSUB_LOOKUP_REVERSE_CHAIN:
+        Free_ReverseChainContextSubst( &st->st.gsub.reverse, memory );
+        break;
+
       case GSUB_LOOKUP_CHAIN:
         Free_ChainContextSubst( &st->st.gsub.chain, memory );
         break;
Only in opentype: ftxopen.c~
diff -u opentypeorig/ftxopenf.h opentype/ftxopenf.h
--- opentypeorig/ftxopenf.h	2002-03-15 11:46:05.000000000 +0500
+++ opentype/ftxopenf.h	2004-08-09 09:05:25.000000000 +0600
@@ -74,6 +74,9 @@
                                FT_Stream          input );
   FT_Error  Load_ChainContextSubst( TTO_ChainContextSubst*  ccs,
                                     FT_Stream               input );
+  /* New code: Load function for LookupType 8 */
+  FT_Error  Load_ReverseChainContextSubst( TTO_ReverseChainContextSubst*  rccs,
+					   FT_Stream               input );
 
   void  Free_SingleSubst( TTO_SingleSubst*  ss,
 			  FT_Memory         memory );
@@ -87,7 +90,9 @@
 			   FT_Memory         memory );
   void  Free_ChainContextSubst( TTO_ChainContextSubst*  ccs,
 				FT_Memory               memory );
-
+  /* New code: Free memory used for LookupType 8 */
+  void  Free_ReverseChainContextSubst( TTO_ReverseChainContextSubst*  rccs,
+				       FT_Memory               memory );
 
   /* functions from ftxgpos.c */
 
Only in opentype: ftxopenf.h~
Common subdirectories: opentypeorig/.libs and opentype/.libs
diff -u opentypeorig/otlbuffer.c opentype/otlbuffer.c
--- opentypeorig/otlbuffer.c	2004-06-22 00:03:56.000000000 +0600
+++ opentype/otlbuffer.c	2004-08-09 09:14:16.000000000 +0600
@@ -213,6 +213,52 @@
 					  &glyph_data, component, ligID );
   }
 
+
+  FT_Error
+  otl_buffer_add_output_glyph_reverse( OTL_Buffer buffer,
+			       FT_UInt    glyph_index,
+			       FT_UShort  component,
+			       FT_UShort  ligID )
+  {
+    FT_UShort glyph_data =  glyph_index;
+
+  
+    FT_Error  error;
+    FT_UShort new_in_pos, new_out_pos;
+    FT_UInt properties;
+    FT_UInt cluster;
+
+    new_in_pos = buffer->in_length - ( buffer->in_pos + 1 );
+    new_out_pos = new_in_pos;/* buffer->out_length - ( buffer->out_pos + 1 );*/
+    
+    error = otl_buffer_ensure( buffer, new_out_pos + 1 );
+    if ( error != FT_Err_Ok )
+      return error;
+
+    properties = buffer->in_string[new_in_pos].properties;
+    cluster = buffer->in_string[new_in_pos].cluster;
+    if ( component == 0xFFFF )
+      component = buffer->in_string[new_in_pos].component;
+    if ( ligID == 0xFFFF )
+      ligID = buffer->in_string[new_in_pos].ligID;
+
+  
+    OTL_GlyphItem item = &buffer->out_string[new_out_pos];
+    item->gindex = glyph_data;
+    item->properties = properties;
+    item->cluster = cluster;
+    item->component = component;
+    item->ligID = ligID;
+    buffer->in_string[new_in_pos].gindex = (FT_UShort)glyph_data;
+
+    buffer->in_pos  += 1;
+    buffer->out_pos += 1;
+
+    buffer->out_length = buffer->out_pos;
+
+    return FT_Err_Ok;
+  }
+
   FT_UShort
   otl_buffer_allocate_ligid( OTL_Buffer buffer )
   {
Only in opentype: otlbuffer.c~
diff -u opentypeorig/otlbuffer.h opentype/otlbuffer.h
--- opentypeorig/otlbuffer.h	2004-02-29 20:44:50.000000000 +0500
+++ opentype/otlbuffer.h	2004-08-09 09:13:03.000000000 +0600
@@ -91,6 +91,12 @@
 			        FT_UShort  component,
 			        FT_UShort  ligID );
 
+  FT_Error
+  otl_buffer_add_output_glyph_reverse ( OTL_Buffer buffer,
+			        FT_UInt    glyph_index,
+			        FT_UShort  component,
+			        FT_UShort  ligID );
+
   FT_UShort
   otl_buffer_allocate_ligid( OTL_Buffer buffer );
 
Only in opentype: otlbuffer.h~
Binary files opentypeorig/ottest and opentype/ottest differ
Binary files opentypeorig/ottest.o and opentype/ottest.o differ
