diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh index 441d4b9ec..e4d3ec851 100644 --- a/src/hb-ot-glyf-table.hh +++ b/src/hb-ot-glyf-table.hh @@ -402,17 +402,17 @@ struct glyf int16_t num_contours = (int16_t) glyph_header.numberOfContours; if (num_contours < 0) { - CompositeGlyphHeader::Iterator *composite_it; + CompositeGlyphHeader::Iterator composite_it; if (unlikely (!CompositeGlyphHeader::get_iterator ( (const char*) this->glyf_table + start_offset, - end_offset - start_offset, composite_it))) return false; + end_offset - start_offset, &composite_it))) return false; const CompositeGlyphHeader *last; do { - last = composite_it->current; - } while (composite_it->move_to_next()); + last = composite_it.current; + } while (composite_it.move_to_next()); if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS) - *instruction_start = start_offset + ((char *) last - (char *) glyf_table->dataX) + last->get_size(); + *instruction_start = ((char *) last - (char *) glyf_table->dataX) + last->get_size(); else *instruction_start = end_offset; *instruction_end = end_offset; diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc index 696a74de1..0b84c856c 100644 --- a/src/hb-subset-glyf.cc +++ b/src/hb-subset-glyf.cc @@ -136,6 +136,20 @@ _update_components (hb_subset_plan_t * plan, } } +static bool _remove_composite_instruction_flag(char *glyf_prime, unsigned int length) +{ + /* remove WE_HAVE_INSTRUCTIONS from flags in dest */ + OT::glyf::CompositeGlyphHeader::Iterator composite_it; + if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (glyf_prime, length, &composite_it))) return false; + const OT::glyf::CompositeGlyphHeader *glyph; + do { + glyph = composite_it.current; + OT::HBUINT16 *flags = const_cast (&glyph->flags); + flags->set ( (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS); + } while (composite_it.move_to_next()); + return true; +} + static bool _write_glyf_and_loca_prime (hb_subset_plan_t *plan, const OT::glyf::accelerator_t &glyf, @@ -178,9 +192,11 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan, { memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset); memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end); - /* if the instructions end at the end this was a composite glyph */ + /* if the instructions end at the end this was a composite glyph, else simple */ if (instruction_end == end_offset) - ; // TODO(rsheeter) remove WE_HAVE_INSTRUCTIONS from last flags + { + if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false; + } else /* zero instruction length, which is just before instruction_start */ memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2); diff --git a/test/api/fonts/Roboto-Regular.components.1fc.nohints.ttf b/test/api/fonts/Roboto-Regular.components.1fc.nohints.ttf new file mode 100644 index 000000000..d36cc8160 Binary files /dev/null and b/test/api/fonts/Roboto-Regular.components.1fc.nohints.ttf differ diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c index df343220c..8e17e8d5a 100644 --- a/test/api/test-subset-glyf.c +++ b/test/api/test-subset-glyf.c @@ -121,7 +121,7 @@ test_subset_glyf_noop (void) } static void -test_subset_glyf_strip_hints (void) +test_subset_glyf_strip_hints_simple (void) { hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf"); hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.nohints.ttf"); @@ -143,7 +143,28 @@ test_subset_glyf_strip_hints (void) hb_face_destroy (face_ac); } -// TODO(rsheeter): test strip hints from composite +static void +test_subset_glyf_strip_hints_composite (void) +{ + hb_face_t *face_components = hb_subset_test_open_font ("fonts/Roboto-Regular.components.ttf"); + hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Roboto-Regular.components.1fc.nohints.ttf"); + + hb_set_t *codepoints = hb_set_create(); + hb_set_add (codepoints, 0x1fc); + hb_subset_input_t *input = hb_subset_test_create_input (codepoints); + *hb_subset_input_drop_hints(input) = true; + + hb_face_t *face_generated_subset = hb_subset_test_create_subset (face_components, input); + hb_set_destroy (codepoints); + + hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('g','l','y','f')); + hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('l','o','c', 'a')); + check_maxp_num_glyphs(face_generated_subset, 4, false); + + hb_face_destroy (face_generated_subset); + hb_face_destroy (face_subset); + hb_face_destroy (face_components); +} // TODO(grieger): test for long loca generation. @@ -154,7 +175,8 @@ main (int argc, char **argv) hb_test_add (test_subset_glyf_noop); hb_test_add (test_subset_glyf); - hb_test_add (test_subset_glyf_strip_hints); + hb_test_add (test_subset_glyf_strip_hints_simple); + hb_test_add (test_subset_glyf_strip_hints_composite); hb_test_add (test_subset_glyf_with_components); return hb_test_run(); diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am index f1234db85..0b0013431 100644 --- a/test/subset/data/Makefile.am +++ b/test/subset/data/Makefile.am @@ -8,6 +8,7 @@ SUBDIRS = EXTRA_DIST = \ $(TESTS) \ expected/basics \ + expected/full-font \ fonts \ profiles \ $(NULL) diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources index 37550b639..bc8139379 100644 --- a/test/subset/data/Makefile.sources +++ b/test/subset/data/Makefile.sources @@ -1,5 +1,6 @@ TESTS = \ tests/basics.tests \ + tests/full-font.tests \ $(NULL) XFAIL_TESTS = \ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.default.61,62,63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.default.61,62,63.ttf new file mode 100644 index 000000000..02cd7efb4 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.default.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.default.61,63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.default.61,63.ttf new file mode 100644 index 000000000..4942ad0cd Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.default.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.default.61.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.default.61.ttf new file mode 100644 index 000000000..08fe7718a Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.default.61.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.default.63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.default.63.ttf new file mode 100644 index 000000000..0f3a934ce Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.default.63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61,62,63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61,62,63.ttf new file mode 100644 index 000000000..70206add6 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61,63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61,63.ttf new file mode 100644 index 000000000..c74c02995 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61.ttf new file mode 100644 index 000000000..8ba816d77 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.61.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.62.ttf new file mode 100644 index 000000000..837438a55 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.62.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.63.ttf new file mode 100644 index 000000000..311737ab4 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.63.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf new file mode 100644 index 000000000..60e361d2c Binary files /dev/null and b/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf new file mode 100644 index 000000000..1fc430a4e Binary files /dev/null and b/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf new file mode 100644 index 000000000..98f01e19a Binary files /dev/null and b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf differ diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf new file mode 100644 index 000000000..ea212f03d Binary files /dev/null and b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf differ diff --git a/test/subset/data/fonts/Roboto-Regular.ttf b/test/subset/data/fonts/Roboto-Regular.ttf new file mode 100644 index 000000000..2c97eeadf Binary files /dev/null and b/test/subset/data/fonts/Roboto-Regular.ttf differ diff --git a/test/subset/data/profiles/drop-hints.txt b/test/subset/data/profiles/drop-hints.txt new file mode 100644 index 000000000..e5cd9743f --- /dev/null +++ b/test/subset/data/profiles/drop-hints.txt @@ -0,0 +1 @@ +--no-hinting diff --git a/test/subset/data/tests/basics.tests b/test/subset/data/tests/basics.tests index 8a7246b98..972544540 100644 --- a/test/subset/data/tests/basics.tests +++ b/test/subset/data/tests/basics.tests @@ -3,6 +3,11 @@ Roboto-Regular.abc.ttf PROFILES: default.txt +drop-hints.txt SUBSETS: +abc b +c +ac +a diff --git a/test/subset/data/tests/full-font.tests b/test/subset/data/tests/full-font.tests new file mode 100644 index 000000000..f0a262bf7 --- /dev/null +++ b/test/subset/data/tests/full-font.tests @@ -0,0 +1,11 @@ +FONTS: +Roboto-Regular.ttf + +PROFILES: +default.txt +drop-hints.txt + +SUBSETS: +abc +Ǽ!A bc + diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py index 6dac890ec..9ebf082f6 100755 --- a/test/subset/generate-expected-outputs.py +++ b/test/subset/generate-expected-outputs.py @@ -15,12 +15,17 @@ def usage(): print "Usage: generate-expected-outputs.py ..." -def generate_expected_output(input_file, unicodes, output_path): - check_call(["fonttools", "subset", - input_file, - "--drop-tables+=DSIG,GPOS,GSUB,GDEF", - "--unicodes=%s" % unicodes, - "--output-file=%s" % output_path]) +def generate_expected_output(input_file, unicodes, profile_flags, output_path): + args = ["fonttools", "subset", input_file] + args.extend(profile_flags) + args.extend(["--notdef-outline", + "--name-IDs=*", + "--name-languages=*", + "--name-legacy", + "--drop-tables+=DSIG,GPOS,GSUB,GDEF", + "--unicodes=%s" % unicodes, + "--output-file=%s" % output_path]) + check_call(args) args = sys.argv[1:] @@ -37,6 +42,6 @@ for path in args: unicodes = test.unicodes() font_name = test.get_font_name() print "Creating subset %s/%s" % (output_directory, font_name) - generate_expected_output(test.font_path, unicodes, - os.path.join(output_directory, - font_name)) + generate_expected_output(test.font_path, unicodes, test.get_profile_flags(), + os.path.join(output_directory, + font_name)) diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py index 99f97826e..f1ef4614a 100755 --- a/test/subset/run-tests.py +++ b/test/subset/run-tests.py @@ -44,6 +44,7 @@ def run_test(test): "--font-file=" + test.font_path, "--output-file=" + out_file, "--unicodes=%s" % test.unicodes()] + cli_args.extend (test.get_profile_flags()) print (' '.join(cli_args)) _, return_code = cmd(cli_args) @@ -78,7 +79,7 @@ def run_ttx(file): def strip_check_sum (ttx_string): return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]', - 'checkSumAdjustment value="0x00000000"', + 'checkSumAdjustment value="0x00000000"', ttx_string, count=1) args = sys.argv[1:] diff --git a/test/subset/subset_test_suite.py b/test/subset/subset_test_suite.py index 256e20713..35386508e 100644 --- a/test/subset/subset_test_suite.py +++ b/test/subset/subset_test_suite.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +import io import os # A single test in a subset test suite. Identifies a font @@ -13,15 +14,19 @@ class Test: def unicodes(self): return ",".join("%X" % ord(c) for (i, c) in enumerate(self.subset)) + def get_profile_flags(self): + with io.open(self.profile_path, mode="r", encoding="utf-8") as f: + return f.read().splitlines(); + def get_font_name(self): font_base_name = os.path.basename(self.font_path) font_base_name_parts = os.path.splitext(font_base_name) profile_name = os.path.splitext(os.path.basename(self.profile_path))[0] return "%s.%s.%s%s" % (font_base_name_parts[0], - profile_name, - self.unicodes(), - font_base_name_parts[1]) + profile_name, + self.unicodes(), + font_base_name_parts[1]) # A group of tests to perform on the subsetter. Each test # Identifies a font a subsetting profile, and a subset to be cut.