提交 a7e096c5 编写于 作者: O Owen Taylor 提交者: Owen Taylor

Rework opentype interfaces and other changes to make GPOS work for Arabic.

Sun Feb 29 09:25:13 2004  Owen Taylor  <otaylor@redhat.com>

        Rework opentype interfaces and other changes to make GPOS
        work for Arabic. (Most of #117282, #121060)

        * pango/opentype/otlbuffer.[ch]: OTL_Buffer that
        acts as a replacement for the separate GSUB and
        GPOS string structures and hides many of the internal
        details.

        * pango/opentype/ftxgsub.[ch] pango/opentype/ftxgpos.[ch]:
        Adapt to OTL_Buffer.

        * pango/opentype/ftxgpos.c: Redo handling of cursive
        chains so that it actually works.

        * pango/pango-ot.h pango/opentype/pango-ot-buffer.c:
        Pango wrapper around OTL_Buffer.

        * pango/pango-ot.h pango/pango-ot-ruleset.c pango/pango-ot-buffer.c:
        Split pango_ot_ruleset_shape() into pango_ot_ruleset_substitute(),
        pango_ot_ruleset_position(), make them act on
        PangoOTBuffer, add a separate pango_ot_buffer_output()
        which does the default positioning and writes to a
        PangoGlyphString.

        * modules/arabic/arabic-fc.c modules/indic/indic-fc.c
        modules/indic/mprefixups.[ch]: Adapt to new OpenType
        interfaces; add GPOS features for Arabic.

        * pango/opentype/pango-ot-info.c: Don't derive class information
        from Unicode properties for Arabic presentation forms,
        let the shaping process derive the properties.
上级 d670ddf9
...@@ -30,6 +30,9 @@ libpango_ot_la_SOURCES = \ ...@@ -30,6 +30,9 @@ libpango_ot_la_SOURCES = \
ftxgpos.h \ ftxgpos.h \
ftxgsub.c \ ftxgsub.c \
ftxgsub.h \ ftxgsub.h \
otlbuffer.c \
otlbuffer.h \
pango-ot-buffer.c \
pango-ot-info.c \ pango-ot-info.c \
pango-ot-private.h \ pango-ot-private.h \
pango-ot-ruleset.c pango-ot-ruleset.c
......
...@@ -761,7 +761,7 @@ ...@@ -761,7 +761,7 @@
if ( glyphID < gcrr[index].Start ) if ( glyphID < gcrr[index].Start )
{ {
array_index = 0; array_index = index;
if ( index == 0 ) if ( index == 0 )
glyph_index = glyphID; glyph_index = glyphID;
else else
...@@ -1129,7 +1129,7 @@ ...@@ -1129,7 +1129,7 @@
if ( glyphID < gcrr[index].Start ) if ( glyphID < gcrr[index].Start )
{ {
array_index = 0; array_index = index;
if ( index == 0 ) if ( index == 0 )
glyph_index = glyphID; glyph_index = glyphID;
else else
......
...@@ -42,8 +42,6 @@ ...@@ -42,8 +42,6 @@
FT_UShort load_flags; /* how the glyph should be loaded */ FT_UShort load_flags; /* how the glyph should be loaded */
FT_Bool r2l; FT_Bool r2l;
FT_UShort first; /* the first glyph in a chain of
cursive connections */
FT_UShort last; /* the last valid glyph -- used FT_UShort last; /* the last valid glyph -- used
with cursive positioning */ with cursive positioning */
FT_Pos anchor_x; /* the coordinates of the anchor point */ FT_Pos anchor_x; /* the coordinates of the anchor point */
...@@ -55,13 +53,19 @@ ...@@ -55,13 +53,19 @@
static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi, static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index, FT_UShort lookup_index,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ); int nesting_level );
/* the client application must replace this with something more #define IN_GLYPH( pos ) (buffer->in_string[(pos)].gindex)
#define IN_CURGLYPH( pos ) (buffer->in_string[(pos) + buffer->in_pos].gindex)
#define IN_PROPERTIES( pos ) (buffer->in_string[(pos)].properties)
#define IN_LIGID( pos ) (buffer->in_string[(pos)].ligID)
#define IN_COMPONENT( pos ) (buffer->in_string[(pos)].component)
#define POSITION( pos ) (&buffer->positions[(pos)])
/* the client application must replace this with something more
meaningful if multiple master fonts are to be supported. */ meaningful if multiple master fonts are to be supported. */
static FT_Error default_mmfunc( FT_Face face, static FT_Error default_mmfunc( FT_Face face,
...@@ -73,100 +77,6 @@ ...@@ -73,100 +77,6 @@
} }
#if 0
#define GPOS_ID Build_Extension_ID( 'G', 'P', 'O', 'S' )
/**********************
* Extension Functions
**********************/
static FT_Error GPOS_Create( void* ext,
FT_Stream stream )
{
FT_Error error;
FT_Memory memory = stream->memory;
TTO_GPOSHeader* gpos = (TTO_GPOSHeader*)ext;
FT_Long table;
/* by convention */
if ( !gpos )
return TT_Err_Ok;
/* a null offset indicates that there is no GPOS table */
gpos->offset = 0;
/* we store the start offset and the size of the subtable */
table = face->lookup_table ( face, TTAG_GPOS );
if ( table < 0 )
return TT_Err_Ok; /* The table is optional */
if ( FILE_Seek( face->dirTables[table].Offset ) ||
ACCESS_Frame( 4L ) )
return error;
gpos->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */
gpos->Version = GET_ULong();
FORGET_Frame();
/* a default mmfunc() handler which just returns an error */
gpos->mmfunc = default_mmfunc;
/* the default glyph function is TT_Load_Glyph() */
gpos->gfunc = FT_Load_Glyph;
gpos->loaded = FALSE;
return TT_Err_Ok;
}
static FT_Error GPOS_Destroy( void* ext,
PFace face )
{
TTO_GPOSHeader* gpos = (TTO_GPOSHeader*)ext;
/* by convention */
if ( !gpos )
return TT_Err_Ok;
if ( gpos->loaded )
{
Free_LookupList( &gpos->LookupList, GPOS );
Free_FeatureList( &gpos->FeatureList );
Free_ScriptList( &gpos->ScriptList );
}
return TT_Err_Ok;
}
EXPORT_FUNC
FT_Error TT_Init_GPOS_Extension( TT_Engine engine )
{
PEngine_Instance _engine = HANDLE_Engine( engine );
if ( !_engine )
return TT_Err_Invalid_Engine;
return TT_Register_Extension( _engine,
GPOS_ID,
sizeof ( TTO_GPOSHeader ),
GPOS_Create,
GPOS_Destroy );
}
#endif
EXPORT_FUNC EXPORT_FUNC
FT_Error TT_Load_GPOS_Table( FT_Face face, FT_Error TT_Load_GPOS_Table( FT_Face face,
TTO_GPOSHeader** retptr, TTO_GPOSHeader** retptr,
...@@ -584,7 +494,7 @@ ...@@ -584,7 +494,7 @@
static FT_Error Get_ValueRecord( GPOS_Instance* gpi, static FT_Error Get_ValueRecord( GPOS_Instance* gpi,
TTO_ValueRecord* vr, TTO_ValueRecord* vr,
FT_UShort format, FT_UShort format,
TTO_GPOS_Data* gd ) OTL_Position gd )
{ {
FT_Pos value; FT_Pos value;
FT_Short pixel_value; FT_Short pixel_value;
...@@ -1123,8 +1033,7 @@ ...@@ -1123,8 +1033,7 @@
static FT_Error Lookup_SinglePos( GPOS_Instance* gpi, static FT_Error Lookup_SinglePos( GPOS_Instance* gpi,
TTO_SinglePos* sp, TTO_SinglePos* sp,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length ) FT_UShort context_length )
{ {
...@@ -1136,10 +1045,10 @@ ...@@ -1136,10 +1045,10 @@
if ( context_length != 0xFFFF && context_length < 1 ) if ( context_length != 0xFFFF && context_length < 1 )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &sp->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &sp->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -1147,7 +1056,7 @@ ...@@ -1147,7 +1056,7 @@
{ {
case 1: case 1:
error = Get_ValueRecord( gpi, &sp->spf.spf1.Value, error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
sp->ValueFormat, &out[in->pos] ); sp->ValueFormat, POSITION( buffer->in_pos ) );
if ( error ) if ( error )
return error; return error;
break; break;
...@@ -1156,7 +1065,7 @@ ...@@ -1156,7 +1065,7 @@
if ( index >= sp->spf.spf2.ValueCount ) if ( index >= sp->spf.spf2.ValueCount )
return TTO_Err_Invalid_GPOS_SubTable; return TTO_Err_Invalid_GPOS_SubTable;
error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index], error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
sp->ValueFormat, &out[in->pos] ); sp->ValueFormat, POSITION( buffer->in_pos ) );
if ( error ) if ( error )
return error; return error;
break; break;
...@@ -1165,7 +1074,7 @@ ...@@ -1165,7 +1074,7 @@
return TTO_Err_Invalid_GPOS_SubTable; return TTO_Err_Invalid_GPOS_SubTable;
} }
(in->pos)++; (buffer->in_pos)++;
return TT_Err_Ok; return TT_Err_Ok;
} }
...@@ -1606,8 +1515,7 @@ ...@@ -1606,8 +1515,7 @@
static FT_Error Lookup_PairPos1( GPOS_Instance* gpi, static FT_Error Lookup_PairPos1( GPOS_Instance* gpi,
TTO_PairPosFormat1* ppf1, TTO_PairPosFormat1* ppf1,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort first_pos, FT_UShort first_pos,
FT_UShort index, FT_UShort index,
FT_UShort format1, FT_UShort format1,
...@@ -1626,7 +1534,7 @@ ...@@ -1626,7 +1534,7 @@
if ( !pvr ) if ( !pvr )
return TTO_Err_Invalid_GPOS_SubTable; return TTO_Err_Invalid_GPOS_SubTable;
glyph2 = in->string[in->pos]; glyph2 = IN_CURGLYPH( 0 );
for ( numpvr = ppf1->PairSet[index].PairValueCount; for ( numpvr = ppf1->PairSet[index].PairValueCount;
numpvr; numpvr;
...@@ -1635,11 +1543,11 @@ ...@@ -1635,11 +1543,11 @@
if ( glyph2 == pvr->SecondGlyph ) if ( glyph2 == pvr->SecondGlyph )
{ {
error = Get_ValueRecord( gpi, &pvr->Value1, format1, error = Get_ValueRecord( gpi, &pvr->Value1, format1,
&out[first_pos] ); POSITION( first_pos ) );
if ( error ) if ( error )
return error; return error;
return Get_ValueRecord( gpi, &pvr->Value2, format2, return Get_ValueRecord( gpi, &pvr->Value2, format2,
&out[in->pos] ); POSITION( buffer->in_pos ) );
} }
} }
...@@ -1649,8 +1557,7 @@ ...@@ -1649,8 +1557,7 @@
static FT_Error Lookup_PairPos2( GPOS_Instance* gpi, static FT_Error Lookup_PairPos2( GPOS_Instance* gpi,
TTO_PairPosFormat2* ppf2, TTO_PairPosFormat2* ppf2,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort first_pos, FT_UShort first_pos,
FT_UShort format1, FT_UShort format1,
FT_UShort format2 ) FT_UShort format2 )
...@@ -1662,11 +1569,11 @@ ...@@ -1662,11 +1569,11 @@
TTO_Class2Record* c2r; TTO_Class2Record* c2r;
error = Get_Class( &ppf2->ClassDef1, in->string[first_pos], error = Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
&cl1, NULL ); &cl1, NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
error = Get_Class( &ppf2->ClassDef2, in->string[in->pos], error = Get_Class( &ppf2->ClassDef2, IN_CURGLYPH( 0 ),
&cl2, NULL ); &cl2, NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
...@@ -1676,17 +1583,16 @@ ...@@ -1676,17 +1583,16 @@
return TTO_Err_Invalid_GPOS_SubTable; return TTO_Err_Invalid_GPOS_SubTable;
c2r = &c1r->Class2Record[cl2]; c2r = &c1r->Class2Record[cl2];
error = Get_ValueRecord( gpi, &c2r->Value1, format1, &out[first_pos] ); error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
if ( error ) if ( error )
return error; return error;
return Get_ValueRecord( gpi, &c2r->Value2, format2, &out[in->pos] ); return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
} }
static FT_Error Lookup_PairPos( GPOS_Instance* gpi, static FT_Error Lookup_PairPos( GPOS_Instance* gpi,
TTO_PairPos* pp, TTO_PairPos* pp,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length ) FT_UShort context_length )
{ {
...@@ -1695,32 +1601,32 @@ ...@@ -1695,32 +1601,32 @@
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
if ( in->pos >= in->length - 1 ) if ( buffer->in_pos >= buffer->in_length - 1 )
return TTO_Err_Not_Covered; /* Not enough glyphs in stream */ return TTO_Err_Not_Covered; /* Not enough glyphs in stream */
if ( context_length != 0xFFFF && context_length < 2 ) if ( context_length != 0xFFFF && context_length < 2 )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &pp->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &pp->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
/* second glyph */ /* second glyph */
first_pos = in->pos; first_pos = buffer->in_pos;
(in->pos)++; (buffer->in_pos)++;
while ( CHECK_Property( gpos->gdef, in->string[in->pos], while ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) ) flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( in->pos < in->length ) if ( buffer->in_pos < buffer->in_length )
(in->pos)++; (buffer->in_pos)++;
else else
break; break;
} }
...@@ -1728,13 +1634,13 @@ ...@@ -1728,13 +1634,13 @@
switch ( pp->PosFormat ) switch ( pp->PosFormat )
{ {
case 1: case 1:
error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, in, out, error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
first_pos, index, first_pos, index,
pp->ValueFormat1, pp->ValueFormat2 ); pp->ValueFormat1, pp->ValueFormat2 );
break; break;
case 2: case 2:
error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, in, out, first_pos, error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
pp->ValueFormat1, pp->ValueFormat2 ); pp->ValueFormat1, pp->ValueFormat2 );
break; break;
...@@ -1745,7 +1651,7 @@ ...@@ -1745,7 +1651,7 @@
/* adjusting the `next' glyph */ /* adjusting the `next' glyph */
if ( pp->ValueFormat2 ) if ( pp->ValueFormat2 )
(in->pos)++; (buffer->in_pos)++;
return error; return error;
} }
...@@ -1893,8 +1799,7 @@ ...@@ -1893,8 +1799,7 @@
static FT_Error Lookup_CursivePos( GPOS_Instance* gpi, static FT_Error Lookup_CursivePos( GPOS_Instance* gpi,
TTO_CursivePos* cp, TTO_CursivePos* cp,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length ) FT_UShort context_length )
{ {
...@@ -1916,7 +1821,7 @@ ...@@ -1916,7 +1821,7 @@
/* Glyphs not having the right GDEF properties will be ignored, i.e., /* Glyphs not having the right GDEF properties will be ignored, i.e.,
gpi->last won't be reset (contrary to user defined properties). */ gpi->last won't be reset (contrary to user defined properties). */
if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
/* We don't handle mark glyphs here. According to Andrei, this isn't /* We don't handle mark glyphs here. According to Andrei, this isn't
...@@ -1928,7 +1833,7 @@ ...@@ -1928,7 +1833,7 @@
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &cp->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &cp->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
{ {
gpi->last = 0xFFFF; gpi->last = 0xFFFF;
...@@ -2063,7 +1968,7 @@ ...@@ -2063,7 +1968,7 @@
/* Get_Anchor() returns TTO_Err_Not_Covered if there is no anchor /* Get_Anchor() returns TTO_Err_Not_Covered if there is no anchor
table. */ table. */
error = Get_Anchor( gpi, &eer->EntryAnchor, in->string[in->pos], error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH( 0 ),
&entry_x, &entry_y ); &entry_x, &entry_y );
if ( error == TTO_Err_Not_Covered ) if ( error == TTO_Err_Not_Covered )
goto end; goto end;
...@@ -2072,34 +1977,41 @@ ...@@ -2072,34 +1977,41 @@
if ( gpi->r2l ) if ( gpi->r2l )
{ {
out[in->pos].x_advance = entry_x - gpi->anchor_x; POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;
out[in->pos].new_advance = TRUE; POSITION( buffer->in_pos )->new_advance = TRUE;
} }
else else
{ {
out[gpi->last].x_advance = gpi->anchor_x - entry_x; POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;
out[gpi->last].new_advance = TRUE; POSITION( gpi->last )->new_advance = TRUE;
} }
out[in->pos].y_pos = gpi->anchor_y - entry_y + out[gpi->last].y_pos; if ( flags & RIGHT_TO_LEFT )
{
POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
}
else
{
POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
}
end: end:
error = Get_Anchor( gpi, &eer->ExitAnchor, in->string[in->pos], error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH( 0 ),
&exit_x, &exit_y ); &exit_x, &exit_y );
if ( error == TTO_Err_Not_Covered ) if ( error == TTO_Err_Not_Covered )
gpi->last = 0xFFFF; gpi->last = 0xFFFF;
else else
{ {
if ( gpi->first == 0xFFFF ) gpi->last = buffer->in_pos;
gpi->first = in->pos;
gpi->last = in->pos;
gpi->anchor_x = exit_x; gpi->anchor_x = exit_x;
gpi->anchor_y = exit_y; gpi->anchor_y = exit_y;
} }
if ( error ) if ( error )
return error; return error;
(in->pos)++; (buffer->in_pos)++;
return TT_Err_Ok; return TT_Err_Ok;
} }
...@@ -2312,8 +2224,7 @@ ...@@ -2312,8 +2224,7 @@
static FT_Error Lookup_MarkBasePos( GPOS_Instance* gpi, static FT_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
TTO_MarkBasePos* mbp, TTO_MarkBasePos* mbp,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length ) FT_UShort context_length )
{ {
...@@ -2328,7 +2239,7 @@ ...@@ -2328,7 +2239,7 @@
TTO_Anchor* mark_anchor; TTO_Anchor* mark_anchor;
TTO_Anchor* base_anchor; TTO_Anchor* base_anchor;
TTO_GPOS_Data* o; OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 ) if ( context_length != 0xFFFF && context_length < 1 )
...@@ -2337,11 +2248,11 @@ ...@@ -2337,11 +2248,11 @@
if ( flags & IGNORE_BASE_GLYPHS ) if ( flags & IGNORE_BASE_GLYPHS )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( CHECK_Property( gpos->gdef, in->string[in->pos], if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) ) flags, &property ) )
return error; return error;
error = Coverage_Index( &mbp->MarkCoverage, in->string[in->pos], error = Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH( 0 ),
&mark_index ); &mark_index );
if ( error ) if ( error )
return error; return error;
...@@ -2349,11 +2260,11 @@ ...@@ -2349,11 +2260,11 @@
/* now we search backwards for a non-mark glyph */ /* now we search backwards for a non-mark glyph */
i = 1; i = 1;
j = in->pos - 1; j = buffer->in_pos - 1;
while ( i <= in->pos ) while ( i <= buffer->in_pos )
{ {
error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
&property ); &property );
if ( error ) if ( error )
return error; return error;
...@@ -2371,10 +2282,10 @@ ...@@ -2371,10 +2282,10 @@
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
#endif #endif
if ( i > in->pos ) if ( i > buffer->in_pos )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
error = Coverage_Index( &mbp->BaseCoverage, in->string[j], error = Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
&base_index ); &base_index );
if ( error ) if ( error )
return error; return error;
...@@ -2398,19 +2309,19 @@ ...@@ -2398,19 +2309,19 @@
br = &ba->BaseRecord[base_index]; br = &ba->BaseRecord[base_index];
base_anchor = &br->BaseAnchor[class]; base_anchor = &br->BaseAnchor[class];
error = Get_Anchor( gpi, mark_anchor, in->string[in->pos], error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH( 0 ),
&x_mark_value, &y_mark_value ); &x_mark_value, &y_mark_value );
if ( error ) if ( error )
return error; return error;
error = Get_Anchor( gpi, base_anchor, in->string[j], error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
&x_base_value, &y_base_value ); &x_base_value, &y_base_value );
if ( error ) if ( error )
return error; return error;
/* anchor points are not cumulative */ /* anchor points are not cumulative */
o = &out[in->pos]; o = POSITION( buffer->in_pos );
o->x_pos = x_base_value - x_mark_value; o->x_pos = x_base_value - x_mark_value;
o->y_pos = y_base_value - y_mark_value; o->y_pos = y_base_value - y_mark_value;
...@@ -2418,7 +2329,7 @@ ...@@ -2418,7 +2329,7 @@
o->y_advance = 0; o->y_advance = 0;
o->back = i; o->back = i;
(in->pos)++; (buffer->in_pos)++;
return TT_Err_Ok; return TT_Err_Ok;
} }
...@@ -2720,8 +2631,7 @@ ...@@ -2720,8 +2631,7 @@
static FT_Error Lookup_MarkLigPos( GPOS_Instance* gpi, static FT_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
TTO_MarkLigPos* mlp, TTO_MarkLigPos* mlp,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length ) FT_UShort context_length )
{ {
...@@ -2739,7 +2649,7 @@ ...@@ -2739,7 +2649,7 @@
TTO_Anchor* mark_anchor; TTO_Anchor* mark_anchor;
TTO_Anchor* lig_anchor; TTO_Anchor* lig_anchor;
TTO_GPOS_Data* o; OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 ) if ( context_length != 0xFFFF && context_length < 1 )
...@@ -2748,7 +2658,7 @@ ...@@ -2748,7 +2658,7 @@
if ( flags & IGNORE_LIGATURES ) if ( flags & IGNORE_LIGATURES )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
mark_glyph = in->string[in->pos]; mark_glyph = IN_CURGLYPH( 0 );
if ( CHECK_Property( gpos->gdef, mark_glyph, flags, &property ) ) if ( CHECK_Property( gpos->gdef, mark_glyph, flags, &property ) )
return error; return error;
...@@ -2760,11 +2670,11 @@ ...@@ -2760,11 +2670,11 @@
/* now we search backwards for a non-mark glyph */ /* now we search backwards for a non-mark glyph */
i = 1; i = 1;
j = in->pos - 1; j = buffer->in_pos - 1;
while ( i <= in->pos ) while ( i <= buffer->in_pos )
{ {
error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
&property ); &property );
if ( error ) if ( error )
return error; return error;
...@@ -2783,10 +2693,10 @@ ...@@ -2783,10 +2693,10 @@
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
#endif #endif
if ( i > in->pos ) if ( i > buffer->in_pos )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
error = Coverage_Index( &mlp->LigatureCoverage, in->string[j], error = Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
&lig_index ); &lig_index );
if ( error ) if ( error )
return error; return error;
...@@ -2814,10 +2724,9 @@ ...@@ -2814,10 +2724,9 @@
can directly use the component index. If not, we attach the mark can directly use the component index. If not, we attach the mark
glyph to the last component of the ligature. */ glyph to the last component of the ligature. */
if ( in->ligIDs && in->components && if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
in->ligIDs[j] == in->ligIDs[in->pos] )
{ {
comp_index = in->components[in->pos]; comp_index = IN_COMPONENT( buffer->in_pos );
if ( comp_index >= lat->ComponentCount ) if ( comp_index >= lat->ComponentCount )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
...@@ -2827,18 +2736,18 @@ ...@@ -2827,18 +2736,18 @@
cr = &lat->ComponentRecord[comp_index]; cr = &lat->ComponentRecord[comp_index];
lig_anchor = &cr->LigatureAnchor[class]; lig_anchor = &cr->LigatureAnchor[class];
error = Get_Anchor( gpi, mark_anchor, in->string[in->pos], error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH( 0 ),
&x_mark_value, &y_mark_value ); &x_mark_value, &y_mark_value );
if ( error ) if ( error )
return error; return error;
error = Get_Anchor( gpi, lig_anchor, in->string[j], error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
&x_lig_value, &y_lig_value ); &x_lig_value, &y_lig_value );
if ( error ) if ( error )
return error; return error;
/* anchor points are not cumulative */ /* anchor points are not cumulative */
o = &out[in->pos]; o = POSITION( buffer->in_pos );
o->x_pos = x_lig_value - x_mark_value; o->x_pos = x_lig_value - x_mark_value;
o->y_pos = y_lig_value - y_mark_value; o->y_pos = y_lig_value - y_mark_value;
...@@ -2846,7 +2755,7 @@ ...@@ -2846,7 +2755,7 @@
o->y_advance = 0; o->y_advance = 0;
o->back = i; o->back = i;
(in->pos)++; (buffer->in_pos)++;
return TT_Err_Ok; return TT_Err_Ok;
} }
...@@ -3061,8 +2970,7 @@ ...@@ -3061,8 +2970,7 @@
static FT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi, static FT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
TTO_MarkMarkPos* mmp, TTO_MarkMarkPos* mmp,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length ) FT_UShort context_length )
{ {
...@@ -3078,7 +2986,7 @@ ...@@ -3078,7 +2986,7 @@
TTO_Anchor* mark1_anchor; TTO_Anchor* mark1_anchor;
TTO_Anchor* mark2_anchor; TTO_Anchor* mark2_anchor;
TTO_GPOS_Data* o; OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 ) if ( context_length != 0xFFFF && context_length < 1 )
...@@ -3087,11 +2995,11 @@ ...@@ -3087,11 +2995,11 @@
if ( flags & IGNORE_MARKS ) if ( flags & IGNORE_MARKS )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( CHECK_Property( gpos->gdef, in->string[in->pos], if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) ) flags, &property ) )
return error; return error;
error = Coverage_Index( &mmp->Mark1Coverage, in->string[in->pos], error = Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH( 0 ),
&mark1_index ); &mark1_index );
if ( error ) if ( error )
return error; return error;
...@@ -3099,11 +3007,11 @@ ...@@ -3099,11 +3007,11 @@
/* now we check the preceding glyph whether it is a suitable /* now we check the preceding glyph whether it is a suitable
mark glyph */ mark glyph */
if ( in->pos == 0 ) if ( buffer->in_pos == 0 )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
j = in->pos - 1; j = buffer->in_pos - 1;
error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
&property ); &property );
if ( error ) if ( error )
return error; return error;
...@@ -3119,7 +3027,7 @@ ...@@ -3119,7 +3027,7 @@
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &mmp->Mark2Coverage, in->string[j], error = Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
&mark2_index ); &mark2_index );
if ( error ) if ( error )
return error; return error;
...@@ -3143,18 +3051,18 @@ ...@@ -3143,18 +3051,18 @@
m2r = &ma2->Mark2Record[mark2_index]; m2r = &ma2->Mark2Record[mark2_index];
mark2_anchor = &m2r->Mark2Anchor[class]; mark2_anchor = &m2r->Mark2Anchor[class];
error = Get_Anchor( gpi, mark1_anchor, in->string[in->pos], error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH( 0 ),
&x_mark1_value, &y_mark1_value ); &x_mark1_value, &y_mark1_value );
if ( error ) if ( error )
return error; return error;
error = Get_Anchor( gpi, mark2_anchor, in->string[j], error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
&x_mark2_value, &y_mark2_value ); &x_mark2_value, &y_mark2_value );
if ( error ) if ( error )
return error; return error;
/* anchor points are not cumulative */ /* anchor points are not cumulative */
o = &out[in->pos]; o = POSITION( buffer->in_pos );
o->x_pos = x_mark2_value - x_mark1_value; o->x_pos = x_mark2_value - x_mark1_value;
o->y_pos = y_mark2_value - y_mark1_value; o->y_pos = y_mark2_value - y_mark1_value;
...@@ -3162,7 +3070,7 @@ ...@@ -3162,7 +3070,7 @@
o->y_advance = 0; o->y_advance = 0;
o->back = 1; o->back = 1;
(in->pos)++; (buffer->in_pos)++;
return TT_Err_Ok; return TT_Err_Ok;
} }
...@@ -3176,8 +3084,7 @@ ...@@ -3176,8 +3084,7 @@
FT_UShort GlyphCount, FT_UShort GlyphCount,
FT_UShort PosCount, FT_UShort PosCount,
TTO_PosLookupRecord* pos, TTO_PosLookupRecord* pos,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
int nesting_level ) int nesting_level )
{ {
FT_Error error; FT_Error error;
...@@ -3190,11 +3097,11 @@ ...@@ -3190,11 +3097,11 @@
{ {
if ( PosCount && i == pos->SequenceIndex ) if ( PosCount && i == pos->SequenceIndex )
{ {
old_pos = in->pos; old_pos = buffer->in_pos;
/* Do a positioning */ /* Do a positioning */
error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, in, out, error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
GlyphCount, nesting_level ); GlyphCount, nesting_level );
if ( error ) if ( error )
...@@ -3202,12 +3109,12 @@ ...@@ -3202,12 +3109,12 @@
pos++; pos++;
PosCount--; PosCount--;
i += in->pos - old_pos; i += buffer->in_pos - old_pos;
} }
else else
{ {
i++; i++;
(in->pos)++; (buffer->in_pos)++;
} }
} }
...@@ -3928,8 +3835,7 @@ ...@@ -3928,8 +3835,7 @@
static FT_Error Lookup_ContextPos1( GPOS_Instance* gpi, static FT_Error Lookup_ContextPos1( GPOS_Instance* gpi,
TTO_ContextPosFormat1* cpf1, TTO_ContextPosFormat1* cpf1,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -3937,7 +3843,6 @@ ...@@ -3937,7 +3843,6 @@
FT_UShort index, property; FT_UShort index, property;
FT_UShort i, j, k, numpr; FT_UShort i, j, k, numpr;
FT_Error error; FT_Error error;
FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
TTO_PosRule* pr; TTO_PosRule* pr;
...@@ -3946,10 +3851,10 @@ ...@@ -3946,10 +3851,10 @@
gdef = gpos->gdef; gdef = gpos->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &cpf1->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &cpf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -3961,32 +3866,30 @@ ...@@ -3961,32 +3866,30 @@
if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount ) if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
continue; continue;
if ( in->pos + pr[k].GlyphCount > in->length ) if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
continue; /* context is too long */ continue; /* context is too long */
s_in = &in->string[in->pos];
for ( i = 1, j = 1; i < pr[k].GlyphCount; i++, j++ ) for ( i = 1, j = 1; i < pr[k].GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( in->pos + j < in->length ) if ( buffer->in_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
} }
if ( s_in[j] != pr[k].Input[i - 1] ) if ( IN_CURGLYPH( j ) != pr[k].Input[i - 1] )
break; break;
} }
if ( i == pr[k].GlyphCount ) if ( i == pr[k].GlyphCount )
return Do_ContextPos( gpi, pr[k].GlyphCount, return Do_ContextPos( gpi, pr[k].GlyphCount,
pr[k].PosCount, pr[k].PosLookupRecord, pr[k].PosCount, pr[k].PosLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
} }
...@@ -3996,8 +3899,7 @@ ...@@ -3996,8 +3899,7 @@
static FT_Error Lookup_ContextPos2( GPOS_Instance* gpi, static FT_Error Lookup_ContextPos2( GPOS_Instance* gpi,
TTO_ContextPosFormat2* cpf2, TTO_ContextPosFormat2* cpf2,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -4008,7 +3910,6 @@ ...@@ -4008,7 +3910,6 @@
FT_UShort i, j, k, known_classes; FT_UShort i, j, k, known_classes;
FT_UShort* classes; FT_UShort* classes;
FT_UShort* s_in;
FT_UShort* cl; FT_UShort* cl;
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
...@@ -4019,21 +3920,21 @@ ...@@ -4019,21 +3920,21 @@
gdef = gpos->gdef; gdef = gpos->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
/* Note: The coverage table in format 2 doesn't give an index into /* Note: The coverage table in format 2 doesn't give an index into
anything. It just lets us know whether or not we need to anything. It just lets us know whether or not we need to
do any lookup at all. */ do any lookup at all. */
error = Coverage_Index( &cpf2->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &cpf2->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, FT_UShort ) ) if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, FT_UShort ) )
return error; return error;
error = Get_Class( &cpf2->ClassDef, in->string[in->pos], error = Get_Class( &cpf2->ClassDef, IN_CURGLYPH( 0 ),
&classes[0], NULL ); &classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
...@@ -4053,22 +3954,21 @@ ...@@ -4053,22 +3954,21 @@
if ( context_length != 0xFFFF && context_length < pr->GlyphCount ) if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
continue; continue;
if ( in->pos + pr->GlyphCount > in->length ) if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
continue; /* context is too long */ continue; /* context is too long */
s_in = &in->string[in->pos];
cl = pr->Class; cl = pr->Class;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < pr->GlyphCount; i++, j++ ) for ( i = 1, j = 1; i < pr->GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
if ( in->pos + j < in->length ) if ( buffer->in_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
...@@ -4078,7 +3978,7 @@ ...@@ -4078,7 +3978,7 @@
{ {
/* Keeps us from having to do this for each rule */ /* Keeps us from having to do this for each rule */
error = Get_Class( &cpf2->ClassDef, s_in[j], &classes[i], NULL ); error = Get_Class( &cpf2->ClassDef, IN_CURGLYPH( j ), &classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
known_classes = i; known_classes = i;
...@@ -4092,7 +3992,7 @@ ...@@ -4092,7 +3992,7 @@
{ {
error = Do_ContextPos( gpi, pr->GlyphCount, error = Do_ContextPos( gpi, pr->GlyphCount,
pr->PosCount, pr->PosLookupRecord, pr->PosCount, pr->PosLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
goto End; goto End;
} }
...@@ -4108,15 +4008,13 @@ ...@@ -4108,15 +4008,13 @@
static FT_Error Lookup_ContextPos3( GPOS_Instance* gpi, static FT_Error Lookup_ContextPos3( GPOS_Instance* gpi,
TTO_ContextPosFormat3* cpf3, TTO_ContextPosFormat3* cpf3,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
{ {
FT_Error error; FT_Error error;
FT_UShort index, i, j, property; FT_UShort index, i, j, property;
FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
TTO_Coverage* c; TTO_Coverage* c;
...@@ -4125,47 +4023,45 @@ ...@@ -4125,47 +4023,45 @@
gdef = gpos->gdef; gdef = gpos->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount ) if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( in->pos + cpf3->GlyphCount > in->length ) if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
return TTO_Err_Not_Covered; /* context is too long */ return TTO_Err_Not_Covered; /* context is too long */
s_in = &in->string[in->pos];
c = cpf3->Coverage; c = cpf3->Coverage;
for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ ) for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( in->pos + j < in->length ) if ( buffer->in_pos + j < buffer->in_length )
j++; j++;
else else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &c[i], s_in[j], &index ); error = Coverage_Index( &c[i], IN_CURGLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
return Do_ContextPos( gpi, cpf3->GlyphCount, return Do_ContextPos( gpi, cpf3->GlyphCount,
cpf3->PosCount, cpf3->PosLookupRecord, cpf3->PosCount, cpf3->PosLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
} }
static FT_Error Lookup_ContextPos( GPOS_Instance* gpi, static FT_Error Lookup_ContextPos( GPOS_Instance* gpi,
TTO_ContextPos* cp, TTO_ContextPos* cp,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -4173,15 +4069,15 @@ ...@@ -4173,15 +4069,15 @@
switch ( cp->PosFormat ) switch ( cp->PosFormat )
{ {
case 1: case 1:
return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, in, out, return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
flags, context_length, nesting_level ); flags, context_length, nesting_level );
case 2: case 2:
return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, in, out, return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
flags, context_length, nesting_level ); flags, context_length, nesting_level );
case 3: case 3:
return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, in, out, return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
flags, context_length, nesting_level ); flags, context_length, nesting_level );
default: default:
...@@ -5210,8 +5106,7 @@ ...@@ -5210,8 +5106,7 @@
static FT_Error Lookup_ChainContextPos1( static FT_Error Lookup_ChainContextPos1(
GPOS_Instance* gpi, GPOS_Instance* gpi,
TTO_ChainContextPosFormat1* ccpf1, TTO_ChainContextPosFormat1* ccpf1,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -5220,7 +5115,6 @@ ...@@ -5220,7 +5115,6 @@
FT_UShort i, j, k, num_cpr, curr_pos; FT_UShort i, j, k, num_cpr, curr_pos;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_Error error; FT_Error error;
FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
TTO_ChainPosRule* cpr; TTO_ChainPosRule* cpr;
...@@ -5230,10 +5124,10 @@ ...@@ -5230,10 +5124,10 @@
gdef = gpos->gdef; gdef = gpos->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &ccpf1->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -5252,7 +5146,7 @@ ...@@ -5252,7 +5146,7 @@
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > in->pos || in->pos + igc + lgc > in->length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue; continue;
if ( bgc ) if ( bgc )
...@@ -5261,11 +5155,10 @@ ...@@ -5261,11 +5155,10 @@
we search backwards for matches in the backtrack glyph array */ we search backwards for matches in the backtrack glyph array */
curr_pos = 0; curr_pos = 0;
s_in = &in->string[curr_pos];
for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
...@@ -5286,7 +5179,7 @@ ...@@ -5286,7 +5179,7 @@
Backtrack offsets - 3 2 1 0 Backtrack offsets - 3 2 1 0
Lookahead offsets - 0 1 2 3 */ Lookahead offsets - 0 1 2 3 */
if ( s_in[j] != curr_cpr.Backtrack[i] ) if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
break; break;
} }
...@@ -5294,25 +5187,24 @@ ...@@ -5294,25 +5187,24 @@
continue; continue;
} }
curr_pos = in->pos; curr_pos = buffer->in_pos;
s_in = &in->string[curr_pos];
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ ) for ( i = 1, j = 1; i < igc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
} }
if ( s_in[j] != curr_cpr.Input[i - 1] ) if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Input[i - 1] )
break; break;
} }
...@@ -5323,22 +5215,21 @@ ...@@ -5323,22 +5215,21 @@
last context glyph */ last context glyph */
curr_pos += j; curr_pos += j;
s_in = &in->string[curr_pos];
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0, j = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
} }
if ( s_in[j] != curr_cpr.Lookahead[i] ) if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Lookahead[i] )
break; break;
} }
...@@ -5346,7 +5237,7 @@ ...@@ -5346,7 +5237,7 @@
return Do_ContextPos( gpi, igc, return Do_ContextPos( gpi, igc,
curr_cpr.PosCount, curr_cpr.PosCount,
curr_cpr.PosLookupRecord, curr_cpr.PosLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
} }
...@@ -5357,8 +5248,7 @@ ...@@ -5357,8 +5248,7 @@
static FT_Error Lookup_ChainContextPos2( static FT_Error Lookup_ChainContextPos2(
GPOS_Instance* gpi, GPOS_Instance* gpi,
TTO_ChainContextPosFormat2* ccpf2, TTO_ChainContextPosFormat2* ccpf2,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -5376,8 +5266,6 @@ ...@@ -5376,8 +5266,6 @@
FT_UShort* input_classes; FT_UShort* input_classes;
FT_UShort* lookahead_classes; FT_UShort* lookahead_classes;
FT_UShort* s_in;
FT_UShort* bc; FT_UShort* bc;
FT_UShort* ic; FT_UShort* ic;
FT_UShort* lc; FT_UShort* lc;
...@@ -5390,14 +5278,14 @@ ...@@ -5390,14 +5278,14 @@
gdef = gpos->gdef; gdef = gpos->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
/* Note: The coverage table in format 2 doesn't give an index into /* Note: The coverage table in format 2 doesn't give an index into
anything. It just lets us know whether or not we need to anything. It just lets us know whether or not we need to
do any lookup at all. */ do any lookup at all. */
error = Coverage_Index( &ccpf2->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -5413,7 +5301,7 @@ ...@@ -5413,7 +5301,7 @@
goto End2; goto End2;
known_lookahead_classes = 0; known_lookahead_classes = 0;
error = Get_Class( &ccpf2->InputClassDef, in->string[in->pos], error = Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH( 0 ),
&input_classes[0], NULL ); &input_classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -5437,7 +5325,7 @@ ...@@ -5437,7 +5325,7 @@
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > in->pos || in->pos + igc + lgc > in->length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue; continue;
if ( bgc ) if ( bgc )
...@@ -5447,12 +5335,11 @@ ...@@ -5447,12 +5335,11 @@
Note that `known_backtrack_classes' starts at index 0. */ Note that `known_backtrack_classes' starts at index 0. */
curr_pos = 0; curr_pos = 0;
s_in = &in->string[curr_pos];
bc = cpcr.Backtrack; bc = cpcr.Backtrack;
for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -5467,7 +5354,7 @@ ...@@ -5467,7 +5354,7 @@
{ {
/* Keeps us from having to do this for each rule */ /* Keeps us from having to do this for each rule */
error = Get_Class( &ccpf2->BacktrackClassDef, s_in[j], error = Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
&backtrack_classes[i], NULL ); &backtrack_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -5482,20 +5369,19 @@ ...@@ -5482,20 +5369,19 @@
continue; continue;
} }
curr_pos = in->pos; curr_pos = buffer->in_pos;
s_in = &in->string[curr_pos];
ic = cpcr.Input; ic = cpcr.Input;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ ) for ( i = 1, j = 1; i < igc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
...@@ -5503,7 +5389,7 @@ ...@@ -5503,7 +5389,7 @@
if ( i >= known_input_classes ) if ( i >= known_input_classes )
{ {
error = Get_Class( &ccpf2->InputClassDef, s_in[j], error = Get_Class( &ccpf2->InputClassDef, IN_GLYPH( curr_pos + j ),
&input_classes[i], NULL ); &input_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -5521,17 +5407,16 @@ ...@@ -5521,17 +5407,16 @@
last context glyph */ last context glyph */
curr_pos += j; curr_pos += j;
s_in = &in->string[curr_pos];
lc = cpcr.Lookahead; lc = cpcr.Lookahead;
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0, j = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
...@@ -5539,7 +5424,7 @@ ...@@ -5539,7 +5424,7 @@
if ( i >= known_lookahead_classes ) if ( i >= known_lookahead_classes )
{ {
error = Get_Class( &ccpf2->LookaheadClassDef, s_in[j], error = Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( curr_pos + j ),
&lookahead_classes[i], NULL ); &lookahead_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -5555,7 +5440,7 @@ ...@@ -5555,7 +5440,7 @@
error = Do_ContextPos( gpi, igc, error = Do_ContextPos( gpi, igc,
cpcr.PosCount, cpcr.PosCount,
cpcr.PosLookupRecord, cpcr.PosLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
goto End1; goto End1;
} }
...@@ -5578,8 +5463,7 @@ ...@@ -5578,8 +5463,7 @@
static FT_Error Lookup_ChainContextPos3( static FT_Error Lookup_ChainContextPos3(
GPOS_Instance* gpi, GPOS_Instance* gpi,
TTO_ChainContextPosFormat3* ccpf3, TTO_ChainContextPosFormat3* ccpf3,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -5587,7 +5471,6 @@ ...@@ -5587,7 +5471,6 @@
FT_UShort index, i, j, curr_pos, property; FT_UShort index, i, j, curr_pos, property;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_Error error; FT_Error error;
FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
TTO_Coverage* bc; TTO_Coverage* bc;
...@@ -5598,7 +5481,7 @@ ...@@ -5598,7 +5481,7 @@
gdef = gpos->gdef; gdef = gpos->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
bgc = ccpf3->BacktrackGlyphCount; bgc = ccpf3->BacktrackGlyphCount;
...@@ -5610,7 +5493,7 @@ ...@@ -5610,7 +5493,7 @@
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > in->pos || in->pos + igc + lgc > in->length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( bgc ) if ( bgc )
...@@ -5619,12 +5502,11 @@ ...@@ -5619,12 +5502,11 @@
we search backwards for matches in the backtrack glyph array */ we search backwards for matches in the backtrack glyph array */
curr_pos = 0; curr_pos = 0;
s_in = &in->string[curr_pos];
bc = ccpf3->BacktrackCoverage; bc = ccpf3->BacktrackCoverage;
for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
...@@ -5635,31 +5517,30 @@ ...@@ -5635,31 +5517,30 @@
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &bc[i], s_in[j], &index ); error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
} }
curr_pos = in->pos; curr_pos = buffer->in_pos;
s_in = &in->string[curr_pos];
ic = ccpf3->InputCoverage; ic = ccpf3->InputCoverage;
for ( i = 0, j = 0; i < igc; i++, j++ ) for ( i = 0, j = 0; i < igc; i++, j++ )
{ {
/* We already called CHECK_Property for s_in[0] */ /* We already called CHECK_Property for s_in[0] */
while ( j > 0 && CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &ic[i], s_in[j], &index ); error = Coverage_Index( &ic[i], IN_GLYPH( curr_pos + j ), &index );
if ( error ) if ( error )
return error; return error;
} }
...@@ -5668,23 +5549,22 @@ ...@@ -5668,23 +5549,22 @@
last context glyph */ last context glyph */
curr_pos += j; curr_pos += j;
s_in = &in->string[curr_pos];
lc = ccpf3->LookaheadCoverage; lc = ccpf3->LookaheadCoverage;
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0, j = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &lc[i], s_in[j], &index ); error = Coverage_Index( &lc[i], IN_GLYPH( curr_pos + j ), &index );
if ( error ) if ( error )
return error; return error;
} }
...@@ -5692,7 +5572,7 @@ ...@@ -5692,7 +5572,7 @@
return Do_ContextPos( gpi, igc, return Do_ContextPos( gpi, igc,
ccpf3->PosCount, ccpf3->PosCount,
ccpf3->PosLookupRecord, ccpf3->PosLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
} }
...@@ -5700,8 +5580,7 @@ ...@@ -5700,8 +5580,7 @@
static FT_Error Lookup_ChainContextPos( static FT_Error Lookup_ChainContextPos(
GPOS_Instance* gpi, GPOS_Instance* gpi,
TTO_ChainContextPos* ccp, TTO_ChainContextPos* ccp,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -5709,17 +5588,17 @@ ...@@ -5709,17 +5588,17 @@
switch ( ccp->PosFormat ) switch ( ccp->PosFormat )
{ {
case 1: case 1:
return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, in, out, return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
case 2: case 2:
return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, in, out, return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
case 3: case 3:
return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, in, out, return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
...@@ -6025,8 +5904,7 @@ ...@@ -6025,8 +5904,7 @@
static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi, static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index, FT_UShort lookup_index,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data* out,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
{ {
...@@ -6051,49 +5929,49 @@ ...@@ -6051,49 +5929,49 @@
case GPOS_LOOKUP_SINGLE: case GPOS_LOOKUP_SINGLE:
error = Lookup_SinglePos( gpi, error = Lookup_SinglePos( gpi,
&lo->SubTable[i].st.gpos.single, &lo->SubTable[i].st.gpos.single,
in, out, buffer,
flags, context_length ); flags, context_length );
break; break;
case GPOS_LOOKUP_PAIR: case GPOS_LOOKUP_PAIR:
error = Lookup_PairPos( gpi, error = Lookup_PairPos( gpi,
&lo->SubTable[i].st.gpos.pair, &lo->SubTable[i].st.gpos.pair,
in, out, buffer,
flags, context_length ); flags, context_length );
break; break;
case GPOS_LOOKUP_CURSIVE: case GPOS_LOOKUP_CURSIVE:
error = Lookup_CursivePos( gpi, error = Lookup_CursivePos( gpi,
&lo->SubTable[i].st.gpos.cursive, &lo->SubTable[i].st.gpos.cursive,
in, out, buffer,
flags, context_length ); flags, context_length );
break; break;
case GPOS_LOOKUP_MARKBASE: case GPOS_LOOKUP_MARKBASE:
error = Lookup_MarkBasePos( gpi, error = Lookup_MarkBasePos( gpi,
&lo->SubTable[i].st.gpos.markbase, &lo->SubTable[i].st.gpos.markbase,
in, out, buffer,
flags, context_length ); flags, context_length );
break; break;
case GPOS_LOOKUP_MARKLIG: case GPOS_LOOKUP_MARKLIG:
error = Lookup_MarkLigPos( gpi, error = Lookup_MarkLigPos( gpi,
&lo->SubTable[i].st.gpos.marklig, &lo->SubTable[i].st.gpos.marklig,
in, out, buffer,
flags, context_length ); flags, context_length );
break; break;
case GPOS_LOOKUP_MARKMARK: case GPOS_LOOKUP_MARKMARK:
error = Lookup_MarkMarkPos( gpi, error = Lookup_MarkMarkPos( gpi,
&lo->SubTable[i].st.gpos.markmark, &lo->SubTable[i].st.gpos.markmark,
in, out, buffer,
flags, context_length ); flags, context_length );
break; break;
case GPOS_LOOKUP_CONTEXT: case GPOS_LOOKUP_CONTEXT:
error = Lookup_ContextPos( gpi, error = Lookup_ContextPos( gpi,
&lo->SubTable[i].st.gpos.context, &lo->SubTable[i].st.gpos.context,
in, out, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
break; break;
...@@ -6101,7 +5979,7 @@ ...@@ -6101,7 +5979,7 @@
case GPOS_LOOKUP_CHAIN: case GPOS_LOOKUP_CHAIN:
error = Lookup_ChainContextPos( gpi, error = Lookup_ChainContextPos( gpi,
&lo->SubTable[i].st.gpos.chain, &lo->SubTable[i].st.gpos.chain,
in, out, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
break; break;
...@@ -6122,28 +6000,23 @@ ...@@ -6122,28 +6000,23 @@
static FT_Error Do_String_Lookup( GPOS_Instance* gpi, static FT_Error Do_String_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index, FT_UShort lookup_index,
TTO_GSUB_String* in, OTL_Buffer buffer )
TTO_GPOS_Data* out )
{ {
FT_Error error, retError = TTO_Err_Not_Covered; FT_Error error, retError = TTO_Err_Not_Covered;
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
FT_UShort* properties = gpos->LookupList.Properties; FT_UShort* properties = gpos->LookupList.Properties;
FT_UShort* p_in = in->properties;
int nesting_level = 0; int nesting_level = 0;
FT_UShort i;
FT_Pos offset;
gpi->first = 0xFFFF;
gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */ gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */
in->pos = 0; buffer->in_pos = 0;
while ( in->pos < in->length ) while ( buffer->in_pos < buffer->in_length )
{ {
if ( ~p_in[in->pos] & properties[lookup_index] ) if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
{ {
/* 0xFFFF indicates that we don't have a context length yet. */ /* 0xFFFF indicates that we don't have a context length yet. */
...@@ -6154,7 +6027,7 @@ ...@@ -6154,7 +6027,7 @@
It is up to the font designer to provide meaningful lookups and It is up to the font designer to provide meaningful lookups and
lookup order. */ lookup order. */
error = Do_Glyph_Lookup( gpi, lookup_index, in, out, error = Do_Glyph_Lookup( gpi, lookup_index, buffer,
0xFFFF, nesting_level ); 0xFFFF, nesting_level );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
...@@ -6168,24 +6041,8 @@ ...@@ -6168,24 +6041,8 @@
error = TTO_Err_Not_Covered; error = TTO_Err_Not_Covered;
} }
/* test whether we have to adjust the offsets for cursive connections */
if ( gpi->first != 0xFFFF && gpi->last == 0xFFFF &&
gpos->LookupList.Lookup[lookup_index].LookupFlag & RIGHT_TO_LEFT )
{
offset = out[in->pos].y_pos;
/* no horizontal offsets (for vertical writing direction)
supported yet */
for ( i = gpi->first; i <= in->pos; i++ )
out[i].y_pos -= offset;
gpi->first = 0xFFFF;
}
if ( error == TTO_Err_Not_Covered ) if ( error == TTO_Err_Not_Covered )
(in->pos)++; (buffer->in_pos)++;
else else
retError = error; retError = error;
} }
...@@ -6194,6 +6051,30 @@ ...@@ -6194,6 +6051,30 @@
} }
static FT_Error Position_CursiveChain ( OTL_Buffer buffer )
{
FT_ULong i, j;
OTL_Position positions = buffer->positions;
/* First handle all left-to-right connections */
for (j = 0; j < buffer->in_length; j--)
{
if (positions[j].cursive_chain > 0)
positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
}
/* Then handle all right-to-left connections */
for (i = buffer->in_length; i > 0; i--)
{
j = i - 1;
if (positions[j].cursive_chain < 0)
positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
}
return TT_Err_Ok;
}
EXPORT_FUNC EXPORT_FUNC
FT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos, FT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos,
FT_UShort feature_index, FT_UShort feature_index,
...@@ -6269,7 +6150,6 @@ ...@@ -6269,7 +6150,6 @@
return TT_Err_Ok; return TT_Err_Ok;
} }
/* If `dvi' is TRUE, glyph contour points for anchor points and device /* If `dvi' is TRUE, glyph contour points for anchor points and device
tables are ignored -- you will get device independent values. */ tables are ignored -- you will get device independent values. */
...@@ -6277,12 +6157,10 @@ ...@@ -6277,12 +6157,10 @@
FT_Error TT_GPOS_Apply_String( FT_Face face, FT_Error TT_GPOS_Apply_String( FT_Face face,
TTO_GPOSHeader* gpos, TTO_GPOSHeader* gpos,
FT_UShort load_flags, FT_UShort load_flags,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data** out,
FT_Bool dvi, FT_Bool dvi,
FT_Bool r2l ) FT_Bool r2l )
{ {
FT_Memory memory = gpos->memory;
FT_Error error, retError = TTO_Err_Not_Covered; FT_Error error, retError = TTO_Err_Not_Covered;
GPOS_Instance gpi; GPOS_Instance gpi;
...@@ -6292,7 +6170,7 @@ ...@@ -6292,7 +6170,7 @@
if ( !face || !gpos || if ( !face || !gpos ||
!in || in->length == 0 || in->pos >= in->length ) !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
return TT_Err_Invalid_Argument; return TT_Err_Invalid_Argument;
properties = gpos->LookupList.Properties; properties = gpos->LookupList.Properties;
...@@ -6303,15 +6181,10 @@ ...@@ -6303,15 +6181,10 @@
gpi.r2l = r2l; gpi.r2l = r2l;
gpi.dvi = dvi; gpi.dvi = dvi;
if ( *out )
FREE( *out );
if ( ALLOC_ARRAY( *out, in->length, TTO_GPOS_Data ) )
return error;
for ( j = 0; j < gpos->LookupList.LookupCount; j++ ) for ( j = 0; j < gpos->LookupList.LookupCount; j++ )
if ( !properties || properties[j] ) if ( !properties || properties[j] )
{ {
error = Do_String_Lookup( &gpi, j, in, *out ); error = Do_String_Lookup( &gpi, j, buffer );
if ( error ) if ( error )
{ {
if ( error != TTO_Err_Not_Covered ) if ( error != TTO_Err_Not_Covered )
...@@ -6321,6 +6194,10 @@ ...@@ -6321,6 +6194,10 @@
retError = error; retError = error;
} }
error = Position_CursiveChain ( buffer );
if ( error )
return error;
return retError; return retError;
} }
......
...@@ -758,26 +758,6 @@ extern "C" { ...@@ -758,26 +758,6 @@ extern "C" {
typedef union TTO_GPOS_SubTable_ TTO_GPOS_SubTable; typedef union TTO_GPOS_SubTable_ TTO_GPOS_SubTable;
/* This `string object' is much simpler compared to TTO_GSUB_String.
A call to TTO_GPOS_Apply_String() will allocate it. */
struct TTO_GPOS_Data_
{
FT_Pos x_pos;
FT_Pos y_pos;
FT_Pos x_advance;
FT_Pos y_advance;
FT_UShort back; /* number of glyphs to go back
for drawing current glyph */
FT_Bool new_advance; /* if set, the advance width values are
absolute, i.e., they won't be
added to the original glyph's value
but rather replace them. */
};
typedef struct TTO_GPOS_Data_ TTO_GPOS_Data;
/* finally, the GPOS API */ /* finally, the GPOS API */
/* EXPORT_DEF /* EXPORT_DEF
...@@ -844,8 +824,7 @@ extern "C" { ...@@ -844,8 +824,7 @@ extern "C" {
FT_Error TT_GPOS_Apply_String( FT_Face face, FT_Error TT_GPOS_Apply_String( FT_Face face,
TTO_GPOSHeader* gpos, TTO_GPOSHeader* gpos,
FT_UShort load_flags, FT_UShort load_flags,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GPOS_Data** out,
FT_Bool dvi, FT_Bool dvi,
FT_Bool r2l ); FT_Bool r2l );
......
...@@ -38,17 +38,26 @@ ...@@ -38,17 +38,26 @@
#define GSUB_ID Build_Extension_ID( 'G', 'S', 'U', 'B' ) #define GSUB_ID Build_Extension_ID( 'G', 'S', 'U', 'B' )
#define ADD_String( in, num_in, out, num_out, glyph_data, component, ligID ) \ #define IN_GLYPH( pos ) buffer->in_string[(pos)].gindex
( ( error = TT_GSUB_Add_String( (in), (num_in), \ #define IN_CURGLYPH( pos ) buffer->in_string[(pos) + buffer->in_pos].gindex
(out), (num_out), \ #define IN_PROPERTIES( pos ) buffer->in_string[(pos)].properties
(glyph_data), (component), (ligID) \ #define IN_LIGID( pos ) buffer->in_string[(pos)].ligID
) ) != TT_Err_Ok )
#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
( ( error = otl_buffer_add_output_glyphs( (buffer), \
(num_in), (num_out), \
(glyph_data), (component), (ligID) \
) ) != TT_Err_Ok )
#define ADD_Glyph( buffer, glyph_index, component, ligID ) \
( ( error = otl_buffer_add_output_glyph( (buffer), \
(glyph_index), (component), (ligID) \
) ) != TT_Err_Ok )
static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub, static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub,
FT_UShort lookup_index, FT_UShort lookup_index,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ); int nesting_level );
...@@ -59,203 +68,6 @@ ...@@ -59,203 +68,6 @@
**********************/ **********************/
/* The following function copies `num_out' elements from `glyph_data'
to `out', advancing the array pointer in the `in' structure by
`num_in' elements, and in `out' by `num_out' elements. If the
string (resp. the properties) array in `out' is empty or too
small, it allocates resp. reallocates the string (and properties)
array. Finally, it sets the `length' field of `out' equal to
`pos' of the `out' structure.
If `component' is 0xFFFF, the value `in->component[in->pos]'
will be copied `num_out' times, otherwise `component' itself will
be used to fill `out->component'.
If `ligID' is 0xFFFF, the value `in->lig_IDs[in->pos]' will be
copied `num_out' times, otherwise `ligID' itself will be used to
fill `out->ligIDs'.
The properties (if defined) for all replaced glyphs are taken
from the glyph at position `in->pos'.
The logClusters[] value for the glyph at position in->pos is used
for all replacement glyphs */
EXPORT_FUNC
FT_Error TT_GSUB_Add_String( TTO_GSUB_String* in,
FT_UShort num_in,
TTO_GSUB_String* out,
FT_UShort num_out,
FT_UShort* glyph_data,
FT_UShort component,
FT_UShort ligID )
{
FT_Memory memory = in->memory;
FT_Error error;
FT_UShort i;
FT_UShort p_in;
FT_UShort*p_out;
/* sanity check */
if ( !in || !out ||
in->length == 0 || in->pos >= in->length ||
in->length < in->pos + num_in )
return TT_Err_Invalid_Argument;
if ( out->pos + num_out >= out->allocated )
{
FT_ULong size = out->pos + num_out + 256L;
/* The following works because all fields in `out' must be
initialized to zero (including the `string' field) for the
first use. */
if ( REALLOC_ARRAY( out->string, out->allocated, size, FT_UShort ) )
return error;
if ( REALLOC_ARRAY( out->components, out->allocated, size, FT_UShort ) )
return error;
if ( REALLOC_ARRAY( out->ligIDs, out->allocated, size, FT_UShort ) )
return error;
if ( in->properties )
if ( REALLOC_ARRAY( out->properties, out->allocated, size, FT_UShort ) )
return error;
if ( REALLOC_ARRAY( out->logClusters, out->allocated, size, FT_Int ) )
return error;
out->allocated = size;
}
if ( num_out )
{
MEM_Copy( &out->string[out->pos], glyph_data,
num_out * sizeof ( FT_UShort ) );
if ( component == 0xFFFF )
component = in->components[in->pos];
p_out = out->components;
for ( i = out->pos; i < out->pos + num_out; i++ )
p_out[i] = component;
p_out = out->ligIDs;
if ( ligID == 0xFFFF )
ligID = in->ligIDs[in->pos];
for ( i = out->pos; i < out->pos + num_out; i++ )
p_out[i] = ligID;
if ( in->properties )
{
p_in = in->properties[in->pos];
p_out = out->properties;
for ( i = out->pos; i < out->pos + num_out; i++ )
p_out[i] = p_in;
}
for ( i = out->pos; i < out->pos + num_out; i++ )
out->logClusters[i] = in->logClusters[in->pos];
}
in->pos += num_in;
out->pos += num_out;
out->length = out->pos;
return TT_Err_Ok;
}
#if 0
/**********************
* Extension Functions
**********************/
static FT_Error GSUB_Create( void* ext,
PFace face )
{
DEFINE_LOAD_LOCALS( face->stream );
TTO_GSUBHeader* gsub = (TTO_GSUBHeader*)ext;
Long table;
/* by convention */
if ( !gsub )
return TT_Err_Ok;
/* a null offset indicates that there is no GSUB table */
gsub->offset = 0;
/* we store the start offset and the size of the subtable */
table = TT_LookUp_Table( face, TTAG_GSUB );
if ( table < 0 )
return TT_Err_Ok; /* The table is optional */
if ( FILE_Seek( face->dirTables[table].Offset ) ||
ACCESS_Frame( 4L ) )
return error;
gsub->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */
gsub->Version = GET_ULong();
FORGET_Frame();
gsub->loaded = FALSE;
return TT_Err_Ok;
}
static FT_Error GSUB_Destroy( void* ext,
PFace face )
{
TTO_GSUBHeader* gsub = (TTO_GSUBHeader*)ext;
/* by convention */
if ( !gsub )
return TT_Err_Ok;
if ( gsub->loaded )
{
Free_LookupList( &gsub->LookupList, GSUB, memory );
Free_FeatureList( &gsub->FeatureList, memory );
Free_ScriptList( &gsub->ScriptList, memory );
}
return TT_Err_Ok;
}
EXPORT_FUNC
FT_Error TT_Init_GSUB_Extension( TT_Engine engine )
{
PEngine_Instance _engine = HANDLE_Engine( engine );
if ( !_engine )
return TT_Err_Invalid_Engine;
return TT_Register_Extension( _engine,
GSUB_ID,
sizeof ( TTO_GSUBHeader ),
GSUB_Create,
GSUB_Destroy );
}
#endif
EXPORT_FUNC EXPORT_FUNC
FT_Error TT_Load_GSUB_Table( FT_Face face, FT_Error TT_Load_GSUB_Table( FT_Face face,
TTO_GSUBHeader** retptr, TTO_GSUBHeader** retptr,
...@@ -502,39 +314,38 @@ ...@@ -502,39 +314,38 @@
static FT_Error Lookup_SingleSubst( TTO_SingleSubst* ss, static FT_Error Lookup_SingleSubst( TTO_SingleSubst* ss,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
TTO_GDEFHeader* gdef ) TTO_GDEFHeader* gdef )
{ {
FT_UShort index, value[1], property; FT_UShort index, value, property;
FT_Error error; FT_Error error;
if ( context_length != 0xFFFF && context_length < 1 ) if ( context_length != 0xFFFF && context_length < 1 )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &ss->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &ss->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
switch ( ss->SubstFormat ) switch ( ss->SubstFormat )
{ {
case 1: case 1:
value[0] = ( in->string[in->pos] + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF; value = ( IN_CURGLYPH( 0 ) + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
if ( ADD_String( in, 1, out, 1, value, 0xFFFF, 0xFFFF ) ) if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
return error; return error;
break; break;
case 2: case 2:
if ( index >= ss->ssf.ssf2.GlyphCount ) if ( index >= ss->ssf.ssf2.GlyphCount )
return TTO_Err_Invalid_GSUB_SubTable; return TTO_Err_Invalid_GSUB_SubTable;
value[0] = ss->ssf.ssf2.Substitute[index]; value = ss->ssf.ssf2.Substitute[index];
if ( ADD_String( in, 1, out, 1, value, 0xFFFF, 0xFFFF ) ) if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
return error; return error;
break; break;
...@@ -546,7 +357,7 @@ ...@@ -546,7 +357,7 @@
{ {
/* we inherit the old glyph class to the substituted glyph */ /* we inherit the old glyph class to the substituted glyph */
error = Add_Glyph_Property( gdef, value[0], property ); error = Add_Glyph_Property( gdef, value, property );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
} }
...@@ -706,8 +517,7 @@ ...@@ -706,8 +517,7 @@
static FT_Error Lookup_MultipleSubst( TTO_MultipleSubst* ms, static FT_Error Lookup_MultipleSubst( TTO_MultipleSubst* ms,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
TTO_GDEFHeader* gdef ) TTO_GDEFHeader* gdef )
...@@ -720,10 +530,10 @@ ...@@ -720,10 +530,10 @@
if ( context_length != 0xFFFF && context_length < 1 ) if ( context_length != 0xFFFF && context_length < 1 )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &ms->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &ms->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -733,7 +543,7 @@ ...@@ -733,7 +543,7 @@
count = ms->Sequence[index].GlyphCount; count = ms->Sequence[index].GlyphCount;
s = ms->Sequence[index].Substitute; s = ms->Sequence[index].Substitute;
if ( ADD_String( in, 1, out, count, s, 0xFFFF, 0xFFFF ) ) if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
return error; return error;
if ( gdef && gdef->NewGlyphClasses ) if ( gdef && gdef->NewGlyphClasses )
...@@ -904,8 +714,7 @@ ...@@ -904,8 +714,7 @@
static FT_Error Lookup_AlternateSubst( TTO_GSUBHeader* gsub, static FT_Error Lookup_AlternateSubst( TTO_GSUBHeader* gsub,
TTO_AlternateSubst* as, TTO_AlternateSubst* as,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
TTO_GDEFHeader* gdef ) TTO_GDEFHeader* gdef )
...@@ -919,10 +728,10 @@ ...@@ -919,10 +728,10 @@
if ( context_length != 0xFFFF && context_length < 1 ) if ( context_length != 0xFFFF && context_length < 1 )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &as->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &as->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -931,14 +740,14 @@ ...@@ -931,14 +740,14 @@
/* we use a user-defined callback function to get the alternate index */ /* we use a user-defined callback function to get the alternate index */
if ( gsub->altfunc ) if ( gsub->altfunc )
alt_index = (gsub->altfunc)( out->pos, in->string[in->pos], alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH( 0 ),
aset.GlyphCount, aset.Alternate, aset.GlyphCount, aset.Alternate,
gsub->data ); gsub->data );
else else
alt_index = 0; alt_index = 0;
if ( ADD_String( in, 1, out, 1, &aset.Alternate[alt_index], if ( ADD_Glyph( buffer, aset.Alternate[alt_index],
0xFFFF, 0xFFFF ) ) 0xFFFF, 0xFFFF ) )
return error; return error;
if ( gdef && gdef->NewGlyphClasses ) if ( gdef && gdef->NewGlyphClasses )
...@@ -1184,8 +993,7 @@ ...@@ -1184,8 +993,7 @@
static FT_Error Lookup_LigatureSubst( TTO_LigatureSubst* ls, static FT_Error Lookup_LigatureSubst( TTO_LigatureSubst* ls,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
TTO_GDEFHeader* gdef ) TTO_GDEFHeader* gdef )
...@@ -1193,19 +1001,18 @@ ...@@ -1193,19 +1001,18 @@
FT_UShort index, property; FT_UShort index, property;
FT_Error error; FT_Error error;
FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE; FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
FT_UShort* s_in;
FT_UShort* c; FT_UShort* c;
TTO_Ligature* lig; TTO_Ligature* lig;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
if ( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) if ( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS )
first_is_mark = TRUE; first_is_mark = TRUE;
error = Coverage_Index( &ls->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &ls->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -1218,10 +1025,9 @@ ...@@ -1218,10 +1025,9 @@
numlig; numlig;
numlig--, lig++ ) numlig--, lig++ )
{ {
if ( in->pos + lig->ComponentCount > in->length ) if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
continue; /* Not enough glyphs in input */ continue; /* Not enough glyphs in input */
s_in = &in->string[in->pos];
c = lig->Component; c = lig->Component;
is_mark = first_is_mark; is_mark = first_is_mark;
...@@ -1231,12 +1037,12 @@ ...@@ -1231,12 +1037,12 @@
for ( i = 1, j = 1; i < lig->ComponentCount; i++, j++ ) for ( i = 1, j = 1; i < lig->ComponentCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( in->pos + j < in->length ) if ( buffer->in_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
...@@ -1245,7 +1051,7 @@ ...@@ -1245,7 +1051,7 @@
if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) ) if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) )
is_mark = FALSE; is_mark = FALSE;
if ( s_in[j] != c[i - 1] ) if ( IN_CURGLYPH( j ) != c[i - 1] )
break; break;
} }
...@@ -1266,25 +1072,25 @@ ...@@ -1266,25 +1072,25 @@
/* We don't use a new ligature ID if there are no skipped /* We don't use a new ligature ID if there are no skipped
glyphs and the ligature already has an ID. */ glyphs and the ligature already has an ID. */
if ( in->ligIDs[in->pos] ) if ( IN_LIGID( buffer->in_pos ) )
{ {
if ( ADD_String( in, i, out, 1, &lig->LigGlyph, if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
0xFFFF, 0xFFFF ) ) 0xFFFF, 0xFFFF ) )
return error; return error;
} }
else else
{ {
if ( ADD_String( in, i, out, 1, &lig->LigGlyph, FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
0xFFFF, in->max_ligID ) ) if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
0xFFFF, ligID ) )
return error; return error;
(in->max_ligID)++;
} }
} }
else else
{ {
if ( ADD_String( in, 1, out, 1, &lig->LigGlyph, FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
0xFFFF, in->max_ligID ) ) if ( ADD_Glyph( buffer, lig->LigGlyph,
0xFFFF, ligID ) )
return error; return error;
/* Now we must do a second loop to copy the skipped glyphs to /* Now we must do a second loop to copy the skipped glyphs to
...@@ -1296,16 +1102,14 @@ ...@@ -1296,16 +1102,14 @@
for ( i = 0; i < lig->ComponentCount - 1; i++ ) for ( i = 0; i < lig->ComponentCount - 1; i++ )
{ {
while ( CHECK_Property( gdef, in->string[in->pos], while ( CHECK_Property( gdef, IN_CURGLYPH( 0 ),
flags, &property ) ) flags, &property ) )
if ( ADD_String( in, 1, out, 1, &in->string[in->pos], if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
i, in->max_ligID ) ) i, ligID ) )
return error; return error;
(in->pos)++; (buffer->in_pos)++;
} }
(in->max_ligID)++;
} }
return TT_Err_Ok; return TT_Err_Ok;
...@@ -1324,8 +1128,7 @@ ...@@ -1324,8 +1128,7 @@
FT_UShort GlyphCount, FT_UShort GlyphCount,
FT_UShort SubstCount, FT_UShort SubstCount,
TTO_SubstLookupRecord* subst, TTO_SubstLookupRecord* subst,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
int nesting_level ) int nesting_level )
{ {
FT_Error error; FT_Error error;
...@@ -1338,23 +1141,23 @@ ...@@ -1338,23 +1141,23 @@
{ {
if ( SubstCount && i == subst->SequenceIndex ) if ( SubstCount && i == subst->SequenceIndex )
{ {
old_pos = in->pos; old_pos = buffer->in_pos;
/* Do a substitution */ /* Do a substitution */
error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, in, out, error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
GlyphCount, nesting_level ); GlyphCount, nesting_level );
subst++; subst++;
SubstCount--; SubstCount--;
i += in->pos - old_pos; i += buffer->in_pos - old_pos;
if ( error == TTO_Err_Not_Covered ) if ( error == TTO_Err_Not_Covered )
{ {
/* XXX "can't happen" -- but don't count on it */ /* XXX "can't happen" -- but don't count on it */
if ( ADD_String( in, 1, out, 1, &in->string[in->pos], if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
0xFFFF, 0xFFFF ) ) 0xFFFF, 0xFFFF ) )
return error; return error;
i++; i++;
} }
...@@ -1365,8 +1168,8 @@ ...@@ -1365,8 +1168,8 @@
{ {
/* No substitution for this index */ /* No substitution for this index */
if ( ADD_String( in, 1, out, 1, &in->string[in->pos], if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
0xFFFF, 0xFFFF ) ) 0xFFFF, 0xFFFF ) )
return error; return error;
i++; i++;
} }
...@@ -2090,8 +1893,7 @@ ...@@ -2090,8 +1893,7 @@
static FT_Error Lookup_ContextSubst1( static FT_Error Lookup_ContextSubst1(
TTO_GSUBHeader* gsub, TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat1* csf1, TTO_ContextSubstFormat1* csf1,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -2099,7 +1901,6 @@ ...@@ -2099,7 +1901,6 @@
FT_UShort index, property; FT_UShort index, property;
FT_UShort i, j, k, numsr; FT_UShort i, j, k, numsr;
FT_Error error; FT_Error error;
FT_UShort* s_in;
TTO_SubRule* sr; TTO_SubRule* sr;
TTO_GDEFHeader* gdef; TTO_GDEFHeader* gdef;
...@@ -2107,10 +1908,10 @@ ...@@ -2107,10 +1908,10 @@
gdef = gsub->gdef; gdef = gsub->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &csf1->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &csf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -2122,32 +1923,30 @@ ...@@ -2122,32 +1923,30 @@
if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount ) if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
continue; continue;
if ( in->pos + sr[k].GlyphCount > in->length ) if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
continue; /* context is too long */ continue; /* context is too long */
s_in = &in->string[in->pos];
for ( i = 1, j = 1; i < sr[k].GlyphCount; i++, j++ ) for ( i = 1, j = 1; i < sr[k].GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( in->pos + j < in->length ) if ( buffer->in_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
} }
if ( s_in[j] != sr[k].Input[i - 1] ) if ( IN_CURGLYPH( j ) != sr[k].Input[i - 1] )
break; break;
} }
if ( i == sr[k].GlyphCount ) if ( i == sr[k].GlyphCount )
return Do_ContextSubst( gsub, sr[k].GlyphCount, return Do_ContextSubst( gsub, sr[k].GlyphCount,
sr[k].SubstCount, sr[k].SubstLookupRecord, sr[k].SubstCount, sr[k].SubstLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
} }
...@@ -2158,8 +1957,7 @@ ...@@ -2158,8 +1957,7 @@
static FT_Error Lookup_ContextSubst2( static FT_Error Lookup_ContextSubst2(
TTO_GSUBHeader* gsub, TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat2* csf2, TTO_ContextSubstFormat2* csf2,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -2170,7 +1968,6 @@ ...@@ -2170,7 +1968,6 @@
FT_UShort i, j, k, known_classes; FT_UShort i, j, k, known_classes;
FT_UShort* classes; FT_UShort* classes;
FT_UShort* s_in;
FT_UShort* cl; FT_UShort* cl;
TTO_SubClassSet* scs; TTO_SubClassSet* scs;
...@@ -2180,21 +1977,21 @@ ...@@ -2180,21 +1977,21 @@
gdef = gsub->gdef; gdef = gsub->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
/* Note: The coverage table in format 2 doesn't give an index into /* Note: The coverage table in format 2 doesn't give an index into
anything. It just lets us know whether or not we need to anything. It just lets us know whether or not we need to
do any lookup at all. */ do any lookup at all. */
error = Coverage_Index( &csf2->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &csf2->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) ) if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) )
return error; return error;
error = Get_Class( &csf2->ClassDef, in->string[in->pos], error = Get_Class( &csf2->ClassDef, IN_CURGLYPH( 0 ),
&classes[0], NULL ); &classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
...@@ -2214,22 +2011,21 @@ ...@@ -2214,22 +2011,21 @@
if ( context_length != 0xFFFF && context_length < sr->GlyphCount ) if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
continue; continue;
if ( in->pos + sr->GlyphCount > in->length ) if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
continue; /* context is too long */ continue; /* context is too long */
s_in = &in->string[in->pos];
cl = sr->Class; cl = sr->Class;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < sr->GlyphCount; i++, j++ ) for ( i = 1, j = 1; i < sr->GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
if ( in->pos + j < in->length ) if ( buffer->in_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
...@@ -2239,7 +2035,7 @@ ...@@ -2239,7 +2035,7 @@
{ {
/* Keeps us from having to do this for each rule */ /* Keeps us from having to do this for each rule */
error = Get_Class( &csf2->ClassDef, s_in[j], &classes[i], NULL ); error = Get_Class( &csf2->ClassDef, IN_CURGLYPH( j ), &classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
known_classes = i; known_classes = i;
...@@ -2253,7 +2049,7 @@ ...@@ -2253,7 +2049,7 @@
{ {
error = Do_ContextSubst( gsub, sr->GlyphCount, error = Do_ContextSubst( gsub, sr->GlyphCount,
sr->SubstCount, sr->SubstLookupRecord, sr->SubstCount, sr->SubstLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
goto End; goto End;
} }
...@@ -2270,15 +2066,13 @@ ...@@ -2270,15 +2066,13 @@
static FT_Error Lookup_ContextSubst3( static FT_Error Lookup_ContextSubst3(
TTO_GSUBHeader* gsub, TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat3* csf3, TTO_ContextSubstFormat3* csf3,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
{ {
FT_Error error; FT_Error error;
FT_UShort index, i, j, property; FT_UShort index, i, j, property;
FT_UShort* s_in;
TTO_Coverage* c; TTO_Coverage* c;
TTO_GDEFHeader* gdef; TTO_GDEFHeader* gdef;
...@@ -2286,47 +2080,45 @@ ...@@ -2286,47 +2080,45 @@
gdef = gsub->gdef; gdef = gsub->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
if ( context_length != 0xFFFF && context_length < csf3->GlyphCount ) if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( in->pos + csf3->GlyphCount > in->length ) if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
return TTO_Err_Not_Covered; /* context is too long */ return TTO_Err_Not_Covered; /* context is too long */
s_in = &in->string[in->pos];
c = csf3->Coverage; c = csf3->Coverage;
for ( i = 1, j = 1; i < csf3->GlyphCount; i++, j++ ) for ( i = 1, j = 1; i < csf3->GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( in->pos + j < in->length ) if ( buffer->in_pos + j < buffer->in_length )
j++; j++;
else else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &c[i], s_in[j], &index ); error = Coverage_Index( &c[i], IN_CURGLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
return Do_ContextSubst( gsub, csf3->GlyphCount, return Do_ContextSubst( gsub, csf3->GlyphCount,
csf3->SubstCount, csf3->SubstLookupRecord, csf3->SubstCount, csf3->SubstLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
} }
static FT_Error Lookup_ContextSubst( TTO_GSUBHeader* gsub, static FT_Error Lookup_ContextSubst( TTO_GSUBHeader* gsub,
TTO_ContextSubst* cs, TTO_ContextSubst* cs,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -2334,15 +2126,15 @@ ...@@ -2334,15 +2126,15 @@
switch ( cs->SubstFormat ) switch ( cs->SubstFormat )
{ {
case 1: case 1:
return Lookup_ContextSubst1( gsub, &cs->csf.csf1, in, out, return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer,
flags, context_length, nesting_level ); flags, context_length, nesting_level );
case 2: case 2:
return Lookup_ContextSubst2( gsub, &cs->csf.csf2, in, out, return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer,
flags, context_length, nesting_level ); flags, context_length, nesting_level );
case 3: case 3:
return Lookup_ContextSubst3( gsub, &cs->csf.csf3, in, out, return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer,
flags, context_length, nesting_level ); flags, context_length, nesting_level );
default: default:
...@@ -3377,8 +3169,7 @@ ...@@ -3377,8 +3169,7 @@
static FT_Error Lookup_ChainContextSubst1( static FT_Error Lookup_ChainContextSubst1(
TTO_GSUBHeader* gsub, TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat1* ccsf1, TTO_ChainContextSubstFormat1* ccsf1,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -3387,7 +3178,6 @@ ...@@ -3387,7 +3178,6 @@
FT_UShort i, j, k, num_csr, curr_pos; FT_UShort i, j, k, num_csr, curr_pos;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_Error error; FT_Error error;
FT_UShort* s_in;
TTO_ChainSubRule* csr; TTO_ChainSubRule* csr;
TTO_ChainSubRule curr_csr; TTO_ChainSubRule curr_csr;
...@@ -3396,10 +3186,10 @@ ...@@ -3396,10 +3186,10 @@
gdef = gsub->gdef; gdef = gsub->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
error = Coverage_Index( &ccsf1->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -3418,7 +3208,7 @@ ...@@ -3418,7 +3208,7 @@
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > in->pos || in->pos + igc + lgc > in->length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue; continue;
if ( bgc ) if ( bgc )
...@@ -3427,11 +3217,10 @@ ...@@ -3427,11 +3217,10 @@
we search backwards for matches in the backtrack glyph array */ we search backwards for matches in the backtrack glyph array */
curr_pos = 0; curr_pos = 0;
s_in = &in->string[curr_pos];
for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
...@@ -3452,7 +3241,7 @@ ...@@ -3452,7 +3241,7 @@
Backtrack offsets - 3 2 1 0 Backtrack offsets - 3 2 1 0
Lookahead offsets - 0 1 2 3 */ Lookahead offsets - 0 1 2 3 */
if ( s_in[j] != curr_csr.Backtrack[i] ) if ( IN_GLYPH( j ) != curr_csr.Backtrack[i] )
break; break;
} }
...@@ -3460,25 +3249,24 @@ ...@@ -3460,25 +3249,24 @@
continue; continue;
} }
curr_pos = in->pos; curr_pos = buffer->in_pos;
s_in = &in->string[curr_pos];
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ ) for ( i = 1, j = 1; i < igc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
} }
if ( s_in[j] != curr_csr.Input[i - 1] ) if ( IN_GLYPH( curr_pos + j ) != curr_csr.Input[i - 1] )
break; break;
} }
...@@ -3489,22 +3277,21 @@ ...@@ -3489,22 +3277,21 @@
last context glyph */ last context glyph */
curr_pos += j; curr_pos += j;
s_in = &in->string[curr_pos];
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0, j = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
} }
if ( s_in[j] != curr_csr.Lookahead[i] ) if ( IN_GLYPH( curr_pos + j ) != curr_csr.Lookahead[i] )
break; break;
} }
...@@ -3512,7 +3299,7 @@ ...@@ -3512,7 +3299,7 @@
return Do_ContextSubst( gsub, igc, return Do_ContextSubst( gsub, igc,
curr_csr.SubstCount, curr_csr.SubstCount,
curr_csr.SubstLookupRecord, curr_csr.SubstLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
} }
...@@ -3523,8 +3310,7 @@ ...@@ -3523,8 +3310,7 @@
static FT_Error Lookup_ChainContextSubst2( static FT_Error Lookup_ChainContextSubst2(
TTO_GSUBHeader* gsub, TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat2* ccsf2, TTO_ChainContextSubstFormat2* ccsf2,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -3542,8 +3328,6 @@ ...@@ -3542,8 +3328,6 @@
FT_UShort* input_classes; FT_UShort* input_classes;
FT_UShort* lookahead_classes; FT_UShort* lookahead_classes;
FT_UShort* s_in;
FT_UShort* bc; FT_UShort* bc;
FT_UShort* ic; FT_UShort* ic;
FT_UShort* lc; FT_UShort* lc;
...@@ -3556,14 +3340,14 @@ ...@@ -3556,14 +3340,14 @@
gdef = gsub->gdef; gdef = gsub->gdef;
memory = gsub->memory; memory = gsub->memory;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
/* Note: The coverage table in format 2 doesn't give an index into /* Note: The coverage table in format 2 doesn't give an index into
anything. It just lets us know whether or not we need to anything. It just lets us know whether or not we need to
do any lookup at all. */ do any lookup at all. */
error = Coverage_Index( &ccsf2->Coverage, in->string[in->pos], &index ); error = Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error ) if ( error )
return error; return error;
...@@ -3579,7 +3363,7 @@ ...@@ -3579,7 +3363,7 @@
goto End2; goto End2;
known_lookahead_classes = 0; known_lookahead_classes = 0;
error = Get_Class( &ccsf2->InputClassDef, in->string[in->pos], error = Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH( 0 ),
&input_classes[0], NULL ); &input_classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -3603,7 +3387,7 @@ ...@@ -3603,7 +3387,7 @@
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > in->pos || in->pos + igc + lgc > in->length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue; continue;
if ( bgc ) if ( bgc )
...@@ -3613,12 +3397,11 @@ ...@@ -3613,12 +3397,11 @@
Note that `known_backtrack_classes' starts at index 0. */ Note that `known_backtrack_classes' starts at index 0. */
curr_pos = 0; curr_pos = 0;
s_in = &in->string[curr_pos];
bc = ccsr.Backtrack; bc = ccsr.Backtrack;
for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -3633,7 +3416,7 @@ ...@@ -3633,7 +3416,7 @@
{ {
/* Keeps us from having to do this for each rule */ /* Keeps us from having to do this for each rule */
error = Get_Class( &ccsf2->BacktrackClassDef, s_in[j], error = Get_Class( &ccsf2->BacktrackClassDef, IN_GLYPH( j ),
&backtrack_classes[i], NULL ); &backtrack_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -3648,20 +3431,19 @@ ...@@ -3648,20 +3431,19 @@
continue; continue;
} }
curr_pos = in->pos; curr_pos = buffer->in_pos;
s_in = &in->string[curr_pos];
ic = ccsr.Input; ic = ccsr.Input;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ ) for ( i = 1, j = 1; i < igc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
...@@ -3669,7 +3451,7 @@ ...@@ -3669,7 +3451,7 @@
if ( i >= known_input_classes ) if ( i >= known_input_classes )
{ {
error = Get_Class( &ccsf2->InputClassDef, s_in[j], error = Get_Class( &ccsf2->InputClassDef, IN_GLYPH( curr_pos + j ),
&input_classes[i], NULL ); &input_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -3687,17 +3469,16 @@ ...@@ -3687,17 +3469,16 @@
last context glyph */ last context glyph */
curr_pos += j; curr_pos += j;
s_in = &in->string[curr_pos];
lc = ccsr.Lookahead; lc = ccsr.Lookahead;
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0, j = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
break; break;
...@@ -3705,7 +3486,7 @@ ...@@ -3705,7 +3486,7 @@
if ( i >= known_lookahead_classes ) if ( i >= known_lookahead_classes )
{ {
error = Get_Class( &ccsf2->LookaheadClassDef, s_in[j], error = Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( curr_pos + j ),
&lookahead_classes[i], NULL ); &lookahead_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -3721,7 +3502,7 @@ ...@@ -3721,7 +3502,7 @@
error = Do_ContextSubst( gsub, igc, error = Do_ContextSubst( gsub, igc,
ccsr.SubstCount, ccsr.SubstCount,
ccsr.SubstLookupRecord, ccsr.SubstLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
goto End1; goto End1;
} }
...@@ -3744,8 +3525,7 @@ ...@@ -3744,8 +3525,7 @@
static FT_Error Lookup_ChainContextSubst3( static FT_Error Lookup_ChainContextSubst3(
TTO_GSUBHeader* gsub, TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat3* ccsf3, TTO_ChainContextSubstFormat3* ccsf3,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -3753,7 +3533,6 @@ ...@@ -3753,7 +3533,6 @@
FT_UShort index, i, j, curr_pos, property; FT_UShort index, i, j, curr_pos, property;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_Error error; FT_Error error;
FT_UShort* s_in;
TTO_Coverage* bc; TTO_Coverage* bc;
TTO_Coverage* ic; TTO_Coverage* ic;
...@@ -3763,7 +3542,7 @@ ...@@ -3763,7 +3542,7 @@
gdef = gsub->gdef; gdef = gsub->gdef;
if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error; return error;
bgc = ccsf3->BacktrackGlyphCount; bgc = ccsf3->BacktrackGlyphCount;
...@@ -3775,7 +3554,7 @@ ...@@ -3775,7 +3554,7 @@
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > in->pos || in->pos + igc + lgc > in->length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
if ( bgc ) if ( bgc )
...@@ -3784,12 +3563,11 @@ ...@@ -3784,12 +3563,11 @@
we search backwards for matches in the backtrack glyph array */ we search backwards for matches in the backtrack glyph array */
curr_pos = 0; curr_pos = 0;
s_in = &in->string[curr_pos];
bc = ccsf3->BacktrackCoverage; bc = ccsf3->BacktrackCoverage;
for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
...@@ -3800,31 +3578,30 @@ ...@@ -3800,31 +3578,30 @@
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &bc[i], s_in[j], &index ); error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
} }
curr_pos = in->pos; curr_pos = buffer->in_pos;
s_in = &in->string[curr_pos];
ic = ccsf3->InputCoverage; ic = ccsf3->InputCoverage;
for ( i = 0, j = 0; i < igc; i++, j++ ) for ( i = 0, j = 0; i < igc; i++, j++ )
{ {
/* We already called CHECK_Property for s_in[0] */ /* We already called CHECK_Property for IN_GLYPH( curr_pos ) */
while ( j > 0 && CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &ic[i], s_in[j], &index ); error = Coverage_Index( &ic[i], IN_GLYPH( curr_pos + j ), &index );
if ( error ) if ( error )
return error; return error;
} }
...@@ -3833,23 +3610,22 @@ ...@@ -3833,23 +3610,22 @@
glyph */ glyph */
curr_pos += j; curr_pos += j;
s_in = &in->string[curr_pos];
lc = ccsf3->LookaheadCoverage; lc = ccsf3->LookaheadCoverage;
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0, j = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < in->length ) if ( curr_pos + j < buffer->in_length )
j++; j++;
else else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &lc[i], s_in[j], &index ); error = Coverage_Index( &lc[i], IN_GLYPH( curr_pos + j ), &index );
if ( error ) if ( error )
return error; return error;
} }
...@@ -3857,7 +3633,7 @@ ...@@ -3857,7 +3633,7 @@
return Do_ContextSubst( gsub, igc, return Do_ContextSubst( gsub, igc,
ccsf3->SubstCount, ccsf3->SubstCount,
ccsf3->SubstLookupRecord, ccsf3->SubstLookupRecord,
in, out, buffer,
nesting_level ); nesting_level );
} }
...@@ -3865,8 +3641,7 @@ ...@@ -3865,8 +3641,7 @@
static FT_Error Lookup_ChainContextSubst( static FT_Error Lookup_ChainContextSubst(
TTO_GSUBHeader* gsub, TTO_GSUBHeader* gsub,
TTO_ChainContextSubst* ccs, TTO_ChainContextSubst* ccs,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort flags, FT_UShort flags,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
...@@ -3874,17 +3649,17 @@ ...@@ -3874,17 +3649,17 @@
switch ( ccs->SubstFormat ) switch ( ccs->SubstFormat )
{ {
case 1: case 1:
return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, in, out, return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
case 2: case 2:
return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, in, out, return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
case 3: case 3:
return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, in, out, return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
...@@ -4196,8 +3971,7 @@ ...@@ -4196,8 +3971,7 @@
static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub, static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub,
FT_UShort lookup_index, FT_UShort lookup_index,
TTO_GSUB_String* in, OTL_Buffer buffer,
TTO_GSUB_String* out,
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
{ {
...@@ -4220,39 +3994,39 @@ ...@@ -4220,39 +3994,39 @@
{ {
case GSUB_LOOKUP_SINGLE: case GSUB_LOOKUP_SINGLE:
error = Lookup_SingleSubst( &lo->SubTable[i].st.gsub.single, error = Lookup_SingleSubst( &lo->SubTable[i].st.gsub.single,
in, out, buffer,
flags, context_length, gsub->gdef ); flags, context_length, gsub->gdef );
break; break;
case GSUB_LOOKUP_MULTIPLE: case GSUB_LOOKUP_MULTIPLE:
error = Lookup_MultipleSubst( &lo->SubTable[i].st.gsub.multiple, error = Lookup_MultipleSubst( &lo->SubTable[i].st.gsub.multiple,
in, out, buffer,
flags, context_length, gsub->gdef ); flags, context_length, gsub->gdef );
break; break;
case GSUB_LOOKUP_ALTERNATE: case GSUB_LOOKUP_ALTERNATE:
error = Lookup_AlternateSubst( gsub, error = Lookup_AlternateSubst( gsub,
&lo->SubTable[i].st.gsub.alternate, &lo->SubTable[i].st.gsub.alternate,
in, out, buffer,
flags, context_length, gsub->gdef ); flags, context_length, gsub->gdef );
break; break;
case GSUB_LOOKUP_LIGATURE: case GSUB_LOOKUP_LIGATURE:
error = Lookup_LigatureSubst( &lo->SubTable[i].st.gsub.ligature, error = Lookup_LigatureSubst( &lo->SubTable[i].st.gsub.ligature,
in, out, buffer,
flags, context_length, gsub->gdef ); flags, context_length, gsub->gdef );
break; break;
case GSUB_LOOKUP_CONTEXT: case GSUB_LOOKUP_CONTEXT:
error = Lookup_ContextSubst( gsub, &lo->SubTable[i].st.gsub.context, error = Lookup_ContextSubst( gsub, &lo->SubTable[i].st.gsub.context,
in, out, buffer,
flags, context_length, nesting_level ); flags, context_length, nesting_level );
break; break;
case GSUB_LOOKUP_CHAIN: case GSUB_LOOKUP_CHAIN:
error = Lookup_ChainContextSubst( gsub, error = Lookup_ChainContextSubst( gsub,
&lo->SubTable[i].st.gsub.chain, &lo->SubTable[i].st.gsub.chain,
in, out, buffer,
flags, context_length, flags, context_length,
nesting_level ); nesting_level );
break; break;
...@@ -4268,29 +4042,25 @@ ...@@ -4268,29 +4042,25 @@
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
} }
/* apply one lookup to the input string object */ /* apply one lookup to the input string object */
static FT_Error Do_String_Lookup( TTO_GSUBHeader* gsub, static FT_Error Do_String_Lookup( TTO_GSUBHeader* gsub,
FT_UShort lookup_index, FT_UShort lookup_index,
TTO_GSUB_String* in, OTL_Buffer buffer )
TTO_GSUB_String* out )
{ {
FT_Error error, retError = TTO_Err_Not_Covered; FT_Error error, retError = TTO_Err_Not_Covered;
FT_UShort* properties = gsub->LookupList.Properties; FT_UShort* properties = gsub->LookupList.Properties;
FT_UShort* p_in = in->properties;
FT_UShort* s_in = in->string;
int nesting_level = 0; int nesting_level = 0;
while ( in->pos < in->length ) while ( buffer->in_pos < buffer->in_length )
{ {
if ( ~p_in[in->pos] & properties[lookup_index] ) if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
{ {
/* 0xFFFF indicates that we don't have a context length yet */ /* 0xFFFF indicates that we don't have a context length yet */
error = Do_Glyph_Lookup( gsub, lookup_index, in, out, error = Do_Glyph_Lookup( gsub, lookup_index, buffer,
0xFFFF, nesting_level ); 0xFFFF, nesting_level );
if ( error ) if ( error )
{ {
...@@ -4304,7 +4074,7 @@ ...@@ -4304,7 +4074,7 @@
error = TTO_Err_Not_Covered; error = TTO_Err_Not_Covered;
if ( error == TTO_Err_Not_Covered ) if ( error == TTO_Err_Not_Covered )
if ( ADD_String( in, 1, out, 1, &s_in[in->pos], 0xFFFF, 0xFFFF ) ) if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ), 0xFFFF, 0xFFFF ) )
return error; return error;
} }
...@@ -4375,149 +4145,25 @@ ...@@ -4375,149 +4145,25 @@
} }
EXPORT_FUNC
FT_Error TT_GSUB_String_New( FT_Memory memory,
TTO_GSUB_String **result )
{
FT_Error error;
TTO_GSUB_String *str;
if ( ALLOC( str, sizeof( *str ) ) )
return error;
str->memory = memory;
str->length = 0;
str->allocated = 0;
str->pos = 0;
str->string = NULL;
str->properties = NULL;
str->components = NULL;
str->max_ligID = 0;
str->ligIDs = 0;
str->logClusters = 0;
*result = str;
return TT_Err_Ok;
}
EXPORT_DEF
FT_Error TT_GSUB_String_Set_Length( TTO_GSUB_String *str,
FT_ULong new_length)
{
FT_Memory memory = str->memory;
FT_Error error;
if ( new_length > str->allocated )
{
if ( REALLOC_ARRAY( str->string, str->allocated, new_length, FT_UShort ) )
return error;
if ( REALLOC_ARRAY( str->properties, str->allocated, new_length, FT_UShort ) )
return error;
if ( REALLOC_ARRAY( str->components, str->allocated, new_length, FT_UShort ) )
return error;
if ( REALLOC_ARRAY( str->ligIDs, str->allocated, new_length, FT_UShort ) )
return error;
if ( REALLOC_ARRAY( str->logClusters, str->allocated, new_length, FT_Int ) )
return error;
str->allocated = new_length;
str->length = new_length;
}
return TT_Err_Ok;
}
EXPORT_FUNC
FT_Error TT_GSUB_String_Done( TTO_GSUB_String *str )
{
FT_Memory memory = str->memory;
FREE( str->string );
FREE( str->properties );
FREE( str->components );
FREE( str->ligIDs );
FREE( str->logClusters );
FREE( str );
return TT_Err_Ok;
}
EXPORT_FUNC EXPORT_FUNC
FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub, FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub,
TTO_GSUB_String* in, OTL_Buffer buffer )
TTO_GSUB_String* out )
{ {
FT_Error error, retError = TTO_Err_Not_Covered; FT_Error error, retError = TTO_Err_Not_Covered;
FT_Memory memory = in->memory;
FT_UShort j; FT_UShort j;
TTO_GSUB_String tmp1;
TTO_GSUB_String* ptmp1;
TTO_GSUB_String tmp2;
TTO_GSUB_String* ptmp2;
TTO_GSUB_String* t;
FT_UShort* properties; FT_UShort* properties;
if ( !gsub || if ( !gsub ||
!in || !out || in->length == 0 || in->pos >= in->length ) !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
return TT_Err_Invalid_Argument; return TT_Err_Invalid_Argument;
properties = gsub->LookupList.Properties; properties = gsub->LookupList.Properties;
tmp1.memory = memory;
tmp1.length = in->length;
tmp1.allocated = in->length;
tmp1.pos = in->pos;
tmp1.max_ligID = 1;
tmp1.string = NULL;
tmp1.properties = NULL;
tmp1.components = NULL;
tmp1.ligIDs = NULL;
tmp1.logClusters = NULL;
tmp2.memory = memory;
tmp2.allocated = 0;
tmp2.pos = 0;
tmp2.string = NULL;
tmp2.properties = NULL;
tmp2.components = NULL;
tmp2.ligIDs = NULL;
tmp2.logClusters = NULL;
ptmp1 = &tmp1;
ptmp2 = &tmp2;
if ( ALLOC_ARRAY( tmp1.string, tmp1.length, FT_UShort ) )
return error;
MEM_Copy( tmp1.string, in->string, in->length * sizeof ( FT_UShort ) );
/* make sure that we always have a `properties', `components', and
`ligIDs' array in the string object */
if ( ALLOC_ARRAY( tmp1.components, tmp1.length, FT_UShort ) )
goto End;
if ( ALLOC_ARRAY( tmp1.ligIDs, tmp1.length, FT_UShort ) )
goto End;
if ( ALLOC_ARRAY( tmp1.properties, tmp1.length, FT_UShort ) )
goto End;
if ( in->properties )
MEM_Copy( tmp1.properties, in->properties,
in->length * sizeof( FT_UShort ) );
if ( ALLOC_ARRAY( tmp1.logClusters, tmp1.length, FT_Int ) )
goto End;
MEM_Copy( tmp1.logClusters, in->logClusters,
in->length * sizeof( FT_Int ) );
for ( j = 0; j < gsub->LookupList.LookupCount; j++ ) for ( j = 0; j < gsub->LookupList.LookupCount; j++ )
if ( properties[j] ) if ( properties[j] )
{ {
error = Do_String_Lookup( gsub, j, ptmp1, ptmp2 ); error = Do_String_Lookup( gsub, j, buffer );
if ( error ) if ( error )
{ {
if ( error != TTO_Err_Not_Covered ) if ( error != TTO_Err_Not_Covered )
...@@ -4526,56 +4172,15 @@ ...@@ -4526,56 +4172,15 @@
else else
retError = error; retError = error;
error = otl_buffer_swap( buffer );
/* flipping `in' and `out', preparing the next loop */ if ( error )
goto End;
ptmp1->pos = in->pos;
ptmp2->length = ptmp2->pos;
ptmp2->pos = in->pos;
ptmp2->max_ligID = ptmp1->max_ligID;
t = ptmp2;
ptmp2 = ptmp1;
ptmp1 = t;
} }
error = retError;
End: End:
FREE( ptmp2->string ); return error;
FREE( ptmp2->properties );
FREE( ptmp2->components );
FREE( ptmp2->ligIDs );
FREE( ptmp2->logClusters );
if ( error && error != TTO_Err_Not_Covered )
{
FREE( ptmp1->string );
FREE( ptmp1->components );
FREE( ptmp1->ligIDs );
FREE( ptmp1->properties );
FREE( ptmp1->logClusters );
return error;
}
else
{
out->length = ptmp1->length;
out->pos = 0;
out->allocated = ptmp1->allocated;
out->string = ptmp1->string;
out->components = ptmp1->components;
out->ligIDs = ptmp1->ligIDs;
out->logClusters = ptmp1->logClusters;
if ( in->properties )
out->properties = ptmp1->properties;
else
{
FREE( ptmp1->properties );
out->properties = NULL;
}
return retError;
}
} }
......
...@@ -504,23 +504,6 @@ extern "C" { ...@@ -504,23 +504,6 @@ extern "C" {
TT_Add_String() will also handle allocation; you should use TT_Add_String() will also handle allocation; you should use
free() in case you want to destroy the arrays in the object. */ free() in case you want to destroy the arrays in the object. */
struct TTO_GSUB_String_
{
FT_Memory memory;
FT_ULong length;
FT_ULong pos;
FT_ULong allocated;
FT_UShort* string;
FT_UShort* properties;
FT_UShort* components;
FT_UShort max_ligID;
FT_UShort* ligIDs;
FT_Int* logClusters;
};
typedef struct TTO_GSUB_String_ TTO_GSUB_String;
/* finally, the GSUB API */ /* finally, the GSUB API */
...@@ -577,31 +560,10 @@ extern "C" { ...@@ -577,31 +560,10 @@ extern "C" {
TTO_AltFunction altfunc, TTO_AltFunction altfunc,
void* data ); void* data );
EXPORT_DEF
FT_Error TT_GSUB_String_New( FT_Memory memory,
TTO_GSUB_String **result );
EXPORT_DEF
FT_Error TT_GSUB_String_Set_Length( TTO_GSUB_String *str,
FT_ULong new_length);
EXPORT_DEF
FT_Error TT_GSUB_String_Done( TTO_GSUB_String *str );
EXPORT_DEF EXPORT_DEF
FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub, FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub,
TTO_GSUB_String* in, OTL_Buffer buffer );
TTO_GSUB_String* out );
EXPORT_DEF
FT_Error TT_GSUB_Add_String( TTO_GSUB_String* in,
FT_UShort num_in,
TTO_GSUB_String* out,
FT_UShort num_out,
FT_UShort* glyph_data,
FT_UShort component,
FT_UShort ligID );
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -280,6 +280,7 @@ extern "C" { ...@@ -280,6 +280,7 @@ extern "C" {
typedef struct TTO_Device_ TTO_Device; typedef struct TTO_Device_ TTO_Device;
#include "otlbuffer.h"
#include "ftxgdef.h" #include "ftxgdef.h"
#include "ftxgsub.h" #include "ftxgsub.h"
#include "ftxgpos.h" #include "ftxgpos.h"
......
/* otlbuffer.c: Buffer of glyphs for substitution/positioning
*
* Copyright 2004 Red Hat Software
*
* Portions Copyright 1996-2000 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
* modified and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*/
#include <otlbuffer.h>
#include FT_INTERNAL_MEMORY_H
static FT_Error
otl_buffer_ensure( OTL_Buffer buffer,
FT_ULong size )
{
FT_Memory memory = buffer->memory;
FT_ULong new_allocated = buffer->allocated;
if (size > new_allocated)
{
FT_Error error;
while (size > new_allocated)
new_allocated += (new_allocated >> 1) + 8;
if ( FT_REALLOC_ARRAY( buffer->in_string, buffer->allocated, new_allocated, OTL_GlyphItemRec ) )
return error;
if ( FT_REALLOC_ARRAY( buffer->out_string, buffer->allocated, new_allocated, OTL_GlyphItemRec ) )
return error;
if ( FT_REALLOC_ARRAY( buffer->positions, buffer->allocated, new_allocated, OTL_PositionRec ) )
return error;
buffer->allocated = new_allocated;
}
return FT_Err_Ok;
}
FT_Error
otl_buffer_new( FT_Memory memory,
OTL_Buffer *buffer )
{
FT_Error error;
if ( FT_ALLOC( *buffer, sizeof( OTL_BufferRec ) ) )
return error;
(*buffer)->memory = memory;
(*buffer)->in_length = 0;
(*buffer)->out_length = 0;
(*buffer)->allocated = 0;
(*buffer)->in_pos = 0;
(*buffer)->out_pos = 0;
(*buffer)->in_string = NULL;
(*buffer)->out_string = NULL;
(*buffer)->positions = NULL;
(*buffer)->max_ligID = 0;
return FT_Err_Ok;
}
FT_Error
otl_buffer_swap( OTL_Buffer buffer )
{
OTL_GlyphItem tmp_string;
tmp_string = buffer->in_string;
buffer->in_string = buffer->out_string;
buffer->out_string = tmp_string;
buffer->in_length = buffer->out_length;
buffer->out_length = 0;
buffer->in_pos = 0;
buffer->out_pos = 0;
return FT_Err_Ok;
}
FT_Error
otl_buffer_free( OTL_Buffer buffer )
{
FT_Memory memory = buffer->memory;
FT_FREE( buffer->in_string );
FT_FREE( buffer->out_string );
FT_FREE( buffer );
return FT_Err_Ok;
}
FT_Error
otl_buffer_clear( OTL_Buffer buffer )
{
buffer->in_length = 0;
buffer->out_length = 0;
buffer->in_pos = 0;
buffer->out_pos = 0;
return FT_Err_Ok;
}
FT_Error
otl_buffer_add_glyph( OTL_Buffer buffer,
FT_UInt glyph_index,
FT_UInt properties,
FT_UInt cluster )
{
FT_Error error;
OTL_GlyphItem glyph;
error = otl_buffer_ensure( buffer, buffer->in_length + 1 );
if ( error != FT_Err_Ok )
return error;
glyph = &buffer->in_string[buffer->in_length];
glyph->gindex = glyph_index;
glyph->properties = properties;
glyph->cluster = cluster;
glyph->component = 0;
glyph->ligID = 0;
buffer->in_length++;
return FT_Err_Ok;
}
/* The following function copies `num_out' elements from `glyph_data'
to `buffer->out_string', advancing the in array pointer in the structure
by `num_in' elements, and the out array pointer by `num_out' elements.
Finally, it sets the `length' field of `out' equal to
`pos' of the `out' structure.
If `component' is 0xFFFF, the component value from buffer->in_pos
will copied `num_out' times, otherwise `component' itself will
be used to fill the `component' fields.
If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
will copied `num_out' times, otherwise `ligID' itself will
be used to fill the `ligID' fields.
The properties for all replacement glyphs are taken
from the glyph at position `buffer->in_pos'.
The cluster value for the glyph at position buffer->in_pos is used
for all replacement glyphs */
FT_Error
otl_buffer_add_output_glyphs( OTL_Buffer buffer,
FT_UShort num_in,
FT_UShort num_out,
FT_UShort *glyph_data,
FT_UShort component,
FT_UShort ligID )
{
FT_Error error;
FT_UShort i;
FT_UInt properties;
FT_UInt cluster;
error = otl_buffer_ensure( buffer, buffer->out_pos + num_out );
if ( error != FT_Err_Ok )
return error;
properties = buffer->in_string[buffer->in_pos].properties;
cluster = buffer->in_string[buffer->in_pos].cluster;
if ( component == 0xFFFF )
component = buffer->in_string[buffer->in_pos].component;
if ( ligID == 0xFFFF )
ligID = buffer->in_string[buffer->in_pos].ligID;
for ( i = 0; i < num_out; i++ )
{
OTL_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
item->gindex = glyph_data[i];
item->properties = properties;
item->cluster = cluster;
item->component = component;
item->ligID = ligID;
}
buffer->in_pos += num_in;
buffer->out_pos += num_out;
buffer->out_length = buffer->out_pos;
return FT_Err_Ok;
}
FT_Error
otl_buffer_add_output_glyph( OTL_Buffer buffer,
FT_UInt glyph_index,
FT_UShort component,
FT_UShort ligID )
{
FT_UShort glyph_data = glyph_index;
return otl_buffer_add_output_glyphs ( buffer, 1, 1,
&glyph_data, component, ligID );
}
FT_UShort
otl_buffer_allocate_ligid( OTL_Buffer buffer )
{
return buffer->max_ligID++;
}
/* otlbuffer.h: Buffer of glyphs for substitution/positioning
*
* Copyrigh 2004 Red Hat Software
*
* Portions Copyright 1996-2000 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
* modified and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*/
#include <ft2build.h>
#include FT_FREETYPE_H
#include <glib.h>
G_BEGIN_DECLS
typedef struct OTL_GlyphItemRec_ {
FT_UInt gindex;
FT_UInt properties;
FT_UInt cluster;
FT_UShort component;
FT_UShort ligID;
} OTL_GlyphItemRec, *OTL_GlyphItem;
typedef struct OTL_PositionRec_ {
FT_Pos x_pos;
FT_Pos y_pos;
FT_Pos x_advance;
FT_Pos y_advance;
FT_UShort back; /* number of glyphs to go back
for drawing current glyph */
FT_Bool new_advance; /* if set, the advance width values are
absolute, i.e., they won't be
added to the original glyph's value
but rather replace them. */
FT_Short cursive_chain; /* character to which this connects,
may be positive or negative; used
only internally */
} OTL_PositionRec, *OTL_Position;
typedef struct OTL_BufferRec_{
FT_Memory memory;
FT_ULong allocated;
FT_ULong in_length;
FT_ULong out_length;
FT_ULong in_pos;
FT_ULong out_pos;
OTL_GlyphItem in_string;
OTL_GlyphItem out_string;
OTL_Position positions;
FT_UShort max_ligID;
} OTL_BufferRec, *OTL_Buffer;
FT_Error
otl_buffer_new( FT_Memory memory,
OTL_Buffer *buffer );
FT_Error
otl_buffer_swap( OTL_Buffer buffer );
FT_Error
otl_buffer_free( OTL_Buffer buffer );
FT_Error
otl_buffer_clear( OTL_Buffer buffer );
FT_Error
otl_buffer_add_glyph( OTL_Buffer buffer,
FT_UInt glyph_index,
FT_UInt properties,
FT_UInt cluster );
FT_Error
otl_buffer_add_output_glyphs( OTL_Buffer buffer,
FT_UShort num_in,
FT_UShort num_out,
FT_UShort *glyph_data,
FT_UShort component,
FT_UShort ligID );
FT_Error
otl_buffer_add_output_glyph ( OTL_Buffer buffer,
FT_UInt glyph_index,
FT_UShort component,
FT_UShort ligID );
FT_UShort
otl_buffer_allocate_ligid( OTL_Buffer buffer );
G_END_DECLS
...@@ -145,6 +145,7 @@ add_features (TTO_GSUB gsub) ...@@ -145,6 +145,7 @@ add_features (TTO_GSUB gsub)
maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('l', 'i', 'g', 'a'), L); maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('l', 'i', 'g', 'a'), L);
} }
#if 0
void void
dump_string (TTO_GSUB_String *str) dump_string (TTO_GSUB_String *str)
{ {
...@@ -203,6 +204,7 @@ try_string (FT_Library library, ...@@ -203,6 +204,7 @@ try_string (FT_Library library,
if ((error = TT_GSUB_String_Done (out_str))) if ((error = TT_GSUB_String_Done (out_str)))
croak ("TT_GSUB_String_New", error); croak ("TT_GSUB_String_New", error);
} }
#endif
int int
main (int argc, char **argv) main (int argc, char **argv)
......
/* Pango
* pango-ot-buffer.c: Buffer of glyphs for shaping/positioning
*
* Copyright (C) 2004 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "pango-ot-private.h"
#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6))
#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d))
PangoOTBuffer *
pango_ot_buffer_new (PangoFcFont *font)
{
/* We lock the font here immediately for the silly reason
* of getting the FT_Memory; otherwise we'd have to
* add a new operation to PangoFcFontmap; callers will
* probably already have the font locked, however,
* so there is little performance penalty.
*/
PangoOTBuffer *buffer = g_new (PangoOTBuffer, 1);
FT_Face face = pango_fc_font_lock_face (font);
if (otl_buffer_new (face->memory, &buffer->buffer) != FT_Err_Ok)
g_error ("Allocation of OTLBuffer failed");
buffer->font = g_object_ref (font);
buffer->applied_gpos = FALSE;
buffer->rtl = FALSE;
pango_fc_font_unlock_face (font);
return buffer;
}
void
pango_ot_buffer_destroy (PangoOTBuffer *buffer)
{
otl_buffer_free (buffer->buffer);
g_object_unref (buffer->font);
g_free (buffer);
}
void
pango_ot_buffer_clear (PangoOTBuffer *buffer)
{
otl_buffer_clear (buffer->buffer);
buffer->applied_gpos = FALSE;
}
void
pango_ot_buffer_add_glyph (PangoOTBuffer *buffer,
guint glyph_index,
guint properties,
guint cluster)
{
otl_buffer_add_glyph (buffer->buffer,
glyph_index, properties, cluster);
}
void
pango_ot_buffer_set_rtl (PangoOTBuffer *buffer,
gboolean rtl)
{
rtl = rtl != FALSE;
buffer->rtl = rtl;
}
void
pango_ot_buffer_get_glyphs (PangoOTBuffer *buffer,
PangoOTGlyph **glyphs,
int *n_glyphs)
{
if (glyphs)
*glyphs = (PangoOTGlyph *)buffer->buffer->in_string;
if (n_glyphs)
*n_glyphs = buffer->buffer->in_length;
}
static void
swap_range (PangoGlyphString *glyphs, int start, int end)
{
int i, j;
for (i = start, j = end - 1; i < j; i++, j--)
{
PangoGlyphInfo glyph_info;
gint log_cluster;
glyph_info = glyphs->glyphs[i];
glyphs->glyphs[i] = glyphs->glyphs[j];
glyphs->glyphs[j] = glyph_info;
log_cluster = glyphs->log_clusters[i];
glyphs->log_clusters[i] = glyphs->log_clusters[j];
glyphs->log_clusters[j] = log_cluster;
}
}
static void
apply_gpos_ltr (PangoGlyphString *glyphs,
OTL_Position positions)
{
int i;
for (i = 0; i < glyphs->num_glyphs; i++)
{
FT_Pos x_pos = positions[i].x_pos;
FT_Pos y_pos = positions[i].y_pos;
int back = i;
int j;
while (positions[back].back != 0)
{
back -= positions[back].back;
x_pos += positions[back].x_pos;
y_pos += positions[back].y_pos;
}
for (j = back; j < i; j++)
glyphs->glyphs[i].geometry.x_offset -= glyphs->glyphs[j].geometry.width;
glyphs->glyphs[i].geometry.x_offset += PANGO_UNITS_26_6(x_pos);
glyphs->glyphs[i].geometry.y_offset += PANGO_UNITS_26_6(y_pos);
if (positions[i].new_advance)
glyphs->glyphs[i].geometry.width = PANGO_UNITS_26_6(positions[i].x_advance);
else
glyphs->glyphs[i].geometry.width += PANGO_UNITS_26_6(positions[i].x_advance);
}
}
static void
apply_gpos_rtl (PangoGlyphString *glyphs,
OTL_Position positions)
{
int i;
for (i = 0; i < glyphs->num_glyphs; i++)
{
int i_rev = glyphs->num_glyphs - i - 1;
int back_rev = i_rev;
int back;
FT_Pos x_pos = positions[i_rev].x_pos;
FT_Pos y_pos = positions[i_rev].y_pos;
int j;
while (positions[back_rev].back != 0)
{
back_rev -= positions[back_rev].back;
x_pos += positions[back_rev].x_pos;
y_pos += positions[back_rev].y_pos;
}
back = glyphs->num_glyphs - back_rev - 1;
for (j = i; j < back; j++)
glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[j].geometry.width;
glyphs->glyphs[i].geometry.x_offset += PANGO_UNITS_26_6(x_pos);
glyphs->glyphs[i].geometry.y_offset -= PANGO_UNITS_26_6(y_pos);
if (positions[i_rev].new_advance)
glyphs->glyphs[i].geometry.width = PANGO_UNITS_26_6(positions[i_rev].x_advance);
else
glyphs->glyphs[i].geometry.width += PANGO_UNITS_26_6(positions[i_rev].x_advance);
}
}
void
pango_ot_buffer_output (PangoOTBuffer *buffer,
PangoGlyphString *glyphs)
{
FT_Face face;
PangoOTInfo *info;
TTO_GDEF gdef = NULL;
int i;
int last_cluster;
face = pango_fc_font_lock_face (buffer->font);
g_assert (face);
/* Copy glyphs into output glyph string */
pango_glyph_string_set_size (glyphs, buffer->buffer->in_length);
last_cluster = -1;
for (i = 0; i < buffer->buffer->in_length; i++)
{
OTL_GlyphItem item = &buffer->buffer->in_string[i];
glyphs->glyphs[i].glyph = item->gindex;
glyphs->log_clusters[i] = item->cluster;
if (glyphs->log_clusters[i] != last_cluster)
glyphs->glyphs[i].attr.is_cluster_start = 1;
else
glyphs->glyphs[i].attr.is_cluster_start = 0;
last_cluster = glyphs->log_clusters[i];
}
info = pango_ot_info_get (face);
gdef = pango_ot_info_get_gdef (info);
/* Apply default positioning */
for (i = 0; i < glyphs->num_glyphs; i++)
{
if (glyphs->glyphs[i].glyph)
{
PangoRectangle logical_rect;
FT_UShort property;
if (gdef &&
TT_GDEF_Get_Glyph_Property (gdef, glyphs->glyphs[i].glyph, &property) == FT_Err_Ok &&
(property == TTO_MARK || (property & IGNORE_SPECIAL_MARKS) != 0))
{
glyphs->glyphs[i].geometry.width = 0;
}
else
{
pango_font_get_glyph_extents ((PangoFont *)buffer->font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
glyphs->glyphs[i].geometry.width = logical_rect.width;
}
}
else
glyphs->glyphs[i].geometry.width = 0;
glyphs->glyphs[i].geometry.x_offset = 0;
glyphs->glyphs[i].geometry.y_offset = 0;
}
if (buffer->rtl)
{
/* Swap all glyphs */
swap_range (glyphs, 0, glyphs->num_glyphs);
}
if (buffer->applied_gpos)
{
if (buffer->rtl)
apply_gpos_rtl (glyphs, buffer->buffer->positions);
else
apply_gpos_ltr (glyphs, buffer->buffer->positions);
}
pango_fc_font_unlock_face (buffer->font);
}
...@@ -162,17 +162,31 @@ compare_glyph_info (gconstpointer a, ...@@ -162,17 +162,31 @@ compare_glyph_info (gconstpointer a,
/* Make a guess at the appropriate class for a glyph given /* Make a guess at the appropriate class for a glyph given
* a character code that maps to the glyph * a character code that maps to the glyph
*/ */
static FT_UShort static gboolean
get_glyph_class (gunichar charcode) get_glyph_class (gunichar charcode,
FT_UShort *class)
{ {
/* For characters mapped into the Arabic Presentation forms, using properties
* derived as we apply GSUB substitutions will be more reliable
*/
if ((charcode >= 0xFB50 && charcode <= 0xFDFF) || /* Arabic Presentation Forms-A */
(charcode >= 0xFE70 && charcode <= 0XFEFF)) /* Arabic Presentation Forms-B */
return FALSE;
switch (g_unichar_type (charcode)) switch (g_unichar_type (charcode))
{ {
case G_UNICODE_COMBINING_MARK: case G_UNICODE_COMBINING_MARK:
case G_UNICODE_ENCLOSING_MARK: case G_UNICODE_ENCLOSING_MARK:
case G_UNICODE_NON_SPACING_MARK: case G_UNICODE_NON_SPACING_MARK:
return 3; /* Mark glyph (non-spacing combining glyph) */ *class = 3; /* Mark glyph (non-spacing combining glyph) */
return TRUE;
case G_UNICODE_UNASSIGNED:
case G_UNICODE_PRIVATE_USE:
return FALSE; /* Unknown, don't assign a class; classes get
* propagated during GSUB application */
default: default:
return 1; /* Base glyph (single character, spacing glyph) */ *class = 1; /* Base glyph (single character, spacing glyph) */
return TRUE;
} }
} }
...@@ -225,9 +239,8 @@ synthesize_class_def (PangoOTInfo *info) ...@@ -225,9 +239,8 @@ synthesize_class_def (PangoOTInfo *info)
if (glyph <= 65535) if (glyph <= 65535)
{ {
glyph_info.glyph = glyph; glyph_info.glyph = glyph;
glyph_info.class = get_glyph_class (charcode); if (get_glyph_class (charcode, &glyph_info.class))
g_array_append_val (glyph_infos, glyph_info);
g_array_append_val (glyph_infos, glyph_info);
} }
charcode = FT_Get_Next_Char (info->face, charcode, &glyph); charcode = FT_Get_Next_Char (info->face, charcode, &glyph);
......
...@@ -80,6 +80,14 @@ struct _PangoOTRulesetClass ...@@ -80,6 +80,14 @@ struct _PangoOTRulesetClass
GObjectClass parent_class; GObjectClass parent_class;
}; };
struct _PangoOTBuffer
{
OTL_Buffer buffer;
PangoFcFont *font;
gboolean rtl;
gboolean applied_gpos;
};
GType pango_ot_info_get_type (void); GType pango_ot_info_get_type (void);
TTO_GDEF pango_ot_info_get_gdef (PangoOTInfo *info); TTO_GDEF pango_ot_info_get_gdef (PangoOTInfo *info);
......
...@@ -24,9 +24,6 @@ ...@@ -24,9 +24,6 @@
#include FT_INTERNAL_MEMORY_H /* For FT_Free() */ #include FT_INTERNAL_MEMORY_H /* For FT_Free() */
#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6))
#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d))
typedef struct _PangoOTRule PangoOTRule; typedef struct _PangoOTRule PangoOTRule;
struct _PangoOTRule struct _PangoOTRule
...@@ -139,34 +136,15 @@ pango_ot_ruleset_add_feature (PangoOTRuleset *ruleset, ...@@ -139,34 +136,15 @@ pango_ot_ruleset_add_feature (PangoOTRuleset *ruleset,
g_array_append_val (ruleset->rules, tmp_rule); g_array_append_val (ruleset->rules, tmp_rule);
} }
/**
* pango_ot_ruleset_shape:
* @ruleset: a #PangoOTRuleset.
* @glyphs: a pointer to a #PangoGlyphString.
* @properties: an array containing one #gulong bitfield for each glyph,
* which gives the glyph's properties: If a certain bit is set for a glyph,
* the feature which has the same bit set in its property value is applied.
*
* Shapes a string of glyphs with the given properties according to @ruleset.
**/
void void
pango_ot_ruleset_shape (PangoOTRuleset *ruleset, pango_ot_ruleset_substitute (PangoOTRuleset *ruleset,
PangoGlyphString *glyphs, PangoOTBuffer *buffer)
gulong *properties)
{ {
int i; int i;
int last_cluster;
int result;
TTO_GSUB gsub = NULL; TTO_GSUB gsub = NULL;
TTO_GPOS gpos = NULL;
TTO_GSUB_String *in_string = NULL;
TTO_GSUB_String *out_string = NULL;
TTO_GSUB_String *result_string = NULL;
gboolean need_gsub = FALSE; gboolean need_gsub = FALSE;
gboolean need_gpos = FALSE;
g_return_if_fail (PANGO_OT_IS_RULESET (ruleset)); g_return_if_fail (PANGO_OT_IS_RULESET (ruleset));
...@@ -176,26 +154,17 @@ pango_ot_ruleset_shape (PangoOTRuleset *ruleset, ...@@ -176,26 +154,17 @@ pango_ot_ruleset_shape (PangoOTRuleset *ruleset,
if (rule->table_type == PANGO_OT_TABLE_GSUB) if (rule->table_type == PANGO_OT_TABLE_GSUB)
need_gsub = TRUE; need_gsub = TRUE;
else
need_gpos = TRUE;
} }
if (need_gsub) if (need_gsub)
{ {
gsub = pango_ot_info_get_gsub (ruleset->info); gsub = pango_ot_info_get_gsub (ruleset->info);
if (gsub) if (gsub)
TT_GSUB_Clear_Features (gsub); TT_GSUB_Clear_Features (gsub);
} }
if (need_gpos)
{
gpos = pango_ot_info_get_gpos (ruleset->info);
if (gpos)
TT_GPOS_Clear_Features (gpos);
}
for (i = 0; i < ruleset->rules->len; i++) for (i = 0; i < ruleset->rules->len; i++)
{ {
PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i); PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
...@@ -205,98 +174,59 @@ pango_ot_ruleset_shape (PangoOTRuleset *ruleset, ...@@ -205,98 +174,59 @@ pango_ot_ruleset_shape (PangoOTRuleset *ruleset,
if (gsub) if (gsub)
TT_GSUB_Add_Feature (gsub, rule->feature_index, rule->property_bit); TT_GSUB_Add_Feature (gsub, rule->feature_index, rule->property_bit);
} }
else
{
if (gpos)
TT_GPOS_Add_Feature (gpos, rule->feature_index, rule->property_bit);
}
} }
if (!gsub && !gpos) if (!gsub)
return; return;
result = TT_GSUB_String_New (ruleset->info->face->memory, &in_string); TT_GSUB_Apply_String (gsub, buffer->buffer);
g_assert (result == FT_Err_Ok); }
result = TT_GSUB_String_Set_Length (in_string, glyphs->num_glyphs);
g_assert (result == FT_Err_Ok);
for (i = 0; i < glyphs->num_glyphs; i++) void
{ pango_ot_ruleset_position (PangoOTRuleset *ruleset,
in_string->string[i] = glyphs->glyphs[i].glyph; PangoOTBuffer *buffer)
in_string->properties[i] = properties[i]; {
in_string->logClusters[i] = glyphs->log_clusters[i]; int i;
}
in_string->max_ligID = i; TTO_GPOS gpos = NULL;
if (gsub) gboolean need_gpos = FALSE;
g_return_if_fail (PANGO_OT_IS_RULESET (ruleset));
for (i = 0; i < ruleset->rules->len; i++)
{ {
result = TT_GSUB_String_New (ruleset->info->face->memory, PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
&out_string);
g_assert (result == FT_Err_Ok);
result_string = out_string;
TT_GSUB_Apply_String (gsub, in_string, out_string); if (rule->table_type == PANGO_OT_TABLE_GPOS)
need_gpos = TRUE;
} }
else
result_string = in_string; if (need_gpos)
gpos = pango_ot_info_get_gpos (ruleset->info);
if (gpos) if (gpos)
{ {
TTO_GPOS_Data *outgpos = NULL; TT_GPOS_Clear_Features (gpos);
if (!TT_GPOS_Apply_String (ruleset->info->face, gpos, 0, result_string, &outgpos, for (i = 0; i < ruleset->rules->len; i++)
FALSE /* enable device-dependant values */,
FALSE /* Even though this might be r2l text, RTL is handled elsewhere */))
{ {
for (i = 0; i < result_string->length; i++) PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
{
FT_Pos x_pos = outgpos[i].x_pos; if (rule->table_type == PANGO_OT_TABLE_GPOS)
FT_Pos y_pos = outgpos[i].y_pos; TT_GPOS_Add_Feature (gpos, rule->feature_index, rule->property_bit);
int back = i;
int j;
while (outgpos[back].back != 0)
{
back -= outgpos[back].back;
x_pos += outgpos[back].x_pos;
y_pos += outgpos[back].y_pos;
}
for (j = back; j < i; j++)
glyphs->glyphs[i].geometry.x_offset -= glyphs->glyphs[j].geometry.width;
glyphs->glyphs[i].geometry.x_offset += PANGO_UNITS_26_6(x_pos);
glyphs->glyphs[i].geometry.y_offset -= PANGO_UNITS_26_6(y_pos);
if (outgpos[i].new_advance)
glyphs->glyphs[i].geometry.width = PANGO_UNITS_26_6(outgpos[i].x_advance);
else
glyphs->glyphs[i].geometry.width += PANGO_UNITS_26_6(outgpos[i].x_advance);
}
FT_Free(gpos->memory, (void *)outgpos);
} }
} }
pango_glyph_string_set_size (glyphs, result_string->length); /* Apply GPOS rules */
if (gpos)
last_cluster = -1;
for (i = 0; i < result_string->length; i++)
{ {
glyphs->glyphs[i].glyph = result_string->string[i]; if (TT_GPOS_Apply_String (ruleset->info->face, gpos, 0, buffer->buffer,
FALSE /* enable device-dependant values */,
glyphs->log_clusters[i] = result_string->logClusters[i]; buffer->rtl) == FT_Err_Ok)
if (glyphs->log_clusters[i] != last_cluster) {
glyphs->glyphs[i].attr.is_cluster_start = 1; buffer->applied_gpos = TRUE;
else }
glyphs->glyphs[i].attr.is_cluster_start = 0;
last_cluster = glyphs->log_clusters[i];
} }
if (in_string)
TT_GSUB_String_Done (in_string);
if (out_string)
TT_GSUB_String_Done (out_string);
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册