From fe42862ab30d17483a1d0c2e2b1d859d01bbaff1 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 21 Feb 2018 14:18:49 -0800 Subject: [PATCH 01/15] [subset] Sketch out a basic hb-ot-hdmx.hh. --- src/Makefile.sources | 1 + src/hb-ot-hdmx-table.hh | 77 +++++++++++++++++++++++++++++++++++++++++ src/hb-subset.cc | 1 + 3 files changed, 79 insertions(+) create mode 100644 src/hb-ot-hdmx-table.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index 9b96716d2..416ee44f7 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -20,6 +20,7 @@ HB_BASE_sources = \ hb-ot-cbdt-table.hh \ hb-ot-cmap-table.hh \ hb-ot-glyf-table.hh \ + hb-ot-hdmx-table.hh \ hb-ot-head-table.hh \ hb-ot-hhea-table.hh \ hb-ot-hmtx-table.hh \ diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh new file mode 100644 index 000000000..7117a9779 --- /dev/null +++ b/src/hb-ot-hdmx-table.hh @@ -0,0 +1,77 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#ifndef HB_OT_HDMX_TABLE_HH +#define HB_OT_HDMX_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + +#define HB_OT_TAG_hdmx HB_TAG('h','d','m','x') + + +struct DeviceRecord +{ + HBUINT8 pixel_size; + HBUINT8 max_width; + HBUINT8 widths[VAR]; +}; + +struct hdmx +{ + inline unsigned int get_size (void) const + { + return min_size + num_records * size_device_record; + } + + inline const DeviceRecord& operator [] (unsigned int i) const + { + if (unlikely (i >= num_records)) return Null(DeviceRecord); + return StructAtOffset (this, min_size + i * size_device_record); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) + && version == 0)); + } + + HBUINT16 version; + HBINT16 num_records; + HBINT32 size_device_record; + + DeviceRecord records[VAR]; + + DEFINE_SIZE_MIN (8); + +}; + +} /* namespace OT */ + + +#endif /* HB_OT_HDMX_TABLE_HH */ diff --git a/src/hb-subset.cc b/src/hb-subset.cc index a4794f18c..1d6e636d4 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -35,6 +35,7 @@ #include "hb-open-file-private.hh" #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" +#include "hb-ot-hdmx-table.hh" #include "hb-ot-head-table.hh" #include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" From ab7a8f3b7419b604816e12cb93e77c0ba45a57af Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 21 Feb 2018 15:15:22 -0800 Subject: [PATCH 02/15] [subset] Begin implementing serialize for hdmx. --- src/hb-ot-hdmx-table.hh | 79 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 7117a9779..a506c2940 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -36,13 +36,61 @@ namespace OT { struct DeviceRecord { + struct SubsetView + { + const DeviceRecord *source_device_record; + hb_subset_plan_t *subset_plan; + + inline void init(const DeviceRecord *source_device_record, + hb_subset_plan_t *subset_plan) + { + this->source_device_record = source_device_record; + this->subset_plan = subset_plan; + } + + inline unsigned int len () const + { + return this->subset_plan->gids_to_retain_sorted.len; + } + + inline const HBUINT8& operator [] (unsigned int i) const + { + if (unlikely (i >= len())) return Null(HBUINT8); + hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i]; + return this->source_device_record->widths[gid]; + } + }; + + inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) + { + TRACE_SERIALIZE (this); + + if (unlikely (!c->extend_min ((*this)))) return_trace (false); + this->pixel_size.set (subset_view.source_device_record->pixel_size); + this->max_width.set (subset_view.source_device_record->max_width); + + for (unsigned int i = 0; i < subset_view.len(); i++) + { + HBUINT8 *width = c->extend (this->widths[i]); + if (unlikely (!width)) return_trace (false); + width->set (subset_view[i]); + } + + return_trace (true); + } + HBUINT8 pixel_size; HBUINT8 max_width; HBUINT8 widths[VAR]; + + DEFINE_SIZE_MIN (2); }; + + struct hdmx { + inline unsigned int get_size (void) const { return min_size + num_records * size_device_record; @@ -54,6 +102,33 @@ struct hdmx return StructAtOffset (this, min_size + i * size_device_record); } + inline bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan) + { + TRACE_SERIALIZE (this); + + if (unlikely (!c->extend_min ((*this)))) return_trace (false); + + this->version.set (source_hdmx->version); + this->num_records.set (source_hdmx->num_records); + this->size_device_record.set (source_hdmx->size_device_record); + + for (unsigned int i = 0; i < source_hdmx->num_records; i++) + { + DeviceRecord::SubsetView subset_view; + subset_view.init (&(*source_hdmx)[i], plan); + + c->start_embed ()->serialize (c, subset_view); + } + + return_trace (true); + } + + inline bool subset (hb_subset_plan_t *plan) const + { + // TODO(grieger) + return false; + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -65,10 +140,10 @@ struct hdmx HBINT16 num_records; HBINT32 size_device_record; - DeviceRecord records[VAR]; - DEFINE_SIZE_MIN (8); + private: + DeviceRecord records[VAR]; }; } /* namespace OT */ From dddf44279f610e77e8b9a0819fd91f48802158b6 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 21 Feb 2018 15:36:09 -0800 Subject: [PATCH 03/15] [subset] When serializing a DeviceRecord in hdmx pad to make 32 bit aligned. --- src/hb-ot-hdmx-table.hh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index a506c2940..deedd3808 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -53,6 +53,15 @@ struct DeviceRecord return this->subset_plan->gids_to_retain_sorted.len; } + inline unsigned int get_size () const + { + unsigned int raw_size = min_size + len () * HBUINT8::static_size; + if (raw_size % 4) + /* Align to 32 bits */ + return raw_size + (4 - (raw_size % 4)); + return raw_size; + } + inline const HBUINT8& operator [] (unsigned int i) const { if (unlikely (i >= len())) return Null(HBUINT8); @@ -65,16 +74,14 @@ struct DeviceRecord { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min ((*this)))) return_trace (false); + if (unlikely (!c->allocate_size (subset_view.get_size()))) + return_trace (false); + this->pixel_size.set (subset_view.source_device_record->pixel_size); this->max_width.set (subset_view.source_device_record->max_width); for (unsigned int i = 0; i < subset_view.len(); i++) - { - HBUINT8 *width = c->extend (this->widths[i]); - if (unlikely (!width)) return_trace (false); - width->set (subset_view[i]); - } + widths[i].set (subset_view[i]); return_trace (true); } From 84b68e58862647b4ede414b2e608c47d390fd60a Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 21 Feb 2018 15:43:47 -0800 Subject: [PATCH 04/15] [subset] In hdmx serialize set the correct value of sizeDeviceRecord. --- src/hb-ot-hdmx-table.hh | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index deedd3808..5f0d197ad 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -53,15 +53,6 @@ struct DeviceRecord return this->subset_plan->gids_to_retain_sorted.len; } - inline unsigned int get_size () const - { - unsigned int raw_size = min_size + len () * HBUINT8::static_size; - if (raw_size % 4) - /* Align to 32 bits */ - return raw_size + (4 - (raw_size % 4)); - return raw_size; - } - inline const HBUINT8& operator [] (unsigned int i) const { if (unlikely (i >= len())) return Null(HBUINT8); @@ -70,11 +61,20 @@ struct DeviceRecord } }; + static inline unsigned int get_size (unsigned int count) + { + unsigned int raw_size = min_size + count * HBUINT8::static_size; + if (raw_size % 4) + /* Align to 32 bits */ + return raw_size + (4 - (raw_size % 4)); + return raw_size; + } + inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) { TRACE_SERIALIZE (this); - if (unlikely (!c->allocate_size (subset_view.get_size()))) + if (unlikely (!c->allocate_size (get_size (subset_view.len())))) return_trace (false); this->pixel_size.set (subset_view.source_device_record->pixel_size); @@ -93,8 +93,6 @@ struct DeviceRecord DEFINE_SIZE_MIN (2); }; - - struct hdmx { @@ -117,7 +115,7 @@ struct hdmx this->version.set (source_hdmx->version); this->num_records.set (source_hdmx->num_records); - this->size_device_record.set (source_hdmx->size_device_record); + this->size_device_record.set (DeviceRecord::get_size (plan->gids_to_retain_sorted.len)); for (unsigned int i = 0; i < source_hdmx->num_records; i++) { @@ -130,6 +128,11 @@ struct hdmx return_trace (true); } + static inline unsigned int get_subsetted_size (hb_subset_plan_t *plan) + { + return min_size + DeviceRecord::get_size (plan->gids_to_retain_sorted.len); + } + inline bool subset (hb_subset_plan_t *plan) const { // TODO(grieger) From 6704cded65985b2de262bdd3bb0887929e5a3b0b Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 21 Feb 2018 16:00:10 -0800 Subject: [PATCH 05/15] [subset] Add hdmx subsetting implementation. --- src/hb-ot-hdmx-table.hh | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 5f0d197ad..d25570585 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -128,15 +128,38 @@ struct hdmx return_trace (true); } - static inline unsigned int get_subsetted_size (hb_subset_plan_t *plan) + static inline size_t get_subsetted_size (hb_subset_plan_t *plan) { return min_size + DeviceRecord::get_size (plan->gids_to_retain_sorted.len); } inline bool subset (hb_subset_plan_t *plan) const { - // TODO(grieger) - return false; + size_t dest_size = get_subsetted_size (plan); + hdmx *dest = (hdmx *) malloc (dest_size); + if (unlikely (!dest)) + { + DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size); + return false; + } + + hb_serialize_context_t c (dest, dest_size); + hdmx *hdmx_prime = c.start_serialize (); + if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan)) { + free (dest); + return false; + } + c.end_serialize (); + + hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest, + dest_size, + HB_MEMORY_MODE_READONLY, + dest, + free); + bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_hdmx, hdmx_prime_blob); + hb_blob_destroy (hdmx_prime_blob); + + return result; } inline bool sanitize (hb_sanitize_context_t *c) const From bd18b6adf8697c1ce3f4e3831b9f2a99d930e97d Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 21 Feb 2018 17:42:58 -0800 Subject: [PATCH 06/15] [subset] Move DeviceRecord inside of hdmx. --- src/hb-ot-hdmx-table.hh | 118 ++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index d25570585..6bf492cbf 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -34,67 +34,69 @@ namespace OT { #define HB_OT_TAG_hdmx HB_TAG('h','d','m','x') -struct DeviceRecord -{ - struct SubsetView - { - const DeviceRecord *source_device_record; - hb_subset_plan_t *subset_plan; - - inline void init(const DeviceRecord *source_device_record, - hb_subset_plan_t *subset_plan) - { - this->source_device_record = source_device_record; - this->subset_plan = subset_plan; - } - - inline unsigned int len () const - { - return this->subset_plan->gids_to_retain_sorted.len; - } - - inline const HBUINT8& operator [] (unsigned int i) const - { - if (unlikely (i >= len())) return Null(HBUINT8); - hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i]; - return this->source_device_record->widths[gid]; - } - }; - - static inline unsigned int get_size (unsigned int count) - { - unsigned int raw_size = min_size + count * HBUINT8::static_size; - if (raw_size % 4) - /* Align to 32 bits */ - return raw_size + (4 - (raw_size % 4)); - return raw_size; - } - - inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) - { - TRACE_SERIALIZE (this); - - if (unlikely (!c->allocate_size (get_size (subset_view.len())))) - return_trace (false); - - this->pixel_size.set (subset_view.source_device_record->pixel_size); - this->max_width.set (subset_view.source_device_record->max_width); - - for (unsigned int i = 0; i < subset_view.len(); i++) - widths[i].set (subset_view[i]); - - return_trace (true); - } - - HBUINT8 pixel_size; - HBUINT8 max_width; - HBUINT8 widths[VAR]; - - DEFINE_SIZE_MIN (2); -}; struct hdmx { + static const hb_tag_t tableTag = HB_OT_TAG_glyf; + + struct DeviceRecord + { + struct SubsetView + { + const DeviceRecord *source_device_record; + hb_subset_plan_t *subset_plan; + + inline void init(const DeviceRecord *source_device_record, + hb_subset_plan_t *subset_plan) + { + this->source_device_record = source_device_record; + this->subset_plan = subset_plan; + } + + inline unsigned int len () const + { + return this->subset_plan->gids_to_retain_sorted.len; + } + + inline const HBUINT8& operator [] (unsigned int i) const + { + if (unlikely (i >= len())) return Null(HBUINT8); + hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i]; + return this->source_device_record->widths[gid]; + } + }; + + static inline unsigned int get_size (unsigned int count) + { + unsigned int raw_size = min_size + count * HBUINT8::static_size; + if (raw_size % 4) + /* Align to 32 bits */ + return raw_size + (4 - (raw_size % 4)); + return raw_size; + } + + inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) + { + TRACE_SERIALIZE (this); + + if (unlikely (!c->allocate_size (get_size (subset_view.len())))) + return_trace (false); + + this->pixel_size.set (subset_view.source_device_record->pixel_size); + this->max_width.set (subset_view.source_device_record->max_width); + + for (unsigned int i = 0; i < subset_view.len(); i++) + widths[i].set (subset_view[i]); + + return_trace (true); + } + + HBUINT8 pixel_size; + HBUINT8 max_width; + HBUINT8 widths[VAR]; + + DEFINE_SIZE_MIN (2); + }; inline unsigned int get_size (void) const { From aa4aa2353c52f86fd56446de6b7ff86a9e990b9c Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 21 Feb 2018 17:43:32 -0800 Subject: [PATCH 07/15] [subset] Enable hdmx subsetting. --- src/hb-subset.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 1d6e636d4..a9f599f93 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -230,6 +230,9 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_glyf: result = _subset (plan); break; + case HB_OT_TAG_hdmx: + result = _subset (plan); + break; case HB_OT_TAG_head: // SKIP head, it's handled by glyf result = true; From 15fc45bfedef433025145289fe916739907b573b Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 21 Feb 2018 17:59:57 -0800 Subject: [PATCH 08/15] [subset] Add a unit test for hdmx subsetting. --- test/api/Makefile.am | 2 + test/api/test-subset-hdmx.c | 81 +++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 test/api/test-subset-hdmx.c diff --git a/test/api/Makefile.am b/test/api/Makefile.am index ecf447545..e2e6166c0 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -33,6 +33,7 @@ TEST_PROGS = \ test-shape \ test-subset-cmap \ test-subset-glyf \ + test-subset-hdmx \ test-subset-hmtx \ test-subset-os2 \ test-unicode \ @@ -42,6 +43,7 @@ TEST_PROGS = \ test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_cmap_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_glyf_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la +test_subset_hdmx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_hmtx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_os2_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la diff --git a/test/api/test-subset-hdmx.c b/test/api/test-subset-hdmx.c new file mode 100644 index 000000000..291eb7937 --- /dev/null +++ b/test/api/test-subset-hdmx.c @@ -0,0 +1,81 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include + +#include "hb-test.h" +#include "hb-subset-test.h" + +/* Unit tests for hdmx subsetting */ + + +static void +test_subset_hdmx_simple_subset (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.ttf"); + + hb_set_t *codepoints = hb_set_create (); + hb_set_add (codepoints, 'a'); + hb_set_add (codepoints, 'c'); + hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints); + hb_set_destroy (codepoints); + + hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('h','d','m','x')); + + hb_face_destroy (face_abc_subset); + hb_face_destroy (face_abc); + hb_face_destroy (face_ac); +} + +static void +test_subset_hdmx_noop (void) +{ + hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf"); + + hb_set_t *codepoints = hb_set_create(); + hb_set_add (codepoints, 'a'); + hb_set_add (codepoints, 'b'); + hb_set_add (codepoints, 'c'); + hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints); + hb_set_destroy (codepoints); + + hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('h','d','m','x')); + + hb_face_destroy (face_abc_subset); + hb_face_destroy (face_abc); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_subset_hdmx_simple_subset); + hb_test_add (test_subset_hdmx_noop); + + return hb_test_run(); +} From ec302ad5bda6bea870f6d33f9698a1782472a213 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 22 Feb 2018 11:57:35 -0800 Subject: [PATCH 09/15] [subset] Fail subset if a table fails to sanitize. --- src/hb-subset.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/hb-subset.cc b/src/hb-subset.cc index a9f599f93..b7d3e3710 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -83,16 +83,19 @@ template static bool _subset (hb_subset_plan_t *plan) { - OT::Sanitizer sanitizer; - hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag)); - const TableType *table = OT::Sanitizer::lock_instance (source_blob); - hb_bool_t result = table->subset(plan); + OT::Sanitizer sanitizer; - hb_blob_destroy (source_blob); + hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag)); + const TableType *table = OT::Sanitizer::lock_instance (source_blob); - hb_tag_t tag = TableType::tableTag; - DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG(tag), result ? "success" : "FAILED!"); - return result; + hb_bool_t result = false; + if (table != &OT::Null(TableType)) + result = table->subset(plan); + + hb_blob_destroy (source_blob); + hb_tag_t tag = TableType::tableTag; + DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG(tag), result ? "success" : "FAILED!"); + return result; } From 6b372f439b257808b048d02ebf5a867dabcd1231 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 22 Feb 2018 12:00:00 -0800 Subject: [PATCH 10/15] [subset] In hb-ot-hdmx-table, s/glyf/hdmx. --- src/hb-ot-hdmx-table.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 6bf492cbf..90d7448b0 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -37,7 +37,7 @@ namespace OT { struct hdmx { - static const hb_tag_t tableTag = HB_OT_TAG_glyf; + static const hb_tag_t tableTag = HB_OT_TAG_hdmx; struct DeviceRecord { From c02532a3d2325c8fb9332f63f687cbaec77b2239 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 22 Feb 2018 16:40:50 -0800 Subject: [PATCH 11/15] [subset] Formatting and comments in hdmx. --- src/hb-ot-hdmx-table.hh | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 90d7448b0..1d9fe07b7 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -31,10 +31,12 @@ namespace OT { +/* + * hdmx - Horizontal Device Metric + */ + #define HB_OT_TAG_hdmx HB_TAG('h','d','m','x') - - struct hdmx { static const hb_tag_t tableTag = HB_OT_TAG_hdmx; @@ -91,10 +93,15 @@ struct hdmx return_trace (true); } - HBUINT8 pixel_size; - HBUINT8 max_width; - HBUINT8 widths[VAR]; + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + HBUINT8 pixel_size; /* Pixel size for following widths (as ppem). */ + HBUINT8 max_width; /* Maximum width. */ + HBUINT8 widths[VAR]; /* Array of widths (numGlyphs is from the 'maxp' table). */ DEFINE_SIZE_MIN (2); }; @@ -171,14 +178,14 @@ struct hdmx && version == 0)); } - HBUINT16 version; - HBINT16 num_records; - HBINT32 size_device_record; - - DEFINE_SIZE_MIN (8); - + public: + HBUINT16 version; /* Table version number (0) */ + HBINT16 num_records; /* Number of device records. */ + HBINT32 size_device_record; /* Size of a device record, 32-bit aligned. */ private: - DeviceRecord records[VAR]; + DeviceRecord records[VAR]; /* Array of device records. */ + public: + DEFINE_SIZE_MIN (8); }; } /* namespace OT */ From 96d7805a9235443972c6b6c5cd9502283c8836e9 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 22 Feb 2018 16:48:28 -0800 Subject: [PATCH 12/15] [subset] More complete sanitization implementation for hdmx. --- src/hb-ot-hdmx-table.hh | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 1d9fe07b7..0033e3ec2 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -93,10 +93,11 @@ struct hdmx return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + inline bool sanitize (hb_sanitize_context_t *c, unsigned int size_device_record) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (likely (c->check_struct (this) + && c->check_range (this, size_device_record))); } HBUINT8 pixel_size; /* Pixel size for following widths (as ppem). */ @@ -174,8 +175,17 @@ struct hdmx inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) - && version == 0)); + if (unlikely (!c->check_struct (this) || version != 0)) + return_trace (false); + if (unlikely (!c->check_range (this, get_size()))) + return_trace (false); + + for (unsigned int i = 0; i < num_records; i++) + { + if (unlikely (!records[i].sanitize (c, size_device_record))) + return_trace (false); + } + return_trace (true); } public: From cf7a6e520e9601da9d27bc8f6bbe5d2eff23998d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 23 Feb 2018 10:34:26 -0800 Subject: [PATCH 13/15] [hdmx] Move DeviceRecord to toplevel again More readable. --- src/hb-ot-hdmx-table.hh | 132 ++++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 65 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 0033e3ec2..d13d7aac5 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -31,81 +31,83 @@ namespace OT { + /* * hdmx - Horizontal Device Metric */ #define HB_OT_TAG_hdmx HB_TAG('h','d','m','x') +struct DeviceRecord +{ + struct SubsetView + { + const DeviceRecord *source_device_record; + hb_subset_plan_t *subset_plan; + + inline void init(const DeviceRecord *source_device_record, + hb_subset_plan_t *subset_plan) + { + this->source_device_record = source_device_record; + this->subset_plan = subset_plan; + } + + inline unsigned int len () const + { + return this->subset_plan->gids_to_retain_sorted.len; + } + + inline const HBUINT8& operator [] (unsigned int i) const + { + if (unlikely (i >= len())) return Null(HBUINT8); + hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i]; + return this->source_device_record->widths[gid]; + } + }; + + static inline unsigned int get_size (unsigned int count) + { + unsigned int raw_size = min_size + count * HBUINT8::static_size; + if (raw_size % 4) + /* Align to 32 bits */ + return raw_size + (4 - (raw_size % 4)); + return raw_size; + } + + inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) + { + TRACE_SERIALIZE (this); + + if (unlikely (!c->allocate_size (get_size (subset_view.len())))) + return_trace (false); + + this->pixel_size.set (subset_view.source_device_record->pixel_size); + this->max_width.set (subset_view.source_device_record->max_width); + + for (unsigned int i = 0; i < subset_view.len(); i++) + widths[i].set (subset_view[i]); + + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int size_device_record) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + c->check_range (this, size_device_record))); + } + + HBUINT8 pixel_size; /* Pixel size for following widths (as ppem). */ + HBUINT8 max_width; /* Maximum width. */ + HBUINT8 widths[VAR]; /* Array of widths (numGlyphs is from the 'maxp' table). */ + DEFINE_SIZE_MIN (2); +}; + + struct hdmx { static const hb_tag_t tableTag = HB_OT_TAG_hdmx; - struct DeviceRecord - { - struct SubsetView - { - const DeviceRecord *source_device_record; - hb_subset_plan_t *subset_plan; - - inline void init(const DeviceRecord *source_device_record, - hb_subset_plan_t *subset_plan) - { - this->source_device_record = source_device_record; - this->subset_plan = subset_plan; - } - - inline unsigned int len () const - { - return this->subset_plan->gids_to_retain_sorted.len; - } - - inline const HBUINT8& operator [] (unsigned int i) const - { - if (unlikely (i >= len())) return Null(HBUINT8); - hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i]; - return this->source_device_record->widths[gid]; - } - }; - - static inline unsigned int get_size (unsigned int count) - { - unsigned int raw_size = min_size + count * HBUINT8::static_size; - if (raw_size % 4) - /* Align to 32 bits */ - return raw_size + (4 - (raw_size % 4)); - return raw_size; - } - - inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) - { - TRACE_SERIALIZE (this); - - if (unlikely (!c->allocate_size (get_size (subset_view.len())))) - return_trace (false); - - this->pixel_size.set (subset_view.source_device_record->pixel_size); - this->max_width.set (subset_view.source_device_record->max_width); - - for (unsigned int i = 0; i < subset_view.len(); i++) - widths[i].set (subset_view[i]); - - return_trace (true); - } - - inline bool sanitize (hb_sanitize_context_t *c, unsigned int size_device_record) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) - && c->check_range (this, size_device_record))); - } - - HBUINT8 pixel_size; /* Pixel size for following widths (as ppem). */ - HBUINT8 max_width; /* Maximum width. */ - HBUINT8 widths[VAR]; /* Array of widths (numGlyphs is from the 'maxp' table). */ - DEFINE_SIZE_MIN (2); - }; - inline unsigned int get_size (void) const { return min_size + num_records * size_device_record; From 84d4bb91ceca22484abb597c19eb18311e2514f1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 23 Feb 2018 10:38:35 -0800 Subject: [PATCH 14/15] [hdmx] Minor --- src/hb-ot-hdmx-table.hh | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index d13d7aac5..a4491518d 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -100,7 +100,8 @@ struct DeviceRecord HBUINT8 pixel_size; /* Pixel size for following widths (as ppem). */ HBUINT8 max_width; /* Maximum width. */ HBUINT8 widths[VAR]; /* Array of widths (numGlyphs is from the 'maxp' table). */ - DEFINE_SIZE_MIN (2); + public: + DEFINE_SIZE_ARRAY (2, widths); }; @@ -164,10 +165,10 @@ struct hdmx c.end_serialize (); hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest, - dest_size, - HB_MEMORY_MODE_READONLY, - dest, - free); + dest_size, + HB_MEMORY_MODE_READONLY, + dest, + free); bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_hdmx, hdmx_prime_blob); hb_blob_destroy (hdmx_prime_blob); @@ -185,17 +186,17 @@ struct hdmx for (unsigned int i = 0; i < num_records; i++) { if (unlikely (!records[i].sanitize (c, size_device_record))) - return_trace (false); + return_trace (false); } return_trace (true); } public: - HBUINT16 version; /* Table version number (0) */ - HBINT16 num_records; /* Number of device records. */ - HBINT32 size_device_record; /* Size of a device record, 32-bit aligned. */ + HBUINT16 version; /* Table version number (0) */ + HBUINT16 num_records; /* Number of device records. */ + HBUINT32 size_device_record; /* Size of a device record, 32-bit aligned. */ private: - DeviceRecord records[VAR]; /* Array of device records. */ + DeviceRecord records[VAR]; /* Array of device records. */ public: DEFINE_SIZE_MIN (8); }; From c2e4713b5b561675b0f7b358ccf83d64ef0b6c41 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 23 Feb 2018 10:45:03 -0800 Subject: [PATCH 15/15] [hdmx] Fix sanitize() --- src/hb-ot-hdmx-table.hh | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index a4491518d..f08fe39d8 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -178,27 +178,18 @@ struct hdmx inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this) || version != 0)) - return_trace (false); - if (unlikely (!c->check_range (this, get_size()))) - return_trace (false); - - for (unsigned int i = 0; i < num_records; i++) - { - if (unlikely (!records[i].sanitize (c, size_device_record))) - return_trace (false); - } - return_trace (true); + return_trace (c->check_struct (this) && version == 0 && + !_hb_unsigned_int_mul_overflows (num_records, size_device_record) && + c->check_range (this, get_size())); } - public: + protected: HBUINT16 version; /* Table version number (0) */ HBUINT16 num_records; /* Number of device records. */ HBUINT32 size_device_record; /* Size of a device record, 32-bit aligned. */ - private: - DeviceRecord records[VAR]; /* Array of device records. */ - public: - DEFINE_SIZE_MIN (8); + HBUINT8 data[VAR]; /* Array of device records. */ + public: + DEFINE_SIZE_ARRAY (8, data); }; } /* namespace OT */