未验证 提交 588a4e0f 编写于 作者: R rsheeter 提交者: GitHub

Merge pull request #845 from googlefonts/drophints

[subset] drop hints from composites
......@@ -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;
......
......@@ -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<OT::HBUINT16 *> (&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);
......
......@@ -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();
......
......@@ -8,6 +8,7 @@ SUBDIRS =
EXTRA_DIST = \
$(TESTS) \
expected/basics \
expected/full-font \
fonts \
profiles \
$(NULL)
......
TESTS = \
tests/basics.tests \
tests/full-font.tests \
$(NULL)
XFAIL_TESTS = \
......
......@@ -3,6 +3,11 @@ Roboto-Regular.abc.ttf
PROFILES:
default.txt
drop-hints.txt
SUBSETS:
abc
b
c
ac
a
FONTS:
Roboto-Regular.ttf
PROFILES:
default.txt
drop-hints.txt
SUBSETS:
abc
Ǽ!A bc
......@@ -15,12 +15,17 @@ def usage():
print "Usage: generate-expected-outputs.py <test suite file> ..."
def generate_expected_output(input_file, unicodes, output_path):
check_call(["fonttools", "subset",
input_file,
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,
generate_expected_output(test.font_path, unicodes, test.get_profile_flags(),
os.path.join(output_directory,
font_name))
......@@ -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)
......
#!/usr/bin/env python
import io
import os
# A single test in a subset test suite. Identifies a font
......@@ -13,6 +14,10 @@ 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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册