From c61c05e431cc54c505236fab90e6b0d316415138 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 21 Jul 2022 19:07:55 +0000 Subject: [PATCH] [repacker] add make_extension_context_t. --- src/graph/graph.hh | 4 ++ src/graph/gsubgpos-graph.cc | 41 ++++++++++++++++++++ src/graph/gsubgpos-graph.hh | 74 ++++++++++++++++++++++++------------- src/hb-repacker.hh | 38 ++++--------------- src/meson.build | 3 +- 5 files changed, 103 insertions(+), 57 deletions(-) create mode 100644 src/graph/gsubgpos-graph.cc diff --git a/src/graph/graph.hh b/src/graph/graph.hh index c9aaec171..0d09f337f 100644 --- a/src/graph/graph.hh +++ b/src/graph/graph.hh @@ -24,6 +24,10 @@ * Google Author(s): Garret Rieger */ +#include "hb-set.hh" +#include "hb-priority-queue.hh" +#include "hb-serialize.hh" + #ifndef GRAPH_GRAPH_HH #define GRAPH_GRAPH_HH diff --git a/src/graph/gsubgpos-graph.cc b/src/graph/gsubgpos-graph.cc new file mode 100644 index 000000000..fefb0da2f --- /dev/null +++ b/src/graph/gsubgpos-graph.cc @@ -0,0 +1,41 @@ +/* + * Copyright © 2022 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 "gsubgpos-graph.hh" + +namespace graph { + +unsigned make_extension_context_t::num_non_ext_subtables () { + unsigned count = 0; + for (auto l : lookups.values ()) + { + if (l->is_extension (table_tag)) continue; + count += l->number_of_subtables (); + } + return count; +} + +} diff --git a/src/graph/gsubgpos-graph.hh b/src/graph/gsubgpos-graph.hh index 27a1e5cb6..3ff9d3c0a 100644 --- a/src/graph/gsubgpos-graph.hh +++ b/src/graph/gsubgpos-graph.hh @@ -24,13 +24,13 @@ * Google Author(s): Garret Rieger */ -#ifndef GRAPH_GSUBGPOS_GRAPH_HH -#define GRAPH_GSUBGPOS_GRAPH_HH - #include "graph.hh" #include "hb-ot-layout-gsubgpos.hh" #include "OT/Layout/GSUB/ExtensionSubst.hh" +#ifndef GRAPH_GSUBGPOS_GRAPH_HH +#define GRAPH_GSUBGPOS_GRAPH_HH + namespace graph { struct Lookup; @@ -69,10 +69,37 @@ struct GSTAR : public OT::GSUBGPOS Lookup* lookup = (Lookup*) graph.object (lookup_idx).head; lookups.set (lookup_idx, lookup); } -} + } +}; +struct make_extension_context_t +{ + hb_tag_t table_tag; + graph_t& graph; + hb_vector_t buffer; + GSTAR* gstar; + hb_hashmap_t lookups; + make_extension_context_t (hb_tag_t table_tag_, + graph_t& graph_) + : table_tag (table_tag_), + graph (graph_), + buffer (), + gstar (graph::GSTAR::graph_to_gstar (graph_)), + lookups () + { + gstar->find_lookups (graph, lookups); + unsigned extension_size = OT::ExtensionFormat1::static_size; + buffer.alloc (num_non_ext_subtables () * extension_size); + } + bool in_error () const + { + return buffer.in_error (); + } + + private: + unsigned num_non_ext_subtables (); }; struct Lookup : public OT::Lookup @@ -87,15 +114,13 @@ struct Lookup : public OT::Lookup return lookupType == extension_type (table_tag); } - bool make_extension (hb_tag_t table_tag, - graph_t& graph, - unsigned this_index, - hb_vector_t& buffer) + bool make_extension (make_extension_context_t& c, + unsigned this_index) { // TODO: use a context_t? unsigned type = lookupType; - unsigned ext_type = extension_type (table_tag); - if (!ext_type || is_extension (table_tag)) + unsigned ext_type = extension_type (c.table_tag); + if (!ext_type || is_extension (c.table_tag)) { // NOOP printf("Already extension (obj %u).\n", this_index); @@ -109,11 +134,10 @@ struct Lookup : public OT::Lookup for (unsigned i = 0; i < subTable.len; i++) { - unsigned subtable_index = graph.index_for_offset (this_index, &subTable[i]); - if (!make_subtable_extension (graph, + unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]); + if (!make_subtable_extension (c, this_index, - subtable_index, - buffer)) + subtable_index)) return false; } @@ -121,23 +145,22 @@ struct Lookup : public OT::Lookup return true; } - bool make_subtable_extension (graph_t& graph, + bool make_subtable_extension (make_extension_context_t& c, unsigned lookup_index, - unsigned subtable_index, - hb_vector_t& buffer) + unsigned subtable_index) { printf(" Promoting subtable %u in lookup %u to extension.\n", subtable_index, lookup_index); unsigned type = lookupType; unsigned extension_size = OT::ExtensionFormat1::static_size; - unsigned start = buffer.length; + unsigned start = c.buffer.length; unsigned end = start + extension_size; - if (!buffer.resize (buffer.length + extension_size)) + if (!c.buffer.resize (c.buffer.length + extension_size)) // TODO: resizing potentially invalidates existing head/tail pointers. return false; OT::ExtensionFormat1* extension = - (OT::ExtensionFormat1*) &buffer[start]; + (OT::ExtensionFormat1*) &c.buffer[start]; extension->format = 1; extension->extensionLookupType = type; extension->extensionOffset = 0; @@ -145,11 +168,11 @@ struct Lookup : public OT::Lookup unsigned type_prime = extension->extensionLookupType; printf("Assigned type %d to extension\n", type_prime); - unsigned ext_index = graph.new_node (&buffer.arrayZ[start], - &buffer.arrayZ[end]); + unsigned ext_index = c.graph.new_node (&c.buffer.arrayZ[start], + &c.buffer.arrayZ[end]); if (ext_index == (unsigned) -1) return false; - auto& lookup_vertex = graph.vertices_[lookup_index]; + auto& lookup_vertex = c.graph.vertices_[lookup_index]; for (auto& l : lookup_vertex.obj.real_links.writer ()) { if (l.objidx == subtable_index) @@ -161,9 +184,8 @@ struct Lookup : public OT::Lookup } // Make extension point at the subtable. - // TODO: update extension parents array. - auto& ext_vertex = graph.vertices_[ext_index]; - auto& subtable_vertex = graph.vertices_[subtable_index]; + auto& ext_vertex = c.graph.vertices_[ext_index]; + auto& subtable_vertex = c.graph.vertices_[subtable_index]; auto* l = ext_vertex.obj.real_links.push (); l->width = 4; diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh index 545da7ac2..1d49c9039 100644 --- a/src/hb-repacker.hh +++ b/src/hb-repacker.hh @@ -29,8 +29,6 @@ #include "hb-open-type.hh" #include "hb-map.hh" -#include "hb-priority-queue.hh" -#include "hb-serialize.hh" #include "hb-vector.hh" #include "graph/graph.hh" #include "graph/gsubgpos-graph.hh" @@ -44,35 +42,12 @@ using graph::graph_t; */ static inline -unsigned _num_non_ext_subtables (hb_tag_t table_tag, - const hb_hashmap_t& lookups) -{ - unsigned count = 0; - for (auto l : lookups.values ()) - { - if (l->is_extension (table_tag)) continue; - count += l->number_of_subtables (); - } - return count; -} - - -static inline -bool _make_extensions (hb_tag_t table_tag, graph_t& sorted_graph, hb_vector_t& buffer) +bool _make_extensions (graph::make_extension_context_t& ext_context) { // TODO: Move this into graph or gsubgpos graph? - graph::GSTAR* gstar = graph::GSTAR::graph_to_gstar (sorted_graph); - hb_hashmap_t lookups; - gstar->find_lookups (sorted_graph, lookups); - - unsigned extension_size = OT::ExtensionFormat1::static_size; - if (!buffer.alloc (_num_non_ext_subtables (table_tag, lookups) * extension_size)) - return false; - - - for (auto p : lookups.iter ()) + for (auto p : ext_context.lookups.iter ()) { - if (!p.second->make_extension (table_tag, sorted_graph, p.first, buffer)) + if (!p.second->make_extension (ext_context, p.first)) return false; } return true; @@ -206,12 +181,15 @@ hb_resolve_overflows (const T& packed, return graph::serialize (sorted_graph); } - hb_vector_t extension_buffer; + graph::make_extension_context_t ext_context (table_tag, sorted_graph); + if (ext_context.in_error ()) + return nullptr; + if ((table_tag == HB_OT_TAG_GPOS || table_tag == HB_OT_TAG_GSUB) && will_overflow) { - if (!_make_extensions (table_tag, sorted_graph, extension_buffer)) { + if (!_make_extensions (ext_context)) { printf("make extensions failed.\n"); return nullptr; } diff --git a/src/meson.build b/src/meson.build index 19fafc965..6e7febae3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -345,6 +345,7 @@ hb_subset_sources = files( 'hb-subset-plan.cc', 'hb-subset-plan.hh', 'hb-subset-repacker.cc', + 'graph/gsubgpos-graph.cc', 'hb-subset.cc', 'hb-subset.hh', ) @@ -565,7 +566,7 @@ if get_option('tests').enabled() 'test-number': ['test-number.cc', 'hb-number.cc'], 'test-ot-tag': ['hb-ot-tag.cc'], 'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'], - 'test-repacker': ['test-repacker.cc', 'hb-static.cc'], + 'test-repacker': ['test-repacker.cc', 'hb-static.cc', 'graph/gsubgpos-graph.cc'], 'test-set': ['test-set.cc', 'hb-static.cc'], 'test-serialize': ['test-serialize.cc', 'hb-static.cc'], 'test-unicode-ranges': ['test-unicode-ranges.cc'],