00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <ft2build.h>
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_STREAM_H
00023 #include FT_TRUETYPE_TAGS_H
00024 #include "ttkern.h"
00025
00026 #include "sferrors.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035 #undef FT_COMPONENT
00036 #define FT_COMPONENT trace_ttkern
00037
00038
00039 #undef TT_KERN_INDEX
00040 #define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) )
00041
00042
00043 FT_LOCAL_DEF( FT_Error )
00044 tt_face_load_kern( TT_Face face,
00045 FT_Stream stream )
00046 {
00047 FT_Error error;
00048 FT_ULong table_size;
00049 FT_Byte* p;
00050 FT_Byte* p_limit;
00051 FT_UInt nn, num_tables;
00052 FT_UInt32 avail = 0, ordered = 0;
00053
00054
00055
00056 error = face->goto_table( face, TTAG_kern, stream, &table_size );
00057 if ( error )
00058 goto Exit;
00059
00060 if ( table_size < 4 )
00061 {
00062 FT_ERROR(( "tt_face_load_kern:"
00063 " kerning table is too small - ignored\n" ));
00064 error = SFNT_Err_Table_Missing;
00065 goto Exit;
00066 }
00067
00068 if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) )
00069 {
00070 FT_ERROR(( "tt_face_load_kern:"
00071 " could not extract kerning table\n" ));
00072 goto Exit;
00073 }
00074
00075 face->kern_table_size = table_size;
00076
00077 p = face->kern_table;
00078 p_limit = p + table_size;
00079
00080 p += 2;
00081 num_tables = FT_NEXT_USHORT( p );
00082
00083 if ( num_tables > 32 )
00084 num_tables = 32;
00085
00086 for ( nn = 0; nn < num_tables; nn++ )
00087 {
00088 FT_UInt num_pairs, length, coverage;
00089 FT_Byte* p_next;
00090 FT_UInt32 mask = (FT_UInt32)1UL << nn;
00091
00092
00093 if ( p + 6 > p_limit )
00094 break;
00095
00096 p_next = p;
00097
00098 p += 2;
00099 length = FT_NEXT_USHORT( p );
00100 coverage = FT_NEXT_USHORT( p );
00101
00102 if ( length <= 6 )
00103 break;
00104
00105 p_next += length;
00106
00107 if ( p_next > p_limit )
00108 p_next = p_limit;
00109
00110
00111 if ( ( coverage & ~8 ) != 0x0001 ||
00112 p + 8 > p_limit )
00113 goto NextTable;
00114
00115 num_pairs = FT_NEXT_USHORT( p );
00116 p += 6;
00117
00118 if ( ( p_next - p ) / 6 < (int)num_pairs )
00119 num_pairs = (FT_UInt)( ( p_next - p ) / 6 );
00120
00121 avail |= mask;
00122
00123
00124
00125
00126
00127 if ( num_pairs > 0 )
00128 {
00129 FT_ULong count;
00130 FT_ULong old_pair;
00131
00132
00133 old_pair = FT_NEXT_ULONG( p );
00134 p += 2;
00135
00136 for ( count = num_pairs - 1; count > 0; count-- )
00137 {
00138 FT_UInt32 cur_pair;
00139
00140
00141 cur_pair = FT_NEXT_ULONG( p );
00142 if ( cur_pair <= old_pair )
00143 break;
00144
00145 p += 2;
00146 old_pair = cur_pair;
00147 }
00148
00149 if ( count == 0 )
00150 ordered |= mask;
00151 }
00152
00153 NextTable:
00154 p = p_next;
00155 }
00156
00157 face->num_kern_tables = nn;
00158 face->kern_avail_bits = avail;
00159 face->kern_order_bits = ordered;
00160
00161 Exit:
00162 return error;
00163 }
00164
00165
00166 FT_LOCAL_DEF( void )
00167 tt_face_done_kern( TT_Face face )
00168 {
00169 FT_Stream stream = face->root.stream;
00170
00171
00172 FT_FRAME_RELEASE( face->kern_table );
00173 face->kern_table_size = 0;
00174 face->num_kern_tables = 0;
00175 face->kern_avail_bits = 0;
00176 face->kern_order_bits = 0;
00177 }
00178
00179
00180 FT_LOCAL_DEF( FT_Int )
00181 tt_face_get_kerning( TT_Face face,
00182 FT_UInt left_glyph,
00183 FT_UInt right_glyph )
00184 {
00185 FT_Int result = 0;
00186 FT_UInt count, mask = 1;
00187 FT_Byte* p = face->kern_table;
00188 FT_Byte* p_limit = p + face->kern_table_size;
00189
00190
00191 p += 4;
00192 mask = 0x0001;
00193
00194 for ( count = face->num_kern_tables;
00195 count > 0 && p + 6 <= p_limit;
00196 count--, mask <<= 1 )
00197 {
00198 FT_Byte* base = p;
00199 FT_Byte* next = base;
00200 FT_UInt version = FT_NEXT_USHORT( p );
00201 FT_UInt length = FT_NEXT_USHORT( p );
00202 FT_UInt coverage = FT_NEXT_USHORT( p );
00203 FT_UInt num_pairs;
00204 FT_Int value = 0;
00205
00206 FT_UNUSED( version );
00207
00208
00209 next = base + length;
00210
00211 if ( next > p_limit )
00212 next = p_limit;
00213
00214 if ( ( face->kern_avail_bits & mask ) == 0 )
00215 goto NextTable;
00216
00217 if ( p + 8 > next )
00218 goto NextTable;
00219
00220 num_pairs = FT_NEXT_USHORT( p );
00221 p += 6;
00222
00223 if ( ( next - p ) / 6 < (int)num_pairs )
00224 num_pairs = (FT_UInt)( ( next - p ) / 6 );
00225
00226 switch ( coverage >> 8 )
00227 {
00228 case 0:
00229 {
00230 FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph );
00231
00232
00233 if ( face->kern_order_bits & mask )
00234 {
00235 FT_UInt min = 0;
00236 FT_UInt max = num_pairs;
00237
00238
00239 while ( min < max )
00240 {
00241 FT_UInt mid = ( min + max ) >> 1;
00242 FT_Byte* q = p + 6 * mid;
00243 FT_ULong key;
00244
00245
00246 key = FT_NEXT_ULONG( q );
00247
00248 if ( key == key0 )
00249 {
00250 value = FT_PEEK_SHORT( q );
00251 goto Found;
00252 }
00253 if ( key < key0 )
00254 min = mid + 1;
00255 else
00256 max = mid;
00257 }
00258 }
00259 else
00260 {
00261 FT_UInt count2;
00262
00263
00264 for ( count2 = num_pairs; count2 > 0; count2-- )
00265 {
00266 FT_ULong key = FT_NEXT_ULONG( p );
00267
00268
00269 if ( key == key0 )
00270 {
00271 value = FT_PEEK_SHORT( p );
00272 goto Found;
00273 }
00274 p += 2;
00275 }
00276 }
00277 }
00278 break;
00279
00280
00281
00282
00283
00284
00285 default:
00286 ;
00287 }
00288
00289 goto NextTable;
00290
00291 Found:
00292 if ( coverage & 8 )
00293 result = value;
00294 else
00295 result += value;
00296
00297 NextTable:
00298 p = next;
00299 }
00300
00301 return result;
00302 }
00303
00304 #undef TT_KERN_INDEX
00305
00306