ftxgpos.h \
ftxgsub.c \
ftxgsub.h \
+ otlbuffer.c \
+ otlbuffer.h \
+ pango-ot-buffer.c \
pango-ot-info.c \
pango-ot-private.h \
pango-ot-ruleset.c
if ( glyphID < gcrr[index].Start )
{
- array_index = 0;
+ array_index = index;
if ( index == 0 )
glyph_index = glyphID;
else
if ( glyphID < gcrr[index].Start )
{
- array_index = 0;
+ array_index = index;
if ( index == 0 )
glyph_index = glyphID;
else
FT_UShort load_flags; /* how the glyph should be loaded */
FT_Bool r2l;
- FT_UShort first; /* the first glyph in a chain of
- cursive connections */
FT_UShort last; /* the last valid glyph -- used
with cursive positioning */
FT_Pos anchor_x; /* the coordinates of the anchor point */
static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort context_length,
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. */
static FT_Error default_mmfunc( FT_Face face,
}
-#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
FT_Error TT_Load_GPOS_Table( FT_Face face,
TTO_GPOSHeader** retptr,
static FT_Error Get_ValueRecord( GPOS_Instance* gpi,
TTO_ValueRecord* vr,
FT_UShort format,
- TTO_GPOS_Data* gd )
+ OTL_Position gd )
{
FT_Pos value;
FT_Short pixel_value;
static FT_Error Lookup_SinglePos( GPOS_Instance* gpi,
TTO_SinglePos* sp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
if ( context_length != 0xFFFF && context_length < 1 )
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;
- error = Coverage_Index( &sp->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &sp->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
{
case 1:
error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
- sp->ValueFormat, &out[in->pos] );
+ sp->ValueFormat, POSITION( buffer->in_pos ) );
if ( error )
return error;
break;
if ( index >= sp->spf.spf2.ValueCount )
return TTO_Err_Invalid_GPOS_SubTable;
error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
- sp->ValueFormat, &out[in->pos] );
+ sp->ValueFormat, POSITION( buffer->in_pos ) );
if ( error )
return error;
break;
return TTO_Err_Invalid_GPOS_SubTable;
}
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
static FT_Error Lookup_PairPos1( GPOS_Instance* gpi,
TTO_PairPosFormat1* ppf1,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort first_pos,
FT_UShort index,
FT_UShort format1,
if ( !pvr )
return TTO_Err_Invalid_GPOS_SubTable;
- glyph2 = in->string[in->pos];
+ glyph2 = IN_CURGLYPH( 0 );
for ( numpvr = ppf1->PairSet[index].PairValueCount;
numpvr;
if ( glyph2 == pvr->SecondGlyph )
{
error = Get_ValueRecord( gpi, &pvr->Value1, format1,
- &out[first_pos] );
+ POSITION( first_pos ) );
if ( error )
return error;
return Get_ValueRecord( gpi, &pvr->Value2, format2,
- &out[in->pos] );
+ POSITION( buffer->in_pos ) );
}
}
static FT_Error Lookup_PairPos2( GPOS_Instance* gpi,
TTO_PairPosFormat2* ppf2,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort first_pos,
FT_UShort format1,
FT_UShort format2 )
TTO_Class2Record* c2r;
- error = Get_Class( &ppf2->ClassDef1, in->string[first_pos],
+ error = Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
&cl1, NULL );
if ( error && error != TTO_Err_Not_Covered )
return error;
- error = Get_Class( &ppf2->ClassDef2, in->string[in->pos],
+ error = Get_Class( &ppf2->ClassDef2, IN_CURGLYPH( 0 ),
&cl2, NULL );
if ( error && error != TTO_Err_Not_Covered )
return error;
return TTO_Err_Invalid_GPOS_SubTable;
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 )
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,
TTO_PairPos* pp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
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 */
if ( context_length != 0xFFFF && context_length < 2 )
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;
- error = Coverage_Index( &pp->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &pp->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
/* second glyph */
- first_pos = in->pos;
- (in->pos)++;
+ first_pos = buffer->in_pos;
+ (buffer->in_pos)++;
- while ( CHECK_Property( gpos->gdef, in->string[in->pos],
+ while ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( in->pos < in->length )
- (in->pos)++;
+ if ( buffer->in_pos < buffer->in_length )
+ (buffer->in_pos)++;
else
break;
}
switch ( pp->PosFormat )
{
case 1:
- error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, in, out,
+ error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
first_pos, index,
pp->ValueFormat1, pp->ValueFormat2 );
break;
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 );
break;
/* adjusting the `next' glyph */
if ( pp->ValueFormat2 )
- (in->pos)++;
+ (buffer->in_pos)++;
return error;
}
static FT_Error Lookup_CursivePos( GPOS_Instance* gpi,
TTO_CursivePos* cp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
/* Glyphs not having the right GDEF properties will be ignored, i.e.,
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;
/* We don't handle mark glyphs here. According to Andrei, this isn't
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 )
{
gpi->last = 0xFFFF;
/* Get_Anchor() returns TTO_Err_Not_Covered if there is no anchor
table. */
- error = Get_Anchor( gpi, &eer->EntryAnchor, in->string[in->pos],
+ error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH( 0 ),
&entry_x, &entry_y );
if ( error == TTO_Err_Not_Covered )
goto end;
if ( gpi->r2l )
{
- out[in->pos].x_advance = entry_x - gpi->anchor_x;
- out[in->pos].new_advance = TRUE;
+ POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;
+ POSITION( buffer->in_pos )->new_advance = TRUE;
}
else
{
- out[gpi->last].x_advance = gpi->anchor_x - entry_x;
- out[gpi->last].new_advance = TRUE;
+ POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;
+ 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:
- error = Get_Anchor( gpi, &eer->ExitAnchor, in->string[in->pos],
+ error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH( 0 ),
&exit_x, &exit_y );
if ( error == TTO_Err_Not_Covered )
gpi->last = 0xFFFF;
else
{
- if ( gpi->first == 0xFFFF )
- gpi->first = in->pos;
- gpi->last = in->pos;
+ gpi->last = buffer->in_pos;
gpi->anchor_x = exit_x;
gpi->anchor_y = exit_y;
}
if ( error )
return error;
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
static FT_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
TTO_MarkBasePos* mbp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
TTO_Anchor* mark_anchor;
TTO_Anchor* base_anchor;
- TTO_GPOS_Data* o;
+ OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 )
if ( flags & IGNORE_BASE_GLYPHS )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gpos->gdef, in->string[in->pos],
+ if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
return error;
- error = Coverage_Index( &mbp->MarkCoverage, in->string[in->pos],
+ error = Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH( 0 ),
&mark_index );
if ( error )
return error;
/* now we search backwards for a non-mark glyph */
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 );
if ( error )
return error;
return TTO_Err_Not_Covered;
#endif
- if ( i > in->pos )
+ if ( i > buffer->in_pos )
return TTO_Err_Not_Covered;
- error = Coverage_Index( &mbp->BaseCoverage, in->string[j],
+ error = Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
&base_index );
if ( error )
return error;
br = &ba->BaseRecord[base_index];
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 );
if ( 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 );
if ( error )
return error;
/* anchor points are not cumulative */
- o = &out[in->pos];
+ o = POSITION( buffer->in_pos );
o->x_pos = x_base_value - x_mark_value;
o->y_pos = y_base_value - y_mark_value;
o->y_advance = 0;
o->back = i;
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
static FT_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
TTO_MarkLigPos* mlp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
TTO_Anchor* mark_anchor;
TTO_Anchor* lig_anchor;
- TTO_GPOS_Data* o;
+ OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 )
if ( flags & IGNORE_LIGATURES )
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 ) )
return error;
/* now we search backwards for a non-mark glyph */
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 );
if ( error )
return error;
return TTO_Err_Not_Covered;
#endif
- if ( i > in->pos )
+ if ( i > buffer->in_pos )
return TTO_Err_Not_Covered;
- error = Coverage_Index( &mlp->LigatureCoverage, in->string[j],
+ error = Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
&lig_index );
if ( error )
return error;
can directly use the component index. If not, we attach the mark
glyph to the last component of the ligature. */
- if ( in->ligIDs && in->components &&
- in->ligIDs[j] == in->ligIDs[in->pos] )
+ if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
{
- comp_index = in->components[in->pos];
+ comp_index = IN_COMPONENT( buffer->in_pos );
if ( comp_index >= lat->ComponentCount )
return TTO_Err_Not_Covered;
}
cr = &lat->ComponentRecord[comp_index];
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 );
if ( 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 );
if ( error )
return error;
/* anchor points are not cumulative */
- o = &out[in->pos];
+ o = POSITION( buffer->in_pos );
o->x_pos = x_lig_value - x_mark_value;
o->y_pos = y_lig_value - y_mark_value;
o->y_advance = 0;
o->back = i;
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
static FT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
TTO_MarkMarkPos* mmp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length )
{
TTO_Anchor* mark1_anchor;
TTO_Anchor* mark2_anchor;
- TTO_GPOS_Data* o;
+ OTL_Position o;
if ( context_length != 0xFFFF && context_length < 1 )
if ( flags & IGNORE_MARKS )
return TTO_Err_Not_Covered;
- if ( CHECK_Property( gpos->gdef, in->string[in->pos],
+ if ( CHECK_Property( gpos->gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
return error;
- error = Coverage_Index( &mmp->Mark1Coverage, in->string[in->pos],
+ error = Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH( 0 ),
&mark1_index );
if ( error )
return error;
/* now we check the preceding glyph whether it is a suitable
mark glyph */
- if ( in->pos == 0 )
+ if ( buffer->in_pos == 0 )
return TTO_Err_Not_Covered;
- j = in->pos - 1;
- error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j],
+ j = buffer->in_pos - 1;
+ error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
&property );
if ( error )
return error;
return TTO_Err_Not_Covered;
}
- error = Coverage_Index( &mmp->Mark2Coverage, in->string[j],
+ error = Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
&mark2_index );
if ( error )
return error;
m2r = &ma2->Mark2Record[mark2_index];
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 );
if ( 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 );
if ( error )
return error;
/* anchor points are not cumulative */
- o = &out[in->pos];
+ o = POSITION( buffer->in_pos );
o->x_pos = x_mark2_value - x_mark1_value;
o->y_pos = y_mark2_value - y_mark1_value;
o->y_advance = 0;
o->back = 1;
- (in->pos)++;
+ (buffer->in_pos)++;
return TT_Err_Ok;
}
FT_UShort GlyphCount,
FT_UShort PosCount,
TTO_PosLookupRecord* pos,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
int nesting_level )
{
FT_Error error;
{
if ( PosCount && i == pos->SequenceIndex )
{
- old_pos = in->pos;
+ old_pos = buffer->in_pos;
/* Do a positioning */
- error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, in, out,
+ error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
GlyphCount, nesting_level );
if ( error )
pos++;
PosCount--;
- i += in->pos - old_pos;
+ i += buffer->in_pos - old_pos;
}
else
{
i++;
- (in->pos)++;
+ (buffer->in_pos)++;
}
}
static FT_Error Lookup_ContextPos1( GPOS_Instance* gpi,
TTO_ContextPosFormat1* cpf1,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort index, property;
FT_UShort i, j, k, numpr;
FT_Error error;
- FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos;
TTO_PosRule* pr;
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &cpf1->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &cpf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
continue;
- if ( in->pos + pr[k].GlyphCount > in->length )
+ if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
continue; /* context is too long */
- s_in = &in->string[in->pos];
-
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 )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != pr[k].Input[i - 1] )
+ if ( IN_CURGLYPH( j ) != pr[k].Input[i - 1] )
break;
}
if ( i == pr[k].GlyphCount )
return Do_ContextPos( gpi, pr[k].GlyphCount,
pr[k].PosCount, pr[k].PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ContextPos2( GPOS_Instance* gpi,
TTO_ContextPosFormat2* cpf2,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort i, j, k, known_classes;
FT_UShort* classes;
- FT_UShort* s_in;
FT_UShort* cl;
TTO_GPOSHeader* gpos = gpi->gpos;
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* 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
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 )
return error;
if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, FT_UShort ) )
return error;
- error = Get_Class( &cpf2->ClassDef, in->string[in->pos],
+ error = Get_Class( &cpf2->ClassDef, IN_CURGLYPH( 0 ),
&classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End;
if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
continue;
- if ( in->pos + pr->GlyphCount > in->length )
+ if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
continue; /* context is too long */
- s_in = &in->string[in->pos];
cl = pr->Class;
/* Start at 1 because [0] is implied */
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 )
goto End;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
{
/* 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 )
goto End;
known_classes = i;
{
error = Do_ContextPos( gpi, pr->GlyphCount,
pr->PosCount, pr->PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
goto End;
}
static FT_Error Lookup_ContextPos3( GPOS_Instance* gpi,
TTO_ContextPosFormat3* cpf3,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
{
FT_Error error;
FT_UShort index, i, j, property;
- FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos;
TTO_Coverage* c;
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
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 */
- s_in = &in->string[in->pos];
c = cpf3->Coverage;
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 )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
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 )
return error;
}
return Do_ContextPos( gpi, cpf3->GlyphCount,
cpf3->PosCount, cpf3->PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ContextPos( GPOS_Instance* gpi,
TTO_ContextPos* cp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
switch ( cp->PosFormat )
{
case 1:
- return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, in, out,
+ return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
flags, context_length, nesting_level );
case 2:
- return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, in, out,
+ return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
flags, context_length, nesting_level );
case 3:
- return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, in, out,
+ return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
flags, context_length, nesting_level );
default:
static FT_Error Lookup_ChainContextPos1(
GPOS_Instance* gpi,
TTO_ChainContextPosFormat1* ccpf1,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort i, j, k, num_cpr, curr_pos;
FT_UShort bgc, igc, lgc;
FT_Error error;
- FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos;
TTO_ChainPosRule* cpr;
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &ccpf1->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
/* 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;
if ( bgc )
we search backwards for matches in the backtrack glyph array */
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 )
return error;
Backtrack offsets - 3 2 1 0
Lookahead offsets - 0 1 2 3 */
- if ( s_in[j] != curr_cpr.Backtrack[i] )
+ if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
break;
}
continue;
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
/* Start at 1 because [0] is implied */
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 )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != curr_cpr.Input[i - 1] )
+ if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Input[i - 1] )
break;
}
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
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 )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != curr_cpr.Lookahead[i] )
+ if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Lookahead[i] )
break;
}
return Do_ContextPos( gpi, igc,
curr_cpr.PosCount,
curr_cpr.PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ChainContextPos2(
GPOS_Instance* gpi,
TTO_ChainContextPosFormat2* ccpf2,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort* input_classes;
FT_UShort* lookahead_classes;
- FT_UShort* s_in;
-
FT_UShort* bc;
FT_UShort* ic;
FT_UShort* lc;
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* 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
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 )
return error;
goto End2;
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 );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
/* 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;
if ( bgc )
Note that `known_backtrack_classes' starts at index 0. */
curr_pos = 0;
- s_in = &in->string[curr_pos];
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 )
goto End1;
{
/* 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 );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
continue;
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
ic = cpcr.Input;
/* Start at 1 because [0] is implied */
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 )
goto End1;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
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 );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
lc = cpcr.Lookahead;
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 )
goto End1;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
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 );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
error = Do_ContextPos( gpi, igc,
cpcr.PosCount,
cpcr.PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
goto End1;
}
static FT_Error Lookup_ChainContextPos3(
GPOS_Instance* gpi,
TTO_ChainContextPosFormat3* ccpf3,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort index, i, j, curr_pos, property;
FT_UShort bgc, igc, lgc;
FT_Error error;
- FT_UShort* s_in;
TTO_GPOSHeader* gpos = gpi->gpos;
TTO_Coverage* bc;
gdef = gpos->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
bgc = ccpf3->BacktrackGlyphCount;
/* 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;
if ( bgc )
we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
- s_in = &in->string[curr_pos];
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 )
return error;
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 )
return error;
}
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
ic = ccpf3->InputCoverage;
for ( i = 0, j = 0; i < igc; i++, j++ )
{
/* 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 )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
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 )
return error;
}
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
lc = ccpf3->LookaheadCoverage;
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 )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
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 )
return error;
}
return Do_ContextPos( gpi, igc,
ccpf3->PosCount,
ccpf3->PosLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ChainContextPos(
GPOS_Instance* gpi,
TTO_ChainContextPos* ccp,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
switch ( ccp->PosFormat )
{
case 1:
- return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, in, out,
+ return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
flags, context_length,
nesting_level );
case 2:
- return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, in, out,
+ return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
flags, context_length,
nesting_level );
case 3:
- return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, in, out,
+ return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
flags, context_length,
nesting_level );
static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out,
+ OTL_Buffer buffer,
FT_UShort context_length,
int nesting_level )
{
case GPOS_LOOKUP_SINGLE:
error = Lookup_SinglePos( gpi,
&lo->SubTable[i].st.gpos.single,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_PAIR:
error = Lookup_PairPos( gpi,
&lo->SubTable[i].st.gpos.pair,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_CURSIVE:
error = Lookup_CursivePos( gpi,
&lo->SubTable[i].st.gpos.cursive,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_MARKBASE:
error = Lookup_MarkBasePos( gpi,
&lo->SubTable[i].st.gpos.markbase,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_MARKLIG:
error = Lookup_MarkLigPos( gpi,
&lo->SubTable[i].st.gpos.marklig,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_MARKMARK:
error = Lookup_MarkMarkPos( gpi,
&lo->SubTable[i].st.gpos.markmark,
- in, out,
+ buffer,
flags, context_length );
break;
case GPOS_LOOKUP_CONTEXT:
error = Lookup_ContextPos( gpi,
&lo->SubTable[i].st.gpos.context,
- in, out,
+ buffer,
flags, context_length,
nesting_level );
break;
case GPOS_LOOKUP_CHAIN:
error = Lookup_ChainContextPos( gpi,
&lo->SubTable[i].st.gpos.chain,
- in, out,
+ buffer,
flags, context_length,
nesting_level );
break;
static FT_Error Do_String_Lookup( GPOS_Instance* gpi,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GPOS_Data* out )
+ OTL_Buffer buffer )
{
FT_Error error, retError = TTO_Err_Not_Covered;
TTO_GPOSHeader* gpos = gpi->gpos;
FT_UShort* properties = gpos->LookupList.Properties;
- FT_UShort* p_in = in->properties;
int nesting_level = 0;
- FT_UShort i;
- FT_Pos offset;
- gpi->first = 0xFFFF;
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. */
It is up to the font designer to provide meaningful lookups and
lookup order. */
- error = Do_Glyph_Lookup( gpi, lookup_index, in, out,
+ error = Do_Glyph_Lookup( gpi, lookup_index, buffer,
0xFFFF, nesting_level );
if ( error && error != TTO_Err_Not_Covered )
return error;
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 )
- (in->pos)++;
+ (buffer->in_pos)++;
else
retError = error;
}
}
+ 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
FT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos,
FT_UShort feature_index,
return TT_Err_Ok;
}
-
/* If `dvi' is TRUE, glyph contour points for anchor points and device
tables are ignored -- you will get device independent values. */
FT_Error TT_GPOS_Apply_String( FT_Face face,
TTO_GPOSHeader* gpos,
FT_UShort load_flags,
- TTO_GSUB_String* in,
- TTO_GPOS_Data** out,
+ OTL_Buffer buffer,
FT_Bool dvi,
FT_Bool r2l )
{
- FT_Memory memory = gpos->memory;
FT_Error error, retError = TTO_Err_Not_Covered;
GPOS_Instance gpi;
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;
properties = gpos->LookupList.Properties;
gpi.r2l = r2l;
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++ )
if ( !properties || properties[j] )
{
- error = Do_String_Lookup( &gpi, j, in, *out );
+ error = Do_String_Lookup( &gpi, j, buffer );
if ( error )
{
if ( error != TTO_Err_Not_Covered )
retError = error;
}
+ error = Position_CursiveChain ( buffer );
+ if ( error )
+ return error;
+
return retError;
}
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 */
/* EXPORT_DEF
FT_Error TT_GPOS_Apply_String( FT_Face face,
TTO_GPOSHeader* gpos,
FT_UShort load_flags,
- TTO_GSUB_String* in,
- TTO_GPOS_Data** out,
+ OTL_Buffer buffer,
FT_Bool dvi,
FT_Bool r2l );
#define GSUB_ID Build_Extension_ID( 'G', 'S', 'U', 'B' )
-#define ADD_String( in, num_in, out, num_out, glyph_data, component, ligID ) \
- ( ( error = TT_GSUB_Add_String( (in), (num_in), \
- (out), (num_out), \
- (glyph_data), (component), (ligID) \
- ) ) != TT_Err_Ok )
+#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 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,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort context_length,
int nesting_level );
**********************/
- /* 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
FT_Error TT_Load_GSUB_Table( FT_Face face,
TTO_GSUBHeader** retptr,
static FT_Error Lookup_SingleSubst( TTO_SingleSubst* ss,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
TTO_GDEFHeader* gdef )
{
- FT_UShort index, value[1], property;
+ FT_UShort index, value, property;
FT_Error error;
if ( context_length != 0xFFFF && context_length < 1 )
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;
- error = Coverage_Index( &ss->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ss->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
switch ( ss->SubstFormat )
{
case 1:
- value[0] = ( in->string[in->pos] + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
- if ( ADD_String( in, 1, out, 1, value, 0xFFFF, 0xFFFF ) )
+ value = ( IN_CURGLYPH( 0 ) + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
+ if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
return error;
break;
case 2:
if ( index >= ss->ssf.ssf2.GlyphCount )
return TTO_Err_Invalid_GSUB_SubTable;
- value[0] = ss->ssf.ssf2.Substitute[index];
- if ( ADD_String( in, 1, out, 1, value, 0xFFFF, 0xFFFF ) )
+ value = ss->ssf.ssf2.Substitute[index];
+ if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
return error;
break;
{
/* 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 )
return error;
}
static FT_Error Lookup_MultipleSubst( TTO_MultipleSubst* ms,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
TTO_GDEFHeader* gdef )
if ( context_length != 0xFFFF && context_length < 1 )
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;
- error = Coverage_Index( &ms->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ms->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
count = ms->Sequence[index].GlyphCount;
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;
if ( gdef && gdef->NewGlyphClasses )
static FT_Error Lookup_AlternateSubst( TTO_GSUBHeader* gsub,
TTO_AlternateSubst* as,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
TTO_GDEFHeader* gdef )
if ( context_length != 0xFFFF && context_length < 1 )
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;
- error = Coverage_Index( &as->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &as->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
/* we use a user-defined callback function to get the alternate index */
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,
gsub->data );
else
alt_index = 0;
- if ( ADD_String( in, 1, out, 1, &aset.Alternate[alt_index],
- 0xFFFF, 0xFFFF ) )
+ if ( ADD_Glyph( buffer, aset.Alternate[alt_index],
+ 0xFFFF, 0xFFFF ) )
return error;
if ( gdef && gdef->NewGlyphClasses )
static FT_Error Lookup_LigatureSubst( TTO_LigatureSubst* ls,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
TTO_GDEFHeader* gdef )
FT_UShort index, property;
FT_Error error;
FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
- FT_UShort* s_in;
FT_UShort* c;
TTO_Ligature* lig;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
if ( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS )
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 )
return error;
numlig;
numlig--, lig++ )
{
- if ( in->pos + lig->ComponentCount > in->length )
+ if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
continue; /* Not enough glyphs in input */
- s_in = &in->string[in->pos];
c = lig->Component;
is_mark = first_is_mark;
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 )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) )
is_mark = FALSE;
- if ( s_in[j] != c[i - 1] )
+ if ( IN_CURGLYPH( j ) != c[i - 1] )
break;
}
/* We don't use a new ligature ID if there are no skipped
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,
- 0xFFFF, 0xFFFF ) )
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
+ 0xFFFF, 0xFFFF ) )
return error;
}
else
{
- if ( ADD_String( in, i, out, 1, &lig->LigGlyph,
- 0xFFFF, in->max_ligID ) )
+ FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
+ 0xFFFF, ligID ) )
return error;
-
- (in->max_ligID)++;
}
}
else
{
- if ( ADD_String( in, 1, out, 1, &lig->LigGlyph,
- 0xFFFF, in->max_ligID ) )
+ FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
+ if ( ADD_Glyph( buffer, lig->LigGlyph,
+ 0xFFFF, ligID ) )
return error;
/* Now we must do a second loop to copy the skipped glyphs to
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 ) )
- if ( ADD_String( in, 1, out, 1, &in->string[in->pos],
- i, in->max_ligID ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
+ i, ligID ) )
return error;
- (in->pos)++;
+ (buffer->in_pos)++;
}
-
- (in->max_ligID)++;
}
return TT_Err_Ok;
FT_UShort GlyphCount,
FT_UShort SubstCount,
TTO_SubstLookupRecord* subst,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
int nesting_level )
{
FT_Error error;
{
if ( SubstCount && i == subst->SequenceIndex )
{
- old_pos = in->pos;
+ old_pos = buffer->in_pos;
/* Do a substitution */
- error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, in, out,
+ error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
GlyphCount, nesting_level );
subst++;
SubstCount--;
- i += in->pos - old_pos;
+ i += buffer->in_pos - old_pos;
if ( error == TTO_Err_Not_Covered )
{
/* XXX "can't happen" -- but don't count on it */
- if ( ADD_String( in, 1, out, 1, &in->string[in->pos],
- 0xFFFF, 0xFFFF ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
+ 0xFFFF, 0xFFFF ) )
return error;
i++;
}
{
/* No substitution for this index */
- if ( ADD_String( in, 1, out, 1, &in->string[in->pos],
- 0xFFFF, 0xFFFF ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
+ 0xFFFF, 0xFFFF ) )
return error;
i++;
}
static FT_Error Lookup_ContextSubst1(
TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat1* csf1,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort index, property;
FT_UShort i, j, k, numsr;
FT_Error error;
- FT_UShort* s_in;
TTO_SubRule* sr;
TTO_GDEFHeader* 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;
- error = Coverage_Index( &csf1->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &csf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
continue;
- if ( in->pos + sr[k].GlyphCount > in->length )
+ if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
continue; /* context is too long */
- s_in = &in->string[in->pos];
-
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 )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != sr[k].Input[i - 1] )
+ if ( IN_CURGLYPH( j ) != sr[k].Input[i - 1] )
break;
}
if ( i == sr[k].GlyphCount )
return Do_ContextSubst( gsub, sr[k].GlyphCount,
sr[k].SubstCount, sr[k].SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ContextSubst2(
TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat2* csf2,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort i, j, k, known_classes;
FT_UShort* classes;
- FT_UShort* s_in;
FT_UShort* cl;
TTO_SubClassSet* scs;
gdef = gsub->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* 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
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 )
return error;
if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) )
return error;
- error = Get_Class( &csf2->ClassDef, in->string[in->pos],
+ error = Get_Class( &csf2->ClassDef, IN_CURGLYPH( 0 ),
&classes[0], NULL );
if ( error && error != TTO_Err_Not_Covered )
goto End;
if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
continue;
- if ( in->pos + sr->GlyphCount > in->length )
+ if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
continue; /* context is too long */
- s_in = &in->string[in->pos];
cl = sr->Class;
/* Start at 1 because [0] is implied */
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 )
goto End;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
break;
{
/* 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 )
goto End;
known_classes = i;
{
error = Do_ContextSubst( gsub, sr->GlyphCount,
sr->SubstCount, sr->SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
goto End;
}
static FT_Error Lookup_ContextSubst3(
TTO_GSUBHeader* gsub,
TTO_ContextSubstFormat3* csf3,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
{
FT_Error error;
FT_UShort index, i, j, property;
- FT_UShort* s_in;
TTO_Coverage* c;
TTO_GDEFHeader* 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;
if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
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 */
- s_in = &in->string[in->pos];
c = csf3->Coverage;
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 )
return error;
- if ( in->pos + j < in->length )
+ if ( buffer->in_pos + j < buffer->in_length )
j++;
else
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 )
return error;
}
return Do_ContextSubst( gsub, csf3->GlyphCount,
csf3->SubstCount, csf3->SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ContextSubst( TTO_GSUBHeader* gsub,
TTO_ContextSubst* cs,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
switch ( cs->SubstFormat )
{
case 1:
- return Lookup_ContextSubst1( gsub, &cs->csf.csf1, in, out,
+ return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer,
flags, context_length, nesting_level );
case 2:
- return Lookup_ContextSubst2( gsub, &cs->csf.csf2, in, out,
+ return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer,
flags, context_length, nesting_level );
case 3:
- return Lookup_ContextSubst3( gsub, &cs->csf.csf3, in, out,
+ return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer,
flags, context_length, nesting_level );
default:
static FT_Error Lookup_ChainContextSubst1(
TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat1* ccsf1,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort i, j, k, num_csr, curr_pos;
FT_UShort bgc, igc, lgc;
FT_Error error;
- FT_UShort* s_in;
TTO_ChainSubRule* csr;
TTO_ChainSubRule curr_csr;
gdef = gsub->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
- error = Coverage_Index( &ccsf1->Coverage, in->string[in->pos], &index );
+ error = Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH( 0 ), &index );
if ( error )
return error;
/* 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;
if ( bgc )
we search backwards for matches in the backtrack glyph array */
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 )
return error;
Backtrack offsets - 3 2 1 0
Lookahead offsets - 0 1 2 3 */
- if ( s_in[j] != curr_csr.Backtrack[i] )
+ if ( IN_GLYPH( j ) != curr_csr.Backtrack[i] )
break;
}
continue;
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
/* Start at 1 because [0] is implied */
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 )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != curr_csr.Input[i - 1] )
+ if ( IN_GLYPH( curr_pos + j ) != curr_csr.Input[i - 1] )
break;
}
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
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 )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
}
- if ( s_in[j] != curr_csr.Lookahead[i] )
+ if ( IN_GLYPH( curr_pos + j ) != curr_csr.Lookahead[i] )
break;
}
return Do_ContextSubst( gsub, igc,
curr_csr.SubstCount,
curr_csr.SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ChainContextSubst2(
TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat2* ccsf2,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort* input_classes;
FT_UShort* lookahead_classes;
- FT_UShort* s_in;
-
FT_UShort* bc;
FT_UShort* ic;
FT_UShort* lc;
gdef = gsub->gdef;
memory = gsub->memory;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
/* 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
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 )
return error;
goto End2;
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 );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
/* 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;
if ( bgc )
Note that `known_backtrack_classes' starts at index 0. */
curr_pos = 0;
- s_in = &in->string[curr_pos];
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 )
goto End1;
{
/* 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 );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
continue;
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
ic = ccsr.Input;
/* Start at 1 because [0] is implied */
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 )
goto End1;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
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 );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
last context glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
lc = ccsr.Lookahead;
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 )
goto End1;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
break;
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 );
if ( error && error != TTO_Err_Not_Covered )
goto End1;
error = Do_ContextSubst( gsub, igc,
ccsr.SubstCount,
ccsr.SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
goto End1;
}
static FT_Error Lookup_ChainContextSubst3(
TTO_GSUBHeader* gsub,
TTO_ChainContextSubstFormat3* ccsf3,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
FT_UShort index, i, j, curr_pos, property;
FT_UShort bgc, igc, lgc;
FT_Error error;
- FT_UShort* s_in;
TTO_Coverage* bc;
TTO_Coverage* ic;
gdef = gsub->gdef;
- if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) )
+ if ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), flags, &property ) )
return error;
bgc = ccsf3->BacktrackGlyphCount;
/* 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;
if ( bgc )
we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
- s_in = &in->string[curr_pos];
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 )
return error;
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 )
return error;
}
}
- curr_pos = in->pos;
- s_in = &in->string[curr_pos];
+ curr_pos = buffer->in_pos;
ic = ccsf3->InputCoverage;
for ( i = 0, j = 0; i < igc; i++, j++ )
{
- /* We already called CHECK_Property for s_in[0] */
- while ( j > 0 && CHECK_Property( gdef, s_in[j], flags, &property ) )
+ /* We already called CHECK_Property for IN_GLYPH( curr_pos ) */
+ while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) )
{
if ( error && error != TTO_Err_Not_Covered )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
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 )
return error;
}
glyph */
curr_pos += j;
- s_in = &in->string[curr_pos];
lc = ccsf3->LookaheadCoverage;
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 )
return error;
- if ( curr_pos + j < in->length )
+ if ( curr_pos + j < buffer->in_length )
j++;
else
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 )
return error;
}
return Do_ContextSubst( gsub, igc,
ccsf3->SubstCount,
ccsf3->SubstLookupRecord,
- in, out,
+ buffer,
nesting_level );
}
static FT_Error Lookup_ChainContextSubst(
TTO_GSUBHeader* gsub,
TTO_ChainContextSubst* ccs,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort flags,
FT_UShort context_length,
int nesting_level )
switch ( ccs->SubstFormat )
{
case 1:
- return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, in, out,
+ return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer,
flags, context_length,
nesting_level );
case 2:
- return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, in, out,
+ return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer,
flags, context_length,
nesting_level );
case 3:
- return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, in, out,
+ return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer,
flags, context_length,
nesting_level );
static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out,
+ OTL_Buffer buffer,
FT_UShort context_length,
int nesting_level )
{
{
case GSUB_LOOKUP_SINGLE:
error = Lookup_SingleSubst( &lo->SubTable[i].st.gsub.single,
- in, out,
+ buffer,
flags, context_length, gsub->gdef );
break;
case GSUB_LOOKUP_MULTIPLE:
error = Lookup_MultipleSubst( &lo->SubTable[i].st.gsub.multiple,
- in, out,
+ buffer,
flags, context_length, gsub->gdef );
break;
case GSUB_LOOKUP_ALTERNATE:
error = Lookup_AlternateSubst( gsub,
&lo->SubTable[i].st.gsub.alternate,
- in, out,
+ buffer,
flags, context_length, gsub->gdef );
break;
case GSUB_LOOKUP_LIGATURE:
error = Lookup_LigatureSubst( &lo->SubTable[i].st.gsub.ligature,
- in, out,
+ buffer,
flags, context_length, gsub->gdef );
break;
case GSUB_LOOKUP_CONTEXT:
error = Lookup_ContextSubst( gsub, &lo->SubTable[i].st.gsub.context,
- in, out,
+ buffer,
flags, context_length, nesting_level );
break;
case GSUB_LOOKUP_CHAIN:
error = Lookup_ChainContextSubst( gsub,
&lo->SubTable[i].st.gsub.chain,
- in, out,
+ buffer,
flags, context_length,
nesting_level );
break;
return TTO_Err_Not_Covered;
}
-
/* apply one lookup to the input string object */
static FT_Error Do_String_Lookup( TTO_GSUBHeader* gsub,
FT_UShort lookup_index,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out )
+ OTL_Buffer buffer )
{
FT_Error error, retError = TTO_Err_Not_Covered;
FT_UShort* properties = gsub->LookupList.Properties;
- FT_UShort* p_in = in->properties;
- FT_UShort* s_in = in->string;
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 */
- error = Do_Glyph_Lookup( gsub, lookup_index, in, out,
+ error = Do_Glyph_Lookup( gsub, lookup_index, buffer,
0xFFFF, nesting_level );
if ( error )
{
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;
}
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
FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out )
+ OTL_Buffer buffer )
{
FT_Error error, retError = TTO_Err_Not_Covered;
- FT_Memory memory = in->memory;
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;
-
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;
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++ )
if ( properties[j] )
{
- error = Do_String_Lookup( gsub, j, ptmp1, ptmp2 );
+ error = Do_String_Lookup( gsub, j, buffer );
if ( error )
{
if ( error != TTO_Err_Not_Covered )
else
retError = error;
-
- /* flipping `in' and `out', preparing the next loop */
-
- 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 = otl_buffer_swap( buffer );
+ if ( error )
+ goto End;
}
+
+ error = retError;
End:
- FREE( ptmp2->string );
- 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;
- }
+ return error;
}
TT_Add_String() will also handle allocation; you should use
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 */
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
FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub,
- TTO_GSUB_String* in,
- TTO_GSUB_String* out );
+ OTL_Buffer buffer );
- 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
}
typedef struct TTO_Device_ TTO_Device;
+#include "otlbuffer.h"
#include "ftxgdef.h"
#include "ftxgsub.h"
#include "ftxgpos.h"
--- /dev/null
+/* 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++;
+ }
--- /dev/null
+/* 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
maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('l', 'i', 'g', 'a'), L);
}
+#if 0
void
dump_string (TTO_GSUB_String *str)
{
if ((error = TT_GSUB_String_Done (out_str)))
croak ("TT_GSUB_String_New", error);
}
+#endif
int
main (int argc, char **argv)
--- /dev/null
+/* 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);
+}
/* Make a guess at the appropriate class for a glyph given
* a character code that maps to the glyph
*/
-static FT_UShort
-get_glyph_class (gunichar charcode)
+static gboolean
+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))
{
case G_UNICODE_COMBINING_MARK:
case G_UNICODE_ENCLOSING_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:
- return 1; /* Base glyph (single character, spacing glyph) */
+ *class = 1; /* Base glyph (single character, spacing glyph) */
+ return TRUE;
}
}
if (glyph <= 65535)
{
glyph_info.glyph = glyph;
- glyph_info.class = get_glyph_class (charcode);
-
- g_array_append_val (glyph_infos, glyph_info);
+ if (get_glyph_class (charcode, &glyph_info.class))
+ g_array_append_val (glyph_infos, glyph_info);
}
charcode = FT_Get_Next_Char (info->face, charcode, &glyph);
GObjectClass parent_class;
};
+struct _PangoOTBuffer
+{
+ OTL_Buffer buffer;
+ PangoFcFont *font;
+ gboolean rtl;
+ gboolean applied_gpos;
+};
+
GType pango_ot_info_get_type (void);
TTO_GDEF pango_ot_info_get_gdef (PangoOTInfo *info);
#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;
struct _PangoOTRule
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
-pango_ot_ruleset_shape (PangoOTRuleset *ruleset,
- PangoGlyphString *glyphs,
- gulong *properties)
+pango_ot_ruleset_substitute (PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer)
{
int i;
- int last_cluster;
- int result;
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_gpos = FALSE;
g_return_if_fail (PANGO_OT_IS_RULESET (ruleset));
if (rule->table_type == PANGO_OT_TABLE_GSUB)
need_gsub = TRUE;
- else
- need_gpos = TRUE;
}
if (need_gsub)
{
+
gsub = pango_ot_info_get_gsub (ruleset->info);
if (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++)
{
PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
if (gsub)
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;
- result = TT_GSUB_String_New (ruleset->info->face->memory, &in_string);
- g_assert (result == FT_Err_Ok);
-
- result = TT_GSUB_String_Set_Length (in_string, glyphs->num_glyphs);
- g_assert (result == FT_Err_Ok);
+ TT_GSUB_Apply_String (gsub, buffer->buffer);
+}
- for (i = 0; i < glyphs->num_glyphs; i++)
- {
- in_string->string[i] = glyphs->glyphs[i].glyph;
- in_string->properties[i] = properties[i];
- in_string->logClusters[i] = glyphs->log_clusters[i];
- }
- in_string->max_ligID = i;
+void
+pango_ot_ruleset_position (PangoOTRuleset *ruleset,
+ PangoOTBuffer *buffer)
+{
+ int 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,
- &out_string);
- g_assert (result == FT_Err_Ok);
- result_string = out_string;
+ PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
- 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)
{
- TTO_GPOS_Data *outgpos = NULL;
+ TT_GPOS_Clear_Features (gpos);
- if (!TT_GPOS_Apply_String (ruleset->info->face, gpos, 0, result_string, &outgpos,
- FALSE /* enable device-dependant values */,
- FALSE /* Even though this might be r2l text, RTL is handled elsewhere */))
+ for (i = 0; i < ruleset->rules->len; i++)
{
- for (i = 0; i < result_string->length; i++)
- {
- FT_Pos x_pos = outgpos[i].x_pos;
- FT_Pos y_pos = outgpos[i].y_pos;
- 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);
+ PangoOTRule *rule = &g_array_index (ruleset->rules, PangoOTRule, i);
+
+ if (rule->table_type == PANGO_OT_TABLE_GPOS)
+ TT_GPOS_Add_Feature (gpos, rule->feature_index, rule->property_bit);
}
}
- pango_glyph_string_set_size (glyphs, result_string->length);
-
- last_cluster = -1;
- for (i = 0; i < result_string->length; i++)
+ /* Apply GPOS rules */
+ if (gpos)
{
- glyphs->glyphs[i].glyph = result_string->string[i];
-
- glyphs->log_clusters[i] = result_string->logClusters[i];
- 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];
+ if (TT_GPOS_Apply_String (ruleset->info->face, gpos, 0, buffer->buffer,
+ FALSE /* enable device-dependant values */,
+ buffer->rtl) == FT_Err_Ok)
+ {
+ buffer->applied_gpos = TRUE;
+ }
}
-
- if (in_string)
- TT_GSUB_String_Done (in_string);
- if (out_string)
- TT_GSUB_String_Done (out_string);
}
+