diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index 453e5ec78..172d4a70b 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -26,6 +26,7 @@ #define HB_OT_COLOR_SBIX_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" /* * sbix -- Standard Bitmap Graphics @@ -40,6 +41,32 @@ namespace OT { struct SBIXGlyph { + static unsigned int get_size (unsigned int data_length) + { return min_size + data_length * HBUINT8::static_size; } + + bool serialize (hb_serialize_context_t *c, unsigned x_offset, unsigned y_offset, Tag graphic_type, const UnsizedArrayOf* src_data, unsigned int data_length) + { + TRACE_SERIALIZE (this); + + if (unlikely (!c->extend (*this, data_length))) return_trace (false); + + xOffset = x_offset; + yOffset = y_offset; + graphicType = graphic_type; + memcpy(&data, src_data, data_length); + return_trace (true); + } + + bool subset (hb_subset_context_t *c, unsigned int data_length) const { + TRACE_SUBSET (this); + + SBIXGlyph* new_glyph = c->serializer->start_embed (); + if (unlikely (!new_glyph)) return_trace (false); + + new_glyph->serialize (c->serializer, xOffset, yOffset, graphicType, &data, data_length); + return_trace (true); + } + HBINT16 xOffset; /* The horizontal (x-axis) offset from the left * edge of the graphic to the glyph’s origin. * That is, the x-coordinate of the point on the @@ -62,6 +89,9 @@ struct SBIXGlyph struct SBIXStrike { + static unsigned int get_size (unsigned num_glyphs) + { return min_size + num_glyphs * HBUINT32::static_size; } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -116,6 +146,38 @@ struct SBIXStrike return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length); } + bool subset (hb_subset_context_t* c) const + { + TRACE_SUBSET (this); + unsigned int num_output_glyphs = c->plan->num_output_glyphs (); + + auto* out = c->serializer->start_embed (); + if (unlikely (!out)) return_trace (false); + if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false); + out->ppem = ppem; + out->resolution = resolution; + HBUINT32 head; + head = get_size(num_output_glyphs + 1); + for (unsigned new_gid = 0; new_gid < num_output_glyphs; new_gid++) + { + hb_codepoint_t old_gid; + if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid) || + unlikely (imageOffsetsZ[old_gid + 1] <= imageOffsetsZ[old_gid] || + imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid] <= SBIXGlyph::min_size)) { + out->imageOffsetsZ[new_gid] = head; + continue; + } + unsigned int delta = imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid]; + unsigned int glyph_data_length = delta - SBIXGlyph::min_size; + if (!(this + imageOffsetsZ[old_gid]).subset(c, glyph_data_length)) + return_trace (false); + out->imageOffsetsZ[new_gid] = head; + head += delta; + } + out->imageOffsetsZ[num_output_glyphs] = head; + return_trace (true); + } + public: HBUINT16 ppem; /* The PPEM size for which this strike was designed. */ HBUINT16 resolution; /* The device pixel density (in PPI) for which this @@ -275,6 +337,70 @@ struct sbix strikes.sanitize (c, this))); } + bool add_strike (hb_subset_context_t *c, + const void *dst_base, + LOffsetTo* o, + unsigned int i) const { + *o = 0; + if (strikes[i].is_null ()) + return false; + + auto *s = c->serializer; + + s->push (); + + return (this+strikes[i]).subset (c); + } + + bool serialize_strike_offsets (hb_subset_context_t *c, + const void *dst_base) const + { + TRACE_SERIALIZE (this); + + auto *out = c->serializer->start_embed> (); + if (unlikely (!out)) return_trace (false); + if (unlikely (!c->serializer->allocate_size (HBUINT32::static_size))) return_trace (false); + + hb_vector_t*> new_strikes; + hb_vector_t objidxs; + for (int i = strikes.len - 1; i >= 0; --i) + { + auto* o = out->serialize_append (c->serializer); + if (unlikely (!o)) return_trace (false); + auto snap = c->serializer->snapshot (); + bool ret = add_strike(c, dst_base, o, i); + if (!ret) + { + c->serializer->pop_discard (); + out->pop(); + c->serializer->revert (snap); + } + else + { + objidxs.push (c->serializer->pop_pack ()); + new_strikes.push (o); + } + } + for (unsigned int i = 0; i < new_strikes.length; ++i) + { + c->serializer->add_link (*new_strikes[i], objidxs[new_strikes.length - 1 - i], dst_base); + } + + return_trace (true); + } + + bool subset (hb_subset_context_t* c) const + { + TRACE_SUBSET (this); + + sbix *sbix_prime = c->serializer->start_embed (); + if (unlikely (!sbix_prime)) return_trace (false); + if (unlikely (!c->serializer->embed (this->version))) return_trace (false); + if (unlikely (!c->serializer->embed (this->flags))) return_trace (false); + + return_trace (serialize_strike_offsets (c, sbix_prime)); + } + protected: HBUINT16 version; /* Table version number — set to 1 */ HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines. diff --git a/src/hb-subset.cc b/src/hb-subset.cc index f8124443c..fc343fec2 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -37,6 +37,7 @@ #include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-maxp-table.hh" +#include "hb-ot-color-sbix-table.hh" #include "hb-ot-os2-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-cff1-table.hh" @@ -187,6 +188,9 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_maxp: result = _subset2 (plan); break; + case HB_OT_TAG_sbix: + result = _subset2 (plan); + break; case HB_OT_TAG_loca: DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf"); return true; diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am index 4508fcde8..fc2e94d36 100644 --- a/test/subset/data/Makefile.am +++ b/test/subset/data/Makefile.am @@ -18,6 +18,7 @@ EXTRA_DIST += \ expected/layout.gpos3 \ expected/layout.gsub6 \ expected/cmap14 \ + expected/sbix \ fonts \ profiles \ $(NULL) diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources index 5b93f27df..d1c248490 100644 --- a/test/subset/data/Makefile.sources +++ b/test/subset/data/Makefile.sources @@ -10,6 +10,7 @@ TESTS = \ tests/layout.gpos3.tests \ tests/layout.gsub6.tests \ tests/cmap14.tests \ + tests/sbix.tests \ $(NULL) XFAIL_TESTS = \ diff --git a/test/subset/data/expected/sbix/sbix.default.58.ttf b/test/subset/data/expected/sbix/sbix.default.58.ttf new file mode 100644 index 000000000..ed75ed46c Binary files /dev/null and b/test/subset/data/expected/sbix/sbix.default.58.ttf differ diff --git a/test/subset/data/expected/sbix/sbix.default.59.ttf b/test/subset/data/expected/sbix/sbix.default.59.ttf new file mode 100644 index 000000000..d5df5ae2b Binary files /dev/null and b/test/subset/data/expected/sbix/sbix.default.59.ttf differ diff --git a/test/subset/data/expected/sbix/sbix.drop-hints-retain-gids.58.ttf b/test/subset/data/expected/sbix/sbix.drop-hints-retain-gids.58.ttf new file mode 100644 index 000000000..38a688c25 Binary files /dev/null and b/test/subset/data/expected/sbix/sbix.drop-hints-retain-gids.58.ttf differ diff --git a/test/subset/data/expected/sbix/sbix.drop-hints-retain-gids.59.ttf b/test/subset/data/expected/sbix/sbix.drop-hints-retain-gids.59.ttf new file mode 100644 index 000000000..ff5838d3b Binary files /dev/null and b/test/subset/data/expected/sbix/sbix.drop-hints-retain-gids.59.ttf differ diff --git a/test/subset/data/expected/sbix/sbix.drop-hints.58.ttf b/test/subset/data/expected/sbix/sbix.drop-hints.58.ttf new file mode 100644 index 000000000..38a688c25 Binary files /dev/null and b/test/subset/data/expected/sbix/sbix.drop-hints.58.ttf differ diff --git a/test/subset/data/expected/sbix/sbix.drop-hints.59.ttf b/test/subset/data/expected/sbix/sbix.drop-hints.59.ttf new file mode 100644 index 000000000..6b7cedf18 Binary files /dev/null and b/test/subset/data/expected/sbix/sbix.drop-hints.59.ttf differ diff --git a/test/subset/data/expected/sbix/sbix.retain-gids.58.ttf b/test/subset/data/expected/sbix/sbix.retain-gids.58.ttf new file mode 100644 index 000000000..ed75ed46c Binary files /dev/null and b/test/subset/data/expected/sbix/sbix.retain-gids.58.ttf differ diff --git a/test/subset/data/expected/sbix/sbix.retain-gids.59.ttf b/test/subset/data/expected/sbix/sbix.retain-gids.59.ttf new file mode 100644 index 000000000..f6957c367 Binary files /dev/null and b/test/subset/data/expected/sbix/sbix.retain-gids.59.ttf differ diff --git a/test/subset/data/fonts/sbix.ttf b/test/subset/data/fonts/sbix.ttf new file mode 100644 index 000000000..e3da30a2e Binary files /dev/null and b/test/subset/data/fonts/sbix.ttf differ diff --git a/test/subset/data/tests/sbix.tests b/test/subset/data/tests/sbix.tests new file mode 100644 index 000000000..551d89aa9 --- /dev/null +++ b/test/subset/data/tests/sbix.tests @@ -0,0 +1,13 @@ +FONTS: +sbix.ttf + +PROFILES: +default.txt +drop-hints.txt +drop-hints-retain-gids.txt +retain-gids.txt +name-ids.txt + +SUBSETS: +X +Y diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py index c33a49f3c..0db969812 100755 --- a/test/subset/generate-expected-outputs.py +++ b/test/subset/generate-expected-outputs.py @@ -24,6 +24,7 @@ def generate_expected_output(input_file, unicodes, profile_flags, output_path): "--name-legacy", "--layout-features=*", "--drop-tables+=DSIG,GPOS,GSUB,GDEF", + "--drop-tables-=sbix", "--unicodes=%s" % unicodes, "--output-file=%s" % output_path]) args.extend(profile_flags) diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py index 4bf57140f..5a90c9b3e 100755 --- a/test/subset/run-tests.py +++ b/test/subset/run-tests.py @@ -67,7 +67,8 @@ def run_test (test, should_check_ots): "--font-file=" + test.font_path, "--output-file=" + out_file, "--unicodes=%s" % test.unicodes (), - "--drop-tables+=DSIG,GPOS,GSUB,GDEF"] + "--drop-tables+=DSIG,GPOS,GSUB,GDEF", + "--drop-tables-=sbix"] cli_args.extend (test.get_profile_flags ()) print (' '.join (cli_args)) _, return_code = cmd (cli_args)