commit
a512ca8eae
|
@ -574,6 +574,7 @@ hb_ot_layout_language_get_feature_indexes
|
|||
hb_ot_layout_language_get_feature_tags
|
||||
hb_ot_layout_language_get_required_feature
|
||||
hb_ot_layout_lookup_collect_glyphs
|
||||
hb_ot_layout_lookup_get_glyph_alternates
|
||||
hb_ot_layout_lookup_substitute_closure
|
||||
hb_ot_layout_lookups_substitute_closure
|
||||
hb_ot_layout_lookup_would_substitute
|
||||
|
|
|
@ -373,10 +373,6 @@ struct hb_no_trace_t {
|
|||
#define HB_DEBUG_FT (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
#ifndef HB_DEBUG_GET_COVERAGE
|
||||
#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
#ifndef HB_DEBUG_OBJECT
|
||||
#define HB_DEBUG_OBJECT (HB_DEBUG+0)
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* Dispatch
|
||||
*/
|
||||
|
||||
template <typename Context, typename Return, unsigned int MaxDebugDepth>
|
||||
template <typename Context, typename Return=hb_empty_t, unsigned int MaxDebugDepth=0>
|
||||
struct hb_dispatch_context_t
|
||||
{
|
||||
private:
|
||||
|
@ -43,6 +43,8 @@ struct hb_dispatch_context_t
|
|||
const Context* thiz () const { return static_cast<const Context *> (this); }
|
||||
Context* thiz () { return static_cast< Context *> (this); }
|
||||
public:
|
||||
const char *get_name () { return "UNKNOWN"; }
|
||||
static constexpr unsigned debug_depth = 0;
|
||||
static constexpr unsigned max_debug_depth = MaxDebugDepth;
|
||||
typedef Return return_t;
|
||||
template <typename T, typename F>
|
||||
|
|
|
@ -151,9 +151,8 @@ struct hb_subset_layout_context_t :
|
|||
};
|
||||
|
||||
struct hb_collect_variation_indices_context_t :
|
||||
hb_dispatch_context_t<hb_collect_variation_indices_context_t, hb_empty_t, 0>
|
||||
hb_dispatch_context_t<hb_collect_variation_indices_context_t>
|
||||
{
|
||||
const char *get_name () { return "CLOSURE_LAYOUT_VARIATION_IDXES"; }
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { obj.collect_variation_indices (this); return hb_empty_t (); }
|
||||
static return_t default_return_value () { return hb_empty_t (); }
|
||||
|
@ -161,15 +160,13 @@ struct hb_collect_variation_indices_context_t :
|
|||
hb_set_t *layout_variation_indices;
|
||||
const hb_set_t *glyph_set;
|
||||
const hb_map_t *gpos_lookups;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_,
|
||||
const hb_set_t *glyph_set_,
|
||||
const hb_map_t *gpos_lookups_) :
|
||||
layout_variation_indices (layout_variation_indices_),
|
||||
glyph_set (glyph_set_),
|
||||
gpos_lookups (gpos_lookups_),
|
||||
debug_depth (0) {}
|
||||
gpos_lookups (gpos_lookups_) {}
|
||||
};
|
||||
|
||||
template<typename OutputArray>
|
||||
|
|
|
@ -556,6 +556,20 @@ struct AlternateSet
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
unsigned
|
||||
get_alternates (unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
||||
{
|
||||
if (alternates.len && alternate_count)
|
||||
{
|
||||
+ alternates.sub_array (start_offset, alternate_count)
|
||||
| hb_sink (hb_array (alternate_glyphs, *alternate_count))
|
||||
;
|
||||
}
|
||||
return alternates.len;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
|
@ -628,6 +642,14 @@ struct AlternateSubstFormat1
|
|||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
||||
|
||||
unsigned
|
||||
get_glyph_alternates (hb_codepoint_t gid,
|
||||
unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
||||
{ return (this+alternateSet[(this+coverage).get_coverage (gid)])
|
||||
.get_alternates (start_offset, alternate_count, alternate_glyphs); }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
|
|
@ -42,26 +42,22 @@ namespace OT {
|
|||
|
||||
|
||||
struct hb_intersects_context_t :
|
||||
hb_dispatch_context_t<hb_intersects_context_t, bool, 0>
|
||||
hb_dispatch_context_t<hb_intersects_context_t, bool>
|
||||
{
|
||||
const char *get_name () { return "INTERSECTS"; }
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { return obj.intersects (this->glyphs); }
|
||||
static return_t default_return_value () { return false; }
|
||||
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||
|
||||
const hb_set_t *glyphs;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_intersects_context_t (const hb_set_t *glyphs_) :
|
||||
glyphs (glyphs_),
|
||||
debug_depth (0) {}
|
||||
glyphs (glyphs_) {}
|
||||
};
|
||||
|
||||
struct hb_closure_context_t :
|
||||
hb_dispatch_context_t<hb_closure_context_t, hb_empty_t, 0>
|
||||
hb_dispatch_context_t<hb_closure_context_t>
|
||||
{
|
||||
const char *get_name () { return "CLOSURE"; }
|
||||
typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { obj.closure (this); return hb_empty_t (); }
|
||||
|
@ -102,7 +98,6 @@ struct hb_closure_context_t :
|
|||
hb_set_t output[1];
|
||||
recurse_func_t recurse_func;
|
||||
unsigned int nesting_level_left;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_closure_context_t (hb_face_t *face_,
|
||||
hb_set_t *glyphs_,
|
||||
|
@ -112,7 +107,6 @@ struct hb_closure_context_t :
|
|||
glyphs (glyphs_),
|
||||
recurse_func (nullptr),
|
||||
nesting_level_left (nesting_level_left_),
|
||||
debug_depth (0),
|
||||
done_lookups (done_lookups_),
|
||||
lookup_count (0)
|
||||
{}
|
||||
|
@ -134,9 +128,8 @@ struct hb_closure_context_t :
|
|||
};
|
||||
|
||||
struct hb_closure_lookups_context_t :
|
||||
hb_dispatch_context_t<hb_closure_lookups_context_t, hb_empty_t, 0>
|
||||
hb_dispatch_context_t<hb_closure_lookups_context_t>
|
||||
{
|
||||
const char *get_name () { return "CLOSURE_LOOKUPS"; }
|
||||
typedef return_t (*recurse_func_t) (hb_closure_lookups_context_t *c, unsigned lookup_index);
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { obj.closure_lookups (this); return hb_empty_t (); }
|
||||
|
@ -177,7 +170,6 @@ struct hb_closure_lookups_context_t :
|
|||
const hb_set_t *glyphs;
|
||||
recurse_func_t recurse_func;
|
||||
unsigned int nesting_level_left;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_closure_lookups_context_t (hb_face_t *face_,
|
||||
const hb_set_t *glyphs_,
|
||||
|
@ -188,7 +180,6 @@ struct hb_closure_lookups_context_t :
|
|||
glyphs (glyphs_),
|
||||
recurse_func (nullptr),
|
||||
nesting_level_left (nesting_level_left_),
|
||||
debug_depth (0),
|
||||
visited_lookups (visited_lookups_),
|
||||
inactive_lookups (inactive_lookups_),
|
||||
lookup_count (0) {}
|
||||
|
@ -202,9 +193,8 @@ struct hb_closure_lookups_context_t :
|
|||
};
|
||||
|
||||
struct hb_would_apply_context_t :
|
||||
hb_dispatch_context_t<hb_would_apply_context_t, bool, 0>
|
||||
hb_dispatch_context_t<hb_would_apply_context_t, bool>
|
||||
{
|
||||
const char *get_name () { return "WOULD_APPLY"; }
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { return obj.would_apply (this); }
|
||||
static return_t default_return_value () { return false; }
|
||||
|
@ -214,7 +204,6 @@ struct hb_would_apply_context_t :
|
|||
const hb_codepoint_t *glyphs;
|
||||
unsigned int len;
|
||||
bool zero_context;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_would_apply_context_t (hb_face_t *face_,
|
||||
const hb_codepoint_t *glyphs_,
|
||||
|
@ -223,15 +212,12 @@ struct hb_would_apply_context_t :
|
|||
face (face_),
|
||||
glyphs (glyphs_),
|
||||
len (len_),
|
||||
zero_context (zero_context_),
|
||||
debug_depth (0) {}
|
||||
zero_context (zero_context_) {}
|
||||
};
|
||||
|
||||
|
||||
struct hb_collect_glyphs_context_t :
|
||||
hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_empty_t, 0>
|
||||
hb_dispatch_context_t<hb_collect_glyphs_context_t>
|
||||
{
|
||||
const char *get_name () { return "COLLECT_GLYPHS"; }
|
||||
typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { obj.collect_glyphs (this); return hb_empty_t (); }
|
||||
|
@ -282,7 +268,6 @@ struct hb_collect_glyphs_context_t :
|
|||
recurse_func_t recurse_func;
|
||||
hb_set_t *recursed_lookups;
|
||||
unsigned int nesting_level_left;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_collect_glyphs_context_t (hb_face_t *face_,
|
||||
hb_set_t *glyphs_before, /* OUT. May be NULL */
|
||||
|
@ -297,8 +282,7 @@ struct hb_collect_glyphs_context_t :
|
|||
output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
|
||||
recurse_func (nullptr),
|
||||
recursed_lookups (hb_set_create ()),
|
||||
nesting_level_left (nesting_level_left_),
|
||||
debug_depth (0) {}
|
||||
nesting_level_left (nesting_level_left_) {}
|
||||
~hb_collect_glyphs_context_t () { hb_set_destroy (recursed_lookups); }
|
||||
|
||||
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
|
||||
|
@ -308,10 +292,9 @@ struct hb_collect_glyphs_context_t :
|
|||
|
||||
template <typename set_t>
|
||||
struct hb_collect_coverage_context_t :
|
||||
hb_dispatch_context_t<hb_collect_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
|
||||
hb_dispatch_context_t<hb_collect_coverage_context_t<set_t>, const Coverage &>
|
||||
{
|
||||
const char *get_name () { return "GET_COVERAGE"; }
|
||||
typedef const Coverage &return_t;
|
||||
typedef const Coverage &return_t; // Stoopid that we have to dupe this here.
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { return obj.get_coverage (); }
|
||||
static return_t default_return_value () { return Null (Coverage); }
|
||||
|
@ -322,11 +305,9 @@ struct hb_collect_coverage_context_t :
|
|||
}
|
||||
|
||||
hb_collect_coverage_context_t (set_t *set_) :
|
||||
set (set_),
|
||||
debug_depth (0) {}
|
||||
set (set_) {}
|
||||
|
||||
set_t *set;
|
||||
unsigned int debug_depth;
|
||||
};
|
||||
|
||||
|
||||
|
@ -701,7 +682,7 @@ struct hb_ot_apply_context_t :
|
|||
|
||||
|
||||
struct hb_get_subtables_context_t :
|
||||
hb_dispatch_context_t<hb_get_subtables_context_t, hb_empty_t, HB_DEBUG_APPLY>
|
||||
hb_dispatch_context_t<hb_get_subtables_context_t>
|
||||
{
|
||||
template <typename Type>
|
||||
static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
|
||||
|
@ -737,7 +718,6 @@ struct hb_get_subtables_context_t :
|
|||
typedef hb_vector_t<hb_applicable_t> array_t;
|
||||
|
||||
/* Dispatch interface. */
|
||||
const char *get_name () { return "GET_SUBTABLES"; }
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj)
|
||||
{
|
||||
|
|
|
@ -1362,7 +1362,6 @@ hb_ot_layout_lookup_would_substitute (hb_face_t *face,
|
|||
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
|
||||
|
||||
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
|
||||
|
||||
return l.would_apply (&c, &face->table.GSUB->accels[lookup_index]);
|
||||
}
|
||||
|
||||
|
@ -1380,7 +1379,7 @@ void
|
|||
hb_ot_layout_substitute_start (hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
_hb_ot_layout_set_glyph_props (font, buffer);
|
||||
_hb_ot_layout_set_glyph_props (font, buffer);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1969,4 +1968,62 @@ hb_ot_layout_get_baseline (hb_font_t *font,
|
|||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct hb_get_glyph_alternates_dispatch_t :
|
||||
hb_dispatch_context_t<hb_get_glyph_alternates_dispatch_t, unsigned>
|
||||
{
|
||||
static return_t default_return_value () { return 0; }
|
||||
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||
|
||||
hb_face_t *face;
|
||||
|
||||
hb_get_glyph_alternates_dispatch_t (hb_face_t *face) :
|
||||
face (face) {}
|
||||
|
||||
private:
|
||||
template <typename T, typename ...Ts> auto
|
||||
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
|
||||
( obj.get_glyph_alternates (hb_forward<Ts> (ds)...) )
|
||||
template <typename T, typename ...Ts> auto
|
||||
_dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
|
||||
( default_return_value () )
|
||||
public:
|
||||
template <typename T, typename ...Ts> auto
|
||||
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
|
||||
( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
|
||||
};
|
||||
|
||||
/**
|
||||
* hb_ot_layout_lookup_get_glyph_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_glyph_alternates (hb_face_t *face,
|
||||
unsigned lookup_index,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */)
|
||||
{
|
||||
hb_get_glyph_alternates_dispatch_t c (face);
|
||||
const OT::SubstLookup &lookup = face->table.GSUB->table->get_lookup (lookup_index);
|
||||
auto ret = lookup.dispatch (&c, glyph, start_offset, alternate_count, alternate_glyphs);
|
||||
if (!ret && alternate_count) *alternate_count = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -323,6 +323,14 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
|
|||
HB_EXTERN hb_bool_t
|
||||
hb_ot_layout_has_substitution (hb_face_t *face);
|
||||
|
||||
HB_EXTERN unsigned
|
||||
hb_ot_layout_lookup_get_glyph_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 /* OUT */);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_layout_lookup_would_substitute (hb_face_t *face,
|
||||
unsigned int lookup_index,
|
||||
|
@ -449,7 +457,6 @@ hb_ot_layout_get_baseline (hb_font_t *font,
|
|||
hb_tag_t language_tag,
|
||||
hb_position_t *coord /* OUT. May be NULL. */);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_OT_LAYOUT_H */
|
||||
|
|
|
@ -40,6 +40,7 @@ TEST_PROGS = \
|
|||
test-font \
|
||||
test-map \
|
||||
test-object \
|
||||
test-ot-alternates \
|
||||
test-ot-color \
|
||||
test-ot-face \
|
||||
test-ot-glyphname \
|
||||
|
|
|
@ -16,6 +16,7 @@ tests = [
|
|||
'test-font.c',
|
||||
'test-map.c',
|
||||
'test-object.c',
|
||||
'test-ot-alternates.c',
|
||||
'test-ot-color.c',
|
||||
'test-ot-face.c',
|
||||
'test-ot-glyphname.c',
|
||||
|
|
|
@ -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_glyph_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_glyph_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_glyph_alternates);
|
||||
return hb_test_run ();
|
||||
}
|
Loading…
Reference in New Issue