src/hb-face.cc | 2 - src/hb-ft.cc | 8 ++-- src/hb-ot-layout.cc | 32 ++++++++++++++++ src/hb-ot-layout.h | 6 +++ src/hb-ot-shape.cc | 10 ----- src/hb-private.hh | 2 - src/hb-subset-input.cc | 17 ++++++++ src/hb-subset-plan.cc | 21 +++++++++- src/hb-subset-plan.hh | 1 src/hb-subset-private.hh | 1 src/hb-subset.cc | 5 +- src/hb-subset.h | 3 + test/api/fonts/Roboto-Regular.gsub.fi.ttf |binary test/api/fonts/Roboto-Regular.gsub.fil.ttf |binary test/api/fonts/Roboto-Regular.nogsub.fi.ttf |binary test/api/test-subset-glyf.c | 56 +++++++++++++++++++++++++++- test/fuzzing/hb-subset-fuzzer.cc | 27 ++++++++++--- 17 files changed, 163 insertions(+), 28 deletions(-)
New commits: commit b8e406f0c7c381d46e2d2bbe35a6107d560f2122 Author: Behdad Esfahbod <[email protected]> Date: Sun Jun 10 17:22:38 2018 -0400 More fixes for SunStudio 12.6 build Followup to https://github.com/harfbuzz/harfbuzz/pull/1053 diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 69132386..7caafba8 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -119,7 +119,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) if (font->immutable) return; - if (font->destroy != _hb_ft_font_destroy) + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) return; hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; @@ -139,7 +139,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) int hb_ft_font_get_load_flags (hb_font_t *font) { - if (font->destroy != _hb_ft_font_destroy) + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) return 0; const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; @@ -150,7 +150,7 @@ hb_ft_font_get_load_flags (hb_font_t *font) FT_Face hb_ft_font_get_face (hb_font_t *font) { - if (font->destroy != _hb_ft_font_destroy) + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) return nullptr; const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; @@ -615,7 +615,7 @@ hb_ft_font_create (FT_Face ft_face, void hb_ft_font_changed (hb_font_t *font) { - if (font->destroy != _hb_ft_font_destroy) + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) return; hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 906327b8..4098832b 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -221,7 +221,7 @@ hb_subset_face_create (void) hb_bool_t hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) { - if (unlikely (face->destroy != _hb_subset_face_data_destroy)) + if (unlikely (face->destroy != (hb_destroy_func_t) _hb_subset_face_data_destroy)) return false; hb_subset_face_data_t *data = (hb_subset_face_data_t *) face->user_data; commit 498e4373dc2eb98fa9b18a0824c7912ed84a4c80 Author: prrace <[email protected]> Date: Sat Jun 9 16:04:28 2018 -0700 Fix SunStudio 12.6 build (#1053) diff --git a/src/hb-face.cc b/src/hb-face.cc index b8d7e84d..2fef09d0 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -514,7 +514,7 @@ hb_face_get_table_tags (hb_face_t *face, unsigned int *table_count, /* IN/OUT */ hb_tag_t *table_tags /* OUT */) { - if (face->destroy != _hb_face_for_data_closure_destroy) + if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy) { if (table_count) *table_count = 0; diff --git a/src/hb-private.hh b/src/hb-private.hh index 4edb27cb..ac00e022 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -147,7 +147,7 @@ extern "C" void hb_free_impl(void *ptr); #define HB_FUNC __func__ #endif -#ifdef __SUNPRO_CC +#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140) /* https://github.com/harfbuzz/harfbuzz/issues/630 */ #define __restrict #endif commit 46f7e7760f4c9b1b2886a27eff3c0fabdab45dbe Author: Garret Rieger <[email protected]> Date: Thu Jun 7 15:55:45 2018 -0700 [subset] Use REPLACEME instead of version. diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index 5aa50883..39c5ac4f 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -127,7 +127,7 @@ hb_subset_input_drop_hints (hb_subset_input_t *subset_input) * the subsetting operation. Currently this defaults to * true. * - * Since: 1.8.0 + * Since: REPLACEME **/ HB_EXTERN hb_bool_t * hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input) commit fc246ec985890f8256f6e03cdf74c86b9b51ff2a Author: Garret Rieger <[email protected]> Date: Thu Jun 7 15:54:19 2018 -0700 [subset] Move variable declaration out of loop. diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c index d6f6ddea..e4440e0f 100644 --- a/test/api/test-subset-glyf.c +++ b/test/api/test-subset-glyf.c @@ -232,10 +232,10 @@ test_subset_glyf_strip_hints_invalid (void) 'A', 'B', 'C', 'D', 'E', 'X', 'Y', 'Z', '1', '2', '3', '@', '_', '%', '&', ')', '*', '$', '!' }; - for (unsigned int i = 0; i < sizeof (text) / sizeof (hb_codepoint_t); i++) + unsigned int i; + for (i = 0; i < sizeof (text) / sizeof (hb_codepoint_t); i++) { hb_set_add (codepoints, text[i]); - // hb_set_add (codepoints_drop_hints, text[i]); } hb_subset_input_t *input = hb_subset_test_create_input (codepoints); commit 197cb18b22ce11f32f5f2c68c13f7068fb5cc338 Author: Garret Rieger <[email protected]> Date: Thu Jun 7 15:32:52 2018 -0700 [subset] Add test cases for gsub closure in subsetting. diff --git a/test/api/fonts/Roboto-Regular.gsub.fi.ttf b/test/api/fonts/Roboto-Regular.gsub.fi.ttf new file mode 100644 index 00000000..f41953bd Binary files /dev/null and b/test/api/fonts/Roboto-Regular.gsub.fi.ttf differ diff --git a/test/api/fonts/Roboto-Regular.gsub.fil.ttf b/test/api/fonts/Roboto-Regular.gsub.fil.ttf new file mode 100644 index 00000000..03e0be1a Binary files /dev/null and b/test/api/fonts/Roboto-Regular.gsub.fil.ttf differ diff --git a/test/api/fonts/Roboto-Regular.nogsub.fi.ttf b/test/api/fonts/Roboto-Regular.nogsub.fi.ttf new file mode 100644 index 00000000..6a08aa9a Binary files /dev/null and b/test/api/fonts/Roboto-Regular.nogsub.fi.ttf differ diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c index acc6143e..d6f6ddea 100644 --- a/test/api/test-subset-glyf.c +++ b/test/api/test-subset-glyf.c @@ -101,6 +101,56 @@ test_subset_glyf_with_components (void) } static void +test_subset_glyf_with_gsub (void) +{ + hb_face_t *face_fil = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fil.ttf"); + hb_face_t *face_fi = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fi.ttf"); + + hb_set_t *codepoints = hb_set_create(); + hb_set_add (codepoints, 102); // f + hb_set_add (codepoints, 105); // i + + hb_subset_input_t *input = hb_subset_test_create_input (codepoints); + hb_set_destroy (codepoints); + *hb_subset_input_drop_ot_layout (input) = false; + + hb_face_t *face_subset = hb_subset_test_create_subset (face_fil, input); + + hb_subset_test_check (face_fi, face_subset, HB_TAG ('g','l','y','f')); + hb_subset_test_check (face_fi, face_subset, HB_TAG ('l','o','c', 'a')); + check_maxp_num_glyphs(face_subset, 5, true); + + hb_face_destroy (face_subset); + hb_face_destroy (face_fi); + hb_face_destroy (face_fil); +} + +static void +test_subset_glyf_without_gsub (void) +{ + hb_face_t *face_fil = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fil.ttf"); + hb_face_t *face_fi = hb_subset_test_open_font ("fonts/Roboto-Regular.nogsub.fi.ttf"); + + hb_set_t *codepoints = hb_set_create(); + hb_set_add (codepoints, 102); // f + hb_set_add (codepoints, 105); // i + + hb_subset_input_t *input = hb_subset_test_create_input (codepoints); + hb_set_destroy (codepoints); + *hb_subset_input_drop_ot_layout (input) = true; + + hb_face_t *face_subset = hb_subset_test_create_subset (face_fil, input); + + hb_subset_test_check (face_fi, face_subset, HB_TAG ('g','l','y','f')); + hb_subset_test_check (face_fi, face_subset, HB_TAG ('l','o','c', 'a')); + check_maxp_num_glyphs(face_subset, 3, true); + + hb_face_destroy (face_subset); + hb_face_destroy (face_fi); + hb_face_destroy (face_fil); +} + +static void test_subset_glyf_noop (void) { hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf"); @@ -213,6 +263,8 @@ main (int argc, char **argv) hb_test_add (test_subset_glyf_strip_hints_composite); hb_test_add (test_subset_glyf_strip_hints_invalid); hb_test_add (test_subset_glyf_with_components); + hb_test_add (test_subset_glyf_with_gsub); + hb_test_add (test_subset_glyf_without_gsub); return hb_test_run(); } commit 37eab27be3b88079614f66e484c700bb2d40af10 Author: Garret Rieger <[email protected]> Date: Thu Jun 7 14:39:03 2018 -0700 [subset] Add fuzzing of gsub closure to hb-subset-fuzzer. diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc index c3703f2c..28ce921c 100644 --- a/test/fuzzing/hb-subset-fuzzer.cc +++ b/test/fuzzing/hb-subset-fuzzer.cc @@ -6,16 +6,17 @@ #include "hb-subset.h" - void trySubset (hb_face_t *face, const hb_codepoint_t text[], int text_length, - bool drop_hints) + bool drop_hints, + bool drop_ot_layout) { hb_subset_profile_t *profile = hb_subset_profile_create (); hb_subset_input_t *input = hb_subset_input_create_or_fail (); - *hb_subset_input_drop_hints(input) = drop_hints; + *hb_subset_input_drop_hints (input) = drop_hints; + *hb_subset_input_drop_ot_layout (input) = drop_ot_layout; hb_set_t *codepoints = hb_subset_input_unicode_set (input); for (int i = 0; i < text_length; i++) @@ -30,6 +31,20 @@ void trySubset (hb_face_t *face, hb_subset_profile_destroy (profile); } +void trySubset (hb_face_t *face, + const hb_codepoint_t text[], + int text_length) +{ + for (unsigned int drop_hints = 0; drop_hints < 2; drop_hints++) + { + for (unsigned int drop_ot_layout = 0; drop_ot_layout < 2; drop_ot_layout++) + { + trySubset (face, text, text_length, + (bool) drop_hints, (bool) drop_ot_layout); + } + } +} + extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { hb_blob_t *blob = hb_blob_create ((const char *)data, size, @@ -42,8 +57,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) '3', '@', '_', '%', '&', ')', '*', '$', '!' }; - trySubset (face, text, sizeof (text) / sizeof (hb_codepoint_t), true); - trySubset (face, text, sizeof (text) / sizeof (hb_codepoint_t), false); + trySubset (face, text, sizeof (text) / sizeof (hb_codepoint_t)); hb_codepoint_t text_from_data[16]; if (size > sizeof(text_from_data)) { @@ -51,8 +65,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) data + size - sizeof(text_from_data), sizeof(text_from_data)); unsigned int text_size = sizeof (text_from_data) / sizeof (hb_codepoint_t); - trySubset (face, text_from_data, text_size, true); - trySubset (face, text_from_data, text_size, false); + trySubset (face, text_from_data, text_size); } hb_face_destroy (face); commit feb23892a36a7c855306db6d21521d5e8362bdf7 Author: Garret Rieger <[email protected]> Date: Thu Jun 7 14:32:34 2018 -0700 [subset] Use gsub closure if ot layout is not being dropped. diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 10814438..e8d4bcae 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -973,8 +973,14 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, do { glyphs_length = glyphs->get_population (); - for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);) - gsub.get_lookup (lookup_index).closure (&c, lookup_index); + if (lookups != nullptr) + { + for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);) + gsub.get_lookup (lookup_index).closure (&c, lookup_index); + } else { + for (unsigned int i = 0; i < gsub.get_lookup_count (); i++) + gsub.get_lookup (i).closure (&c, i); + } } while (glyphs_length != glyphs->get_population ()); } diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 53f83ee8..55c4e3f6 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -54,8 +54,21 @@ _add_gid_and_children (const OT::glyf::accelerator_t &glyf, } static void +_gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain) +{ + // TODO(grieger): This uses all lookups, instead collect + // the set of lookups that are relevant. + // See fontTools implementation. + hb_ot_layout_lookups_substitute_closure (face, + nullptr, + gids_to_retain); +} + + +static void _populate_gids_to_retain (hb_face_t *face, const hb_set_t *unicodes, + bool close_over_gsub, hb_set_t *unicodes_to_retain, hb_map_t *codepoint_to_glyph, hb_vector_t<hb_codepoint_t> *glyphs) @@ -82,10 +95,12 @@ _populate_gids_to_retain (hb_face_t *face, initial_gids_to_retain->add (gid); } + if (close_over_gsub) + // Add all glyphs needed for GSUB substitutions. + _gsub_closure (face, initial_gids_to_retain); + // Populate a full set of glyphs to retain by adding all referenced // composite glyphs. - // TODO expand with glyphs reached by G* - hb_codepoint_t gid = HB_SET_VALUE_INVALID; hb_set_t *all_gids_to_retain = hb_set_create (); while (initial_gids_to_retain->next (&gid)) @@ -141,6 +156,7 @@ hb_subset_plan_create (hb_face_t *face, _populate_gids_to_retain (face, input->unicodes, + !plan->drop_ot_layout, plan->unicodes, plan->codepoint_to_glyph, &plan->glyphs); commit a5673da9be70f2ba0ff79aab4bd9a4480cb0223e Author: Garret Rieger <[email protected]> Date: Thu Jun 7 14:23:03 2018 -0700 [subset] Add drop_ot_layout setting to subset input. diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index c4003dd3..5aa50883 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -45,6 +45,7 @@ hb_subset_input_create_or_fail (void) input->unicodes = hb_set_create (); input->glyphs = hb_set_create (); + input->drop_ot_layout = true; return input; } @@ -117,3 +118,19 @@ hb_subset_input_drop_hints (hb_subset_input_t *subset_input) { return &subset_input->drop_hints; } + +/** + * hb_subset_input_drop_ot_layout: + * @subset_input: a subset_input. + * + * If enabled ot layout tables will be dropped as part of + * the subsetting operation. Currently this defaults to + * true. + * + * Since: 1.8.0 + **/ +HB_EXTERN hb_bool_t * +hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input) +{ + return &subset_input->drop_ot_layout; +} diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 7100efc8..53f83ee8 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -131,6 +131,7 @@ hb_subset_plan_create (hb_face_t *face, hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> (); plan->drop_hints = input->drop_hints; + plan->drop_ot_layout = input->drop_ot_layout; plan->unicodes = hb_set_create(); plan->glyphs.init(); plan->source = hb_face_reference (face); diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index c9904af8..f4b261df 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -41,6 +41,7 @@ struct hb_subset_plan_t ASSERT_POD (); hb_bool_t drop_hints; + hb_bool_t drop_ot_layout; // For each cp that we'd like to retain maps to the corresponding gid. hb_set_t *unicodes; diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh index 5fa72527..6b2b207f 100644 --- a/src/hb-subset-private.hh +++ b/src/hb-subset-private.hh @@ -44,6 +44,7 @@ struct hb_subset_input_t { hb_set_t *glyphs; hb_bool_t drop_hints; + hb_bool_t drop_ot_layout; /* TODO * * features diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 6d388e29..906327b8 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -302,10 +302,11 @@ _should_drop_table(hb_subset_plan_t *plan, hb_tag_t tag) case HB_TAG ('h', 'd', 'm', 'x'): /* hint table, fallthrough */ case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */ return plan->drop_hints; - // Drop Layout Tables until subsetting is supported. + // Drop Layout Tables if requested. case HB_TAG ('G', 'D', 'E', 'F'): /* temporary */ case HB_TAG ('G', 'P', 'O', 'S'): /* temporary */ case HB_TAG ('G', 'S', 'U', 'B'): /* temporary */ + return plan->drop_ot_layout; // Drop these tables below by default, list pulled // from fontTools: case HB_TAG ('B', 'A', 'S', 'E'): diff --git a/src/hb-subset.h b/src/hb-subset.h index 409581c7..f6d2ae0a 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -71,6 +71,9 @@ hb_subset_input_glyph_set (hb_subset_input_t *subset_input); HB_EXTERN hb_bool_t * hb_subset_input_drop_hints (hb_subset_input_t *subset_input); +HB_EXTERN hb_bool_t * +hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input); + /* hb_subset() */ HB_EXTERN hb_face_t * hb_subset (hb_face_t *source, commit 57badadb769d0bcdbee00afce3af4972bc5c6bf1 Author: Garret Rieger <[email protected]> Date: Wed Jun 6 16:02:51 2018 -0700 [subset] add a new closure call to hb-ot-layout that can compute the closure over multiple lookups. diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index a7607f62..10814438 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -952,6 +952,32 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face, l.closure (&c, lookup_index); } +/** + * hb_ot_layout_lookups_substitute_closure: + * + * Compute the transitive closure of glyphs needed for all of the + * provided lookups. + * + * Since: 1.8.1 + **/ +void +hb_ot_layout_lookups_substitute_closure (hb_face_t *face, + const hb_set_t *lookups, + hb_set_t *glyphs) +{ + hb_auto_t<hb_map_t> done_lookups; + OT::hb_closure_context_t c (face, glyphs, &done_lookups); + const OT::GSUB& gsub = _get_gsub (face); + + unsigned int glyphs_length; + do + { + glyphs_length = glyphs->get_population (); + for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);) + gsub.get_lookup (lookup_index).closure (&c, lookup_index); + } while (glyphs_length != glyphs->get_population ()); +} + /* * OT::GPOS */ diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index d82dc022..02787962 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -277,6 +277,12 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face, hb_set_t *glyphs /*TODO , hb_bool_t inclusive */); +HB_EXTERN void +hb_ot_layout_lookups_substitute_closure (hb_face_t *face, + const hb_set_t *lookups, + hb_set_t *glyphs); + + #ifdef HB_NOT_IMPLEMENTED /* Note: You better have GDEF when using this API, or marks won't do much. */ HB_EXTERN hb_bool_t diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index c20b110e..36e0bf9c 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -957,15 +957,7 @@ hb_ot_shape_glyphs_closure (hb_font_t *font, hb_set_t *lookups = hb_set_create (); hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups); - - /* And find transitive closure. */ - hb_set_t *copy = hb_set_create (); - do { - copy->set (glyphs); - for (hb_codepoint_t lookup_index = HB_SET_VALUE_INVALID; hb_set_next (lookups, &lookup_index);) - hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); - } while (!copy->is_equal (glyphs)); - hb_set_destroy (copy); + hb_ot_layout_lookups_substitute_closure (font->face, lookups, glyphs); hb_set_destroy (lookups); _______________________________________________ HarfBuzz mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/harfbuzz
