| ... |
... |
@@ -136,3 +136,222 @@ adjustment_database[] = |
|
136
|
136
|
{0x17D, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0},
|
|
137
|
137
|
{0x17E, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP, 0}
|
|
138
|
138
|
};
|
|
|
139
|
+
|
|
|
140
|
+/*Helper function: get the adjustment database entry for a codepoint*/
|
|
|
141
|
+FT_LOCAL_DEF( const AF_AdjustmentDatabaseEntry* )
|
|
|
142
|
+af_adjustment_database_lookup( FT_UInt32 codepoint ) {
|
|
|
143
|
+ /* Binary search for database entry */
|
|
|
144
|
+ FT_Int low = 0;
|
|
|
145
|
+ FT_Int high = AF_ADJUSTMENT_DATABASE_LENGTH - 1;
|
|
|
146
|
+ while ( high >= low )
|
|
|
147
|
+ {
|
|
|
148
|
+ FT_Int mid = ( low + high ) / 2;
|
|
|
149
|
+ FT_UInt32 mid_codepoint = adjustment_database[mid].codepoint;
|
|
|
150
|
+ if ( mid_codepoint < codepoint )
|
|
|
151
|
+ {
|
|
|
152
|
+ low = mid + 1;
|
|
|
153
|
+ }
|
|
|
154
|
+ else if ( mid_codepoint > codepoint )
|
|
|
155
|
+ {
|
|
|
156
|
+ high = mid - 1;
|
|
|
157
|
+ }
|
|
|
158
|
+ else
|
|
|
159
|
+ {
|
|
|
160
|
+ return &adjustment_database[mid];
|
|
|
161
|
+ }
|
|
|
162
|
+ }
|
|
|
163
|
+
|
|
|
164
|
+ return NULL;
|
|
|
165
|
+}
|
|
|
166
|
+
|
|
|
167
|
+FT_LOCAL_DEF( AF_VerticalSeparationAdjustmentType )
|
|
|
168
|
+af_lookup_vertical_seperation_type( AF_ReverseCharacterMap map, FT_Int glyph_index ) {
|
|
|
169
|
+ FT_UInt32 codepoint = af_reverse_character_map_lookup( map, glyph_index );
|
|
|
170
|
+ const AF_AdjustmentDatabaseEntry *entry = af_adjustment_database_lookup( codepoint );
|
|
|
171
|
+ if ( entry == NULL )
|
|
|
172
|
+ {
|
|
|
173
|
+ return AF_VERTICAL_ADJUSTMENT_NONE;
|
|
|
174
|
+ }
|
|
|
175
|
+ return entry->vertical_separation_adjustment_type;
|
|
|
176
|
+}
|
|
|
177
|
+
|
|
|
178
|
+/*1 if tilde correction should be applied to the topmost contour
|
|
|
179
|
+else 0*/
|
|
|
180
|
+FT_LOCAL_DEF( FT_Bool )
|
|
|
181
|
+af_lookup_tilde_correction_type( AF_ReverseCharacterMap map, FT_Int glyph_index ) {
|
|
|
182
|
+ FT_UInt32 codepoint = af_reverse_character_map_lookup( map, glyph_index );
|
|
|
183
|
+ const AF_AdjustmentDatabaseEntry *entry = af_adjustment_database_lookup( codepoint );
|
|
|
184
|
+ if ( entry == NULL )
|
|
|
185
|
+ {
|
|
|
186
|
+ return 0;
|
|
|
187
|
+ }
|
|
|
188
|
+ return entry->apply_tilde;
|
|
|
189
|
+}
|
|
|
190
|
+
|
|
|
191
|
+typedef struct AF_ReverseMapEntry_
|
|
|
192
|
+{
|
|
|
193
|
+ FT_Int glyph_index;
|
|
|
194
|
+ FT_UInt32 codepoint;
|
|
|
195
|
+} AF_ReverseMapEntry;
|
|
|
196
|
+
|
|
|
197
|
+typedef struct AF_ReverseCharacterMap_
|
|
|
198
|
+{
|
|
|
199
|
+ FT_Long length;
|
|
|
200
|
+ AF_ReverseMapEntry *entries;
|
|
|
201
|
+} AF_ReverseCharacterMap_Rec;
|
|
|
202
|
+
|
|
|
203
|
+/* qsort compare function for reverse character map */
|
|
|
204
|
+FT_LOCAL_DEF( FT_Int )
|
|
|
205
|
+af_reverse_character_map_entry_compare( const void *a, const void *b ) {
|
|
|
206
|
+ const AF_ReverseMapEntry entry_a = *((const AF_ReverseMapEntry *)a);
|
|
|
207
|
+ const AF_ReverseMapEntry entry_b = *((const AF_ReverseMapEntry *)b);
|
|
|
208
|
+ return entry_a.glyph_index < entry_b.glyph_index ? -1 : entry_a.glyph_index > entry_b.glyph_index ? 1 : 0;
|
|
|
209
|
+}
|
|
|
210
|
+
|
|
|
211
|
+FT_LOCAL_DEF( FT_UInt32 )
|
|
|
212
|
+af_reverse_character_map_lookup_( AF_ReverseCharacterMap map, FT_Int glyph_index, FT_Long length )
|
|
|
213
|
+{
|
|
|
214
|
+ if ( map == NULL )
|
|
|
215
|
+ {
|
|
|
216
|
+ return 0;
|
|
|
217
|
+ }
|
|
|
218
|
+ /* Binary search for reverse character map entry */
|
|
|
219
|
+ FT_Int low = 0;
|
|
|
220
|
+ FT_Int high = length - 1;
|
|
|
221
|
+ while ( high >= low )
|
|
|
222
|
+ {
|
|
|
223
|
+ FT_Int mid = ( high + low ) / 2;
|
|
|
224
|
+ FT_Int mid_glyph_index = map->entries[mid].glyph_index;
|
|
|
225
|
+ if ( glyph_index < mid_glyph_index )
|
|
|
226
|
+ {
|
|
|
227
|
+ high = mid - 1;
|
|
|
228
|
+ }
|
|
|
229
|
+ else if ( glyph_index > mid_glyph_index )
|
|
|
230
|
+ {
|
|
|
231
|
+ low = mid + 1;
|
|
|
232
|
+ }
|
|
|
233
|
+ else
|
|
|
234
|
+ {
|
|
|
235
|
+ return map->entries[mid].codepoint;
|
|
|
236
|
+ }
|
|
|
237
|
+ }
|
|
|
238
|
+
|
|
|
239
|
+ return 0;
|
|
|
240
|
+}
|
|
|
241
|
+
|
|
|
242
|
+FT_LOCAL_DEF( FT_UInt32 )
|
|
|
243
|
+af_reverse_character_map_lookup( AF_ReverseCharacterMap map, FT_Int glyph_index )
|
|
|
244
|
+{
|
|
|
245
|
+ return af_reverse_character_map_lookup_( map, glyph_index, map->length );
|
|
|
246
|
+}
|
|
|
247
|
+
|
|
|
248
|
+/*prepare to add one more entry to the reverse character map
|
|
|
249
|
+ this is a helper for af_reverse_character_map_new*/
|
|
|
250
|
+FT_LOCAL_DEF( FT_Error )
|
|
|
251
|
+af_reverse_character_map_expand( AF_ReverseCharacterMap map, FT_Long *capacity, FT_Memory memory )
|
|
|
252
|
+{
|
|
|
253
|
+ FT_Error error;
|
|
|
254
|
+ if ( map->length < *capacity )
|
|
|
255
|
+ {
|
|
|
256
|
+ return FT_Err_Ok;
|
|
|
257
|
+ }
|
|
|
258
|
+
|
|
|
259
|
+ if ( map->length == *capacity )
|
|
|
260
|
+ {
|
|
|
261
|
+ FT_Long new_capacity = *capacity + *capacity / 2;
|
|
|
262
|
+ if ( FT_RENEW_ARRAY( map->entries, map->length, new_capacity ) ) {
|
|
|
263
|
+ return error;
|
|
|
264
|
+ }
|
|
|
265
|
+ *capacity = new_capacity;
|
|
|
266
|
+ }
|
|
|
267
|
+
|
|
|
268
|
+ return FT_Err_Ok;
|
|
|
269
|
+}
|
|
|
270
|
+
|
|
|
271
|
+FT_LOCAL_DEF( FT_Error )
|
|
|
272
|
+af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals globals )
|
|
|
273
|
+{
|
|
|
274
|
+ FT_Face face = globals->face;
|
|
|
275
|
+ FT_Memory memory = face->memory;
|
|
|
276
|
+ /* Search for a unicode charmap */
|
|
|
277
|
+ /* If there isn't one, create a blank map */
|
|
|
278
|
+
|
|
|
279
|
+ FT_TRACE4(( "af_reverse_character_map_new: building reverse character map\n" ));
|
|
|
280
|
+
|
|
|
281
|
+ FT_Error error;
|
|
|
282
|
+ /* backup face->charmap because find_unicode_charmap sets it */
|
|
|
283
|
+ FT_CharMap old_charmap = face->charmap;
|
|
|
284
|
+ if ( ( error = find_unicode_charmap( face ) ) )
|
|
|
285
|
+ {
|
|
|
286
|
+ *map = NULL;
|
|
|
287
|
+ goto Exit;
|
|
|
288
|
+ }
|
|
|
289
|
+
|
|
|
290
|
+ if ( FT_NEW( *map ) )
|
|
|
291
|
+ {
|
|
|
292
|
+ goto Exit;
|
|
|
293
|
+ }
|
|
|
294
|
+
|
|
|
295
|
+ FT_Long capacity = 10;
|
|
|
296
|
+ ( *map )->length = 0;
|
|
|
297
|
+
|
|
|
298
|
+ if ( FT_NEW_ARRAY( ( *map )->entries, capacity) )
|
|
|
299
|
+ {
|
|
|
300
|
+ goto Exit;
|
|
|
301
|
+ }
|
|
|
302
|
+
|
|
|
303
|
+#ifdef FT_DEBUG_LEVEL_TRACE
|
|
|
304
|
+ int failed_lookups = 0;
|
|
|
305
|
+#endif
|
|
|
306
|
+ for ( FT_Int i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ )
|
|
|
307
|
+ {
|
|
|
308
|
+ FT_UInt32 codepoint = adjustment_database[i].codepoint;
|
|
|
309
|
+ FT_Int glyph = FT_Get_Char_Index( face, codepoint );
|
|
|
310
|
+ if ( glyph == 0 )
|
|
|
311
|
+ {
|
|
|
312
|
+#ifdef FT_DEBUG_LEVEL_TRACE
|
|
|
313
|
+ failed_lookups++;
|
|
|
314
|
+#endif
|
|
|
315
|
+ continue;
|
|
|
316
|
+ }
|
|
|
317
|
+ error = af_reverse_character_map_expand( *map, &capacity, memory );
|
|
|
318
|
+ if ( error ) {
|
|
|
319
|
+ goto Exit;
|
|
|
320
|
+ }
|
|
|
321
|
+
|
|
|
322
|
+ ( *map )->length++;
|
|
|
323
|
+ ( *map )->entries[i].glyph_index = glyph;
|
|
|
324
|
+ ( *map )->entries[i].codepoint = codepoint;
|
|
|
325
|
+ }
|
|
|
326
|
+
|
|
|
327
|
+ ft_qsort(
|
|
|
328
|
+ ( *map )->entries,
|
|
|
329
|
+ ( *map )->length,
|
|
|
330
|
+ sizeof( AF_ReverseMapEntry ),
|
|
|
331
|
+ af_reverse_character_map_entry_compare
|
|
|
332
|
+ );
|
|
|
333
|
+
|
|
|
334
|
+ FT_TRACE4(( " reverse character map built successfully"\
|
|
|
335
|
+ " with %d entries\n", (*map)->length ));
|
|
|
336
|
+
|
|
|
337
|
+Exit:
|
|
|
338
|
+ face->charmap = old_charmap;
|
|
|
339
|
+ if ( error )
|
|
|
340
|
+ {
|
|
|
341
|
+ FT_TRACE4(( " error while building reverse character map. Using blank map.\n" ));
|
|
|
342
|
+ if ( *map )
|
|
|
343
|
+ {
|
|
|
344
|
+ FT_FREE( ( *map )->entries );
|
|
|
345
|
+ }
|
|
|
346
|
+ FT_FREE( *map );
|
|
|
347
|
+ return error;
|
|
|
348
|
+ }
|
|
|
349
|
+
|
|
|
350
|
+ return FT_Err_Ok;
|
|
|
351
|
+}
|
|
|
352
|
+
|
|
|
353
|
+FT_LOCAL_DEF( FT_Error )
|
|
|
354
|
+af_reverse_character_map_done( AF_ReverseCharacterMap map, FT_Memory memory ) {
|
|
|
355
|
+ FT_FREE( map->entries );
|
|
|
356
|
+ return FT_Err_Ok;
|
|
|
357
|
+} |