* 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 !!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
diff --git a/src/sfnt/ttcmap0.c b/src/sfnt/ttcmap0.c
index be318c1..b464a5b 100644
--- 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;
}