src/Makefile.sources | 1 src/hb-ot-hdmx-table.hh | 198 ++++++++++++++++++++++++++++++++++++++++++++ src/hb-subset.cc | 23 +++-- test/api/Makefile.am | 2 test/api/test-subset-hdmx.c | 81 ++++++++++++++++++ 5 files changed, 297 insertions(+), 8 deletions(-)
New commits: commit b1ec82105189053d648a798cf5b3ab2887046298 Merge: e15e41ef c2e4713b Author: Garret Rieger <grie...@google.com> Date: Fri Feb 23 12:32:18 2018 -0700 Merge pull request #823 from googlefonts/hdmx [subset] Add hdmx subsetting. commit c2e4713b5b561675b0f7b358ccf83d64ef0b6c41 Author: Behdad Esfahbod <beh...@behdad.org> Date: Fri Feb 23 10:45:03 2018 -0800 [hdmx] Fix sanitize() diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index a4491518..f08fe39d 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 */ commit 84d4bb91ceca22484abb597c19eb18311e2514f1 Author: Behdad Esfahbod <beh...@behdad.org> Date: Fri Feb 23 10:38:35 2018 -0800 [hdmx] Minor diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index d13d7aac..a4491518 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); }; commit cf7a6e520e9601da9d27bc8f6bbe5d2eff23998d Author: Behdad Esfahbod <beh...@behdad.org> Date: Fri Feb 23 10:34:26 2018 -0800 [hdmx] Move DeviceRecord to toplevel again More readable. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 0033e3ec..d13d7aac 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -31,80 +31,82 @@ namespace OT { + /* * hdmx - Horizontal Device Metric */ #define HB_OT_TAG_hdmx HB_TAG('h','d','m','x') -struct hdmx +struct DeviceRecord { - static const hb_tag_t tableTag = HB_OT_TAG_hdmx; - - struct DeviceRecord + struct SubsetView { - 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) { - 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) + this->source_device_record = source_device_record; + this->subset_plan = subset_plan; + } + + inline unsigned int len () const { - 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; + return this->subset_plan->gids_to_retain_sorted.len; } - inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) + inline const HBUINT8& operator [] (unsigned int i) const { - TRACE_SERIALIZE (this); + 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]; + } + }; - if (unlikely (!c->allocate_size<DeviceRecord> (get_size (subset_view.len())))) - return_trace (false); + 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; + } - this->pixel_size.set (subset_view.source_device_record->pixel_size); - this->max_width.set (subset_view.source_device_record->max_width); + inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) + { + TRACE_SERIALIZE (this); - for (unsigned int i = 0; i < subset_view.len(); i++) - widths[i].set (subset_view[i]); + if (unlikely (!c->allocate_size<DeviceRecord> (get_size (subset_view.len())))) + return_trace (false); - return_trace (true); - } + this->pixel_size.set (subset_view.source_device_record->pixel_size); + this->max_width.set (subset_view.source_device_record->max_width); - 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))); - } + for (unsigned int i = 0; i < subset_view.len(); i++) + widths[i].set (subset_view[i]); - 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); - }; + 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; inline unsigned int get_size (void) const { commit 96d7805a9235443972c6b6c5cd9502283c8836e9 Author: Garret Rieger <grie...@google.com> Date: Thu Feb 22 16:48:28 2018 -0800 [subset] More complete sanitization implementation for hdmx. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 1d9fe07b..0033e3ec 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: commit c02532a3d2325c8fb9332f63f687cbaec77b2239 Author: Garret Rieger <grie...@google.com> Date: Thu Feb 22 16:40:50 2018 -0800 [subset] Formatting and comments in hdmx. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 90d7448b..1d9fe07b 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -31,9 +31,11 @@ namespace OT { -#define HB_OT_TAG_hdmx HB_TAG('h','d','m','x') - +/* + * hdmx - Horizontal Device Metric + */ +#define HB_OT_TAG_hdmx HB_TAG('h','d','m','x') struct 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 */ commit 6b372f439b257808b048d02ebf5a867dabcd1231 Author: Garret Rieger <grie...@google.com> Date: Thu Feb 22 12:00:00 2018 -0800 [subset] In hb-ot-hdmx-table, s/glyf/hdmx. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 6bf492cb..90d7448b 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 { commit ec302ad5bda6bea870f6d33f9698a1782472a213 Author: Garret Rieger <grie...@google.com> Date: Thu Feb 22 11:57:35 2018 -0800 [subset] Fail subset if a table fails to sanitize. diff --git a/src/hb-subset.cc b/src/hb-subset.cc index a9f599f9..b7d3e371 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -83,16 +83,19 @@ template<typename TableType> static bool _subset (hb_subset_plan_t *plan) { - OT::Sanitizer<TableType> sanitizer; - hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag)); - const TableType *table = OT::Sanitizer<TableType>::lock_instance (source_blob); - hb_bool_t result = table->subset(plan); + OT::Sanitizer<TableType> sanitizer; - hb_blob_destroy (source_blob); + hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag)); + const TableType *table = OT::Sanitizer<TableType>::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; } commit 15fc45bfedef433025145289fe916739907b573b Author: Garret Rieger <grie...@google.com> Date: Wed Feb 21 17:59:57 2018 -0800 [subset] Add a unit test for hdmx subsetting. diff --git a/test/api/Makefile.am b/test/api/Makefile.am index ecf44754..e2e6166c 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 00000000..291eb793 --- /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 <stdbool.h> + +#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(); +} commit aa4aa2353c52f86fd56446de6b7ff86a9e990b9c Author: Garret Rieger <grie...@google.com> Date: Wed Feb 21 17:43:32 2018 -0800 [subset] Enable hdmx subsetting. diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 1d6e636d..a9f599f9 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<const OT::glyf> (plan); break; + case HB_OT_TAG_hdmx: + result = _subset<const OT::hdmx> (plan); + break; case HB_OT_TAG_head: // SKIP head, it's handled by glyf result = true; commit bd18b6adf8697c1ce3f4e3831b9f2a99d930e97d Author: Garret Rieger <grie...@google.com> Date: Wed Feb 21 17:42:58 2018 -0800 [subset] Move DeviceRecord inside of hdmx. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index d2557058..6bf492cb 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 hdmx { - struct SubsetView - { - const DeviceRecord *source_device_record; - hb_subset_plan_t *subset_plan; + static const hb_tag_t tableTag = HB_OT_TAG_glyf; - inline void init(const DeviceRecord *source_device_record, - hb_subset_plan_t *subset_plan) + struct DeviceRecord + { + struct SubsetView { - this->source_device_record = source_device_record; - this->subset_plan = subset_plan; - } - - inline unsigned int len () const + 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) { - return this->subset_plan->gids_to_retain_sorted.len; + 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 const HBUINT8& operator [] (unsigned int i) const + inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) { - 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; - } + TRACE_SERIALIZE (this); - inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) - { - TRACE_SERIALIZE (this); - - if (unlikely (!c->allocate_size<DeviceRecord> (get_size (subset_view.len())))) - return_trace (false); + if (unlikely (!c->allocate_size<DeviceRecord> (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); + 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); - } + for (unsigned int i = 0; i < subset_view.len(); i++) + widths[i].set (subset_view[i]); - HBUINT8 pixel_size; - HBUINT8 max_width; - HBUINT8 widths[VAR]; + return_trace (true); + } - DEFINE_SIZE_MIN (2); -}; + HBUINT8 pixel_size; + HBUINT8 max_width; + HBUINT8 widths[VAR]; -struct hdmx -{ + DEFINE_SIZE_MIN (2); + }; inline unsigned int get_size (void) const { commit 6704cded65985b2de262bdd3bb0887929e5a3b0b Author: Garret Rieger <grie...@google.com> Date: Wed Feb 21 16:00:10 2018 -0800 [subset] Add hdmx subsetting implementation. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 5f0d197a..d2557058 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<hdmx> (); + 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 commit 84b68e58862647b4ede414b2e608c47d390fd60a Author: Garret Rieger <grie...@google.com> Date: Wed Feb 21 15:43:47 2018 -0800 [subset] In hdmx serialize set the correct value of sizeDeviceRecord. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index deedd380..5f0d197a 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<DeviceRecord> (subset_view.get_size()))) + if (unlikely (!c->allocate_size<DeviceRecord> (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) commit dddf44279f610e77e8b9a0819fd91f48802158b6 Author: Garret Rieger <grie...@google.com> Date: Wed Feb 21 15:36:09 2018 -0800 [subset] When serializing a DeviceRecord in hdmx pad to make 32 bit aligned. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index a506c294..deedd380 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<DeviceRecord> (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); } commit ab7a8f3b7419b604816e12cb93e77c0ba45a57af Author: Garret Rieger <grie...@google.com> Date: Wed Feb 21 15:15:22 2018 -0800 [subset] Begin implementing serialize for hdmx. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 7117a977..a506c294 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<DeviceRecord> (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<DeviceRecord> ()->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 */ commit fe42862ab30d17483a1d0c2e2b1d859d01bbaff1 Author: Garret Rieger <grie...@google.com> Date: Wed Feb 21 14:18:49 2018 -0800 [subset] Sketch out a basic hb-ot-hdmx.hh. diff --git a/src/Makefile.sources b/src/Makefile.sources index 9b96716d..416ee44f 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 00000000..7117a977 --- /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<DeviceRecord> (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 a4794f18..1d6e636d 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" _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/harfbuzz