| OLD | NEW |
| (Empty) |
| 1 /***************************************************************************/ | |
| 2 /* */ | |
| 3 /* ttkern.c */ | |
| 4 /* */ | |
| 5 /* Load the basic TrueType kerning table. This doesn't handle */ | |
| 6 /* kerning data within the GPOS table at the moment. */ | |
| 7 /* */ | |
| 8 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */ | |
| 9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | |
| 10 /* */ | |
| 11 /* This file is part of the FreeType project, and may only be used, */ | |
| 12 /* modified, and distributed under the terms of the FreeType project */ | |
| 13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | |
| 14 /* this file you indicate that you have read the license and */ | |
| 15 /* understand and accept it fully. */ | |
| 16 /* */ | |
| 17 /***************************************************************************/ | |
| 18 | |
| 19 | |
| 20 #include "../../include/ft2build.h" | |
| 21 #include "../../include/freetype/internal/ftdebug.h" | |
| 22 #include "../../include/freetype/internal/ftstream.h" | |
| 23 #include "../../include/freetype/tttags.h" | |
| 24 #include "ttkern.h" | |
| 25 | |
| 26 #include "sferrors.h" | |
| 27 | |
| 28 | |
| 29 /*************************************************************************/ | |
| 30 /* */ | |
| 31 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
| 32 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
| 33 /* messages during execution. */ | |
| 34 /* */ | |
| 35 #undef FT_COMPONENT | |
| 36 #define FT_COMPONENT trace_ttkern | |
| 37 | |
| 38 | |
| 39 #undef TT_KERN_INDEX | |
| 40 #define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) ) | |
| 41 | |
| 42 | |
| 43 FT_LOCAL_DEF( FT_Error ) | |
| 44 tt_face_load_kern( TT_Face face, | |
| 45 FT_Stream stream ) | |
| 46 { | |
| 47 FT_Error error; | |
| 48 FT_ULong table_size; | |
| 49 FT_Byte* p; | |
| 50 FT_Byte* p_limit; | |
| 51 FT_UInt nn, num_tables; | |
| 52 FT_UInt32 avail = 0, ordered = 0; | |
| 53 | |
| 54 | |
| 55 /* the kern table is optional; exit silently if it is missing */ | |
| 56 error = face->goto_table( face, TTAG_kern, stream, &table_size ); | |
| 57 if ( error ) | |
| 58 goto Exit; | |
| 59 | |
| 60 if ( table_size < 4 ) /* the case of a malformed table */ | |
| 61 { | |
| 62 FT_ERROR(( "tt_face_load_kern:" | |
| 63 " kerning table is too small - ignored\n" )); | |
| 64 error = FT_THROW( Table_Missing ); | |
| 65 goto Exit; | |
| 66 } | |
| 67 | |
| 68 if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) ) | |
| 69 { | |
| 70 FT_ERROR(( "tt_face_load_kern:" | |
| 71 " could not extract kerning table\n" )); | |
| 72 goto Exit; | |
| 73 } | |
| 74 | |
| 75 face->kern_table_size = table_size; | |
| 76 | |
| 77 p = face->kern_table; | |
| 78 p_limit = p + table_size; | |
| 79 | |
| 80 p += 2; /* skip version */ | |
| 81 num_tables = FT_NEXT_USHORT( p ); | |
| 82 | |
| 83 if ( num_tables > 32 ) /* we only support up to 32 sub-tables */ | |
| 84 num_tables = 32; | |
| 85 | |
| 86 for ( nn = 0; nn < num_tables; nn++ ) | |
| 87 { | |
| 88 FT_UInt num_pairs, length, coverage; | |
| 89 FT_Byte* p_next; | |
| 90 FT_UInt32 mask = (FT_UInt32)1UL << nn; | |
| 91 | |
| 92 | |
| 93 if ( p + 6 > p_limit ) | |
| 94 break; | |
| 95 | |
| 96 p_next = p; | |
| 97 | |
| 98 p += 2; /* skip version */ | |
| 99 length = FT_NEXT_USHORT( p ); | |
| 100 coverage = FT_NEXT_USHORT( p ); | |
| 101 | |
| 102 if ( length <= 6 ) | |
| 103 break; | |
| 104 | |
| 105 p_next += length; | |
| 106 | |
| 107 if ( p_next > p_limit ) /* handle broken table */ | |
| 108 p_next = p_limit; | |
| 109 | |
| 110 /* only use horizontal kerning tables */ | |
| 111 if ( ( coverage & ~8 ) != 0x0001 || | |
| 112 p + 8 > p_limit ) | |
| 113 goto NextTable; | |
| 114 | |
| 115 num_pairs = FT_NEXT_USHORT( p ); | |
| 116 p += 6; | |
| 117 | |
| 118 if ( ( p_next - p ) < 6 * (int)num_pairs ) /* handle broken count */ | |
| 119 num_pairs = (FT_UInt)( ( p_next - p ) / 6 ); | |
| 120 | |
| 121 avail |= mask; | |
| 122 | |
| 123 /* | |
| 124 * Now check whether the pairs in this table are ordered. | |
| 125 * We then can use binary search. | |
| 126 */ | |
| 127 if ( num_pairs > 0 ) | |
| 128 { | |
| 129 FT_ULong count; | |
| 130 FT_ULong old_pair; | |
| 131 | |
| 132 | |
| 133 old_pair = FT_NEXT_ULONG( p ); | |
| 134 p += 2; | |
| 135 | |
| 136 for ( count = num_pairs - 1; count > 0; count-- ) | |
| 137 { | |
| 138 FT_UInt32 cur_pair; | |
| 139 | |
| 140 | |
| 141 cur_pair = FT_NEXT_ULONG( p ); | |
| 142 if ( cur_pair <= old_pair ) | |
| 143 break; | |
| 144 | |
| 145 p += 2; | |
| 146 old_pair = cur_pair; | |
| 147 } | |
| 148 | |
| 149 if ( count == 0 ) | |
| 150 ordered |= mask; | |
| 151 } | |
| 152 | |
| 153 NextTable: | |
| 154 p = p_next; | |
| 155 } | |
| 156 | |
| 157 face->num_kern_tables = nn; | |
| 158 face->kern_avail_bits = avail; | |
| 159 face->kern_order_bits = ordered; | |
| 160 | |
| 161 Exit: | |
| 162 return error; | |
| 163 } | |
| 164 | |
| 165 | |
| 166 FT_LOCAL_DEF( void ) | |
| 167 tt_face_done_kern( TT_Face face ) | |
| 168 { | |
| 169 FT_Stream stream = face->root.stream; | |
| 170 | |
| 171 | |
| 172 FT_FRAME_RELEASE( face->kern_table ); | |
| 173 face->kern_table_size = 0; | |
| 174 face->num_kern_tables = 0; | |
| 175 face->kern_avail_bits = 0; | |
| 176 face->kern_order_bits = 0; | |
| 177 } | |
| 178 | |
| 179 | |
| 180 FT_LOCAL_DEF( FT_Int ) | |
| 181 tt_face_get_kerning( TT_Face face, | |
| 182 FT_UInt left_glyph, | |
| 183 FT_UInt right_glyph ) | |
| 184 { | |
| 185 FT_Int result = 0; | |
| 186 FT_UInt count, mask = 1; | |
| 187 FT_Byte* p = face->kern_table; | |
| 188 FT_Byte* p_limit = p + face->kern_table_size; | |
| 189 | |
| 190 | |
| 191 p += 4; | |
| 192 mask = 0x0001; | |
| 193 | |
| 194 for ( count = face->num_kern_tables; | |
| 195 count > 0 && p + 6 <= p_limit; | |
| 196 count--, mask <<= 1 ) | |
| 197 { | |
| 198 FT_Byte* base = p; | |
| 199 FT_Byte* next = base; | |
| 200 FT_UInt version = FT_NEXT_USHORT( p ); | |
| 201 FT_UInt length = FT_NEXT_USHORT( p ); | |
| 202 FT_UInt coverage = FT_NEXT_USHORT( p ); | |
| 203 FT_UInt num_pairs; | |
| 204 FT_Int value = 0; | |
| 205 | |
| 206 FT_UNUSED( version ); | |
| 207 | |
| 208 | |
| 209 next = base + length; | |
| 210 | |
| 211 if ( next > p_limit ) /* handle broken table */ | |
| 212 next = p_limit; | |
| 213 | |
| 214 if ( ( face->kern_avail_bits & mask ) == 0 ) | |
| 215 goto NextTable; | |
| 216 | |
| 217 if ( p + 8 > next ) | |
| 218 goto NextTable; | |
| 219 | |
| 220 num_pairs = FT_NEXT_USHORT( p ); | |
| 221 p += 6; | |
| 222 | |
| 223 if ( ( next - p ) < 6 * (int)num_pairs ) /* handle broken count */ | |
| 224 num_pairs = (FT_UInt)( ( next - p ) / 6 ); | |
| 225 | |
| 226 switch ( coverage >> 8 ) | |
| 227 { | |
| 228 case 0: | |
| 229 { | |
| 230 FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph ); | |
| 231 | |
| 232 | |
| 233 if ( face->kern_order_bits & mask ) /* binary search */ | |
| 234 { | |
| 235 FT_UInt min = 0; | |
| 236 FT_UInt max = num_pairs; | |
| 237 | |
| 238 | |
| 239 while ( min < max ) | |
| 240 { | |
| 241 FT_UInt mid = ( min + max ) >> 1; | |
| 242 FT_Byte* q = p + 6 * mid; | |
| 243 FT_ULong key; | |
| 244 | |
| 245 | |
| 246 key = FT_NEXT_ULONG( q ); | |
| 247 | |
| 248 if ( key == key0 ) | |
| 249 { | |
| 250 value = FT_PEEK_SHORT( q ); | |
| 251 goto Found; | |
| 252 } | |
| 253 if ( key < key0 ) | |
| 254 min = mid + 1; | |
| 255 else | |
| 256 max = mid; | |
| 257 } | |
| 258 } | |
| 259 else /* linear search */ | |
| 260 { | |
| 261 FT_UInt count2; | |
| 262 | |
| 263 | |
| 264 for ( count2 = num_pairs; count2 > 0; count2-- ) | |
| 265 { | |
| 266 FT_ULong key = FT_NEXT_ULONG( p ); | |
| 267 | |
| 268 | |
| 269 if ( key == key0 ) | |
| 270 { | |
| 271 value = FT_PEEK_SHORT( p ); | |
| 272 goto Found; | |
| 273 } | |
| 274 p += 2; | |
| 275 } | |
| 276 } | |
| 277 } | |
| 278 break; | |
| 279 | |
| 280 /* | |
| 281 * We don't support format 2 because we haven't seen a single font | |
| 282 * using it in real life... | |
| 283 */ | |
| 284 | |
| 285 default: | |
| 286 ; | |
| 287 } | |
| 288 | |
| 289 goto NextTable; | |
| 290 | |
| 291 Found: | |
| 292 if ( coverage & 8 ) /* override or add */ | |
| 293 result = value; | |
| 294 else | |
| 295 result += value; | |
| 296 | |
| 297 NextTable: | |
| 298 p = next; | |
| 299 } | |
| 300 | |
| 301 return result; | |
| 302 } | |
| 303 | |
| 304 #undef TT_KERN_INDEX | |
| 305 | |
| 306 /* END */ | |
| OLD | NEW |