diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh index 441d4b9ecde441f1cf35a85038be8f526b2c9961..e4d3ec851dc15bd5b8bea23fde584b425e6d7f1c 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 696a74de1a40b04be543ecf1774e23d9c7579410..0b84c856c2b3e2c5019590441f1610f18e9597cb 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 0000000000000000000000000000000000000000..d36cc81601e000d07b2c1813440424a01eed097e 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 df343220c615506611c7383403d5bd545fa2f975..8e17e8d5af18cd5d62ccb849a0f7ef404495ef30 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 f1234db8581ca2573b7e287e4dfb7e4620f3796c..0b0013431388117051fed4667987d6b68f51a225 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 37550b639cbf4402cb503f05d22380be62d1af9f..bc813937985917667126faa8a21952dc074cbd74 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 0000000000000000000000000000000000000000..02cd7efb4de6e6a1cac4364eea570b04096aa2bf 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 0000000000000000000000000000000000000000..4942ad0cd27f1dcec12907127de7b7ceae024438 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 0000000000000000000000000000000000000000..08fe7718a817656f1ebd2c134d8d1bb810416982 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 0000000000000000000000000000000000000000..0f3a934ce55e15d31d7c1ecfb13ae79eca5644eb 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 0000000000000000000000000000000000000000..70206add65ff879a49e98a4948080533c647520f 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 0000000000000000000000000000000000000000..c74c029959570a40455093c1056c22a1c6af54c5 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 0000000000000000000000000000000000000000..8ba816d77726379d8378b1d1ee350a2abae7591e 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 0000000000000000000000000000000000000000..837438a55fef2308c78ed0624df113ba7cb59af0 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 0000000000000000000000000000000000000000..311737ab4ef7749105ca1aaea3a229819eaabd01 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 0000000000000000000000000000000000000000..60e361d2c72972f37995d7ace5023551387ca817 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 0000000000000000000000000000000000000000..1fc430a4e654b726e274a9abdbc88a55b64ea9ac 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 0000000000000000000000000000000000000000..98f01e19a30d842bb71ab0966b186f02005fe62a 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 0000000000000000000000000000000000000000..ea212f03d3583492f14c04535fd55b1385c3bdd9 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 0000000000000000000000000000000000000000..2c97eeadffe1a34bd67d3ff1c3887fd53e22c2ca 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 0000000000000000000000000000000000000000..e5cd9743fff6b143509bb949300e656af8b66446 --- /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 8a7246b98acb5561e763ce9d66da9fbba6836dee..972544540f4df178de68d17ea874bbf62ecc6611 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 0000000000000000000000000000000000000000..f0a262bf7a355e26aa66e79cd7cb3e3f9f646bf7 --- /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 6dac890ecbbb401bb6227a51c47112d74c78c579..9ebf082f6330c8915510090b00fcc169bf686e9f 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 99f97826ea8923b4bd9ca65a58a3ae71d0f7d44b..f1ef4614aa2f609b1ac7b59eeb356df32a6294d4 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 256e20713bed1010125230776d9e9ca891698c4c..35386508ea0cf9fea202e669938645cd14dc1f02 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.