[layout] hb_ot_layout_lookup_get_alternates, a new API

An API to retrieve one-to-one alternates from a given GSUB lookup index.
This commit is contained in:
Ebrahim Byagowi 2020-06-16 21:05:16 -04:00
parent a4955e21fd
commit 1348a2c865
7 changed files with 130 additions and 0 deletions

View File

@ -574,6 +574,7 @@ hb_ot_layout_language_get_feature_indexes
hb_ot_layout_language_get_feature_tags hb_ot_layout_language_get_feature_tags
hb_ot_layout_language_get_required_feature hb_ot_layout_language_get_required_feature
hb_ot_layout_lookup_collect_glyphs hb_ot_layout_lookup_collect_glyphs
hb_ot_layout_lookup_get_alternates
hb_ot_layout_lookup_substitute_closure hb_ot_layout_lookup_substitute_closure
hb_ot_layout_lookups_substitute_closure hb_ot_layout_lookups_substitute_closure
hb_ot_layout_lookup_would_substitute hb_ot_layout_lookup_would_substitute

View File

@ -522,6 +522,8 @@ struct MultipleSubst
struct AlternateSet struct AlternateSet
{ {
friend struct AlternateSubstFormat1;
bool intersects (const hb_set_t *glyphs) const bool intersects (const hb_set_t *glyphs) const
{ return hb_any (alternates, glyphs); } { return hb_any (alternates, glyphs); }
@ -628,6 +630,14 @@ struct AlternateSubstFormat1
bool would_apply (hb_would_apply_context_t *c) const bool would_apply (hb_would_apply_context_t *c) const
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
const ArrayOf<HBGlyphID> &get_alternates (hb_codepoint_t gid) const
{
unsigned index = (this+coverage).get_coverage (gid);
if (index == NOT_COVERED) return Null (ArrayOf<HBGlyphID>);
return (this+alternateSet[index]).alternates;
}
bool apply (hb_ot_apply_context_t *c) const bool apply (hb_ot_apply_context_t *c) const
{ {
TRACE_APPLY (this); TRACE_APPLY (this);
@ -715,6 +725,14 @@ struct AlternateSubst
} }
} }
const ArrayOf<HBGlyphID> &get_alternates (hb_codepoint_t gid) const
{
switch (u.format) {
case 1: return u.format1.get_alternates (gid);
default:return Null (ArrayOf<HBGlyphID>);
}
}
template <typename context_t, typename ...Ts> template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{ {
@ -1463,6 +1481,18 @@ struct SubstLookup : Lookup
substitute_glyphs_list)); substitute_glyphs_list));
} }
const ArrayOf<HBGlyphID> &get_alternates (hb_codepoint_t gid) const
{
if (get_type () != SubTable::Alternate) return Null (ArrayOf<HBGlyphID>);
unsigned size = get_subtable_count ();
for (unsigned i = 0; i < size; ++i)
{
const ArrayOf<HBGlyphID> &alternates = get_subtable (i).u.alternate.get_alternates (gid);
if (alternates.len) return alternates;
}
return Null (ArrayOf<HBGlyphID>);
}
bool serialize_alternate (hb_serialize_context_t *c, bool serialize_alternate (hb_serialize_context_t *c,
uint32_t lookup_props, uint32_t lookup_props,
hb_sorted_array_t<const HBGlyphID> glyphs, hb_sorted_array_t<const HBGlyphID> glyphs,

View File

@ -1969,4 +1969,41 @@ hb_ot_layout_get_baseline (hb_font_t *font,
return result; return result;
} }
#endif #endif
/**
* hb_ot_layout_lookup_get_alternates:
* @face: a face.
* @lookup_index: index of the feature lookup to query.
* @glyph: a glyph id.
* @start_offset: starting offset.
* @alternate_count: (inout) (allow-none): Input = the maximum number of alternate glyphs to return;
* Output = the actual number of alternate glyphs returned (may be zero).
* @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer.
* Alternate glyphs associated with the glyph id.
*
* Fetches alternates of a glyph from a given GSUB lookup index.
*
* Return value: total number of alternates found in the specific lookup index for the given glyph id.
*
* Since: REPLACEME
**/
HB_EXTERN unsigned
hb_ot_layout_lookup_get_alternates (hb_face_t *face,
unsigned lookup_index,
hb_codepoint_t glyph,
unsigned start_offset,
unsigned *alternate_count /* IN/OUT */,
hb_codepoint_t *alternate_glyphs)
{
const OT::SubstLookup &lookup = face->table.GSUB->table->get_lookup (lookup_index);
const OT::ArrayOf<OT::HBGlyphID> &alternates = lookup.get_alternates (glyph);
if (alternate_count)
{
+ alternates.sub_array (start_offset, alternate_count)
| hb_sink (hb_array (alternate_glyphs, *alternate_count))
;
}
return alternates.len;
}
#endif #endif

View File

@ -449,6 +449,13 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag, hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */); hb_position_t *coord /* OUT. May be NULL. */);
HB_EXTERN unsigned
hb_ot_layout_lookup_get_alternates (hb_face_t *face,
unsigned lookup_index,
hb_codepoint_t glyph,
unsigned start_offset,
unsigned *alternate_count /* IN/OUT */,
hb_codepoint_t *alternate_glyphs);
HB_END_DECLS HB_END_DECLS

View File

@ -40,6 +40,7 @@ TEST_PROGS = \
test-font \ test-font \
test-map \ test-map \
test-object \ test-object \
test-ot-alternates \
test-ot-color \ test-ot-color \
test-ot-face \ test-ot-face \
test-ot-glyphname \ test-ot-glyphname \

View File

@ -16,6 +16,7 @@ tests = [
'test-font.c', 'test-font.c',
'test-map.c', 'test-map.c',
'test-object.c', 'test-object.c',
'test-ot-alternates.c',
'test-ot-color.c', 'test-ot-color.c',
'test-ot-face.c', 'test-ot-face.c',
'test-ot-glyphname.c', 'test-ot-glyphname.c',

View File

@ -0,0 +1,53 @@
/*
* Copyright © 2020 Ebrahim Byagowi
*
* 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-test.h"
#include <hb.h>
#include <hb-ot.h>
static void
test_ot_layout_lookup_get_alternates (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/SourceSansPro-Regular.otf");
hb_codepoint_t alternates[3];
unsigned alternates_count = 3;
g_assert_cmpuint (7, ==, hb_ot_layout_lookup_get_alternates (face, 1, 1091, 2, &alternates_count, alternates));
g_assert_cmpuint (3, ==, alternates_count);
g_assert_cmpuint (1606, ==, alternates[0]);
g_assert_cmpuint (1578, ==, alternates[1]);
g_assert_cmpuint (1592, ==, alternates[2]);
hb_face_destroy (face);
}
int
main (int argc, char **argv)
{
hb_test_init (&argc, &argv);
hb_test_add (test_ot_layout_lookup_get_alternates);
return hb_test_run ();
}