... |
... |
@@ -21,7 +21,7 @@ |
21
|
21
|
FT_LOCAL_ARRAY_DEF( AF_AdjustmentDatabaseEntry )
|
22
|
22
|
adjustment_database[] =
|
23
|
23
|
{
|
24
|
|
- {0x21, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* ! */
|
|
24
|
+ {0x21, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* !
|
25
|
25
|
{0x69, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* i */
|
26
|
26
|
{0x6A, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /* j */
|
27
|
27
|
{0xA1, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}, /*Inverted Exclamation Mark*/
|
... |
... |
@@ -138,11 +138,11 @@ adjustment_database[] = |
138
|
138
|
{0x17E, AF_VERTICAL_ADJUSTMENT_TOP_CONTOUR_UP}
|
139
|
139
|
};
|
140
|
140
|
|
141
|
|
-FT_LOCAL_DEF( FT_Bool )
|
|
141
|
+/*FT_LOCAL_DEF( FT_Bool )
|
142
|
142
|
af_adjustment_database_entry_equals( const AF_AdjustmentDatabaseEntry* a, const AF_AdjustmentDatabaseEntry* b )
|
143
|
143
|
{
|
144
|
144
|
return a->codepoint == b->codepoint && a->vertical_separation_adjustment_type == b->vertical_separation_adjustment_type;
|
145
|
|
-}
|
|
145
|
+}*/
|
146
|
146
|
|
147
|
147
|
/*Helper function: get the adjustment database entry for a codepoint*/
|
148
|
148
|
FT_LOCAL_DEF( const AF_AdjustmentDatabaseEntry* )
|
... |
... |
@@ -282,6 +282,174 @@ af_reverse_character_map_entry_compare( const void *a, const void *b ) { |
282
|
282
|
return entry_a.glyph_index < entry_b.glyph_index ? -1 : entry_a.glyph_index > entry_b.glyph_index ? 1 : 0;
|
283
|
283
|
}
|
284
|
284
|
|
|
285
|
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
|
|
286
|
+FT_LOCAL_DEF( FT_Error )
|
|
287
|
+af_all_glyph_variants_helper( hb_font_t *font,
|
|
288
|
+ hb_buffer_t *buffer,
|
|
289
|
+ hb_set_t *feature_tag_pool,
|
|
290
|
+ hb_feature_t *current_features,
|
|
291
|
+ FT_UInt32 num_features,
|
|
292
|
+ hb_set_t* result )
|
|
293
|
+{
|
|
294
|
+ hb_set_t *baseline_glyphs = hb_set_create();
|
|
295
|
+ if ( !hb_set_allocation_successful( baseline_glyphs ) )
|
|
296
|
+ {
|
|
297
|
+ return FT_Err_Out_Of_Memory;
|
|
298
|
+ }
|
|
299
|
+
|
|
300
|
+ hb_ot_shape_glyphs_closure ( font,
|
|
301
|
+ buffer,
|
|
302
|
+ current_features,
|
|
303
|
+ num_features,
|
|
304
|
+ baseline_glyphs );
|
|
305
|
+
|
|
306
|
+ hb_set_union( result, baseline_glyphs );
|
|
307
|
+ if ( !hb_set_allocation_successful( result ) )
|
|
308
|
+ {
|
|
309
|
+ return FT_Err_Out_Of_Memory;
|
|
310
|
+ }
|
|
311
|
+ if ( hb_set_get_population( feature_tag_pool ) == 0 )
|
|
312
|
+ {
|
|
313
|
+ return FT_Err_Ok;
|
|
314
|
+ }
|
|
315
|
+
|
|
316
|
+ /*set the feature to apply to the entire input buffer*/
|
|
317
|
+ current_features[num_features].start = HB_FEATURE_GLOBAL_START;
|
|
318
|
+ current_features[num_features].end = HB_FEATURE_GLOBAL_END;
|
|
319
|
+ current_features[num_features].value = 1; /*set the feature to enabled*/
|
|
320
|
+ /*quote from docs about value attribute:
|
|
321
|
+ 0 disables the feature, non-zero (usually 1) enables the feature. For features implemented as lookup type 3 (like 'salt') the value is a one based index into the alternates.
|
|
322
|
+ this does not handle these lookup type 3 cases fully*/
|
|
323
|
+
|
|
324
|
+ /*feature tag will be determined by trying all feature tags, looking for anything that affects the result of the lookup*/
|
|
325
|
+ hb_set_t *new_glyphs = hb_set_create();
|
|
326
|
+ if ( !hb_set_allocation_successful( new_glyphs ) )
|
|
327
|
+ {
|
|
328
|
+ return FT_Err_Out_Of_Memory;
|
|
329
|
+ }
|
|
330
|
+ hb_tag_t feature_tag = HB_SET_VALUE_INVALID;
|
|
331
|
+ while ( hb_set_next( feature_tag_pool, &feature_tag ) )
|
|
332
|
+ {
|
|
333
|
+ hb_set_clear( new_glyphs );
|
|
334
|
+ current_features[num_features].tag = feature_tag;
|
|
335
|
+ FT_TRACE4(("P3. num: %d\n", num_features));
|
|
336
|
+ hb_ot_shape_glyphs_closure ( font,
|
|
337
|
+ buffer,
|
|
338
|
+ current_features,
|
|
339
|
+ num_features + 1,
|
|
340
|
+ new_glyphs );
|
|
341
|
+ if ( !hb_set_allocation_successful( new_glyphs ) )
|
|
342
|
+ {
|
|
343
|
+ return FT_Err_Out_Of_Memory;
|
|
344
|
+ }
|
|
345
|
+
|
|
346
|
+ hb_set_subtract( new_glyphs, baseline_glyphs );
|
|
347
|
+ /*glyphs now contains all glyphs that were added to the*/
|
|
348
|
+ /*closure as a result of adding this feature*/
|
|
349
|
+ /*If this is not a subset of result, this feature is relevant*/
|
|
350
|
+ /*and we should recurse*/
|
|
351
|
+ if ( !hb_set_is_subset( new_glyphs, result ) )
|
|
352
|
+ {
|
|
353
|
+ /*remove this feature from the feature pool so that
|
|
354
|
+ the later recursion won't try it*/
|
|
355
|
+ hb_set_del( feature_tag_pool, feature_tag );
|
|
356
|
+ FT_Error error = af_all_glyph_variants_helper( font,
|
|
357
|
+ buffer,
|
|
358
|
+ feature_tag_pool,
|
|
359
|
+ current_features,
|
|
360
|
+ num_features + 1,
|
|
361
|
+ result );
|
|
362
|
+ if ( error )
|
|
363
|
+ {
|
|
364
|
+ return error;
|
|
365
|
+ }
|
|
366
|
+ /*add back the feature we removed*/
|
|
367
|
+ hb_set_add( feature_tag_pool, feature_tag );
|
|
368
|
+ if ( !hb_set_allocation_successful( feature_tag_pool ) ) {
|
|
369
|
+ return FT_Err_Out_Of_Memory;
|
|
370
|
+ }
|
|
371
|
+ } /* if( !hb_set_is_subset( glyphs, result ) ) */
|
|
372
|
+
|
|
373
|
+ } /*while ( hb_set_next( feature_tag_pool, &feature_tag ) )*/
|
|
374
|
+
|
|
375
|
+ hb_set_destroy( baseline_glyphs );
|
|
376
|
+ hb_set_destroy( new_glyphs );
|
|
377
|
+ return FT_Err_Ok;
|
|
378
|
+}
|
|
379
|
+
|
|
380
|
+FT_LOCAL_DEF( FT_Error )
|
|
381
|
+af_all_glyph_variants( FT_Face face,
|
|
382
|
+ hb_font_t *hb_font,
|
|
383
|
+ FT_UInt32 codepoint,
|
|
384
|
+ hb_set_t* result )
|
|
385
|
+{
|
|
386
|
+ FT_Memory memory = face->memory;
|
|
387
|
+ FT_Error error;
|
|
388
|
+ hb_face_t *hb_face = hb_font_get_face( hb_font );
|
|
389
|
+ hb_set_t *feature_tags = hb_set_create();
|
|
390
|
+ if ( !hb_set_allocation_successful( feature_tags ) )
|
|
391
|
+ {
|
|
392
|
+ return FT_Err_Out_Of_Memory;
|
|
393
|
+ }
|
|
394
|
+
|
|
395
|
+ FT_Bool feature_list_done = 0;
|
|
396
|
+ unsigned int start_offset = 0;
|
|
397
|
+ while ( !feature_list_done ) {
|
|
398
|
+ unsigned int feature_count = 20;
|
|
399
|
+ hb_tag_t tags[20];
|
|
400
|
+ hb_ot_layout_table_get_feature_tags ( hb_face,
|
|
401
|
+ HB_OT_TAG_GSUB,
|
|
402
|
+ start_offset,
|
|
403
|
+ &feature_count,
|
|
404
|
+ tags );
|
|
405
|
+ start_offset += 20;
|
|
406
|
+ if ( feature_count < 20 )
|
|
407
|
+ {
|
|
408
|
+ feature_list_done = 1;
|
|
409
|
+ }
|
|
410
|
+ for ( int i = 0; i < feature_count; i++ )
|
|
411
|
+ {
|
|
412
|
+ hb_set_add( feature_tags, tags[i] );
|
|
413
|
+ }
|
|
414
|
+ if ( !hb_set_allocation_successful( feature_tags ) )
|
|
415
|
+ {
|
|
416
|
+ return FT_Err_Out_Of_Memory;
|
|
417
|
+ }
|
|
418
|
+ }
|
|
419
|
+
|
|
420
|
+ hb_buffer_t *codepoint_buffer = hb_buffer_create();
|
|
421
|
+ if ( !hb_buffer_allocation_successful( codepoint_buffer ) )
|
|
422
|
+ {
|
|
423
|
+ return FT_Err_Out_Of_Memory;
|
|
424
|
+ }
|
|
425
|
+ if ( !hb_buffer_pre_allocate( codepoint_buffer, 1 ) )
|
|
426
|
+ {
|
|
427
|
+ return FT_Err_Out_Of_Memory;
|
|
428
|
+ }
|
|
429
|
+ hb_buffer_set_direction (codepoint_buffer,
|
|
430
|
+ HB_DIRECTION_LTR);
|
|
431
|
+ hb_buffer_add( codepoint_buffer, codepoint, 0 );
|
|
432
|
+
|
|
433
|
+ hb_feature_t *feature_buffer;
|
|
434
|
+ if ( FT_NEW_ARRAY( feature_buffer, hb_set_get_population( feature_tags ) ) ) {
|
|
435
|
+ return error;
|
|
436
|
+ }
|
|
437
|
+
|
|
438
|
+ /*hb_codepoint_t and hb_tag_t are both uint32_t, so we can put feature tags inside hb_set*/
|
|
439
|
+ error = af_all_glyph_variants_helper( hb_font,
|
|
440
|
+ codepoint_buffer,
|
|
441
|
+ feature_tags,
|
|
442
|
+ feature_buffer,
|
|
443
|
+ 0,
|
|
444
|
+ result );
|
|
445
|
+
|
|
446
|
+ hb_set_destroy( feature_tags );
|
|
447
|
+ hb_buffer_destroy( codepoint_buffer );
|
|
448
|
+ FT_FREE( feature_buffer );
|
|
449
|
+ return FT_Err_Ok;
|
|
450
|
+}
|
|
451
|
+#endif /*FT_CONFIG_OPTION_USE_HARFBUZZ*/
|
|
452
|
+
|
285
|
453
|
FT_LOCAL_DEF( FT_Error )
|
286
|
454
|
af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals globals )
|
287
|
455
|
{
|
... |
... |
@@ -290,8 +458,6 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global |
290
|
458
|
/* Search for a unicode charmap */
|
291
|
459
|
/* If there isn't one, create a blank map */
|
292
|
460
|
|
293
|
|
-
|
294
|
|
- /*TODO: use GSUB lookups */
|
295
|
461
|
FT_TRACE4(( "af_reverse_character_map_new: building reverse character map\n" ));
|
296
|
462
|
|
297
|
463
|
FT_Error error;
|
... |
... |
@@ -314,6 +480,60 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global |
314
|
480
|
{
|
315
|
481
|
goto Exit;
|
316
|
482
|
}
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
|
|
486
|
+ hb_font_t *hb_font = globals->hb_font;
|
|
487
|
+ /*hb_face_t *hb_face = hb_font_get_face( hb_font );*/
|
|
488
|
+ hb_set_t *result_set = hb_set_create();
|
|
489
|
+ if ( !hb_set_allocation_successful( result_set ) )
|
|
490
|
+ {
|
|
491
|
+ error = FT_Err_Out_Of_Memory;
|
|
492
|
+ goto harfbuzz_path_Exit;
|
|
493
|
+ }
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+ /*
|
|
497
|
+ af_all_glyph_variants( FT_Face face,
|
|
498
|
+ hb_font_t *hb_font,
|
|
499
|
+ FT_UInt32 codepoint,
|
|
500
|
+ hb_set_t* result )*/
|
|
501
|
+
|
|
502
|
+ for ( FT_Long i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ )
|
|
503
|
+ {
|
|
504
|
+ FT_UInt32 codepoint = adjustment_database[i].codepoint;
|
|
505
|
+ error = af_all_glyph_variants( face,
|
|
506
|
+ hb_font,
|
|
507
|
+ codepoint,
|
|
508
|
+ result_set );
|
|
509
|
+ if ( error ) {
|
|
510
|
+ goto harfbuzz_path_Exit;
|
|
511
|
+ }
|
|
512
|
+
|
|
513
|
+ hb_codepoint_t glyph = HB_SET_VALUE_INVALID;
|
|
514
|
+ while ( hb_set_next( result_set, &glyph ) )
|
|
515
|
+ {
|
|
516
|
+ error = af_reverse_character_map_expand( *map, &capacity, memory );
|
|
517
|
+ if ( error ) {
|
|
518
|
+ goto harfbuzz_path_Exit;
|
|
519
|
+ }
|
|
520
|
+
|
|
521
|
+ ( *map )->length++;
|
|
522
|
+ ( *map )->entries[i].glyph_index = glyph;
|
|
523
|
+ ( *map )->entries[i].codepoint = codepoint;
|
|
524
|
+
|
|
525
|
+ }
|
|
526
|
+
|
|
527
|
+ hb_set_clear( result_set );
|
|
528
|
+
|
|
529
|
+ }
|
|
530
|
+harfbuzz_path_Exit:
|
|
531
|
+ hb_set_destroy( result_set );
|
|
532
|
+ if ( error )
|
|
533
|
+ {
|
|
534
|
+ goto Exit;
|
|
535
|
+ }
|
|
536
|
+#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
|
317
|
537
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
318
|
538
|
int failed_lookups = 0;
|
319
|
539
|
#endif
|
... |
... |
@@ -338,6 +558,8 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global |
338
|
558
|
( *map )->entries[i].codepoint = codepoint;
|
339
|
559
|
}
|
340
|
560
|
|
|
561
|
+#endif /*FT_CONFIG_OPTION_USE_HARFBUZZ*/
|
|
562
|
+
|
341
|
563
|
ft_qsort(
|
342
|
564
|
( *map )->entries,
|
343
|
565
|
( *map )->length,
|
... |
... |
@@ -345,120 +567,13 @@ af_reverse_character_map_new( AF_ReverseCharacterMap *map, AF_FaceGlobals global |
345
|
567
|
af_reverse_character_map_entry_compare
|
346
|
568
|
);
|
347
|
569
|
|
348
|
|
-#if 0
|
349
|
|
-/*#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ*/
|
350
|
|
- hb_font_t *hb_font = globals->hb_font;
|
351
|
|
- hb_face_t *hb_face = hb_font_get_face( hb_font );
|
352
|
|
- hb_set_t *feature_indicies = hb_set_create();
|
353
|
|
- FT_Long oldlength = ( *map )->length;
|
354
|
|
- hb_ot_layout_collect_lookups(
|
355
|
|
- hb_face,
|
356
|
|
- HB_OT_TAG_GSUB,
|
357
|
|
- NULL, /*all scripts*/
|
358
|
|
- NULL, /*all languages*/
|
359
|
|
- NULL, /*all features*/
|
360
|
|
- feature_indicies
|
361
|
|
- );
|
362
|
|
- hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
|
363
|
|
- while ( hb_set_next(feature_indicies, &feature_index) )
|
|
570
|
+ for ( FT_Long i = 0; i < ( *map )->length; i++ )
|
364
|
571
|
{
|
365
|
|
- hb_codepoint_t output_glyph_index;
|
366
|
|
- /*TODO: find out whether I can reuse set instances instead of recreating*/
|
367
|
|
- hb_set_t *glyphs_before = hb_set_create();
|
368
|
|
- hb_set_t *glyphs_input = hb_set_create();
|
369
|
|
- hb_set_t *glyphs_after = hb_set_create();
|
370
|
|
- hb_set_t *glyphs_output = hb_set_create();
|
371
|
|
- hb_ot_layout_lookup_collect_glyphs( hb_face, HB_OT_TAG_GSUB,
|
372
|
|
- feature_index, glyphs_before,
|
373
|
|
- glyphs_input, glyphs_after,
|
374
|
|
- glyphs_output);
|
375
|
|
- /*Don't consider anything involving context. Just do the
|
376
|
|
- simple cases*/
|
377
|
|
- FT_TRACE4(("num inputs: %d\n", hb_set_get_population( glyphs_input )));
|
378
|
|
- FT_TRACE4(("num outputs: %d\n", hb_set_get_population( glyphs_output )));
|
379
|
|
- FT_TRACE4(("num before: %d\n", hb_set_get_population( glyphs_before )));
|
380
|
|
- FT_TRACE4(("num after: %d\n", hb_set_get_population( glyphs_after )));
|
381
|
|
- hb_codepoint_t input = HB_SET_VALUE_INVALID;
|
382
|
|
- while ( hb_set_next( glyphs_input, &input ) )
|
383
|
|
- {
|
384
|
|
- FT_TRACE4(("input: %d\n", input));
|
385
|
|
- }
|
386
|
|
- hb_codepoint_t output = HB_SET_VALUE_INVALID;
|
387
|
|
- while ( hb_set_next( glyphs_output, &output ) )
|
388
|
|
- {
|
389
|
|
- FT_TRACE4(("output: %d\n", output));
|
390
|
|
- }
|
391
|
|
- if ( hb_set_get_population( glyphs_before ) > 0 ||
|
392
|
|
- hb_set_get_population( glyphs_after ) > 0 )
|
393
|
|
- {
|
394
|
|
- continue;
|
395
|
|
- }
|
396
|
|
- if ( hb_set_get_population( glyphs_output ) != 1 )
|
397
|
|
- {
|
398
|
|
- continue;
|
399
|
|
- }
|
400
|
|
-
|
401
|
|
- hb_codepoint_t input_glyph_index = HB_SET_VALUE_INVALID;
|
402
|
|
- const AF_AdjustmentDatabaseEntry* input_entry = NULL;
|
403
|
|
- FT_UInt32 input_codepoint = 0;
|
404
|
|
- while ( hb_set_next( glyphs_input, &input_glyph_index ) ) {
|
405
|
|
- FT_TRACE4(("input glyph: %d\n", input_glyph_index));
|
406
|
|
- FT_UInt32 inner_codepoint = af_reverse_character_map_lookup_( *map, input_glyph_index, oldlength );
|
407
|
|
- if ( inner_codepoint == 0 )
|
408
|
|
- {
|
409
|
|
- continue;
|
410
|
|
- }
|
411
|
|
- const AF_AdjustmentDatabaseEntry* entry = af_adjustment_database_lookup( inner_codepoint );
|
412
|
|
- if ( entry == NULL )
|
413
|
|
- {
|
414
|
|
- continue;
|
415
|
|
- }
|
416
|
|
- if ( input_codepoint == 0 ) {
|
417
|
|
- input_codepoint = inner_codepoint;
|
418
|
|
- }
|
419
|
|
-
|
420
|
|
- if ( input_entry == NULL )
|
421
|
|
- {
|
422
|
|
- input_entry = entry;
|
423
|
|
- }
|
424
|
|
- else
|
425
|
|
- {
|
426
|
|
- if ( !af_adjustment_database_entry_equals( input_entry, entry ) )
|
427
|
|
- {
|
428
|
|
- goto end;
|
429
|
|
- }
|
430
|
|
- }
|
431
|
|
- }
|
432
|
|
-
|
433
|
|
- if ( input_codepoint == 0 )
|
434
|
|
- {
|
435
|
|
- continue;
|
436
|
|
- }
|
437
|
|
-
|
438
|
|
- output_glyph_index = HB_SET_VALUE_INVALID;
|
439
|
|
- hb_set_next( glyphs_output, &output_glyph_index );
|
440
|
|
-
|
441
|
|
- /*Make pair output glyph index -> input unicode*/
|
442
|
|
- error = af_reverse_character_map_expand( *map, &capacity, memory );
|
443
|
|
- if ( error ) {
|
444
|
|
- goto Exit;
|
445
|
|
- }
|
446
|
|
-
|
447
|
|
- FT_Long index = ( *map )->length++;
|
448
|
|
- ( *map )->entries[index].glyph_index = output_glyph_index;
|
449
|
|
- ( *map )->entries[index].codepoint = input_codepoint;
|
450
|
|
-
|
451
|
|
- end: ;
|
|
572
|
+ FT_TRACE4(("char: %c, glyph: %d\n", ( *map )->entries[i].codepoint, ( *map )->entries[i].glyph_index ) );
|
452
|
573
|
}
|
453
|
574
|
|
454
|
|
- ft_qsort(
|
455
|
|
- ( *map )->entries,
|
456
|
|
- ( *map )->length,
|
457
|
|
- sizeof( AF_ReverseMapEntry ),
|
458
|
|
- af_reverse_character_map_entry_compare
|
459
|
|
- );
|
460
|
|
-
|
461
|
|
-#endif /*FT_CONFIG_OPTION_USE_HARFBUZZ*/
|
|
575
|
+ FT_TRACE4(( " reverse character map built successfully"\
|
|
576
|
+ " with %d entries\n", (*map)->length ));
|
462
|
577
|
|
463
|
578
|
Exit:
|
464
|
579
|
face->charmap = old_charmap;
|
... |
... |
@@ -472,10 +587,7 @@ Exit: |
472
|
587
|
FT_FREE( *map );
|
473
|
588
|
return error;
|
474
|
589
|
}
|
475
|
|
-#ifdef FT_DEBUG_LEVEL_TRACE
|
476
|
|
- FT_TRACE4(( " reverse character map built successfully"\
|
477
|
|
- " with %d entries and %d failed lookups.\n", (*map)->length, failed_lookups ));
|
478
|
|
-#endif
|
|
590
|
+
|
479
|
591
|
return FT_Err_Ok;
|
480
|
592
|
}
|
481
|
593
|
|