ref: 3c5a3e45c959de4b17daecb63d3aab92a6741256
parent: af48e32c17a5f5ab88509c3730fd875a2e94a990
author: David Turner <[email protected]>
date: Wed May 1 04:40:32 EDT 2002
* src/sfnt/ttcmap0.c (tt_cmap4_validate): fixed over-restrictive validation test. the charmap validator now accepts overlapping ranges in format 4 charmaps. * src/sfnt/ttcmap0.c (tt_cmap4_char_index): switched to a binary search algorithm. Certain fonts contain more than 170 distinct segments !!
--- a/src/sfnt/ttcmap0.c
+++ b/src/sfnt/ttcmap0.c
@@ -638,7 +638,7 @@
offsets = deltas + num_segs * 2;
glyph_ids = offsets + num_segs * 2;
- if ( glyph_ids >= table + length )
+ if ( glyph_ids > table + length )
FT_INVALID_TOO_SHORT;
/* check last segment, its end count must be FFFF */
@@ -670,8 +670,15 @@
if ( start > end )
FT_INVALID_DATA;
- if ( n > 0 && start <= last )
- FT_INVALID_DATA;
+ /* this test should be performed at default validation level */
+ /* unfortunately, some popular asian fonts present overlapping */
+ /* ranges in their charmaps.. */
+ /* */
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+ if ( n > 0 && start <= last )
+ FT_INVALID_DATA;
+ }
if ( offset )
{
@@ -718,49 +725,108 @@
if ( char_code < 0x10000UL )
{
- FT_Byte* p;
- FT_Byte* q;
FT_UInt idx, num_segs2;
FT_Int delta;
- FT_UInt n, code = (FT_UInt)char_code;
+ FT_UInt code = (FT_UInt)char_code;
+ FT_Byte* p;
p = table + 6;
num_segs2 = TT_PEEK_USHORT( p ) & -2; /* be paranoid! */
- p = table + 14; /* ends table */
- q = table + 16 + num_segs2; /* starts table */
-
- for ( n = 0; n < num_segs2; n += 2 )
+#if 1
+ /* some fonts have more than 170 segments in their charmaps !! */
+ /* we changed this function to use a more efficient binary */
+ /* search to boost its performance */
{
- FT_UInt end = TT_NEXT_USHORT( p );
- FT_UInt start = TT_NEXT_USHORT( q );
- FT_UInt offset;
+ FT_UInt min = 0;
+ FT_UInt max = num_segs2 >> 1;
+ FT_UInt mid, start, end, offset;
+
+ while ( min < max )
+ {
+ mid = ( min + max ) >> 1;
+ p = table + 14 + mid*2;
+ end = TT_NEXT_USHORT( p );
+ p += num_segs2;
+ start = TT_PEEK_USHORT( p);
+
+ if ( code < start )
+ max = mid;
+
+ else if ( code > end )
+ min = mid+1;
+
+ else
+ {
+ /* we found the segment */
+ idx = code;
+
+ p += num_segs2;
+ delta = TT_PEEK_SHORT( p );
+
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
+ if ( offset != 0 )
+ {
+ p += offset + 2*( idx - start );
+ idx = TT_PEEK_USHORT( p );
+ }
+
+ if ( idx != 0 )
+ result = (FT_UInt)( idx + delta ) & 0xFFFU;
+
+ goto Exit;
+ }
+ }
+ }
- if ( code < start )
- break;
+#else /* 0 - old code */
+ {
+ FT_UInt n;
+ FT_Byte* q;
- if ( code <= end )
- {
- idx = code;
- p = q + num_segs2 - 2;
- delta = TT_PEEK_SHORT( p );
- p += num_segs2;
- offset = TT_PEEK_USHORT( p );
+ p = table + 14; /* ends table */
+ q = table + 16 + num_segs2; /* starts table */
- if ( offset != 0 )
+
+ for ( n = 0; n < num_segs2; n += 2 )
+ {
+ FT_UInt end = TT_NEXT_USHORT( p );
+ FT_UInt start = TT_NEXT_USHORT( q );
+ FT_UInt offset;
+
+
+ if ( code < start )
+ break;
+
+ if ( code <= end )
{
- p += offset + 2 * ( idx - start );
- idx = TT_PEEK_USHORT( p );
+ idx = code;
+
+ p = q + num_segs2 - 2;
+ delta = TT_PEEK_SHORT( p );
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
+ if ( offset != 0 )
+ {
+ p += offset + 2 * ( idx - start );
+ idx = TT_PEEK_USHORT( p );
+ }
+
+ if ( idx != 0 )
+ result = (FT_UInt)( idx + delta ) & 0xFFFFU;
}
-
- if ( idx != 0 )
- result = (FT_UInt)( idx + delta ) & 0xFFFFU;
}
}
+#endif /* 0 */
}
+
+ Exit:
return result;
}