src/Makefile.sources | 5 + src/hb-aat-layout-common-private.hh | 2 src/hb-aat-layout-morx-table.hh | 3 src/hb-debug.hh | 13 ++++ src/hb-open-type-private.hh | 4 - src/hb-subset-glyf.cc | 52 +++++++++++++++++ src/hb-subset-glyf.hh | 37 ++++++++++++ src/hb-subset-plan.cc | 109 ++++++++++++++++++++++++++++++++++++ src/hb-subset-plan.hh | 58 +++++++++++++++++++ src/hb-subset-private.hh | 54 +++++++++++++++++ src/hb-subset.cc | 74 ++++++++++++++++-------- src/hb-subset.h | 2 test/api/test-subset.c | 2 util/hb-subset.cc | 17 +++++ 14 files changed, 405 insertions(+), 27 deletions(-)
New commits: commit b95aa204ee284c47e63dc1e34b3c5b4bdf9e7ab7 Author: Rod Sheeter <rshee...@google.com> Date: Wed Feb 7 09:37:06 2018 -0800 glyph ids to retain should most likely keep the glyph id not the codepoint diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 6bb0513c..470fa03e 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -55,7 +55,7 @@ glyph_ids_to_retain (hb_subset_face_t *face, hb_codepoint_t gid; if (face->cmap.get_nominal_glyph(cp, &gid)) { DEBUG_MSG(SUBSET, nullptr, "gid for U+%04X is %d", cp, gid); - hb_set_add(gids, cp); + hb_set_add(gids, gid); } else { DEBUG_MSG(SUBSET, nullptr, "Unable to resolve gid for U+%04X", cp); } commit 91428713bd6975b3bbfbdce54701f6aef5457121 Author: Rod Sheeter <rshee...@google.com> Date: Wed Feb 7 09:35:59 2018 -0800 Remove \ns leftover from fprintf diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index a9e11fc0..6bb0513c 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -54,10 +54,10 @@ glyph_ids_to_retain (hb_subset_face_t *face, while (hb_set_next(codepoints, &cp)) { hb_codepoint_t gid; if (face->cmap.get_nominal_glyph(cp, &gid)) { - DEBUG_MSG(SUBSET, nullptr, "gid for U+%04X is %d\n", cp, gid); + DEBUG_MSG(SUBSET, nullptr, "gid for U+%04X is %d", cp, gid); hb_set_add(gids, cp); } else { - DEBUG_MSG(SUBSET, nullptr, "Unable to resolve gid for U+%04X\n", cp); + DEBUG_MSG(SUBSET, nullptr, "Unable to resolve gid for U+%04X", cp); } } diff --git a/src/hb-subset.cc b/src/hb-subset.cc index dc0d4925..5849efd2 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -155,9 +155,9 @@ hb_subset (hb_subset_profile_t *profile, while (hb_set_next(plan->glyphs_to_retain, &old_gid)) { hb_codepoint_t new_gid; if (hb_subset_plan_new_gid_for_old_id(plan, old_gid, &new_gid)) { - DEBUG_MSG(SUBSET, nullptr, "Remap %d : %d\n", old_gid, new_gid); + DEBUG_MSG(SUBSET, nullptr, "Remap %d : %d", old_gid, new_gid); } else { - DEBUG_MSG(SUBSET, nullptr, "Remap %d : DOOM! No new ID\n", old_gid); + DEBUG_MSG(SUBSET, nullptr, "Remap %d : DOOM! No new ID", old_gid); } } // TODO: commit eb485bb9e90017abaf7dcdd7e39a82125d6807c3 Author: Rod Sheeter <rshee...@google.com> Date: Wed Feb 7 09:32:36 2018 -0800 Horrid hack to assign new gids. Use DEBUG_MSG over fprintf diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 5d23f88b..a9e11fc0 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -27,7 +27,24 @@ #include "hb-subset-plan.hh" #include "hb-subset-private.hh" -// TODO(Q1) map from old:new gid +hb_bool_t +hb_subset_plan_new_gid_for_old_id(hb_subset_plan_t *plan, + hb_codepoint_t old_gid, + hb_codepoint_t *new_gid) { + // TODO(Q1) lookup in map from old:new gid + // TEMPORARY: just loop over ids to retain and count up + hb_codepoint_t current = -1; + hb_codepoint_t count = 0; + while (hb_set_next(plan->glyphs_to_retain, ¤t)) { + if (old_gid == current) { + *new_gid = count; + return true; + } + count++; + } + return false; +} + hb_set_t * glyph_ids_to_retain (hb_subset_face_t *face, hb_set_t *codepoints) @@ -37,13 +54,15 @@ glyph_ids_to_retain (hb_subset_face_t *face, while (hb_set_next(codepoints, &cp)) { hb_codepoint_t gid; if (face->cmap.get_nominal_glyph(cp, &gid)) { - // TODO(Q1) a nice way to turn on/off logs - fprintf(stderr, "gid for U+%04X is %d\n", cp, gid); + DEBUG_MSG(SUBSET, nullptr, "gid for U+%04X is %d\n", cp, gid); hb_set_add(gids, cp); } else { - fprintf(stderr, "Unable to resolve gid for U+%04X\n", cp); + DEBUG_MSG(SUBSET, nullptr, "Unable to resolve gid for U+%04X\n", cp); } } + + // TODO(Q1) expand with glyphs that make up complex glyphs + // TODO expand with glyphs reached by G* return gids; } diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index 6e94a76f..549c87e2 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -44,6 +44,11 @@ hb_subset_plan_create (hb_subset_face_t *face, hb_subset_profile_t *profile, hb_subset_input_t *input); +hb_bool_t +hb_subset_plan_new_gid_for_old_id(hb_subset_plan_t *plan, + hb_codepoint_t old_gid, + hb_codepoint_t *new_gid /* OUT */); + hb_subset_plan_t * hb_subset_plan_get_empty (); diff --git a/src/hb-subset.cc b/src/hb-subset.cc index e8b87ca3..dc0d4925 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -151,6 +151,15 @@ hb_subset (hb_subset_profile_t *profile, hb_subset_plan_t *plan = hb_subset_plan_create (face, profile, input); + hb_codepoint_t old_gid = -1; + while (hb_set_next(plan->glyphs_to_retain, &old_gid)) { + hb_codepoint_t new_gid; + if (hb_subset_plan_new_gid_for_old_id(plan, old_gid, &new_gid)) { + DEBUG_MSG(SUBSET, nullptr, "Remap %d : %d\n", old_gid, new_gid); + } else { + DEBUG_MSG(SUBSET, nullptr, "Remap %d : DOOM! No new ID\n", old_gid); + } + } // TODO: // - Create initial header + table directory // - Loop through the set of tables to be kept: commit 8b80cbb1dd13e2870a956825f5dafc4419b44200 Author: Rod Sheeter <rshee...@google.com> Date: Wed Feb 7 09:31:31 2018 -0800 Add a subset debug category diff --git a/src/hb-debug.hh b/src/hb-debug.hh index 6c425f7b..c244347b 100644 --- a/src/hb-debug.hh +++ b/src/hb-debug.hh @@ -396,6 +396,18 @@ struct hb_no_trace_t { #define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace #endif +#ifndef HB_DEBUG_SUBSET +#define HB_DEBUG_SUBSET (HB_DEBUG+0) +#endif +#if HB_DEBUG_SUBSET +#define TRACE_SUBSET(this) \ + hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + " "); +#else +#define TRACE_SUBSET(this) hb_no_trace_t<bool> trace +#endif + #ifndef HB_DEBUG_WOULD_APPLY #define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0) #endif @@ -415,6 +427,7 @@ struct hb_no_trace_t { HB_DEBUG_COLLECT_GLYPHS + \ HB_DEBUG_SANITIZE + \ HB_DEBUG_SERIALIZE + \ + HB_DEBUG_SUBSET + \ HB_DEBUG_WOULD_APPLY + \ 0) #endif commit ee433d36fa544c3138718cc3f796b29e6df8a195 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Feb 7 12:30:18 2018 -0500 [aat] Set debug lookup_index diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh index a421a4cf..e0f59a4a 100644 --- a/src/hb-aat-layout-common-private.hh +++ b/src/hb-aat-layout-common-private.hh @@ -713,6 +713,8 @@ struct hb_aat_apply_context_t : sanitizer.start_processing (); } + inline void set_lookup_index (unsigned int i) { lookup_index = i; } + inline ~hb_aat_apply_context_t (void) { sanitizer.end_processing (); diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index f16f6a4a..f8209a60 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -617,6 +617,8 @@ struct Chain { subtable->apply (c); subtable = &StructAfter<ChainSubtable> (*subtable); + + c->set_lookup_index (c->lookup_index + 1); } } @@ -670,6 +672,7 @@ struct morx inline void apply (hb_aat_apply_context_t *c) const { + c->set_lookup_index (0); const Chain *chain = chains; unsigned int count = chainCount; for (unsigned int i = 0; i < count; i++) commit 38df1ec8e0b457be9140c67e2c5c19153714d90e Author: Rod Sheeter <rshee...@google.com> Date: Wed Feb 7 07:58:58 2018 -0800 TEMPORARY: remove HB_INTERNAL from null pool so subset builds again diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 04e4a4e1..959f743b 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -134,7 +134,9 @@ static inline Type& StructAfter(TObject &X) #define HB_NULL_POOL_SIZE 264 static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE."); -extern HB_INTERNAL const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]; +// TODO add back HB_INTERNAL once we figure out how to not have that break +// subset compile +extern const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]; /* Generic nul-content Null objects. */ template <typename Type> commit 53aa0e95420c5c3bfe8af21cf7956535d35b06e6 Author: Garret Rieger <grie...@google.com> Date: Tue Feb 6 17:05:22 2018 -0800 Add an instance of glyf::accelerator_t to hb-subset-glyf. diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc index 099f506c..5a3dff6d 100644 --- a/src/hb-subset-glyf.cc +++ b/src/hb-subset-glyf.cc @@ -24,6 +24,7 @@ * Google Author(s): Garret Rieger */ +#include "hb-ot-glyf-table.hh" #include "hb-subset-glyf.hh" /** @@ -36,10 +37,16 @@ **/ bool hb_subset_glyf (hb_subset_plan_t *plan, - hb_blob_t *glyf, - hb_blob_t **glyf_prime /* OUT */) + hb_face_t *face, + hb_blob_t **glyf_prime /* OUT */) { - *glyf_prime = hb_blob_get_empty (); + OT::glyf::accelerator_t glyf_accelerator; + glyf_accelerator.init(face); + + // TODO + glyf_accelerator.fini(); + + *glyf_prime = hb_blob_get_empty (); return true; } diff --git a/src/hb-subset-glyf.hh b/src/hb-subset-glyf.hh index 8bb0d864..fd217e79 100644 --- a/src/hb-subset-glyf.hh +++ b/src/hb-subset-glyf.hh @@ -31,7 +31,7 @@ bool hb_subset_glyf (hb_subset_plan_t *plan, - hb_blob_t *glyf, + hb_face_t *face, hb_blob_t **glyf_prime /* OUT */); #endif /* HB_SUBSET_GLYF_HH */ diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 7108eb87..e8b87ca3 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -160,15 +160,13 @@ hb_subset (hb_subset_profile_t *profile, bool success = true; - hb_blob_t *glyf = hb_face_reference_table (face->face, HB_OT_TAG_glyf); hb_blob_t *glyf_prime = nullptr; - if (hb_subset_glyf (plan, glyf, &glyf_prime)) { + if (hb_subset_glyf (plan, face->face, &glyf_prime)) { // TODO: write new glyf to new face. } else { success = false; } hb_blob_destroy (glyf_prime); - hb_blob_destroy (glyf); *result = hb_face_reference_blob(face->face); hb_subset_plan_destroy (plan); commit ef62dfed3fc7cfad7f7ce9292cb3bd1616f09384 Author: Rod Sheeter <rshee...@google.com> Date: Tue Feb 6 17:12:17 2018 -0800 add back assert_pod diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh index eb4147dc..31fceb47 100644 --- a/src/hb-subset-private.hh +++ b/src/hb-subset-private.hh @@ -45,6 +45,7 @@ struct hb_subset_input_t { struct hb_subset_face_t { hb_object_header_t header; + ASSERT_POD (); hb_face_t *face; OT::cmap::accelerator_t cmap; commit d0ce3c66e2af2785203f7bbb1d4abca5c226045d Author: Rod Sheeter <rshee...@google.com> Date: Tue Feb 6 16:58:35 2018 -0800 Resolve codepoints:glyph ids. Does not compile; undefined reference to OT::_hb_NullPool diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 8111d519..5d23f88b 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -21,17 +21,30 @@ * 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 + * Google Author(s): Garret Rieger, Roderick Sheeter */ #include "hb-subset-plan.hh" #include "hb-subset-private.hh" +// TODO(Q1) map from old:new gid hb_set_t * -get_glyph_ids_from_cmap (hb_face_t *face, - hb_set_t *codepoints) +glyph_ids_to_retain (hb_subset_face_t *face, + hb_set_t *codepoints) { - return hb_set_get_empty (); + hb_codepoint_t cp = -1; + hb_set_t *gids = hb_set_create(); + while (hb_set_next(codepoints, &cp)) { + hb_codepoint_t gid; + if (face->cmap.get_nominal_glyph(cp, &gid)) { + // TODO(Q1) a nice way to turn on/off logs + fprintf(stderr, "gid for U+%04X is %d\n", cp, gid); + hb_set_add(gids, cp); + } else { + fprintf(stderr, "Unable to resolve gid for U+%04X\n", cp); + } + } + return gids; } /** @@ -45,12 +58,12 @@ get_glyph_ids_from_cmap (hb_face_t *face, * Since: 1.7.5 **/ hb_subset_plan_t * -hb_subset_plan_create (hb_face_t *face, +hb_subset_plan_create (hb_subset_face_t *face, hb_subset_profile_t *profile, hb_subset_input_t *input) { hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> (); - plan->glyphs_to_retain = get_glyph_ids_from_cmap (face, input->codepoints); + plan->glyphs_to_retain = glyph_ids_to_retain (face, input->codepoints); return plan; } diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index 54b1e651..6e94a76f 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -40,7 +40,7 @@ struct hb_subset_plan_t { typedef struct hb_subset_plan_t hb_subset_plan_t; hb_subset_plan_t * -hb_subset_plan_create (hb_face_t *face, +hb_subset_plan_create (hb_subset_face_t *face, hb_subset_profile_t *profile, hb_subset_input_t *input); diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh index b38ab0b2..eb4147dc 100644 --- a/src/hb-subset-private.hh +++ b/src/hb-subset-private.hh @@ -21,15 +21,21 @@ * 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 + * Google Author(s): Garret Rieger, Roderick Sheeter */ #ifndef HB_SUBSET_PRIVATE_HH #define HB_SUBSET_PRIVATE_HH -#include "hb-object-private.hh" + #include "hb-private.hh" +#include "hb-ot.h" + +#include "hb-font-private.hh" + +#include "hb-ot-cmap-table.hh" + struct hb_subset_input_t { hb_object_header_t header; ASSERT_POD (); @@ -37,4 +43,11 @@ struct hb_subset_input_t { hb_set_t *codepoints; }; +struct hb_subset_face_t { + hb_object_header_t header; + + hb_face_t *face; + OT::cmap::accelerator_t cmap; +}; + #endif /* HB_SUBSET_PRIVATE_HH */ diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 7b44d516..7108eb87 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -27,6 +27,7 @@ #include "hb-object-private.hh" #include "hb-private.hh" + #include "hb-subset-glyf.hh" #include "hb-subset-private.hh" #include "hb-subset-plan.hh" @@ -38,14 +39,6 @@ struct hb_subset_profile_t { ASSERT_POD (); }; -struct hb_subset_face_t { - hb_object_header_t header; - ASSERT_POD (); - - hb_face_t *face; -}; - - /** * hb_subset_profile_create: * @@ -119,6 +112,7 @@ hb_subset_face_create (hb_face_t *face) hb_subset_face_t *subset_face = hb_object_create<hb_subset_face_t> (); subset_face->face = hb_face_reference (face); + subset_face->cmap.init(face); return subset_face; } @@ -133,6 +127,7 @@ hb_subset_face_destroy (hb_subset_face_t *subset_face) { if (!hb_object_destroy (subset_face)) return; + subset_face->cmap.fini(); hb_face_destroy(subset_face->face); free (subset_face); } @@ -154,7 +149,7 @@ hb_subset (hb_subset_profile_t *profile, { if (!profile || !input || !face) return false; - hb_subset_plan_t *plan = hb_subset_plan_create (face->face, profile, input); + hb_subset_plan_t *plan = hb_subset_plan_create (face, profile, input); // TODO: // - Create initial header + table directory commit 6a45e5df24ccc59c5a39bf42323c9b550f49e16d Author: Garret Rieger <grie...@google.com> Date: Tue Feb 6 16:04:09 2018 -0800 Add skeleton of hb-subset-glyf, call if from hb_subset(...) diff --git a/src/Makefile.sources b/src/Makefile.sources index 0d5af324..f2821e3d 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -184,11 +184,13 @@ HB_ICU_headers = hb-icu.h # Sources for libharfbuzz-subset HB_SUBSET_sources = \ hb-subset.cc \ + hb-subset-glyf.cc \ hb-subset-plan.cc \ $(NULL) HB_SUBSET_headers = \ hb-subset.h \ + hb-subset-glyf.hh \ hb-subset-plan.hh \ hb-subset-private.hh \ $(NULL) diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc new file mode 100644 index 00000000..099f506c --- /dev/null +++ b/src/hb-subset-glyf.cc @@ -0,0 +1,45 @@ +/* + * 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 "hb-subset-glyf.hh" + +/** + * hb_subset_glyf: + * Subsets the glyph table according to a provided plan. + * + * Return value: subsetted glyf table. + * + * Since: 1.7.5 + **/ +bool +hb_subset_glyf (hb_subset_plan_t *plan, + hb_blob_t *glyf, + hb_blob_t **glyf_prime /* OUT */) +{ + *glyf_prime = hb_blob_get_empty (); + + return true; +} diff --git a/src/hb-subset-glyf.hh b/src/hb-subset-glyf.hh new file mode 100644 index 00000000..8bb0d864 --- /dev/null +++ b/src/hb-subset-glyf.hh @@ -0,0 +1,37 @@ +/* + * Copyright © 2018 Google + * + * 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_SUBSET_GLYF_H +#define HB_SUBSET_GLYF_H + +#include "hb-subset-plan.hh" + +bool +hb_subset_glyf (hb_subset_plan_t *plan, + hb_blob_t *glyf, + hb_blob_t **glyf_prime /* OUT */); + +#endif /* HB_SUBSET_GLYF_HH */ diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 6ae3ed7a..7b44d516 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -27,9 +27,12 @@ #include "hb-object-private.hh" #include "hb-private.hh" +#include "hb-subset-glyf.hh" #include "hb-subset-private.hh" #include "hb-subset-plan.hh" +#include "hb-ot-glyf-table.hh" + struct hb_subset_profile_t { hb_object_header_t header; ASSERT_POD (); @@ -160,8 +163,19 @@ hb_subset (hb_subset_profile_t *profile, // - copy the table into the output. // - Fix header + table directory. - *result = hb_face_reference_blob(face->face); + bool success = true; + hb_blob_t *glyf = hb_face_reference_table (face->face, HB_OT_TAG_glyf); + hb_blob_t *glyf_prime = nullptr; + if (hb_subset_glyf (plan, glyf, &glyf_prime)) { + // TODO: write new glyf to new face. + } else { + success = false; + } + hb_blob_destroy (glyf_prime); + hb_blob_destroy (glyf); + + *result = hb_face_reference_blob(face->face); hb_subset_plan_destroy (plan); - return true; + return success; } commit 31ec3c2ec41161c6ae75bc91d1c237bf2d245e37 Author: Garret Rieger <grie...@google.com> Date: Tue Feb 6 15:37:34 2018 -0800 Create a subset plan in hb_subset. diff --git a/src/hb-subset.cc b/src/hb-subset.cc index fe821e0a..6ae3ed7a 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -28,6 +28,7 @@ #include "hb-object-private.hh" #include "hb-private.hh" #include "hb-subset-private.hh" +#include "hb-subset-plan.hh" struct hb_subset_profile_t { hb_object_header_t header; @@ -150,6 +151,17 @@ hb_subset (hb_subset_profile_t *profile, { if (!profile || !input || !face) return false; + hb_subset_plan_t *plan = hb_subset_plan_create (face->face, profile, input); + + // TODO: + // - Create initial header + table directory + // - Loop through the set of tables to be kept: + // - Perform table specific subsetting if defined. + // - copy the table into the output. + // - Fix header + table directory. + *result = hb_face_reference_blob(face->face); + + hb_subset_plan_destroy (plan); return true; } commit 6c52d94fd11915b76e858bc45633ee60b8c1d8f4 Author: Rod Sheeter <rshee...@google.com> Date: Tue Feb 6 15:31:14 2018 -0800 capture the set of codepoints passed by --unicodes diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 2ec0efe3..67cfed19 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -43,6 +43,7 @@ struct subset_consumer_t const font_options_t *font_opts) { font = hb_font_reference (font_opts->get_font ()); + codepoints = hb_set_create(); } void consume_line (const char *text, @@ -50,6 +51,16 @@ struct subset_consumer_t const char *text_before, const char *text_after) { + // text appears to be a g_string when set by --unicodes + // TODO(Q1) are gunichar and hbcodepoint_t interchangeable? + // TODO(Q1) does this only get called with at least 1 codepoint? + gchar *c = (gchar *)text; + do { + gunichar cp = g_utf8_get_char(c); + hb_codepoint_t hb_cp = cp; // TODO(Q1) is this safe? + hb_set_add(codepoints, hb_cp); + g_print (" U+%04X %" G_GINT32_FORMAT "\n", cp, cp); + } while ((c = g_utf8_find_next_char(c, text + text_len)) != nullptr); } hb_bool_t @@ -80,16 +91,19 @@ struct subset_consumer_t { // TODO(Q1) check for errors from creates and such hb_subset_profile_t *subset_profile = hb_subset_profile_create(); - hb_subset_input_t *subset_input = hb_subset_input_create (hb_set_get_empty ()); + hb_subset_input_t *subset_input = hb_subset_input_create (codepoints); hb_face_t *face = hb_font_get_face (font); hb_subset_face_t *subset_face = hb_subset_face_create(face); + + hb_blob_t *result = nullptr; failed = !(hb_subset(subset_profile, subset_input, subset_face, &result) && write_file(options.output_file, result)); hb_subset_profile_destroy (subset_profile); hb_subset_input_destroy (subset_input); + hb_set_destroy (codepoints); hb_subset_face_destroy (subset_face); hb_blob_destroy (result); hb_font_destroy (font); @@ -101,6 +115,7 @@ struct subset_consumer_t private: output_options_t options; hb_font_t *font; + hb_set_t *codepoints; }; int commit 25e9173fe8446735f7e36ec963c7d3554c85631b Author: Garret Rieger <grie...@google.com> Date: Mon Feb 5 17:26:25 2018 -0800 Make hb-subset-plan private. diff --git a/src/Makefile.sources b/src/Makefile.sources index 5e1c4e4f..0d5af324 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -189,7 +189,7 @@ HB_SUBSET_sources = \ HB_SUBSET_headers = \ hb-subset.h \ - hb-subset-plan.h \ + hb-subset-plan.hh \ hb-subset-private.hh \ $(NULL) diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 7da9dae8..8111d519 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -24,15 +24,15 @@ * Google Author(s): Garret Rieger */ -#include "hb-private.hh" +#include "hb-subset-plan.hh" +#include "hb-subset-private.hh" -#include "hb-object-private.hh" - - -struct hb_subset_plan_t { - hb_object_header_t header; - ASSERT_POD (); -}; +hb_set_t * +get_glyph_ids_from_cmap (hb_face_t *face, + hb_set_t *codepoints) +{ + return hb_set_get_empty (); +} /** * hb_subset_plan_create: @@ -49,13 +49,17 @@ hb_subset_plan_create (hb_face_t *face, hb_subset_profile_t *profile, hb_subset_input_t *input) { - return hb_object_create<hb_subset_plan_t>(); + hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> (); + plan->glyphs_to_retain = get_glyph_ids_from_cmap (face, input->codepoints); + return plan; } hb_subset_plan_t * -hb_subset_plan_create_empty () +hb_subset_plan_get_empty () { - return hb_object_create<hb_subset_plan_t>(); + hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> (); + plan->glyphs_to_retain = hb_set_get_empty(); + return plan; } /** @@ -68,5 +72,6 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) { if (!hb_object_destroy (plan)) return; + hb_set_destroy (plan->glyphs_to_retain); free (plan); } diff --git a/src/hb-subset-plan.h b/src/hb-subset-plan.hh similarity index 86% rename from src/hb-subset-plan.h rename to src/hb-subset-plan.hh index 2fd46ae2..54b1e651 100644 --- a/src/hb-subset-plan.h +++ b/src/hb-subset-plan.hh @@ -24,26 +24,30 @@ * Google Author(s): Garret Rieger */ -#ifndef HB_H_IN -#error "Include <hb.h> instead." -#endif - #ifndef HB_SUBSET_PLAN_H #define HB_SUBSET_PLAN_H -HB_BEGIN_DECLS +#include "hb-private.hh" +#include "hb-object-private.hh" + +struct hb_subset_plan_t { + hb_object_header_t header; + ASSERT_POD (); + + hb_set_t *glyphs_to_retain; +}; typedef struct hb_subset_plan_t hb_subset_plan_t; -HB_EXTERN hb_subset_plan_t * +hb_subset_plan_t * hb_subset_plan_create (hb_face_t *face, hb_subset_profile_t *profile, hb_subset_input_t *input); -HB_EXTERN hb_subset_plan_t * -hb_subset_plan_create_empty (); +hb_subset_plan_t * +hb_subset_plan_get_empty (); -HB_EXTERN void +void hb_subset_plan_destroy (hb_subset_plan_t *plan); #endif /* HB_SUBSET_PLAN_PRIVATE_HH */ commit af46a4da5a47dd6e0dd98e1740f18e93c337e689 Author: Garret Rieger <grie...@google.com> Date: Mon Feb 5 17:14:46 2018 -0800 Move definition of hb_subset_input into hb-subset-private.hh. diff --git a/src/Makefile.sources b/src/Makefile.sources index eb9cd36a..5e1c4e4f 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -190,6 +190,7 @@ HB_SUBSET_sources = \ HB_SUBSET_headers = \ hb-subset.h \ hb-subset-plan.h \ + hb-subset-private.hh \ $(NULL) HB_GOBJECT_sources = hb-gobject-structs.cc diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 705c17f1..7da9dae8 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -40,7 +40,7 @@ struct hb_subset_plan_t { * to a provide profile and input. The plan describes * which tables and glyphs should be retained. * - * Return value: New plan with default settings. + * Return value: New subset plan. * * Since: 1.7.5 **/ diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh new file mode 100644 index 00000000..b38ab0b2 --- /dev/null +++ b/src/hb-subset-private.hh @@ -0,0 +1,40 @@ +/* + * 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_SUBSET_PRIVATE_HH +#define HB_SUBSET_PRIVATE_HH + +#include "hb-object-private.hh" +#include "hb-private.hh" + +struct hb_subset_input_t { + hb_object_header_t header; + ASSERT_POD (); + + hb_set_t *codepoints; +}; + +#endif /* HB_SUBSET_PRIVATE_HH */ diff --git a/src/hb-subset.cc b/src/hb-subset.cc index f56217f6..fe821e0a 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -25,23 +25,15 @@ * Google Author(s): Garret Rieger, Rod Sheeter */ -#include "hb-private.hh" - #include "hb-object-private.hh" - +#include "hb-private.hh" +#include "hb-subset-private.hh" struct hb_subset_profile_t { hb_object_header_t header; ASSERT_POD (); }; -struct hb_subset_input_t { - hb_object_header_t header; - ASSERT_POD (); - - hb_set_t *codepoints; -}; - struct hb_subset_face_t { hb_object_header_t header; ASSERT_POD (); commit 7481f0ce21489d2b19b2e33d05358736ddee20bf Author: Garret Rieger <grie...@google.com> Date: Mon Feb 5 16:05:12 2018 -0800 Add codepoints to subset input. diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 62f7f0ad..f56217f6 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -38,6 +38,8 @@ struct hb_subset_profile_t { struct hb_subset_input_t { hb_object_header_t header; ASSERT_POD (); + + hb_set_t *codepoints; }; struct hb_subset_face_t { @@ -82,9 +84,14 @@ hb_subset_profile_destroy (hb_subset_profile_t *profile) * Since: 1.7.5 **/ hb_subset_input_t * -hb_subset_input_create() +hb_subset_input_create (hb_set_t *codepoints) { - return hb_object_create<hb_subset_input_t>(); + if (unlikely (!codepoints)) + codepoints = hb_set_get_empty(); + + hb_subset_input_t *input = hb_object_create<hb_subset_input_t>(); + input->codepoints = hb_set_reference(codepoints); + return input; } /** @@ -97,6 +104,7 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input) { if (!hb_object_destroy (subset_input)) return; + hb_set_destroy (subset_input->codepoints); free (subset_input); } @@ -108,7 +116,7 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input) * Since: 1.7.5 **/ hb_subset_face_t * -hb_subset_face_create(hb_face_t *face) +hb_subset_face_create (hb_face_t *face) { if (unlikely (!face)) face = hb_face_get_empty(); @@ -125,7 +133,7 @@ hb_subset_face_create(hb_face_t *face) * Since: 1.7.5 **/ void -hb_subset_face_destroy(hb_subset_face_t *subset_face) +hb_subset_face_destroy (hb_subset_face_t *subset_face) { if (!hb_object_destroy (subset_face)) return; @@ -143,10 +151,10 @@ hb_subset_face_destroy(hb_subset_face_t *subset_face) * Subsets a font according to provided profile and input. **/ hb_bool_t -hb_subset(hb_subset_profile_t *profile, - hb_subset_input_t *input, - hb_subset_face_t *face, - hb_blob_t **result /* OUT */) +hb_subset (hb_subset_profile_t *profile, + hb_subset_input_t *input, + hb_subset_face_t *face, + hb_blob_t **result /* OUT */) { if (!profile || !input || !face) return false; diff --git a/src/hb-subset.h b/src/hb-subset.h index 969cf5d2..47127e03 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -53,7 +53,7 @@ hb_subset_profile_destroy (hb_subset_profile_t *profile); typedef struct hb_subset_input_t hb_subset_input_t; HB_EXTERN hb_subset_input_t * -hb_subset_input_create (); +hb_subset_input_create (hb_set_t *codepoints); HB_EXTERN void hb_subset_input_destroy (hb_subset_input_t *subset_input); diff --git a/test/api/test-subset.c b/test/api/test-subset.c index 33a1ef29..4841af62 100644 --- a/test/api/test-subset.c +++ b/test/api/test-subset.c @@ -42,7 +42,7 @@ test_subset (void) hb_face_t *face = hb_face_create(font_blob, 0); hb_subset_profile_t *profile = hb_subset_profile_create(); - hb_subset_input_t *input = hb_subset_input_create(); + hb_subset_input_t *input = hb_subset_input_create (hb_set_get_empty ()); hb_subset_face_t *subset_face = hb_subset_face_create(face); hb_blob_t *output; diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 27398ab0..2ec0efe3 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -80,7 +80,7 @@ struct subset_consumer_t { // TODO(Q1) check for errors from creates and such hb_subset_profile_t *subset_profile = hb_subset_profile_create(); - hb_subset_input_t *subset_input = hb_subset_input_create(); + hb_subset_input_t *subset_input = hb_subset_input_create (hb_set_get_empty ()); hb_face_t *face = hb_font_get_face (font); hb_subset_face_t *subset_face = hb_subset_face_create(face); commit 1cfe650f020cf440bf157daa9907bffd6e35bd7a Author: Garret Rieger <grie...@google.com> Date: Mon Feb 5 15:22:30 2018 -0800 Add a basic sketch of hb-subset-plan. diff --git a/src/Makefile.sources b/src/Makefile.sources index 0b9beb96..eb9cd36a 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -184,10 +184,12 @@ HB_ICU_headers = hb-icu.h # Sources for libharfbuzz-subset HB_SUBSET_sources = \ hb-subset.cc \ + hb-subset-plan.cc \ $(NULL) HB_SUBSET_headers = \ hb-subset.h \ + hb-subset-plan.h \ $(NULL) HB_GOBJECT_sources = hb-gobject-structs.cc diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc new file mode 100644 index 00000000..705c17f1 --- /dev/null +++ b/src/hb-subset-plan.cc @@ -0,0 +1,72 @@ +/* + * 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 "hb-private.hh" + +#include "hb-object-private.hh" + + +struct hb_subset_plan_t { + hb_object_header_t header; + ASSERT_POD (); +}; + +/** + * hb_subset_plan_create: + * Computes a plan for subsetting the supplied face according + * to a provide profile and input. The plan describes + * which tables and glyphs should be retained. + * + * Return value: New plan with default settings. + * + * Since: 1.7.5 + **/ +hb_subset_plan_t * +hb_subset_plan_create (hb_face_t *face, + hb_subset_profile_t *profile, + hb_subset_input_t *input) +{ + return hb_object_create<hb_subset_plan_t>(); +} + +hb_subset_plan_t * +hb_subset_plan_create_empty () +{ + return hb_object_create<hb_subset_plan_t>(); +} + +/** + * hb_subset_plan_destroy: + * + * Since: 1.7.5 + **/ +void +hb_subset_plan_destroy (hb_subset_plan_t *plan) +{ + if (!hb_object_destroy (plan)) return; + + free (plan); +} diff --git a/src/hb-subset-plan.h b/src/hb-subset-plan.h new file mode 100644 index 00000000..2fd46ae2 --- /dev/null +++ b/src/hb-subset-plan.h @@ -0,0 +1,49 @@ +/* + * Copyright © 2018 Google + * + * 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_H_IN +#error "Include <hb.h> instead." +#endif + +#ifndef HB_SUBSET_PLAN_H +#define HB_SUBSET_PLAN_H + +HB_BEGIN_DECLS + +typedef struct hb_subset_plan_t hb_subset_plan_t; + +HB_EXTERN hb_subset_plan_t * +hb_subset_plan_create (hb_face_t *face, + hb_subset_profile_t *profile, + hb_subset_input_t *input); + +HB_EXTERN hb_subset_plan_t * +hb_subset_plan_create_empty (); + +HB_EXTERN void +hb_subset_plan_destroy (hb_subset_plan_t *plan); + +#endif /* HB_SUBSET_PLAN_PRIVATE_HH */ _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/harfbuzz