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

Fix pervasive buffer overruns when skipping glyphs when matching contexts.

Mon Jul 19 16:29:45 2004  Owen Taylor  <otaylor@redhat.com>

        * pango/opentype/ftxgsub.c pango/opentype/ftxgpos.c:
        Fix pervasive buffer overruns when skipping glyphs
        when matching contexts. (#118592, Kailash C. Chowksey)
上级 99848cfa
...@@ -1625,10 +1625,9 @@ ...@@ -1625,10 +1625,9 @@
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( buffer->in_pos < buffer->in_length ) if ( buffer->in_pos == buffer->in_length )
(buffer->in_pos)++; return TTO_Err_Not_Covered;
else (buffer->in_pos)++;
break;
} }
switch ( pp->PosFormat ) switch ( pp->PosFormat )
...@@ -3864,33 +3863,34 @@ ...@@ -3864,33 +3863,34 @@
for ( k = 0; k < numpr; k++ ) for ( k = 0; k < numpr; k++ )
{ {
if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount ) if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
continue; goto next_posrule;
if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length ) if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
continue; /* context is too long */ goto next_posrule; /* context is too long */
for ( i = 1, j = 1; i < pr[k].GlyphCount; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( buffer->in_pos + j < buffer->in_length ) if ( j + pr[k].GlyphCount - i == buffer->in_length )
j++; goto next_posrule;
else j++;
break;
} }
if ( IN_CURGLYPH( j ) != pr[k].Input[i - 1] ) if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )
break; goto next_posrule;
} }
if ( i == pr[k].GlyphCount ) return Do_ContextPos( gpi, pr[k].GlyphCount,
return Do_ContextPos( gpi, pr[k].GlyphCount, pr[k].PosCount, pr[k].PosLookupRecord,
pr[k].PosCount, pr[k].PosLookupRecord, buffer,
buffer, nesting_level );
nesting_level );
next_posrule:
;
} }
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
...@@ -3952,50 +3952,49 @@ ...@@ -3952,50 +3952,49 @@
pr = &pcs->PosClassRule[k]; pr = &pcs->PosClassRule[k];
if ( context_length != 0xFFFF && context_length < pr->GlyphCount ) if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
continue; goto next_posclassrule;
if ( buffer->in_pos + pr->GlyphCount > buffer->in_length ) if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
continue; /* context is too long */ goto next_posclassrule; /* context is too long */
cl = pr->Class; cl = pr->Class;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < pr->GlyphCount; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
if ( buffer->in_pos + j < buffer->in_length ) if ( j + pr->GlyphCount - i == buffer->in_length )
j++; goto next_posclassrule;
else j++;
break;
} }
if ( i > known_classes ) if ( i > known_classes )
{ {
/* Keeps us from having to do this for each rule */ /* Keeps us from having to do this for each rule */
error = Get_Class( &cpf2->ClassDef, IN_CURGLYPH( j ), &classes[i], NULL ); error = Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
known_classes = i; known_classes = i;
} }
if ( cl[i - 1] != classes[i] ) if ( cl[i - 1] != classes[i] )
break; goto next_posclassrule;
} }
if ( i == pr->GlyphCount ) error = Do_ContextPos( gpi, pr->GlyphCount,
{ pr->PosCount, pr->PosLookupRecord,
error = Do_ContextPos( gpi, pr->GlyphCount, buffer,
pr->PosCount, pr->PosLookupRecord, nesting_level );
buffer, goto End;
nesting_level );
goto End; next_posclassrule:
} ;
} }
error = TTO_Err_Not_Covered; error = TTO_Err_Not_Covered;
...@@ -4036,18 +4035,17 @@ ...@@ -4036,18 +4035,17 @@
for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ ) for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( buffer->in_pos + j < buffer->in_length ) if ( j + cpf3->GlyphCount - i == buffer->in_length )
j++;
else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
j++;
} }
error = Coverage_Index( &c[i], IN_CURGLYPH( j ), &index ); error = Coverage_Index( &c[i], IN_GLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
...@@ -5112,7 +5110,7 @@ ...@@ -5112,7 +5110,7 @@
int nesting_level ) int nesting_level )
{ {
FT_UShort index, property; FT_UShort index, property;
FT_UShort i, j, k, num_cpr, curr_pos; FT_UShort i, j, k, num_cpr;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_Error error; FT_Error error;
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
...@@ -5142,20 +5140,18 @@ ...@@ -5142,20 +5140,18 @@
lgc = curr_cpr.LookaheadGlyphCount; lgc = curr_cpr.LookaheadGlyphCount;
if ( context_length != 0xFFFF && context_length < igc ) if ( context_length != 0xFFFF && context_length < igc )
continue; goto next_chainposrule;
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue; goto next_chainposrule;
if ( bgc ) if ( bgc )
{ {
/* Since we don't know in advance the number of glyphs to inspect, /* Since we don't know in advance the number of glyphs to inspect,
we search backwards for matches in the backtrack glyph array */ we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
...@@ -5163,10 +5159,9 @@ ...@@ -5163,10 +5159,9 @@
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( j > curr_pos ) if ( j + 1 == bgc - i )
j--; goto next_chainposrule;
else j--;
break;
} }
/* In OpenType 1.3, it is undefined whether the offsets of /* In OpenType 1.3, it is undefined whether the offsets of
...@@ -5180,65 +5175,55 @@ ...@@ -5180,65 +5175,55 @@
Lookahead offsets - 0 1 2 3 */ Lookahead offsets - 0 1 2 3 */
if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] ) if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
break; goto next_chainposrule;
} }
if ( i != bgc )
continue;
} }
curr_pos = buffer->in_pos;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < buffer->in_length ) if ( j + igc - i + lgc == buffer->in_length )
j++; goto next_chainposrule;
else j++;
break;
} }
if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Input[i - 1] ) if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )
break; goto next_chainposrule;
} }
if ( i != igc )
continue;
/* we are starting to check for lookahead glyphs right after the /* we are starting to check for lookahead glyphs right after the
last context glyph */ last context glyph */
curr_pos += j; for ( i = 0; i < lgc; i++, j++ )
for ( i = 0, j = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < buffer->in_length ) if ( j + lgc - i == buffer->in_length )
j++; goto next_chainposrule;
else j++;
break;
} }
if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Lookahead[i] ) if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )
break; goto next_chainposrule;
} }
if ( i == lgc ) return Do_ContextPos( gpi, igc,
return Do_ContextPos( gpi, igc, curr_cpr.PosCount,
curr_cpr.PosCount, curr_cpr.PosLookupRecord,
curr_cpr.PosLookupRecord, buffer,
buffer, nesting_level );
nesting_level );
next_chainposrule:
;
} }
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
...@@ -5256,7 +5241,7 @@ ...@@ -5256,7 +5241,7 @@
FT_UShort index, property; FT_UShort index, property;
FT_Memory memory = gpi->face->memory; FT_Memory memory = gpi->face->memory;
FT_Error error; FT_Error error;
FT_UShort i, j, k, curr_pos; FT_UShort i, j, k;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_UShort known_backtrack_classes, FT_UShort known_backtrack_classes,
known_input_classes, known_input_classes,
...@@ -5321,12 +5306,12 @@ ...@@ -5321,12 +5306,12 @@
lgc = cpcr.LookaheadGlyphCount; lgc = cpcr.LookaheadGlyphCount;
if ( context_length != 0xFFFF && context_length < igc ) if ( context_length != 0xFFFF && context_length < igc )
continue; goto next_chainposclassrule;
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue; goto next_chainposclassrule;
if ( bgc ) if ( bgc )
{ {
...@@ -5334,7 +5319,6 @@ ...@@ -5334,7 +5319,6 @@
we search backwards for matches in the backtrack glyph array. we search backwards for matches in the backtrack glyph array.
Note that `known_backtrack_classes' starts at index 0. */ Note that `known_backtrack_classes' starts at index 0. */
curr_pos = 0;
bc = cpcr.Backtrack; bc = cpcr.Backtrack;
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
...@@ -5344,10 +5328,9 @@ ...@@ -5344,10 +5328,9 @@
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( j > curr_pos ) if ( j + 1 == bgc - i )
j--; goto next_chainposclassrule;
else j++;
break;
} }
if ( i >= known_backtrack_classes ) if ( i >= known_backtrack_classes )
...@@ -5362,34 +5345,29 @@ ...@@ -5362,34 +5345,29 @@
} }
if ( bc[i] != backtrack_classes[i] ) if ( bc[i] != backtrack_classes[i] )
break; goto next_chainposclassrule;
} }
if ( i != bgc )
continue;
} }
curr_pos = buffer->in_pos;
ic = cpcr.Input; ic = cpcr.Input;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( curr_pos + j < buffer->in_length ) if ( j + igc - i + lgc == buffer->in_length )
j++; goto next_chainposclassrule;
else j++;
break;
} }
if ( i >= known_input_classes ) if ( i >= known_input_classes )
{ {
error = Get_Class( &ccpf2->InputClassDef, IN_GLYPH( curr_pos + j ), error = Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),
&input_classes[i], NULL ); &input_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -5397,34 +5375,29 @@ ...@@ -5397,34 +5375,29 @@
} }
if ( ic[i - 1] != input_classes[i] ) if ( ic[i - 1] != input_classes[i] )
break; goto next_chainposclassrule;
} }
if ( i != igc )
continue;
/* we are starting to check for lookahead glyphs right after the /* we are starting to check for lookahead glyphs right after the
last context glyph */ last context glyph */
curr_pos += j;
lc = cpcr.Lookahead; lc = cpcr.Lookahead;
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( curr_pos + j < buffer->in_length ) if ( j + lgc - i == buffer->in_length )
j++; goto next_chainposclassrule;
else j++;
break;
} }
if ( i >= known_lookahead_classes ) if ( i >= known_lookahead_classes )
{ {
error = Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( curr_pos + j ), error = Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),
&lookahead_classes[i], NULL ); &lookahead_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -5432,18 +5405,18 @@ ...@@ -5432,18 +5405,18 @@
} }
if ( lc[i] != lookahead_classes[i] ) if ( lc[i] != lookahead_classes[i] )
break; goto next_chainposclassrule;
} }
if ( i == lgc ) error = Do_ContextPos( gpi, igc,
{ cpcr.PosCount,
error = Do_ContextPos( gpi, igc, cpcr.PosLookupRecord,
cpcr.PosCount, buffer,
cpcr.PosLookupRecord, nesting_level );
buffer, goto End1;
nesting_level );
goto End1; next_chainposclassrule:
} ;
} }
error = TTO_Err_Not_Covered; error = TTO_Err_Not_Covered;
...@@ -5468,7 +5441,7 @@ ...@@ -5468,7 +5441,7 @@
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
{ {
FT_UShort index, i, j, curr_pos, property; FT_UShort index, i, j, property;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_Error error; FT_Error error;
TTO_GPOSHeader* gpos = gpi->gpos; TTO_GPOSHeader* gpos = gpi->gpos;
...@@ -5501,7 +5474,6 @@ ...@@ -5501,7 +5474,6 @@
/* Since we don't know in advance the number of glyphs to inspect, /* Since we don't know in advance the number of glyphs to inspect,
we search backwards for matches in the backtrack glyph array */ we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
bc = ccpf3->BacktrackCoverage; bc = ccpf3->BacktrackCoverage;
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
...@@ -5511,10 +5483,9 @@ ...@@ -5511,10 +5483,9 @@
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( j > curr_pos ) if ( j + 1 == bgc - i )
j--;
else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
j--;
} }
error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index ); error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
...@@ -5523,24 +5494,22 @@ ...@@ -5523,24 +5494,22 @@
} }
} }
curr_pos = buffer->in_pos;
ic = ccpf3->InputCoverage; ic = ccpf3->InputCoverage;
for ( i = 0, j = 0; i < igc; i++, j++ ) for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
{ {
/* We already called CHECK_Property for s_in[0] */ /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( j > buffer->in_pos && CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < buffer->in_length ) if ( j + igc - i + lgc == buffer->in_length )
j++;
else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
j++;
} }
error = Coverage_Index( &ic[i], IN_GLYPH( curr_pos + j ), &index ); error = Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
...@@ -5548,23 +5517,21 @@ ...@@ -5548,23 +5517,21 @@
/* we are starting to check for lookahead glyphs right after the /* we are starting to check for lookahead glyphs right after the
last context glyph */ last context glyph */
curr_pos += j;
lc = ccpf3->LookaheadCoverage; lc = ccpf3->LookaheadCoverage;
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < buffer->in_length ) if ( j + lgc - i == buffer->in_length )
j++;
else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
j++;
} }
error = Coverage_Index( &lc[i], IN_GLYPH( curr_pos + j ), &index ); error = Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
......
...@@ -1026,7 +1026,7 @@ ...@@ -1026,7 +1026,7 @@
numlig--, lig++ ) numlig--, lig++ )
{ {
if ( buffer->in_pos + lig->ComponentCount > buffer->in_length ) if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
continue; /* Not enough glyphs in input */ goto next_ligature; /* Not enough glyphs in input */
c = lig->Component; c = lig->Component;
...@@ -1035,85 +1035,84 @@ ...@@ -1035,85 +1035,84 @@
if ( context_length != 0xFFFF && context_length < lig->ComponentCount ) if ( context_length != 0xFFFF && context_length < lig->ComponentCount )
break; break;
for ( i = 1, j = 1; i < lig->ComponentCount; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( buffer->in_pos + j < buffer->in_length ) if ( j + lig->ComponentCount - i == buffer->in_length )
j++; goto next_ligature;
else j++;
break;
} }
if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) ) if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) )
is_mark = FALSE; is_mark = FALSE;
if ( IN_CURGLYPH( j ) != c[i - 1] ) if ( IN_GLYPH( j ) != c[i - 1] )
break; goto next_ligature;
} }
if ( i == lig->ComponentCount ) if ( gdef && gdef->NewGlyphClasses )
{ {
if ( gdef && gdef->NewGlyphClasses ) /* this is just a guess ... */
{
/* this is just a guess ... */
error = Add_Glyph_Property( gdef, lig->LigGlyph, error = Add_Glyph_Property( gdef, lig->LigGlyph,
is_mark ? TTO_MARK : TTO_LIGATURE ); is_mark ? TTO_MARK : TTO_LIGATURE );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
} }
if ( i == j ) if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
{ {
/* We don't use a new ligature ID if there are no skipped /* We don't use a new ligature ID if there are no skipped
glyphs and the ligature already has an ID. */ glyphs and the ligature already has an ID. */
if ( IN_LIGID( buffer->in_pos ) ) if ( IN_LIGID( buffer->in_pos ) )
{ {
if ( ADD_String( buffer, i, 1, &lig->LigGlyph, if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
0xFFFF, 0xFFFF ) ) 0xFFFF, 0xFFFF ) )
return error; return error;
} }
else else
{ {
FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
0xFFFF, ligID ) )
return error;
}
}
else
{
FT_UShort ligID = otl_buffer_allocate_ligid( buffer ); FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
if ( ADD_Glyph( buffer, lig->LigGlyph, if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
0xFFFF, ligID ) ) 0xFFFF, ligID ) )
return error; return error;
}
}
else
{
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
`out' and assign component values to it. We start with the
glyph after the first component. Glyphs between component
i and i+1 belong to component i. Together with the ligID
value it is later possible to check whether a specific
component value really belongs to a given ligature. */
for ( i = 0; i < lig->ComponentCount - 1; i++ )
{
while ( CHECK_Property( gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
i, ligID ) )
return error;
/* Now we must do a second loop to copy the skipped glyphs to (buffer->in_pos)++;
`out' and assign component values to it. We start with the }
glyph after the first component. Glyphs between component }
i and i+1 belong to component i. Together with the ligID
value it is later possible to check whether a specific
component value really belongs to a given ligature. */
for ( i = 0; i < lig->ComponentCount - 1; i++ ) return TT_Err_Ok;
{
while ( CHECK_Property( gdef, IN_CURGLYPH( 0 ),
flags, &property ) )
if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ),
i, ligID ) )
return error;
(buffer->in_pos)++; next_ligature:
} ;
}
return TT_Err_Ok;
}
} }
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
...@@ -1921,33 +1920,33 @@ ...@@ -1921,33 +1920,33 @@
for ( k = 0; k < numsr; k++ ) for ( k = 0; k < numsr; k++ )
{ {
if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount ) if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
continue; goto next_subrule;
if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length ) if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
continue; /* context is too long */ goto next_subrule; /* context is too long */
for ( i = 1, j = 1; i < sr[k].GlyphCount; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( buffer->in_pos + j < buffer->in_length ) if ( j + sr[k].GlyphCount - i == buffer->in_length )
j++; goto next_subrule;
else j++;
break;
} }
if ( IN_CURGLYPH( j ) != sr[k].Input[i - 1] ) if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )
break; goto next_subrule;
} }
if ( i == sr[k].GlyphCount ) return Do_ContextSubst( gsub, sr[k].GlyphCount,
return Do_ContextSubst( gsub, sr[k].GlyphCount, sr[k].SubstCount, sr[k].SubstLookupRecord,
sr[k].SubstCount, sr[k].SubstLookupRecord, buffer,
buffer, nesting_level );
nesting_level ); next_subrule:
;
} }
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
...@@ -2009,50 +2008,49 @@ ...@@ -2009,50 +2008,49 @@
sr = &scs->SubClassRule[k]; sr = &scs->SubClassRule[k];
if ( context_length != 0xFFFF && context_length < sr->GlyphCount ) if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
continue; goto next_subclassrule;
if ( buffer->in_pos + sr->GlyphCount > buffer->in_length ) if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
continue; /* context is too long */ goto next_subclassrule; /* context is too long */
cl = sr->Class; cl = sr->Class;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < sr->GlyphCount; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
if ( buffer->in_pos + j < buffer->in_length ) if ( j + sr->GlyphCount - i < buffer->in_length )
j++; goto next_subclassrule;
else j++;
break;
} }
if ( i > known_classes ) if ( i > known_classes )
{ {
/* Keeps us from having to do this for each rule */ /* Keeps us from having to do this for each rule */
error = Get_Class( &csf2->ClassDef, IN_CURGLYPH( j ), &classes[i], NULL ); error = Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End; goto End;
known_classes = i; known_classes = i;
} }
if ( cl[i - 1] != classes[i] ) if ( cl[i - 1] != classes[i] )
break; goto next_subclassrule;
} }
if ( i == sr->GlyphCount ) error = Do_ContextSubst( gsub, sr->GlyphCount,
{ sr->SubstCount, sr->SubstLookupRecord,
error = Do_ContextSubst( gsub, sr->GlyphCount, buffer,
sr->SubstCount, sr->SubstLookupRecord, nesting_level );
buffer, goto End;
nesting_level );
goto End; next_subclassrule:
} ;
} }
error = TTO_Err_Not_Covered; error = TTO_Err_Not_Covered;
...@@ -2091,20 +2089,19 @@ ...@@ -2091,20 +2089,19 @@
c = csf3->Coverage; c = csf3->Coverage;
for ( i = 1, j = 1; i < csf3->GlyphCount; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( buffer->in_pos + j < buffer->in_length ) if ( j + csf3->GlyphCount - i == buffer->in_length )
j++;
else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
j++;
} }
error = Coverage_Index( &c[i], IN_CURGLYPH( j ), &index ); error = Coverage_Index( &c[i], IN_GLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
...@@ -3175,7 +3172,7 @@ ...@@ -3175,7 +3172,7 @@
int nesting_level ) int nesting_level )
{ {
FT_UShort index, property; FT_UShort index, property;
FT_UShort i, j, k, num_csr, curr_pos; FT_UShort i, j, k, num_csr;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_Error error; FT_Error error;
...@@ -3204,20 +3201,18 @@ ...@@ -3204,20 +3201,18 @@
lgc = curr_csr.LookaheadGlyphCount; lgc = curr_csr.LookaheadGlyphCount;
if ( context_length != 0xFFFF && context_length < igc ) if ( context_length != 0xFFFF && context_length < igc )
continue; goto next_chainsubrule;
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue; goto next_chainsubrule;
if ( bgc ) if ( bgc )
{ {
/* since we don't know in advance the number of glyphs to inspect, /* since we don't know in advance the number of glyphs to inspect,
we search backwards for matches in the backtrack glyph array */ we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
...@@ -3225,10 +3220,9 @@ ...@@ -3225,10 +3220,9 @@
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( j > curr_pos ) if ( j + 1 == bgc - i )
j--; goto next_chainsubrule;
else j--;
break;
} }
/* In OpenType 1.3, it is undefined whether the offsets of /* In OpenType 1.3, it is undefined whether the offsets of
...@@ -3242,65 +3236,55 @@ ...@@ -3242,65 +3236,55 @@
Lookahead offsets - 0 1 2 3 */ Lookahead offsets - 0 1 2 3 */
if ( IN_GLYPH( j ) != curr_csr.Backtrack[i] ) if ( IN_GLYPH( j ) != curr_csr.Backtrack[i] )
break; goto next_chainsubrule;
} }
if ( i != bgc )
continue;
} }
curr_pos = buffer->in_pos;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < buffer->in_length ) if ( j + igc - i + lgc == buffer->in_length )
j++; goto next_chainsubrule;
else j++;
break;
} }
if ( IN_GLYPH( curr_pos + j ) != curr_csr.Input[i - 1] ) if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )
break; goto next_chainsubrule;
} }
if ( i != igc )
continue;
/* we are starting to check for lookahead glyphs right after the /* we are starting to check for lookahead glyphs right after the
last context glyph */ last context glyph */
curr_pos += j; for ( i = 0; i < lgc; i++, j++ )
for ( i = 0, j = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < buffer->in_length ) if ( j + lgc - i == buffer->in_length )
j++; goto next_chainsubrule;
else j++;
break;
} }
if ( IN_GLYPH( curr_pos + j ) != curr_csr.Lookahead[i] ) if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )
break; goto next_chainsubrule;
} }
if ( i == lgc ) return Do_ContextSubst( gsub, igc,
return Do_ContextSubst( gsub, igc, curr_csr.SubstCount,
curr_csr.SubstCount, curr_csr.SubstLookupRecord,
curr_csr.SubstLookupRecord, buffer,
buffer, nesting_level );
nesting_level );
next_chainsubrule:
;
} }
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
...@@ -3318,7 +3302,7 @@ ...@@ -3318,7 +3302,7 @@
FT_UShort index, property; FT_UShort index, property;
FT_Memory memory; FT_Memory memory;
FT_Error error; FT_Error error;
FT_UShort i, j, k, curr_pos; FT_UShort i, j, k;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_UShort known_backtrack_classes, FT_UShort known_backtrack_classes,
known_input_classes, known_input_classes,
...@@ -3383,12 +3367,12 @@ ...@@ -3383,12 +3367,12 @@
lgc = ccsr.LookaheadGlyphCount; lgc = ccsr.LookaheadGlyphCount;
if ( context_length != 0xFFFF && context_length < igc ) if ( context_length != 0xFFFF && context_length < igc )
continue; goto next_chainsubclassrule;
/* check whether context is too long; it is a first guess only */ /* check whether context is too long; it is a first guess only */
if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
continue; goto next_chainsubclassrule;
if ( bgc ) if ( bgc )
{ {
...@@ -3396,7 +3380,6 @@ ...@@ -3396,7 +3380,6 @@
we search backwards for matches in the backtrack glyph array. we search backwards for matches in the backtrack glyph array.
Note that `known_backtrack_classes' starts at index 0. */ Note that `known_backtrack_classes' starts at index 0. */
curr_pos = 0;
bc = ccsr.Backtrack; bc = ccsr.Backtrack;
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
...@@ -3406,10 +3389,9 @@ ...@@ -3406,10 +3389,9 @@
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( j > curr_pos ) if ( j + 1 == bgc - i )
j--; goto next_chainsubclassrule;
else j--;
break;
} }
if ( i >= known_backtrack_classes ) if ( i >= known_backtrack_classes )
...@@ -3424,34 +3406,29 @@ ...@@ -3424,34 +3406,29 @@
} }
if ( bc[i] != backtrack_classes[i] ) if ( bc[i] != backtrack_classes[i] )
break; goto next_chainsubclassrule;
} }
if ( i != bgc )
continue;
} }
curr_pos = buffer->in_pos;
ic = ccsr.Input; ic = ccsr.Input;
/* Start at 1 because [0] is implied */ /* Start at 1 because [0] is implied */
for ( i = 1, j = 1; i < igc; i++, j++ ) for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( curr_pos + j < buffer->in_length ) if ( j + igc - i + lgc == buffer->in_length )
j++; goto next_chainsubclassrule;
else j++;
break;
} }
if ( i >= known_input_classes ) if ( i >= known_input_classes )
{ {
error = Get_Class( &ccsf2->InputClassDef, IN_GLYPH( curr_pos + j ), error = Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ),
&input_classes[i], NULL ); &input_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -3459,34 +3436,29 @@ ...@@ -3459,34 +3436,29 @@
} }
if ( ic[i - 1] != input_classes[i] ) if ( ic[i - 1] != input_classes[i] )
break; goto next_chainsubclassrule;
} }
if ( i != igc )
continue;
/* we are starting to check for lookahead glyphs right after the /* we are starting to check for lookahead glyphs right after the
last context glyph */ last context glyph */
curr_pos += j;
lc = ccsr.Lookahead; lc = ccsr.Lookahead;
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
if ( curr_pos + j < buffer->in_length ) if ( j + lgc - i == buffer->in_length )
j++; goto next_chainsubclassrule;
else j++;
break;
} }
if ( i >= known_lookahead_classes ) if ( i >= known_lookahead_classes )
{ {
error = Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( curr_pos + j ), error = Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ),
&lookahead_classes[i], NULL ); &lookahead_classes[i], NULL );
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
goto End1; goto End1;
...@@ -3494,18 +3466,18 @@ ...@@ -3494,18 +3466,18 @@
} }
if ( lc[i] != lookahead_classes[i] ) if ( lc[i] != lookahead_classes[i] )
break; goto next_chainsubclassrule;
} }
if ( i == lgc ) error = Do_ContextSubst( gsub, igc,
{ ccsr.SubstCount,
error = Do_ContextSubst( gsub, igc, ccsr.SubstLookupRecord,
ccsr.SubstCount, buffer,
ccsr.SubstLookupRecord, nesting_level );
buffer, goto End1;
nesting_level );
goto End1; next_chainsubclassrule:
} ;
} }
error = TTO_Err_Not_Covered; error = TTO_Err_Not_Covered;
...@@ -3530,7 +3502,7 @@ ...@@ -3530,7 +3502,7 @@
FT_UShort context_length, FT_UShort context_length,
int nesting_level ) int nesting_level )
{ {
FT_UShort index, i, j, curr_pos, property; FT_UShort index, i, j, property;
FT_UShort bgc, igc, lgc; FT_UShort bgc, igc, lgc;
FT_Error error; FT_Error error;
...@@ -3562,7 +3534,6 @@ ...@@ -3562,7 +3534,6 @@
/* Since we don't know in advance the number of glyphs to inspect, /* Since we don't know in advance the number of glyphs to inspect,
we search backwards for matches in the backtrack glyph array */ we search backwards for matches in the backtrack glyph array */
curr_pos = 0;
bc = ccsf3->BacktrackCoverage; bc = ccsf3->BacktrackCoverage;
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
...@@ -3572,10 +3543,9 @@ ...@@ -3572,10 +3543,9 @@
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( j > curr_pos ) if ( j + 1 == bgc - i )
j--; return TTO_Err_Not_Covered;
else j--;
return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index ); error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
...@@ -3584,24 +3554,22 @@ ...@@ -3584,24 +3554,22 @@
} }
} }
curr_pos = buffer->in_pos;
ic = ccsf3->InputCoverage; ic = ccsf3->InputCoverage;
for ( i = 0, j = 0; i < igc; i++, j++ ) for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
{ {
/* We already called CHECK_Property for IN_GLYPH( curr_pos ) */ /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( j > buffer->in_pos && CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < buffer->in_length ) if ( j + igc - i + lgc == buffer->in_length )
j++;
else
return TTO_Err_Not_Covered; return TTO_Err_Not_Covered;
j++;
} }
error = Coverage_Index( &ic[i], IN_GLYPH( curr_pos + j ), &index ); error = Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
...@@ -3609,23 +3577,21 @@ ...@@ -3609,23 +3577,21 @@
/* we are starting for lookahead glyphs right after the last context /* we are starting for lookahead glyphs right after the last context
glyph */ glyph */
curr_pos += j;
lc = ccsf3->LookaheadCoverage; lc = ccsf3->LookaheadCoverage;
for ( i = 0, j = 0; i < lgc; i++, j++ ) for ( i = 0; i < lgc; i++, j++ )
{ {
while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) )
{ {
if ( error && error != TTO_Err_Not_Covered ) if ( error && error != TTO_Err_Not_Covered )
return error; return error;
if ( curr_pos + j < buffer->in_length ) if ( j + lgc - i == buffer->in_length )
j++; return TTO_Err_Not_Covered;
else j++;
return TTO_Err_Not_Covered;
} }
error = Coverage_Index( &lc[i], IN_GLYPH( curr_pos + j ), &index ); error = Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
if ( error ) if ( error )
return error; return error;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册