From a35757c6bc3a792791c0714d143f47537d7ec110 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Wed, 2 Feb 2022 10:30:34 -0800 Subject: [PATCH] [repacker] expose hb_subset_repack() API, hb_object_t and hb_link_t structs --- src/Makefile.sources | 2 + src/gen-def.py | 2 +- src/hb-repacker.hh | 19 ++- src/hb-serialize.hh | 35 +++++ src/hb-subset-repacker.cc | 49 ++++++ src/hb-subset-repacker.h | 80 ++++++++++ src/meson.build | 6 +- test/api/Makefile.am | 2 + test/api/fonts/repacker_expected.otf | Bin 0 -> 1400 bytes test/api/meson.build | 1 + test/api/test-subset-repacker.c | 225 +++++++++++++++++++++++++++ 11 files changed, 411 insertions(+), 10 deletions(-) create mode 100644 src/hb-subset-repacker.cc create mode 100644 src/hb-subset-repacker.h create mode 100644 test/api/fonts/repacker_expected.otf create mode 100644 test/api/test-subset-repacker.c diff --git a/src/Makefile.sources b/src/Makefile.sources index ce6501443..40fbd99a6 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -275,6 +275,7 @@ HB_SUBSET_sources = \ hb-subset-input.hh \ hb-subset-plan.cc \ hb-subset-plan.hh \ + hb-subset-repacker.cc \ hb-subset.cc \ hb-subset.hh \ hb-repacker.hh \ @@ -282,6 +283,7 @@ HB_SUBSET_sources = \ HB_SUBSET_headers = \ hb-subset.h \ + hb-subset-repacker.h \ $(NULL) HB_GOBJECT_DIST_sources = hb-gobject-structs.cc diff --git a/src/gen-def.py b/src/gen-def.py index 7b609a97a..205ed7ebd 100755 --- a/src/gen-def.py +++ b/src/gen-def.py @@ -19,7 +19,7 @@ symbols = sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re if '--experimental-api' not in sys.argv: # Move these to harfbuzz-sections.txt when got stable experimental_symbols = \ -"""""".splitlines () +"""hb_subset_repack_or_fail""".splitlines () symbols = [x for x in symbols if x not in experimental_symbols] symbols = "\n".join (symbols) diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh index b1726d8be..2a9e75c45 100644 --- a/src/hb-repacker.hh +++ b/src/hb-repacker.hh @@ -37,7 +37,6 @@ * For a detailed writeup on the overflow resolution algorithm see: * docs/repacker.md */ - struct graph_t { struct vertex_t @@ -140,7 +139,8 @@ struct graph_t * the 'packed' object stack used internally in the * serializer */ - graph_t (const hb_vector_t& objects) + template + graph_t (const T& objects) : parents_invalid (true), distance_invalid (true), positions_invalid (true), @@ -1098,8 +1098,9 @@ struct graph_t hb_vector_t num_roots_for_space_; }; -static bool _try_isolating_subgraphs (const hb_vector_t& overflows, - graph_t& sorted_graph) +static inline +bool _try_isolating_subgraphs (const hb_vector_t& overflows, + graph_t& sorted_graph) { unsigned space = 0; hb_set_t roots_to_isolate; @@ -1147,9 +1148,10 @@ static bool _try_isolating_subgraphs (const hb_vector_t& overflows, - hb_set_t& priority_bumped_parents, - graph_t& sorted_graph) +static inline +bool _process_overflows (const hb_vector_t& overflows, + hb_set_t& priority_bumped_parents, + graph_t& sorted_graph) { bool resolution_attempted = false; @@ -1207,8 +1209,9 @@ static bool _process_overflows (const hb_vector_t& o * For a detailed writeup describing how the algorithm operates see: * docs/repacker.md */ +template inline hb_blob_t* -hb_resolve_overflows (const hb_vector_t& packed, +hb_resolve_overflows (const T& packed, hb_tag_t table_tag, unsigned max_rounds = 20) { // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 6615f033c..40895a454 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -36,6 +36,9 @@ #include "hb-map.hh" #include "hb-pool.hh" +#ifdef HB_EXPERIMENTAL_API +#include "hb-subset-repacker.h" +#endif /* * Serialize @@ -70,6 +73,24 @@ struct hb_serialize_context_t virtual_links.fini (); } + object_t () = default; + +#ifdef HB_EXPERIMENTAL_API + object_t (const hb_object_t &o) + { + head = o.head; + tail = o.tail; + next = nullptr; + real_links.alloc (o.num_real_links); + for (unsigned i = 0 ; i < o.num_real_links; i++) + real_links.push (o.real_links[i]); + + virtual_links.alloc (o.num_virtual_links); + for (unsigned i = 0; i < o.num_virtual_links; i++) + virtual_links.push (o.virtual_links[i]); + } +#endif + bool operator == (const object_t &o) const { // Virtual links aren't considered for equality since they don't affect the functionality @@ -95,6 +116,20 @@ struct hb_serialize_context_t unsigned position: 28; unsigned bias; objidx_t objidx; + + link_t () = default; + +#ifdef HB_EXPERIMENTAL_API + link_t (const hb_link_t &o) + { + width = o.width; + is_signed = 0; + whence = 0; + position = o.position; + bias = 0; + objidx = o.objidx; + } +#endif }; char *head; diff --git a/src/hb-subset-repacker.cc b/src/hb-subset-repacker.cc new file mode 100644 index 000000000..2447d296b --- /dev/null +++ b/src/hb-subset-repacker.cc @@ -0,0 +1,49 @@ +/* + * 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. + * + */ +#include "hb-repacker.hh" + +#ifdef HB_EXPERIMENTAL_API +/** + * hb_subset_repack_or_fail: + * @hb_objects: raw array of struct hb_object_t, which provides + * object graph info + * @num_hb_objs: number of hb_object_t in the hb_objects array. + * + * Given the input object graph info, repack a table to eliminate + * offset overflows. A nullptr is returned if the repacking attempt fails. + * + * Since: EXPERIMENTAL + **/ +hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs) +{ + hb_vector_t packed; + packed.alloc (num_hb_objs + 1); + packed.push (nullptr); + for (unsigned i = 0 ; i < num_hb_objs ; i++) + packed.push (&(hb_objects[i])); + return hb_resolve_overflows (packed, HB_OT_TAG_GSUB); +} +#endif + diff --git a/src/hb-subset-repacker.h b/src/hb-subset-repacker.h new file mode 100644 index 000000000..f9a238369 --- /dev/null +++ b/src/hb-subset-repacker.h @@ -0,0 +1,80 @@ +/* + * 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. + * + */ + +#ifndef HB_SUBSET_REPACKER_H +#define HB_SUBSET_REPACKER_H + +#include "hb.h" + +HB_BEGIN_DECLS + +#ifdef HB_EXPERIMENTAL_API +/** + * struct hb_link_t + * width: offsetSize in bytes + * position: position of the offset field in bytes + * from beginning of subtable + * objidx: index of subtable + **/ +struct hb_link_t +{ + unsigned width; + unsigned position; + unsigned objidx; +}; + +typedef struct hb_link_t hb_link_t; + +/** + * struct hb_object_t + * head: start of object data + * tail: end of object data + * num_real_links: num of offset field in the object + * real_links: pointer to array of offset info + * num_virtual_links: num of objects that must be packed + * after current object in the final serialized order + * virtual_links: array of virtual link info + **/ +struct hb_object_t +{ + char *head; + char *tail; + unsigned num_real_links; + hb_link_t *real_links; + unsigned num_virtual_links; + hb_link_t *virtual_links; +}; + +typedef struct hb_object_t hb_object_t; + +HB_EXTERN hb_blob_t* +hb_subset_repack_or_fail (hb_object_t* hb_objects, + unsigned num_hb_objs); + +#endif + +HB_END_DECLS + +#endif /* HB_SUBSET_REPACKER_H */ diff --git a/src/meson.build b/src/meson.build index c9d3f1788..e6a5f221a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -276,11 +276,15 @@ hb_subset_sources = files( 'hb-subset-input.hh', 'hb-subset-plan.cc', 'hb-subset-plan.hh', + 'hb-subset-repacker.cc', 'hb-subset.cc', 'hb-subset.hh', ) -hb_subset_headers = files('hb-subset.h') +hb_subset_headers = files( + 'hb-subset.h', + 'hb-subset-repacker.h' +) hb_gobject_sources = files( 'hb-gobject-structs.cc' diff --git a/test/api/Makefile.am b/test/api/Makefile.am index a2412f9f1..ffd4a0fc6 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -78,6 +78,7 @@ TEST_PROGS = \ test-subset-gpos \ test-subset-colr \ test-subset-cbdt \ + test-subset-repacker \ test-unicode \ test-var-coords \ test-version \ @@ -105,6 +106,7 @@ test_subset_cbdt_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_nameids_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_gpos_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_colr_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la +test_subset_repacker_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_unicode_CPPFLAGS = \ $(AM_CPPFLAGS) \ diff --git a/test/api/fonts/repacker_expected.otf b/test/api/fonts/repacker_expected.otf new file mode 100644 index 0000000000000000000000000000000000000000..d8ed67835c37b96f32a935b21976dfdaed79b02a GIT binary patch literal 1400 zcmZ8fYfM{Z7=FLg_UzDhz$R@L#_#|VMxf0@4O z27Tm=(!hO&Q~?}Qv2k(pBm^qZl4Y_Ccfb(s0Wl&ht9b>l(r_HRNw&s6&1BBq4^M&# za%1OUd2t`XEwPg!GvOB-vjr0IEjiFbDiELK^??Ya#^Q4@9`z*S4w!dKG!xhy?e(Y- zNXF3PO-8V19)dFwoR6UxW<1t-c!u4WG7c3pq_1HP;vs1bE7s}Cby$TCb}wu!AJv}& z2|VD1li&mgJPbP^2MSTM;-6Im7OYvZS_>zj49cS(A6DzZhu$)JqXtsKh%4CB7&jd_}F@-oVh|6!HqBkam(nIyekP3TaW&O&&4d9dI zjYE{bb9wcE3K?8TNP!{-e%j3PrA?qB#C+)Kg2FtftHE>9YV(QP%d<8pc|KB;1dXsW3Z3z^+37D`^p^D>Ij?OBbxtwy7Dj}f1NbaJ4? zeQOeR8R`sme41KhDNP-p&XOm*ni;0;VcGodY?$_jd3h{+cP@NAd^o(}|25&?THLUD zQ8TR7E{3!l@epzINztsslideO_Rbv;A;skA#HwBw>NSk}qF;wO3ulls~hrs2oo1q^EFMTJ3#{w67CkL({ zpR!yy@-2PDv+tw2sn6$Hzq!@-N84@x_?v-ATQ4O+%7rML68ynHAeihKIp#hm2`dlX z+pW{AWUOx2S-UFVwl&l2>LR+Wk|x`zewOCRX%;!>C3&m-##3@a#n06pkM+4j)+X=k z)<$Q8+dXjWimaFUbHZ@w