remove empty lookup subtables

Added a variant of subset_offset_array which takes an extra arg passed to serialize_subset for this impl.
Added a new api test "test-subset-gpos" for this.
This commit is contained in:
ariza 2020-01-18 16:35:52 -08:00 committed by Garret Rieger
parent a3cf4ae080
commit 72cbfb9059
7 changed files with 139 additions and 10 deletions

View File

@ -155,6 +155,43 @@ struct subset_offset_array_t
const void *_dest_base;
};
template<typename OutputArray, typename Arg>
struct subset_offset_array_arg_t
{
subset_offset_array_arg_t
(hb_subset_context_t *subset_context,
OutputArray& out,
const void *src_base,
const void *dest_base,
Arg &&arg)
: _subset_context(subset_context), _out (out), _src_base (src_base), _dest_base (dest_base), _arg (arg) {}
template <typename T>
bool
operator ()
(T&& offset)
{
auto *o = _out.serialize_append (_subset_context->serializer);
if (unlikely (!o)) return false;
auto snap = _subset_context->serializer->snapshot ();
bool ret = o->serialize_subset (_subset_context, offset, _src_base, _dest_base, _arg);
if (!ret)
{
_out.pop ();
_subset_context->serializer->revert (snap);
}
return ret;
}
private:
hb_subset_context_t *_subset_context;
OutputArray &_out;
const void *_src_base;
const void *_dest_base;
Arg &&_arg;
};
/*
* Helper to subset an array of offsets. Subsets the thing pointed to by each offset
* and discards the offset in the array if the subset operation results in an empty
@ -172,6 +209,19 @@ struct
{
return subset_offset_array_t<OutputArray> (subset_context, out, src_base, dest_base);
}
/* Variant with one extra argument passed to serialize_subset */
template<typename OutputArray, typename Arg>
subset_offset_array_arg_t<OutputArray, Arg>
operator ()
(hb_subset_context_t *subset_context,
OutputArray& out,
const void *src_base,
const void *dest_base,
Arg &&arg) const
{
return subset_offset_array_arg_t<OutputArray, Arg> (subset_context, out, src_base, dest_base, arg);
}
}
HB_FUNCOBJ (subset_offset_array);
@ -1006,17 +1056,17 @@ struct Lookup
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
out->lookupType = lookupType;
out->lookupFlag = lookupFlag;
/* Subset the actual subtables. */
/* TODO Drop empty ones, either by calling intersects() beforehand,
* or just dropping null offsets after. */
const OffsetArrayOf<TSubTable>& subtables = get_subtables<TSubTable> ();
OffsetArrayOf<TSubTable>& out_subtables = out->get_subtables<TSubTable> ();
unsigned int count = subTable.len;
for (unsigned int i = 0; i < count; i++)
out_subtables[i].serialize_subset (c, subtables[i], this, out, get_type ());
const hb_set_t *glyphset = c->plan->glyphset ();
unsigned int lookup_type = get_type ();
+ hb_iter (get_subtables <TSubTable> ())
| hb_filter ([=] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
| hb_apply (subset_offset_array (c, out->get_subtables<TSubTable> (), this, out, lookup_type))
;
return_trace (true);
}

View File

@ -1931,6 +1931,12 @@ struct PosLookupSubTable
}
}
bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
{
hb_intersects_context_t c (glyphs);
return dispatch (&c, lookup_type);
}
protected:
union {
SinglePos single;

View File

@ -1324,6 +1324,12 @@ struct SubstLookupSubTable
}
}
bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
{
hb_intersects_context_t c (glyphs);
return dispatch (&c, lookup_type);
}
protected:
union {
SingleSubst single;

View File

@ -56,6 +56,7 @@ TEST_PROGS = \
test-subset-hvar \
test-subset-vvar \
test-subset-sbix \
test-subset-gpos \
test-unicode \
test-version \
test-subset-nameids \
@ -77,6 +78,7 @@ test_subset_hvar_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_subset_vvar_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_subset_sbix_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_unicode_CPPFLAGS = \
$(AM_CPPFLAGS) \

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,65 @@
/*
* Copyright © 2020 Adobe 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.
*
* Adobe Author(s): Michiharu Ariza
*/
#include "hb-test.h"
#include "hb-subset-test.h"
/* Unit tests for GPOS subsetting */
static void
test_subset_gpos_lookup_subtable (void)
{
hb_face_t *face_pwa = hb_test_open_font_file ("fonts/Roboto-Regular-gpos-.aw.ttf");
hb_face_t *face_wa = hb_test_open_font_file ("fonts/Roboto-Regular-gpos-aw.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_pwa_subset;
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'w');
hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'P', 'O', 'S'));
face_pwa_subset = hb_subset_test_create_subset (face_pwa, input);
hb_set_destroy (codepoints);
hb_subset_test_check (face_wa, face_pwa_subset, HB_TAG ('G','P','O','S'));
hb_face_destroy (face_pwa_subset);
hb_face_destroy (face_pwa);
hb_face_destroy (face_wa);
}
int
main (int argc, char **argv)
{
hb_test_init (&argc, &argv);
hb_test_add (test_subset_gpos_lookup_subtable);
return hb_test_run ();
}