mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset 815c0c1d5619 (bug 1226175) for bustage on a CLOSED TREE
This commit is contained in:
parent
253a5aa7f0
commit
9d241ae457
@ -15,7 +15,6 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
|
||||
|
||||
# Convenience targets:
|
||||
lib: $(BUILT_SOURCES) libharfbuzz.la
|
||||
fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la
|
||||
|
||||
lib_LTLIBRARIES = libharfbuzz.la
|
||||
|
||||
@ -220,22 +219,6 @@ pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = harfbuzz.pc
|
||||
EXTRA_DIST += harfbuzz.pc.in
|
||||
|
||||
FUZZING_CPPFLAGS= \
|
||||
-DHB_MAX_NESTING_LEVEL=3 \
|
||||
-DHB_SANITIZE_MAX_EDITS=3 \
|
||||
-DHB_BUFFER_MAX_EXPANSION_FACTOR=3 \
|
||||
-DHB_BUFFER_MAX_LEN_MIN=8 \
|
||||
-DHB_BUFFER_MAX_LEN_DEFAULT=128 \
|
||||
$(NULL)
|
||||
EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la
|
||||
libharfbuzz_fuzzing_la_LINK = $(libharfbuzz_la_LINK)
|
||||
libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES)
|
||||
libharfbuzz_fuzzing_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(FUZZING_CPPFLAGS)
|
||||
libharfbuzz_fuzzing_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS)
|
||||
libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
|
||||
EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
|
||||
CLEANFILES += libharfbuzz-fuzzing.la
|
||||
|
||||
if HAVE_ICU
|
||||
lib_LTLIBRARIES += libharfbuzz-icu.la
|
||||
libharfbuzz_icu_la_SOURCES = hb-icu.cc
|
||||
|
@ -35,37 +35,9 @@
|
||||
#include "hb-unicode-private.hh"
|
||||
|
||||
|
||||
#ifndef HB_BUFFER_MAX_EXPANSION_FACTOR
|
||||
#define HB_BUFFER_MAX_EXPANSION_FACTOR 32
|
||||
#endif
|
||||
#ifndef HB_BUFFER_MAX_LEN_MIN
|
||||
#define HB_BUFFER_MAX_LEN_MIN 8192
|
||||
#endif
|
||||
#ifndef HB_BUFFER_MAX_LEN_DEFAULT
|
||||
#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
|
||||
#endif
|
||||
|
||||
ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20);
|
||||
ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
|
||||
|
||||
HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
|
||||
HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
|
||||
|
||||
enum hb_buffer_scratch_flags_t {
|
||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII = 0x00000001u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE = 0x00000008u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000010u,
|
||||
/* Reserved for complex shapers' internal use. */
|
||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
|
||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
|
||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u,
|
||||
HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u,
|
||||
};
|
||||
HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
|
||||
|
||||
|
||||
/*
|
||||
* hb_buffer_t
|
||||
@ -80,8 +52,6 @@ struct hb_buffer_t {
|
||||
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
|
||||
hb_buffer_cluster_level_t cluster_level;
|
||||
hb_codepoint_t replacement; /* U+FFFD or something else. */
|
||||
hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */
|
||||
unsigned int max_len; /* Maximum allowed len. */
|
||||
|
||||
/* Buffer contents */
|
||||
hb_buffer_content_type_t content_type;
|
||||
@ -106,8 +76,8 @@ struct hb_buffer_t {
|
||||
inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
|
||||
inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
|
||||
|
||||
inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
|
||||
inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
|
||||
inline hb_glyph_info_t &prev (void) { return out_info[out_len - 1]; }
|
||||
inline hb_glyph_info_t prev (void) const { return info[out_len - 1]; }
|
||||
|
||||
inline bool has_separate_output (void) const { return info != out_info; }
|
||||
|
||||
@ -174,13 +144,12 @@ struct hb_buffer_t {
|
||||
if (have_output)
|
||||
{
|
||||
if (unlikely (out_info != info || out_len != idx)) {
|
||||
if (unlikely (!make_room_for (1, 1)))
|
||||
goto done;
|
||||
if (unlikely (!make_room_for (1, 1))) return;
|
||||
out_info[out_len] = info[idx];
|
||||
}
|
||||
out_len++;
|
||||
}
|
||||
done:
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
|
@ -91,11 +91,6 @@ hb_buffer_t::enlarge (unsigned int size)
|
||||
{
|
||||
if (unlikely (in_error))
|
||||
return false;
|
||||
if (unlikely (size > max_len))
|
||||
{
|
||||
in_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int new_allocated = allocated;
|
||||
hb_glyph_position_t *new_pos = NULL;
|
||||
@ -203,7 +198,6 @@ hb_buffer_t::clear (void)
|
||||
|
||||
hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
|
||||
props = default_props;
|
||||
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
|
||||
|
||||
content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
|
||||
in_error = false;
|
||||
@ -324,9 +318,7 @@ hb_buffer_t::replace_glyphs (unsigned int num_in,
|
||||
unsigned int num_out,
|
||||
const uint32_t *glyph_data)
|
||||
{
|
||||
if (unlikely (!make_room_for (num_in, num_out)))
|
||||
goto done;
|
||||
{
|
||||
if (unlikely (!make_room_for (num_in, num_out))) return;
|
||||
|
||||
merge_clusters (idx, idx + num_in);
|
||||
|
||||
@ -339,50 +331,39 @@ hb_buffer_t::replace_glyphs (unsigned int num_in,
|
||||
pinfo++;
|
||||
}
|
||||
|
||||
out_len += num_out;
|
||||
}
|
||||
done:
|
||||
idx += num_in;
|
||||
out_len += num_out;
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
|
||||
{
|
||||
if (unlikely (!make_room_for (0, 1)))
|
||||
goto done;
|
||||
if (unlikely (!make_room_for (0, 1))) return;
|
||||
|
||||
out_info[out_len] = info[idx];
|
||||
out_info[out_len].codepoint = glyph_index;
|
||||
|
||||
out_len++;
|
||||
done:
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
|
||||
{
|
||||
if (unlikely (!make_room_for (0, 1)))
|
||||
goto done;
|
||||
if (unlikely (!make_room_for (0, 1))) return;
|
||||
|
||||
out_info[out_len] = glyph_info;
|
||||
|
||||
out_len++;
|
||||
done:
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::copy_glyph (void)
|
||||
{
|
||||
if (unlikely (!make_room_for (0, 1)))
|
||||
goto done;
|
||||
if (unlikely (!make_room_for (0, 1))) return;
|
||||
|
||||
out_info[out_len] = info[idx];
|
||||
|
||||
out_len++;
|
||||
done:
|
||||
;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -400,7 +381,7 @@ hb_buffer_t::move_to (unsigned int i)
|
||||
if (out_len < i)
|
||||
{
|
||||
unsigned int count = i - out_len;
|
||||
if (unlikely (!make_room_for (count, count))) return false; // XXX verify bailout
|
||||
if (unlikely (!make_room_for (count, count))) return false;
|
||||
|
||||
memmove (out_info + out_len, info + idx, count * sizeof (out_info[0]));
|
||||
idx += count;
|
||||
@ -427,15 +408,13 @@ void
|
||||
hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
|
||||
{
|
||||
if (unlikely (out_info != info || out_len != idx)) {
|
||||
if (unlikely (!make_room_for (1, 1)))
|
||||
goto out;
|
||||
if (unlikely (!make_room_for (1, 1))) return;
|
||||
out_info[out_len] = info[idx];
|
||||
}
|
||||
out_info[out_len].codepoint = glyph_index;
|
||||
|
||||
out_len++;
|
||||
out:
|
||||
idx++;
|
||||
out_len++;
|
||||
}
|
||||
|
||||
|
||||
@ -735,8 +714,6 @@ hb_buffer_create (void)
|
||||
if (!(buffer = hb_object_create<hb_buffer_t> ()))
|
||||
return hb_buffer_get_empty ();
|
||||
|
||||
buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
|
||||
|
||||
buffer->reset ();
|
||||
|
||||
return buffer;
|
||||
@ -761,8 +738,6 @@ hb_buffer_get_empty (void)
|
||||
HB_BUFFER_FLAG_DEFAULT,
|
||||
HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
|
||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
|
||||
HB_BUFFER_MAX_LEN_DEFAULT,
|
||||
|
||||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||
|
@ -61,6 +61,14 @@ struct hb_font_funcs_t {
|
||||
|
||||
hb_bool_t immutable;
|
||||
|
||||
/* Don't access these directly. Call hb_font_get_*() instead. */
|
||||
|
||||
struct {
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
} get;
|
||||
|
||||
struct {
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
@ -72,16 +80,6 @@ struct hb_font_funcs_t {
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
} destroy;
|
||||
|
||||
/* Don't access these directly. Call font->get_*() instead. */
|
||||
union get_t {
|
||||
struct get_funcs_t {
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
} f;
|
||||
void (*array[]) (void);
|
||||
} get;
|
||||
};
|
||||
|
||||
|
||||
@ -146,20 +144,6 @@ struct hb_font_t {
|
||||
|
||||
/* Public getters */
|
||||
|
||||
HB_INTERNAL bool has_func (unsigned int i);
|
||||
|
||||
/* has_* ... */
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) \
|
||||
bool \
|
||||
has_##name##_func (void) \
|
||||
{ \
|
||||
hb_font_funcs_t *funcs = this->klass; \
|
||||
unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
|
||||
return has_func (i); \
|
||||
}
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
|
||||
inline hb_bool_t has_glyph (hb_codepoint_t unicode)
|
||||
{
|
||||
hb_codepoint_t glyph;
|
||||
@ -170,85 +154,85 @@ struct hb_font_t {
|
||||
hb_codepoint_t *glyph)
|
||||
{
|
||||
*glyph = 0;
|
||||
return klass->get.f.glyph (this, user_data,
|
||||
unicode, variation_selector, glyph,
|
||||
klass->user_data.glyph);
|
||||
return klass->get.glyph (this, user_data,
|
||||
unicode, variation_selector, glyph,
|
||||
klass->user_data.glyph);
|
||||
}
|
||||
|
||||
inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
|
||||
{
|
||||
return klass->get.f.glyph_h_advance (this, user_data,
|
||||
glyph,
|
||||
klass->user_data.glyph_h_advance);
|
||||
return klass->get.glyph_h_advance (this, user_data,
|
||||
glyph,
|
||||
klass->user_data.glyph_h_advance);
|
||||
}
|
||||
|
||||
inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
|
||||
{
|
||||
return klass->get.f.glyph_v_advance (this, user_data,
|
||||
glyph,
|
||||
klass->user_data.glyph_v_advance);
|
||||
return klass->get.glyph_v_advance (this, user_data,
|
||||
glyph,
|
||||
klass->user_data.glyph_v_advance);
|
||||
}
|
||||
|
||||
inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
*x = *y = 0;
|
||||
return klass->get.f.glyph_h_origin (this, user_data,
|
||||
glyph, x, y,
|
||||
klass->user_data.glyph_h_origin);
|
||||
return klass->get.glyph_h_origin (this, user_data,
|
||||
glyph, x, y,
|
||||
klass->user_data.glyph_h_origin);
|
||||
}
|
||||
|
||||
inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
*x = *y = 0;
|
||||
return klass->get.f.glyph_v_origin (this, user_data,
|
||||
glyph, x, y,
|
||||
klass->user_data.glyph_v_origin);
|
||||
return klass->get.glyph_v_origin (this, user_data,
|
||||
glyph, x, y,
|
||||
klass->user_data.glyph_v_origin);
|
||||
}
|
||||
|
||||
inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
|
||||
{
|
||||
return klass->get.f.glyph_h_kerning (this, user_data,
|
||||
left_glyph, right_glyph,
|
||||
klass->user_data.glyph_h_kerning);
|
||||
return klass->get.glyph_h_kerning (this, user_data,
|
||||
left_glyph, right_glyph,
|
||||
klass->user_data.glyph_h_kerning);
|
||||
}
|
||||
|
||||
inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
|
||||
{
|
||||
return klass->get.f.glyph_v_kerning (this, user_data,
|
||||
top_glyph, bottom_glyph,
|
||||
klass->user_data.glyph_v_kerning);
|
||||
return klass->get.glyph_v_kerning (this, user_data,
|
||||
top_glyph, bottom_glyph,
|
||||
klass->user_data.glyph_v_kerning);
|
||||
}
|
||||
|
||||
inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents)
|
||||
{
|
||||
memset (extents, 0, sizeof (*extents));
|
||||
return klass->get.f.glyph_extents (this, user_data,
|
||||
glyph,
|
||||
extents,
|
||||
klass->user_data.glyph_extents);
|
||||
return klass->get.glyph_extents (this, user_data,
|
||||
glyph,
|
||||
extents,
|
||||
klass->user_data.glyph_extents);
|
||||
}
|
||||
|
||||
inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
*x = *y = 0;
|
||||
return klass->get.f.glyph_contour_point (this, user_data,
|
||||
glyph, point_index,
|
||||
x, y,
|
||||
klass->user_data.glyph_contour_point);
|
||||
return klass->get.glyph_contour_point (this, user_data,
|
||||
glyph, point_index,
|
||||
x, y,
|
||||
klass->user_data.glyph_contour_point);
|
||||
}
|
||||
|
||||
inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
|
||||
char *name, unsigned int size)
|
||||
{
|
||||
if (size) *name = '\0';
|
||||
return klass->get.f.glyph_name (this, user_data,
|
||||
glyph,
|
||||
name, size,
|
||||
klass->user_data.glyph_name);
|
||||
return klass->get.glyph_name (this, user_data,
|
||||
glyph,
|
||||
name, size,
|
||||
klass->user_data.glyph_name);
|
||||
}
|
||||
|
||||
inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
|
||||
@ -256,10 +240,10 @@ struct hb_font_t {
|
||||
{
|
||||
*glyph = 0;
|
||||
if (len == -1) len = strlen (name);
|
||||
return klass->get.f.glyph_from_name (this, user_data,
|
||||
name, len,
|
||||
glyph,
|
||||
klass->user_data.glyph_from_name);
|
||||
return klass->get.glyph_from_name (this, user_data,
|
||||
name, len,
|
||||
glyph,
|
||||
klass->user_data.glyph_from_name);
|
||||
}
|
||||
|
||||
|
||||
@ -314,26 +298,6 @@ struct hb_font_t {
|
||||
}
|
||||
}
|
||||
|
||||
inline void add_glyph_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_h_origin (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x += origin_x;
|
||||
*y += origin_y;
|
||||
}
|
||||
inline void add_glyph_v_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_v_origin (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x += origin_x;
|
||||
*y += origin_y;
|
||||
}
|
||||
inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
|
||||
hb_direction_t direction,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
@ -346,26 +310,6 @@ struct hb_font_t {
|
||||
*y += origin_y;
|
||||
}
|
||||
|
||||
inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_h_origin (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x -= origin_x;
|
||||
*y -= origin_y;
|
||||
}
|
||||
inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_v_origin (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x -= origin_x;
|
||||
*y -= origin_y;
|
||||
}
|
||||
inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
|
||||
hb_direction_t direction,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
|
@ -45,176 +45,130 @@
|
||||
*/
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return font->parent->get_glyph (unicode, variation_selector, glyph);
|
||||
|
||||
*glyph = 0;
|
||||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent->get_glyph (unicode, variation_selector, glyph);
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_h_advance_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
|
||||
|
||||
return font->x_scale;
|
||||
}
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_h_advance_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_v_advance_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
|
||||
|
||||
return font->y_scale;
|
||||
}
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_v_advance_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_h_origin_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent) {
|
||||
hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*x = *y = 0;
|
||||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_h_origin_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_v_origin_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent) {
|
||||
hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*x = *y = 0;
|
||||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_v_origin_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t left_glyph,
|
||||
hb_codepoint_t right_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
|
||||
|
||||
return 0;
|
||||
}
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t left_glyph,
|
||||
hb_codepoint_t right_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t top_glyph,
|
||||
hb_codepoint_t bottom_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
|
||||
|
||||
return 0;
|
||||
}
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t top_glyph,
|
||||
hb_codepoint_t bottom_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_extents_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent) {
|
||||
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
|
||||
if (ret) {
|
||||
font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
|
||||
font->parent_scale_distance (&extents->width, &extents->height);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset (extents, 0, sizeof (*extents));
|
||||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_extents_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
|
||||
if (ret) {
|
||||
font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
|
||||
font->parent_scale_distance (&extents->width, &extents->height);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_contour_point_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned int point_index,
|
||||
@ -222,63 +176,44 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent) {
|
||||
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*x = *y = 0;
|
||||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_contour_point_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned int point_index,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_name_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
char *name, unsigned int size,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return font->parent->get_glyph_name (glyph, name, size);
|
||||
|
||||
if (size) *name = '\0';
|
||||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_name_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
char *name, unsigned int size,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent->get_glyph_name (glyph, name, size);
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
|
||||
hb_font_get_glyph_from_name_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
const char *name, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return font->parent->get_glyph_from_name (name, len, glyph);
|
||||
|
||||
*glyph = 0;
|
||||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_from_name_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
const char *name, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent->get_glyph_from_name (name, len, glyph);
|
||||
}
|
||||
|
||||
|
||||
static const hb_font_funcs_t _hb_font_funcs_nil = {
|
||||
@ -286,43 +221,12 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
},
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
},
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
}
|
||||
};
|
||||
static const hb_font_funcs_t _hb_font_funcs_parent = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
},
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) NULL,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
},
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -342,7 +246,7 @@ hb_font_funcs_create (void)
|
||||
if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
|
||||
return hb_font_funcs_get_empty ();
|
||||
|
||||
ffuncs->get = _hb_font_funcs_parent.get;
|
||||
ffuncs->get = _hb_font_funcs_nil.get;
|
||||
|
||||
return ffuncs;
|
||||
}
|
||||
@ -359,7 +263,7 @@ hb_font_funcs_create (void)
|
||||
hb_font_funcs_t *
|
||||
hb_font_funcs_get_empty (void)
|
||||
{
|
||||
return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
|
||||
return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -494,11 +398,11 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
|
||||
ffuncs->destroy.name (ffuncs->user_data.name); \
|
||||
\
|
||||
if (func) { \
|
||||
ffuncs->get.f.name = func; \
|
||||
ffuncs->get.name = func; \
|
||||
ffuncs->user_data.name = user_data; \
|
||||
ffuncs->destroy.name = destroy; \
|
||||
} else { \
|
||||
ffuncs->get.f.name = hb_font_get_##name##_parent; \
|
||||
ffuncs->get.name = hb_font_get_##name##_nil; \
|
||||
ffuncs->user_data.name = NULL; \
|
||||
ffuncs->destroy.name = NULL; \
|
||||
} \
|
||||
@ -507,13 +411,6 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
|
||||
bool
|
||||
hb_font_t::has_func (unsigned int i)
|
||||
{
|
||||
if (parent && parent != hb_font_get_empty () && parent->has_func (i))
|
||||
return true;
|
||||
return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
|
||||
}
|
||||
|
||||
/* Public getters */
|
||||
|
||||
@ -961,7 +858,6 @@ hb_font_create (hb_face_t *face)
|
||||
return hb_font_get_empty ();
|
||||
|
||||
hb_face_make_immutable (face);
|
||||
font->parent = hb_font_get_empty ();
|
||||
font->face = hb_face_reference (face);
|
||||
font->klass = hb_font_funcs_get_empty ();
|
||||
|
||||
@ -1021,8 +917,8 @@ hb_font_get_empty (void)
|
||||
NULL, /* parent */
|
||||
const_cast<hb_face_t *> (&_hb_face_nil),
|
||||
|
||||
1000, /* x_scale */
|
||||
1000, /* y_scale */
|
||||
0, /* x_scale */
|
||||
0, /* y_scale */
|
||||
|
||||
0, /* x_ppem */
|
||||
0, /* y_ppem */
|
||||
|
@ -216,6 +216,18 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
|
||||
return (-v + (1<<9)) >> 10;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ft_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph HB_UNUSED,
|
||||
hb_position_t *x HB_UNUSED,
|
||||
hb_position_t *y HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* We always work in the horizontal coordinates. */
|
||||
return true;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
@ -260,6 +272,17 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
|
||||
return kerningv.x;
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t top_glyph HB_UNUSED,
|
||||
hb_codepoint_t bottom_glyph HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* FreeType API doesn't support vertical kerning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
@ -277,16 +300,6 @@ hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
|
||||
extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
|
||||
extents->width = ft_face->glyph->metrics.width;
|
||||
extents->height = -ft_face->glyph->metrics.height;
|
||||
if (font->x_scale < 0)
|
||||
{
|
||||
extents->x_bearing = -extents->x_bearing;
|
||||
extents->width = -extents->width;
|
||||
}
|
||||
if (font->y_scale < 0)
|
||||
{
|
||||
extents->y_bearing = -extents->y_bearing;
|
||||
extents->height = -extents->height;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -367,52 +380,23 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static hb_font_funcs_t *static_ft_funcs = NULL;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_ft_funcs (void)
|
||||
{
|
||||
hb_font_funcs_destroy (static_ft_funcs);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
|
||||
{
|
||||
retry:
|
||||
hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
|
||||
static const hb_font_funcs_t ft_ffuncs = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
if (unlikely (!funcs))
|
||||
{
|
||||
funcs = hb_font_funcs_create ();
|
||||
true, /* immutable */
|
||||
|
||||
hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL);
|
||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL);
|
||||
//hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL);
|
||||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) {
|
||||
hb_font_funcs_destroy (funcs);
|
||||
goto retry;
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
}
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
|
||||
#endif
|
||||
};
|
||||
|
||||
hb_font_set_funcs (font,
|
||||
funcs,
|
||||
const_cast<hb_font_funcs_t *> (&ft_ffuncs),
|
||||
_hb_ft_font_create (ft_face, unref),
|
||||
(hb_destroy_func_t) _hb_ft_font_destroy);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ struct hb_dispatch_context_t
|
||||
|
||||
/* This limits sanitizing time on really broken fonts. */
|
||||
#ifndef HB_SANITIZE_MAX_EDITS
|
||||
#define HB_SANITIZE_MAX_EDITS 8
|
||||
#define HB_SANITIZE_MAX_EDITS 100
|
||||
#endif
|
||||
|
||||
struct hb_sanitize_context_t :
|
||||
@ -399,9 +399,9 @@ struct Sanitizer
|
||||
|
||||
struct hb_serialize_context_t
|
||||
{
|
||||
inline hb_serialize_context_t (void *start_, unsigned int size)
|
||||
inline hb_serialize_context_t (void *start, unsigned int size)
|
||||
{
|
||||
this->start = (char *) start_;
|
||||
this->start = (char *) start;
|
||||
this->end = this->start + size;
|
||||
|
||||
this->ran_out_of_room = false;
|
||||
@ -495,10 +495,10 @@ struct hb_serialize_context_t
|
||||
return reinterpret_cast<Type *> (&obj);
|
||||
}
|
||||
|
||||
inline void truncate (void *new_head)
|
||||
inline void truncate (void *head)
|
||||
{
|
||||
assert (this->start < new_head && new_head <= this->head);
|
||||
this->head = (char *) new_head;
|
||||
assert (this->start < head && head <= this->head);
|
||||
this->head = (char *) head;
|
||||
}
|
||||
|
||||
unsigned int debug_depth;
|
||||
|
@ -46,9 +46,11 @@ struct hb_ot_face_metrics_accelerator_t
|
||||
hb_blob_t *blob;
|
||||
|
||||
inline void init (hb_face_t *face,
|
||||
hb_tag_t _hea_tag, hb_tag_t _mtx_tag)
|
||||
hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
|
||||
unsigned int default_advance_)
|
||||
{
|
||||
this->default_advance = face->get_upem ();
|
||||
this->default_advance = default_advance_;
|
||||
this->num_metrics = face->get_num_glyphs ();
|
||||
|
||||
hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag));
|
||||
const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob);
|
||||
@ -56,16 +58,8 @@ struct hb_ot_face_metrics_accelerator_t
|
||||
hb_blob_destroy (_hea_blob);
|
||||
|
||||
this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
|
||||
|
||||
/* Cap num_metrics() and num_advances() based on table length. */
|
||||
unsigned int len = hb_blob_get_length (this->blob);
|
||||
if (unlikely (this->num_advances * 4 > len))
|
||||
this->num_advances = len / 4;
|
||||
this->num_metrics = this->num_advances + (len - 4 * this->num_advances) / 2;
|
||||
|
||||
/* We MUST set num_metrics to zero if num_advances is zero.
|
||||
* Our get_advance() depends on that. */
|
||||
if (unlikely (!this->num_advances))
|
||||
if (unlikely (!this->num_advances ||
|
||||
2 * (this->num_advances + this->num_metrics) > hb_blob_get_length (this->blob)))
|
||||
{
|
||||
this->num_metrics = this->num_advances = 0;
|
||||
hb_blob_destroy (this->blob);
|
||||
@ -251,9 +245,11 @@ _hb_ot_font_create (hb_face_t *face)
|
||||
if (unlikely (!ot_font))
|
||||
return NULL;
|
||||
|
||||
unsigned int upem = face->get_upem ();
|
||||
|
||||
ot_font->cmap.init (face);
|
||||
ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx);
|
||||
ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx); /* TODO Can we do this lazily? */
|
||||
ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
|
||||
ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */
|
||||
ot_font->glyf.init (face);
|
||||
|
||||
return ot_font;
|
||||
@ -304,6 +300,52 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
|
||||
return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph));
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph HB_UNUSED,
|
||||
hb_position_t *x HB_UNUSED,
|
||||
hb_position_t *y HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* We always work in the horizontal coordinates. */
|
||||
return true;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ot_get_glyph_h_kerning (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t left_glyph,
|
||||
hb_codepoint_t right_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t top_glyph HB_UNUSED,
|
||||
hb_codepoint_t bottom_glyph HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* OpenType doesn't have vertical-kerning other than GPOS. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
@ -320,52 +362,58 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static hb_font_funcs_t *static_ot_funcs = NULL;
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_ot_funcs (void)
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned int point_index,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_font_funcs_destroy (static_ot_funcs);
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
char *name, unsigned int size,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
const char *name, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static hb_font_funcs_t *
|
||||
_hb_ot_get_font_funcs (void)
|
||||
{
|
||||
retry:
|
||||
hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
|
||||
static const hb_font_funcs_t ot_ffuncs = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
if (unlikely (!funcs))
|
||||
{
|
||||
funcs = hb_font_funcs_create ();
|
||||
true, /* immutable */
|
||||
|
||||
hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL);
|
||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL);
|
||||
//hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL);
|
||||
//hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO
|
||||
//hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL);
|
||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL);
|
||||
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); TODO
|
||||
//hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); TODO
|
||||
//hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); TODO
|
||||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, NULL, funcs)) {
|
||||
hb_font_funcs_destroy (funcs);
|
||||
goto retry;
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
}
|
||||
|
||||
#ifdef HB_USE_ATEXIT
|
||||
atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
|
||||
#endif
|
||||
};
|
||||
|
||||
return funcs;
|
||||
return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,14 +34,6 @@
|
||||
#include "hb-set-private.hh"
|
||||
|
||||
|
||||
#ifndef HB_MAX_NESTING_LEVEL
|
||||
#define HB_MAX_NESTING_LEVEL 6
|
||||
#endif
|
||||
#ifndef HB_MAX_CONTEXT_LENGTH
|
||||
#define HB_MAX_CONTEXT_LENGTH 64
|
||||
#endif
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
@ -52,6 +44,8 @@ namespace OT {
|
||||
|
||||
|
||||
#define NOT_COVERED ((unsigned int) -1)
|
||||
#define MAX_NESTING_LEVEL 6
|
||||
#define MAX_CONTEXT_LENGTH 64
|
||||
|
||||
|
||||
|
||||
@ -579,11 +573,6 @@ struct LookupFlag : USHORT
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
/* This has to be outside the namespace. */
|
||||
HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
|
||||
namespace OT {
|
||||
|
||||
struct Lookup
|
||||
{
|
||||
inline unsigned int get_subtable_count (void) const { return subTable.len; }
|
||||
|
@ -426,7 +426,6 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
|
||||
o.x_offset = base_x - mark_x;
|
||||
o.y_offset = base_y - mark_y;
|
||||
o.attach_lookback() = buffer->idx - glyph_pos;
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
@ -994,7 +993,6 @@ struct CursivePosFormat1
|
||||
reverse_cursive_minor_offset (pos, child, c->direction, parent);
|
||||
|
||||
pos[child].cursive_chain() = parent - child;
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE;
|
||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
|
||||
pos[child].y_offset = y_offset;
|
||||
else
|
||||
@ -1601,14 +1599,12 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
||||
hb_direction_t direction = buffer->props.direction;
|
||||
|
||||
/* Handle cursive connections */
|
||||
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE)
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
fix_cursive_minor_offset (pos, i, direction);
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
fix_cursive_minor_offset (pos, i, direction);
|
||||
|
||||
/* Handle attachments */
|
||||
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
fix_mark_attachment (pos, i, direction);
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
fix_mark_attachment (pos, i, direction);
|
||||
}
|
||||
|
||||
|
||||
|
@ -630,7 +630,7 @@ struct Ligature
|
||||
unsigned int total_component_count = 0;
|
||||
|
||||
unsigned int match_length = 0;
|
||||
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
|
||||
unsigned int match_positions[MAX_CONTEXT_LENGTH];
|
||||
|
||||
if (likely (!match_input (c, count,
|
||||
&component[1],
|
||||
@ -970,7 +970,7 @@ struct ReverseChainSingleSubstFormat1
|
||||
inline bool apply (hb_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
|
||||
if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL))
|
||||
return_trace (false); /* No chaining to this type */
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
|
@ -74,7 +74,7 @@ struct hb_closure_context_t :
|
||||
|
||||
hb_closure_context_t (hb_face_t *face_,
|
||||
hb_set_t *glyphs_,
|
||||
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
|
||||
unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
|
||||
face (face_),
|
||||
glyphs (glyphs_),
|
||||
recurse_func (NULL),
|
||||
@ -196,7 +196,7 @@ struct hb_collect_glyphs_context_t :
|
||||
hb_set_t *glyphs_input, /* OUT. May be NULL */
|
||||
hb_set_t *glyphs_after, /* OUT. May be NULL */
|
||||
hb_set_t *glyphs_output, /* OUT. May be NULL */
|
||||
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
|
||||
unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
|
||||
face (face_),
|
||||
before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
|
||||
input (glyphs_input ? glyphs_input : hb_set_get_empty ()),
|
||||
@ -355,11 +355,11 @@ struct hb_apply_context_t :
|
||||
{
|
||||
matcher.set_lookup_props (lookup_props);
|
||||
}
|
||||
inline void set_match_func (matcher_t::match_func_t match_func_,
|
||||
const void *match_data_,
|
||||
inline void set_match_func (matcher_t::match_func_t match_func,
|
||||
const void *match_data,
|
||||
const USHORT glyph_data[])
|
||||
{
|
||||
matcher.set_match_func (match_func_, match_data_);
|
||||
matcher.set_match_func (match_func, match_data);
|
||||
match_glyph_data = glyph_data;
|
||||
}
|
||||
|
||||
@ -483,7 +483,7 @@ struct hb_apply_context_t :
|
||||
lookup_mask (1),
|
||||
auto_zwj (true),
|
||||
recurse_func (NULL),
|
||||
nesting_level_left (HB_MAX_NESTING_LEVEL),
|
||||
nesting_level_left (MAX_NESTING_LEVEL),
|
||||
lookup_props (0),
|
||||
gdef (*hb_ot_layout_from_face (face)->gdef),
|
||||
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||
@ -704,13 +704,13 @@ static inline bool match_input (hb_apply_context_t *c,
|
||||
match_func_t match_func,
|
||||
const void *match_data,
|
||||
unsigned int *end_offset,
|
||||
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
|
||||
unsigned int match_positions[MAX_CONTEXT_LENGTH],
|
||||
bool *p_is_mark_ligature = NULL,
|
||||
unsigned int *p_total_component_count = NULL)
|
||||
{
|
||||
TRACE_APPLY (NULL);
|
||||
|
||||
if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
|
||||
if (unlikely (count > MAX_CONTEXT_LENGTH)) return_trace (false);
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
@ -784,7 +784,7 @@ static inline bool match_input (hb_apply_context_t *c,
|
||||
}
|
||||
static inline bool ligate_input (hb_apply_context_t *c,
|
||||
unsigned int count, /* Including the first glyph */
|
||||
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
|
||||
unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */
|
||||
unsigned int match_length,
|
||||
hb_codepoint_t lig_glyph,
|
||||
bool is_mark_ligature,
|
||||
@ -836,13 +836,14 @@ static inline bool ligate_input (hb_apply_context_t *c,
|
||||
if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
{
|
||||
_hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
|
||||
_hb_glyph_info_set_modified_combining_class (&buffer->cur(), 0);
|
||||
}
|
||||
}
|
||||
c->replace_glyph_with_ligature (lig_glyph, klass);
|
||||
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
{
|
||||
while (buffer->idx < match_positions[i] && !buffer->in_error)
|
||||
while (buffer->idx < match_positions[i])
|
||||
{
|
||||
if (!is_mark_ligature) {
|
||||
unsigned int new_lig_comp = components_so_far - last_num_components +
|
||||
@ -943,7 +944,7 @@ static inline void recurse_lookups (context_t *c,
|
||||
|
||||
static inline bool apply_lookup (hb_apply_context_t *c,
|
||||
unsigned int count, /* Including the first glyph */
|
||||
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
|
||||
unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */
|
||||
unsigned int lookupCount,
|
||||
const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
|
||||
unsigned int match_length)
|
||||
@ -988,13 +989,13 @@ static inline bool apply_lookup (hb_apply_context_t *c,
|
||||
/* end can't go back past the current match position.
|
||||
* Note: this is only true because we do NOT allow MultipleSubst
|
||||
* with zero sequence len. */
|
||||
end = MAX (MIN((int) match_positions[idx] + 1, (int) new_len), int (end) + delta);
|
||||
end = MAX ((int) match_positions[idx] + 1, int (end) + delta);
|
||||
|
||||
unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
|
||||
|
||||
if (delta > 0)
|
||||
{
|
||||
if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
|
||||
if (unlikely (delta + count > MAX_CONTEXT_LENGTH))
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -1093,7 +1094,7 @@ static inline bool context_apply_lookup (hb_apply_context_t *c,
|
||||
ContextApplyLookupContext &lookup_context)
|
||||
{
|
||||
unsigned int match_length = 0;
|
||||
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
|
||||
unsigned int match_positions[MAX_CONTEXT_LENGTH];
|
||||
return match_input (c,
|
||||
inputCount, input,
|
||||
lookup_context.funcs.match, lookup_context.match_data,
|
||||
@ -1620,7 +1621,7 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
|
||||
ChainContextApplyLookupContext &lookup_context)
|
||||
{
|
||||
unsigned int match_length = 0;
|
||||
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
|
||||
unsigned int match_positions[MAX_CONTEXT_LENGTH];
|
||||
return match_input (c,
|
||||
inputCount, input,
|
||||
lookup_context.funcs.match, lookup_context.match_data[1],
|
||||
|
@ -49,7 +49,7 @@ hb_ot_layout_table_find_feature (hb_face_t *face,
|
||||
* GDEF
|
||||
*/
|
||||
|
||||
enum hb_ot_layout_glyph_props_flags_t
|
||||
typedef enum
|
||||
{
|
||||
/* The following three match LookupFlags::Ignore* numbers. */
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 0x02u,
|
||||
@ -64,8 +64,7 @@ enum hb_ot_layout_glyph_props_flags_t
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
|
||||
};
|
||||
HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
|
||||
} hb_ot_layout_glyph_class_mask_t;
|
||||
|
||||
|
||||
/*
|
||||
@ -181,7 +180,8 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout);
|
||||
*/
|
||||
|
||||
/* buffer var allocations, used during the entire shaping process */
|
||||
#define unicode_props() var2.u16[0]
|
||||
#define unicode_props0() var2.u8[0]
|
||||
#define unicode_props1() var2.u8[1]
|
||||
|
||||
/* buffer var allocations, used during the GSUB/GPOS processing */
|
||||
#define glyph_props() var1.u16[0] /* GDEF glyph properties */
|
||||
@ -214,123 +214,48 @@ _next_syllable (hb_buffer_t *buffer, unsigned int start)
|
||||
|
||||
/* unicode_props */
|
||||
|
||||
/* Design:
|
||||
* unicode_props() is a two-byte number. The low byte includes:
|
||||
* - General_Category: 5 bits.
|
||||
* - A bit each for:
|
||||
* * Is it Default_Ignorable(); we have a modified Default_Ignorable().
|
||||
* * Is it U+200D ZWJ?
|
||||
* * Is it U+200C ZWNJ?
|
||||
*
|
||||
* The high-byte has different meanings, switched by the Gen-Cat:
|
||||
* - For Mn,Mc,Me: the modified Combining_Class.
|
||||
* - For Ws: index of which space character this is, if space fallback
|
||||
* is needed, ie. we don't set this by default, only if asked to.
|
||||
*
|
||||
* If needed, we can use the ZWJ/ZWNJ to use the high byte as well,
|
||||
* freeing two more bits.
|
||||
*/
|
||||
|
||||
enum hb_unicode_props_flags_t {
|
||||
UPROPS_MASK_ZWJ = 0x20u,
|
||||
UPROPS_MASK_ZWNJ = 0x40u,
|
||||
UPROPS_MASK_IGNORABLE = 0x80u,
|
||||
UPROPS_MASK_GEN_CAT = 0x1Fu
|
||||
enum {
|
||||
MASK0_ZWJ = 0x20u,
|
||||
MASK0_ZWNJ = 0x40u,
|
||||
MASK0_IGNORABLE = 0x80u,
|
||||
MASK0_GEN_CAT = 0x1Fu
|
||||
};
|
||||
HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
|
||||
|
||||
static inline void
|
||||
_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
|
||||
_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
|
||||
{
|
||||
hb_unicode_funcs_t *unicode = buffer->unicode;
|
||||
unsigned int u = info->codepoint;
|
||||
unsigned int gen_cat = (unsigned int) unicode->general_category (u);
|
||||
unsigned int props = gen_cat;
|
||||
|
||||
if (u >= 0x80)
|
||||
{
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
|
||||
if (unlikely (unicode->is_default_ignorable (u)))
|
||||
{
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
|
||||
props |= UPROPS_MASK_IGNORABLE;
|
||||
if (u == 0x200Cu) props |= UPROPS_MASK_ZWNJ;
|
||||
if (u == 0x200Du) props |= UPROPS_MASK_ZWJ;
|
||||
}
|
||||
else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK (gen_cat)))
|
||||
{
|
||||
/* Only Mn and Mc can have non-zero ccc:
|
||||
* http://www.unicode.org/policies/stability_policy.html#Property_Value
|
||||
* """
|
||||
* Canonical_Combining_Class, General_Category
|
||||
* All characters other than those with General_Category property values
|
||||
* Spacing_Mark (Mc) and Nonspacing_Mark (Mn) have the Canonical_Combining_Class
|
||||
* property value 0.
|
||||
* 1.1.5+
|
||||
* """
|
||||
*
|
||||
* Also, all Mn's that are Default_Ignorable, have ccc=0, hence
|
||||
* the "else if".
|
||||
*/
|
||||
props |= unicode->modified_combining_class (info->codepoint)<<8;
|
||||
}
|
||||
}
|
||||
|
||||
info->unicode_props() = props;
|
||||
/* XXX This shouldn't be inlined, or at least not while is_default_ignorable() is inline. */
|
||||
info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) |
|
||||
(unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) |
|
||||
(info->codepoint == 0x200Cu ? MASK0_ZWNJ : 0) |
|
||||
(info->codepoint == 0x200Du ? MASK0_ZWJ : 0);
|
||||
info->unicode_props1() = unicode->modified_combining_class (info->codepoint);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
|
||||
hb_unicode_general_category_t gen_cat)
|
||||
{
|
||||
/* Clears top-byte. */
|
||||
info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
|
||||
info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT);
|
||||
}
|
||||
|
||||
static inline hb_unicode_general_category_t
|
||||
_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
|
||||
{
|
||||
return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
|
||||
return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
|
||||
{
|
||||
return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
|
||||
}
|
||||
static inline void
|
||||
_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
|
||||
unsigned int modified_class)
|
||||
{
|
||||
if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
|
||||
return;
|
||||
info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
|
||||
info->unicode_props1() = modified_class;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
|
||||
{
|
||||
return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
|
||||
{
|
||||
return _hb_glyph_info_get_general_category (info) ==
|
||||
HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
|
||||
}
|
||||
static inline void
|
||||
_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
|
||||
{
|
||||
if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
|
||||
return;
|
||||
info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
|
||||
}
|
||||
static inline hb_unicode_funcs_t::space_t
|
||||
_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
|
||||
{
|
||||
return _hb_glyph_info_is_unicode_space (info) ?
|
||||
(hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
|
||||
hb_unicode_funcs_t::NOT_SPACE;
|
||||
return info->unicode_props1();
|
||||
}
|
||||
|
||||
static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
|
||||
@ -338,25 +263,25 @@ static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
|
||||
static inline hb_bool_t
|
||||
_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
|
||||
{
|
||||
return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && !_hb_glyph_info_ligated (info);
|
||||
return (info->unicode_props0() & MASK0_IGNORABLE) && !_hb_glyph_info_ligated (info);
|
||||
}
|
||||
|
||||
static inline hb_bool_t
|
||||
_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->unicode_props() & UPROPS_MASK_ZWNJ);
|
||||
return !!(info->unicode_props0() & MASK0_ZWNJ);
|
||||
}
|
||||
|
||||
static inline hb_bool_t
|
||||
_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
|
||||
{
|
||||
return !!(info->unicode_props() & UPROPS_MASK_ZWJ);
|
||||
return !!(info->unicode_props0() & MASK0_ZWJ);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
|
||||
{
|
||||
info->unicode_props() ^= UPROPS_MASK_ZWNJ | UPROPS_MASK_ZWJ;
|
||||
info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ;
|
||||
}
|
||||
|
||||
/* lig_props: aka lig_id / lig_comp
|
||||
@ -530,19 +455,22 @@ _hb_glyph_info_clear_substituted_and_ligated_and_multiplied (hb_glyph_info_t *in
|
||||
static inline void
|
||||
_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
|
||||
{
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props0);
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
|
||||
{
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0);
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
|
||||
{
|
||||
HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
|
||||
HB_BUFFER_ASSERT_VAR (buffer, unicode_props0);
|
||||
HB_BUFFER_ASSERT_VAR (buffer, unicode_props1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -890,7 +890,7 @@ apply_forward (OT::hb_apply_context_t *c,
|
||||
{
|
||||
bool ret = false;
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
while (buffer->idx < buffer->len && !buffer->in_error)
|
||||
while (buffer->idx < buffer->len)
|
||||
{
|
||||
if (accel.may_have (buffer->cur().codepoint) &&
|
||||
(buffer->cur().mask & c->lookup_mask) &&
|
||||
|
@ -159,9 +159,23 @@ enum hb_ot_map_feature_flags_t {
|
||||
F_MANUAL_ZWJ = 0x0004u, /* Don't skip over ZWJ when matching. */
|
||||
F_GLOBAL_SEARCH = 0x0008u /* If feature not found in LangSys, look for it in global feature list and pick one. */
|
||||
};
|
||||
HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
|
||||
/* Macro version for where const is desired. */
|
||||
#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
|
||||
static inline hb_ot_map_feature_flags_t
|
||||
operator | (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
|
||||
{ return hb_ot_map_feature_flags_t ((unsigned int) l | (unsigned int) r); }
|
||||
static inline hb_ot_map_feature_flags_t
|
||||
operator & (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r)
|
||||
{ return hb_ot_map_feature_flags_t ((unsigned int) l & (unsigned int) r); }
|
||||
static inline hb_ot_map_feature_flags_t
|
||||
operator ~ (hb_ot_map_feature_flags_t r)
|
||||
{ return hb_ot_map_feature_flags_t (~(unsigned int) r); }
|
||||
static inline hb_ot_map_feature_flags_t&
|
||||
operator |= (hb_ot_map_feature_flags_t &l, hb_ot_map_feature_flags_t r)
|
||||
{ l = l | r; return l; }
|
||||
static inline hb_ot_map_feature_flags_t&
|
||||
operator &= (hb_ot_map_feature_flags_t& l, hb_ot_map_feature_flags_t r)
|
||||
{ l = l & r; return l; }
|
||||
|
||||
|
||||
struct hb_ot_map_builder_t
|
||||
|
@ -28,38 +28,9 @@
|
||||
#include "hb-ot-shape-private.hh"
|
||||
|
||||
|
||||
#ifndef HB_DEBUG_ARABIC
|
||||
#define HB_DEBUG_ARABIC (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
|
||||
/* buffer var allocations */
|
||||
#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
|
||||
|
||||
#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
|
||||
|
||||
/* See:
|
||||
* https://github.com/behdad/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
|
||||
#define HB_ARABIC_GENERAL_CATEGORY_IS_WORD(gen_cat) \
|
||||
(FLAG_SAFE (gen_cat) & \
|
||||
(FLAG (HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE) | \
|
||||
/*FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |*/ \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) | \
|
||||
/*FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |*/ \
|
||||
/*FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |*/ \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL)))
|
||||
|
||||
|
||||
/*
|
||||
* Joining types:
|
||||
@ -113,7 +84,7 @@ static const hb_tag_t arabic_features[] =
|
||||
|
||||
|
||||
/* Same order as the feature array */
|
||||
enum arabic_action_t {
|
||||
enum {
|
||||
ISOL,
|
||||
FINA,
|
||||
FIN2,
|
||||
@ -124,11 +95,7 @@ enum arabic_action_t {
|
||||
|
||||
NONE,
|
||||
|
||||
ARABIC_NUM_FEATURES = NONE,
|
||||
|
||||
/* We abuse the same byte for other things... */
|
||||
STCH_FIXED,
|
||||
STCH_REPEATING,
|
||||
ARABIC_NUM_FEATURES = NONE
|
||||
};
|
||||
|
||||
static const struct arabic_state_table_entry {
|
||||
@ -172,11 +139,6 @@ arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
static void
|
||||
record_stch (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
static void
|
||||
collect_features_arabic (hb_ot_shape_planner_t *plan)
|
||||
{
|
||||
@ -203,9 +165,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
||||
|
||||
map->add_gsub_pause (nuke_joiners);
|
||||
|
||||
map->add_global_bool_feature (HB_TAG('s','t','c','h'));
|
||||
map->add_gsub_pause (record_stch);
|
||||
|
||||
map->add_global_bool_feature (HB_TAG('c','c','m','p'));
|
||||
map->add_global_bool_feature (HB_TAG('l','o','c','l'));
|
||||
|
||||
@ -249,10 +208,8 @@ struct arabic_shape_plan_t
|
||||
* mask_array[NONE] == 0. */
|
||||
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
|
||||
|
||||
bool do_fallback;
|
||||
arabic_fallback_plan_t *fallback_plan;
|
||||
|
||||
unsigned int do_fallback : 1;
|
||||
unsigned int has_stch : 1;
|
||||
};
|
||||
|
||||
void *
|
||||
@ -263,7 +220,6 @@ data_create_arabic (const hb_ot_shape_plan_t *plan)
|
||||
return NULL;
|
||||
|
||||
arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
|
||||
arabic_plan->has_stch = !!plan->map.get_1_mask (HB_TAG ('s','t','c','h'));
|
||||
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
|
||||
arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
|
||||
arabic_plan->do_fallback = arabic_plan->do_fallback &&
|
||||
@ -364,6 +320,8 @@ setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()];
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -413,194 +371,6 @@ retry:
|
||||
arabic_fallback_plan_shape (fallback_plan, font, buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stretch feature: "stch".
|
||||
* See example here:
|
||||
* https://www.microsoft.com/typography/OpenTypeDev/syriac/intro.htm
|
||||
* We implement this in a generic way, such that the Arabic subtending
|
||||
* marks can use it as well.
|
||||
*/
|
||||
|
||||
static void
|
||||
record_stch (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
|
||||
if (!arabic_plan->has_stch)
|
||||
return;
|
||||
|
||||
/* 'stch' feature was just applied. Look for anything that multiplied,
|
||||
* and record it for stch treatment later. Note that rtlm, frac, etc
|
||||
* are applied before stch, but we assume that they didn't result in
|
||||
* anything multiplying into 5 pieces, so it's safe-ish... */
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (_hb_glyph_info_multiplied (&info[i])))
|
||||
{
|
||||
unsigned int comp = _hb_glyph_info_get_lig_comp (&info[i]);
|
||||
info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED;
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
apply_stch (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
{
|
||||
if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH)))
|
||||
return;
|
||||
|
||||
/* The Arabic shaper currently always processes in RTL mode, so we should
|
||||
* stretch / position the stretched pieces to the left / preceding glyphs. */
|
||||
|
||||
/* We do a two pass implementation:
|
||||
* First pass calculates the exact number of extra glyphs we need,
|
||||
* We then enlarge buffer to have that much room,
|
||||
* Second pass applies the stretch, copying things to the end of buffer.
|
||||
*/
|
||||
|
||||
/* 30 = 2048 / 70.
|
||||
* https://www.microsoft.com/typography/cursivescriptguidelines.mspx */
|
||||
hb_position_t overlap = font->x_scale / 30;
|
||||
DEBUG_MSG (ARABIC, NULL, "overlap for stretching is %d", overlap);
|
||||
int sign = font->x_scale < 0 ? -1 : +1;
|
||||
unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
|
||||
typedef enum { MEASURE, CUT } step_t;
|
||||
|
||||
for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1))
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
unsigned int new_len = count + extra_glyphs_needed; // write head during CUT
|
||||
unsigned int j = new_len;
|
||||
for (unsigned int i = count; i; i--)
|
||||
{
|
||||
if (!hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
|
||||
{
|
||||
if (step == CUT)
|
||||
{
|
||||
--j;
|
||||
info[j] = info[i - 1];
|
||||
pos[j] = pos[i - 1];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Yay, justification! */
|
||||
|
||||
hb_position_t w_total = 0; // Total to be filled
|
||||
hb_position_t w_fixed = 0; // Sum of fixed tiles
|
||||
hb_position_t w_repeating = 0; // Sum of repeating tiles
|
||||
int n_fixed = 0;
|
||||
int n_repeating = 0;
|
||||
|
||||
unsigned int end = i;
|
||||
while (i &&
|
||||
hb_in_range<unsigned> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
|
||||
{
|
||||
i--;
|
||||
hb_glyph_extents_t extents;
|
||||
if (!font->get_glyph_extents (info[i].codepoint, &extents))
|
||||
extents.width = 0;
|
||||
extents.width -= overlap;
|
||||
if (info[i].arabic_shaping_action() == STCH_FIXED)
|
||||
{
|
||||
w_fixed += extents.width;
|
||||
n_fixed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
w_repeating += extents.width;
|
||||
n_repeating++;
|
||||
}
|
||||
}
|
||||
unsigned int start = i;
|
||||
unsigned int context = i;
|
||||
while (context &&
|
||||
!hb_in_range<unsigned> (info[context - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING) &&
|
||||
(_hb_glyph_info_is_default_ignorable (&info[context - 1]) ||
|
||||
HB_ARABIC_GENERAL_CATEGORY_IS_WORD (_hb_glyph_info_get_general_category (&info[context - 1]))))
|
||||
{
|
||||
context--;
|
||||
w_total += pos[context].x_advance;
|
||||
}
|
||||
i++; // Don't touch i again.
|
||||
|
||||
DEBUG_MSG (ARABIC, NULL, "%s stretch at (%d,%d,%d)",
|
||||
step == MEASURE ? "measuring" : "cutting", context, start, end);
|
||||
DEBUG_MSG (ARABIC, NULL, "rest of word: count=%d width %d", start - context, w_total);
|
||||
DEBUG_MSG (ARABIC, NULL, "fixed tiles: count=%d width=%d", n_fixed, w_fixed);
|
||||
DEBUG_MSG (ARABIC, NULL, "repeating tiles: count=%d width=%d", n_repeating, w_repeating);
|
||||
|
||||
/* Number of additional times to repeat each repeating tile. */
|
||||
int n_copies = 0;
|
||||
|
||||
hb_position_t w_remaining = w_total - w_fixed - overlap;
|
||||
if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
|
||||
n_copies = (sign * w_remaining + sign * w_repeating / 4) / (sign * w_repeating) - 1;
|
||||
|
||||
if (step == MEASURE)
|
||||
{
|
||||
extra_glyphs_needed += n_copies * n_repeating;
|
||||
DEBUG_MSG (ARABIC, NULL, "will add extra %d copies of repeating tiles", n_copies);
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_position_t x_offset = -overlap;
|
||||
for (unsigned int k = end; k > start; k--)
|
||||
{
|
||||
hb_glyph_extents_t extents;
|
||||
if (!font->get_glyph_extents (info[k - 1].codepoint, &extents))
|
||||
extents.width = 0;
|
||||
extents.width -= overlap;
|
||||
|
||||
unsigned int repeat = 1;
|
||||
if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
|
||||
repeat += n_copies;
|
||||
|
||||
DEBUG_MSG (ARABIC, NULL, "appending %d copies of glyph %d; j=%d",
|
||||
repeat, info[k - 1].codepoint, j);
|
||||
for (unsigned int n = 0; n < repeat; n++)
|
||||
{
|
||||
x_offset -= extents.width;
|
||||
pos[k - 1].x_offset = x_offset;
|
||||
/* Append copy. */
|
||||
--j;
|
||||
info[j] = info[k - 1];
|
||||
pos[j] = pos[k - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (step == MEASURE)
|
||||
{
|
||||
if (unlikely (!buffer->ensure (count + extra_glyphs_needed)))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (j == 0);
|
||||
buffer->len = new_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
{
|
||||
apply_stch (plan, buffer, font);
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
|
||||
}
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
|
||||
{
|
||||
@ -609,8 +379,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
|
||||
NULL, /* override_features */
|
||||
data_create_arabic,
|
||||
data_destroy_arabic,
|
||||
NULL, /* preprocess_text */
|
||||
postprocess_glyphs_arabic,
|
||||
NULL, /* preprocess_text_arabic */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
|
@ -35,7 +35,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
|
@ -188,7 +188,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
|
||||
*/
|
||||
unsigned int count = buffer->len;
|
||||
|
||||
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
|
||||
for (buffer->idx = 0; buffer->idx < count;)
|
||||
{
|
||||
hb_codepoint_t u = buffer->cur().codepoint;
|
||||
|
||||
@ -411,14 +411,13 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
|
||||
"hangul",
|
||||
collect_features_hangul,
|
||||
override_features_hangul,
|
||||
data_create_hangul,
|
||||
data_destroy_hangul,
|
||||
data_create_hangul, /* data_create */
|
||||
data_destroy_hangul, /* data_destroy */
|
||||
preprocess_text_hangul,
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
setup_masks_hangul,
|
||||
setup_masks_hangul, /* setup_masks */
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
|
||||
false, /* fallback_position */
|
||||
};
|
||||
|
@ -163,7 +163,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
compose_hebrew,
|
||||
|
@ -756,7 +756,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
||||
{
|
||||
default:
|
||||
assert (false);
|
||||
HB_FALLTHROUGH;
|
||||
/* fallthrough */
|
||||
|
||||
case BASE_POS_LAST:
|
||||
{
|
||||
@ -1243,7 +1243,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
|
||||
buffer->idx = 0;
|
||||
unsigned int last_syllable = 0;
|
||||
while (buffer->idx < buffer->len && !buffer->in_error)
|
||||
while (buffer->idx < buffer->len)
|
||||
{
|
||||
unsigned int syllable = buffer->cur().syllable();
|
||||
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
|
||||
@ -1251,10 +1251,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
{
|
||||
last_syllable = syllable;
|
||||
|
||||
hb_glyph_info_t ginfo = dottedcircle;
|
||||
ginfo.cluster = buffer->cur().cluster;
|
||||
ginfo.mask = buffer->cur().mask;
|
||||
ginfo.syllable() = buffer->cur().syllable();
|
||||
hb_glyph_info_t info = dottedcircle;
|
||||
info.cluster = buffer->cur().cluster;
|
||||
info.mask = buffer->cur().mask;
|
||||
info.syllable() = buffer->cur().syllable();
|
||||
/* TODO Set glyph_props? */
|
||||
|
||||
/* Insert dottedcircle after possible Repha. */
|
||||
@ -1263,7 +1263,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
buffer->cur().indic_category() == OT_Repha)
|
||||
buffer->next_glyph ();
|
||||
|
||||
buffer->output_info (ginfo);
|
||||
buffer->output_info (info);
|
||||
}
|
||||
else
|
||||
buffer->next_glyph ();
|
||||
@ -1631,8 +1631,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
if (new_pos > start && info[new_pos - 1].indic_category() == OT_M)
|
||||
{
|
||||
unsigned int old_pos = i;
|
||||
for (unsigned int j = base + 1; j < old_pos; j++)
|
||||
if (info[j].indic_category() == OT_M)
|
||||
for (unsigned int i = base + 1; i < old_pos; i++)
|
||||
if (info[i].indic_category() == OT_M)
|
||||
{
|
||||
new_pos--;
|
||||
break;
|
||||
@ -1834,7 +1834,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
|
||||
data_create_indic,
|
||||
data_destroy_indic,
|
||||
NULL, /* preprocess_text */
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
|
||||
decompose_indic,
|
||||
compose_indic,
|
||||
|
@ -455,12 +455,12 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
{
|
||||
last_syllable = syllable;
|
||||
|
||||
hb_glyph_info_t ginfo = dottedcircle;
|
||||
ginfo.cluster = buffer->cur().cluster;
|
||||
ginfo.mask = buffer->cur().mask;
|
||||
ginfo.syllable() = buffer->cur().syllable();
|
||||
hb_glyph_info_t info = dottedcircle;
|
||||
info.cluster = buffer->cur().cluster;
|
||||
info.mask = buffer->cur().mask;
|
||||
info.syllable() = buffer->cur().syllable();
|
||||
|
||||
buffer->output_info (ginfo);
|
||||
buffer->output_info (info);
|
||||
}
|
||||
else
|
||||
buffer->next_glyph ();
|
||||
@ -507,7 +507,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
@ -524,7 +523,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
|
@ -110,15 +110,6 @@ struct hb_ot_complex_shaper_t
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font);
|
||||
|
||||
/* postprocess_glyphs()
|
||||
* Called during shape().
|
||||
* Shapers can use to modify glyphs after shaping ends.
|
||||
* May be NULL.
|
||||
*/
|
||||
void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font);
|
||||
|
||||
|
||||
hb_ot_shape_normalization_mode_t normalization_preference;
|
||||
|
||||
|
@ -139,7 +139,7 @@ thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
|
||||
};
|
||||
|
||||
switch (action) {
|
||||
default: assert (false); HB_FALLTHROUGH;
|
||||
default: assert (false); /* Fallthrough */
|
||||
case NOP: return u;
|
||||
case SD: pua_mappings = SD_mappings; break;
|
||||
case SDL: pua_mappings = SDL_mappings; break;
|
||||
@ -315,7 +315,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
|
||||
|
||||
buffer->clear_output ();
|
||||
unsigned int count = buffer->len;
|
||||
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
|
||||
for (buffer->idx = 0; buffer->idx < count;)
|
||||
{
|
||||
hb_codepoint_t u = buffer->cur().codepoint;
|
||||
if (likely (!IS_SARA_AM (u))) {
|
||||
@ -330,7 +330,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
|
||||
if (unlikely (buffer->in_error))
|
||||
return;
|
||||
|
||||
/* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */
|
||||
/* Make Nikhahit be recognized as a mark when zeroing widths. */
|
||||
unsigned int end = buffer->out_len;
|
||||
_hb_glyph_info_set_general_category (&buffer->out_info[end - 2], HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
|
||||
|
||||
@ -372,7 +372,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
preprocess_text_thai,
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
|
@ -52,7 +52,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
|
@ -490,6 +490,11 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
if (likely (!has_broken_syllables))
|
||||
return;
|
||||
|
||||
|
||||
hb_codepoint_t dottedcircle_glyph;
|
||||
if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
|
||||
return;
|
||||
|
||||
hb_glyph_info_t dottedcircle = {0};
|
||||
if (!font->get_glyph (0x25CCu, 0, &dottedcircle.codepoint))
|
||||
return;
|
||||
@ -498,8 +503,9 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
buffer->clear_output ();
|
||||
|
||||
buffer->idx = 0;
|
||||
|
||||
unsigned int last_syllable = 0;
|
||||
while (buffer->idx < buffer->len && !buffer->in_error)
|
||||
while (buffer->idx < buffer->len)
|
||||
{
|
||||
unsigned int syllable = buffer->cur().syllable();
|
||||
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
|
||||
@ -507,10 +513,10 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
{
|
||||
last_syllable = syllable;
|
||||
|
||||
hb_glyph_info_t ginfo = dottedcircle;
|
||||
ginfo.cluster = buffer->cur().cluster;
|
||||
ginfo.mask = buffer->cur().mask;
|
||||
ginfo.syllable() = buffer->cur().syllable();
|
||||
hb_glyph_info_t info = dottedcircle;
|
||||
info.cluster = buffer->cur().cluster;
|
||||
info.mask = buffer->cur().mask;
|
||||
info.syllable() = buffer->cur().syllable();
|
||||
/* TODO Set glyph_props? */
|
||||
|
||||
/* Insert dottedcircle after possible Repha. */
|
||||
@ -519,7 +525,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
buffer->cur().use_category() == USE_R)
|
||||
buffer->next_glyph ();
|
||||
|
||||
buffer->output_info (ginfo);
|
||||
buffer->output_info (info);
|
||||
}
|
||||
else
|
||||
buffer->next_glyph ();
|
||||
@ -570,7 +576,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
|
||||
data_create_use,
|
||||
data_destroy_use,
|
||||
NULL, /* preprocess_text */
|
||||
NULL, /* postprocess_glyphs */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
|
||||
NULL, /* decompose */
|
||||
compose_use,
|
||||
|
@ -45,9 +45,5 @@ HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
|
||||
#endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */
|
||||
|
@ -224,7 +224,7 @@ position_mark (const hb_ot_shape_plan_t *plan,
|
||||
pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
|
||||
break;
|
||||
}
|
||||
HB_FALLTHROUGH;
|
||||
/* Fall through */
|
||||
|
||||
default:
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
|
||||
@ -259,7 +259,6 @@ position_mark (const hb_ot_shape_plan_t *plan,
|
||||
case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
|
||||
/* Add gap, fall-through. */
|
||||
base_extents.height -= y_gap;
|
||||
HB_FALLTHROUGH;
|
||||
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
|
||||
@ -280,7 +279,6 @@ position_mark (const hb_ot_shape_plan_t *plan,
|
||||
/* Add gap, fall-through. */
|
||||
base_extents.y_bearing += y_gap;
|
||||
base_extents.height -= y_gap;
|
||||
HB_FALLTHROUGH;
|
||||
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
|
||||
@ -484,70 +482,3 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
|
||||
idx = skippy_iter.idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Adjusts width of various spaces. */
|
||||
void
|
||||
_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||
return;
|
||||
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
|
||||
{
|
||||
hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
|
||||
hb_codepoint_t glyph;
|
||||
typedef hb_unicode_funcs_t t;
|
||||
switch (space_type)
|
||||
{
|
||||
case t::NOT_SPACE: /* Shouldn't happen. */
|
||||
case t::SPACE:
|
||||
break;
|
||||
|
||||
case t::SPACE_EM:
|
||||
case t::SPACE_EM_2:
|
||||
case t::SPACE_EM_3:
|
||||
case t::SPACE_EM_4:
|
||||
case t::SPACE_EM_5:
|
||||
case t::SPACE_EM_6:
|
||||
case t::SPACE_EM_16:
|
||||
pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
|
||||
break;
|
||||
|
||||
case t::SPACE_4_EM_18:
|
||||
pos[i].x_advance = font->x_scale * 4 / 18;
|
||||
break;
|
||||
|
||||
case t::SPACE_FIGURE:
|
||||
for (char u = '0'; u <= '9'; u++)
|
||||
if (font->get_glyph (u, 0, &glyph))
|
||||
{
|
||||
pos[i].x_advance = font->get_glyph_h_advance (glyph);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case t::SPACE_PUNCTUATION:
|
||||
if (font->get_glyph ('.', 0, &glyph))
|
||||
pos[i].x_advance = font->get_glyph_h_advance (glyph);
|
||||
else if (font->get_glyph (',', 0, &glyph))
|
||||
pos[i].x_advance = font->get_glyph_h_advance (glyph);
|
||||
break;
|
||||
|
||||
case t::SPACE_NARROW:
|
||||
/* Half-space?
|
||||
* Unicode doc http://www.unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
|
||||
* However, in my testing, many fonts have their regular space being about that
|
||||
* size. To me, a percentage of the space width makes more sense. Half is as
|
||||
* good as any. */
|
||||
pos[i].x_advance /= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,12 +62,24 @@
|
||||
* with previous base, use that. This needs the itemizer to have this
|
||||
* knowledge too. We need to provide assistance to the itemizer.
|
||||
*
|
||||
* - When a font does not support a character but supports its canonical
|
||||
* decomposition, well, use the decomposition.
|
||||
* - When a font does not support a character but supports its decomposition,
|
||||
* well, use the decomposition (preferring the canonical decomposition, but
|
||||
* falling back to the compatibility decomposition if necessary). The
|
||||
* compatibility decomposition is really nice to have, for characters like
|
||||
* ellipsis, or various-sized space characters.
|
||||
*
|
||||
* - The complex shapers can customize the compose and decompose functions to
|
||||
* offload some of their requirements to the normalizer. For example, the
|
||||
* Indic shaper may want to disallow recomposing of two matras.
|
||||
*
|
||||
* - We try compatibility decomposition if decomposing through canonical
|
||||
* decomposition alone failed to find a sequence that the font supports.
|
||||
* We don't try compatibility decomposition recursively during the canonical
|
||||
* decomposition phase. This has minimal impact. There are only a handful
|
||||
* of Greek letter that have canonical decompositions that include characters
|
||||
* with compatibility decomposition. Those can be found using this command:
|
||||
*
|
||||
* egrep "`echo -n ';('; grep ';<' UnicodeData.txt | cut -d';' -f1 | tr '\n' '|'; echo ') '`" UnicodeData.txt
|
||||
*/
|
||||
|
||||
static bool
|
||||
@ -98,8 +110,8 @@ static inline void
|
||||
output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
|
||||
{
|
||||
buffer->cur().glyph_index() = glyph;
|
||||
buffer->output_glyph (unichar); /* This is very confusing indeed. */
|
||||
_hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
|
||||
buffer->output_glyph (unichar);
|
||||
_hb_glyph_info_set_unicode_props (&buffer->prev(), buffer->unicode);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -159,6 +171,28 @@ decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns 0 if didn't decompose, number of resulting characters otherwise. */
|
||||
static inline unsigned int
|
||||
decompose_compatibility (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t u)
|
||||
{
|
||||
unsigned int len, i;
|
||||
hb_codepoint_t decomposed[HB_UNICODE_MAX_DECOMPOSITION_LEN];
|
||||
hb_codepoint_t glyphs[HB_UNICODE_MAX_DECOMPOSITION_LEN];
|
||||
|
||||
len = c->buffer->unicode->decompose_compatibility (u, decomposed);
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (!c->font->get_glyph (decomposed[i], 0, &glyphs[i]))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
output_char (c->buffer, decomposed[i], glyphs[i]);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline void
|
||||
decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest)
|
||||
{
|
||||
@ -166,50 +200,17 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
|
||||
hb_codepoint_t u = buffer->cur().codepoint;
|
||||
hb_codepoint_t glyph;
|
||||
|
||||
/* Kind of a cute waterfall here... */
|
||||
if (shortest && c->font->get_glyph (u, 0, &glyph))
|
||||
{
|
||||
next_char (buffer, glyph);
|
||||
return;
|
||||
}
|
||||
|
||||
if (decompose (c, shortest, u))
|
||||
{
|
||||
else if (decompose (c, shortest, u))
|
||||
skip_char (buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shortest && c->font->get_glyph (u, 0, &glyph))
|
||||
{
|
||||
else if (!shortest && c->font->get_glyph (u, 0, &glyph))
|
||||
next_char (buffer, glyph);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hb_glyph_info_is_unicode_space (&buffer->cur()))
|
||||
{
|
||||
hb_codepoint_t space_glyph;
|
||||
hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u);
|
||||
if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_glyph (0x0020u, 0, &space_glyph))
|
||||
{
|
||||
_hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type);
|
||||
next_char (buffer, space_glyph);
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (u == 0x2011u)
|
||||
{
|
||||
/* U+2011 is the only sensible character that is a no-break version of another character
|
||||
* and not a space. The space ones are handled already. Handle this lone one. */
|
||||
hb_codepoint_t other_glyph;
|
||||
if (c->font->get_glyph (0x2010u, 0, &other_glyph))
|
||||
{
|
||||
next_char (buffer, other_glyph);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
|
||||
else if (decompose_compatibility (c, u))
|
||||
skip_char (buffer);
|
||||
else
|
||||
next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -218,7 +219,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns
|
||||
/* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
|
||||
hb_buffer_t * const buffer = c->buffer;
|
||||
hb_font_t * const font = c->font;
|
||||
for (; buffer->idx < end - 1 && !buffer->in_error;) {
|
||||
for (; buffer->idx < end - 1;) {
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
|
||||
/* The next two lines are some ugly lines... But work. */
|
||||
if (font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
|
||||
@ -254,13 +255,13 @@ static inline void
|
||||
decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
|
||||
{
|
||||
hb_buffer_t * const buffer = c->buffer;
|
||||
for (unsigned int i = buffer->idx; i < end && !buffer->in_error; i++)
|
||||
for (unsigned int i = buffer->idx; i < end; i++)
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) {
|
||||
handle_variation_selector_cluster (c, end, short_circuit);
|
||||
return;
|
||||
}
|
||||
|
||||
while (buffer->idx < end && !buffer->in_error)
|
||||
while (buffer->idx < end)
|
||||
decompose_current_character (c, short_circuit);
|
||||
}
|
||||
|
||||
@ -320,7 +321,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
||||
|
||||
buffer->clear_output ();
|
||||
count = buffer->len;
|
||||
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
|
||||
for (buffer->idx = 0; buffer->idx < count;)
|
||||
{
|
||||
unsigned int end;
|
||||
for (end = buffer->idx + 1; end < count; end++)
|
||||
@ -370,7 +371,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
||||
count = buffer->len;
|
||||
unsigned int starter = 0;
|
||||
buffer->next_glyph ();
|
||||
while (buffer->idx < count && !buffer->in_error)
|
||||
while (buffer->idx < count)
|
||||
{
|
||||
hb_codepoint_t composed, glyph;
|
||||
if (/* We don't try to compose a non-mark character with it's preceding starter.
|
||||
@ -399,7 +400,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
||||
/* Modify starter and carry on. */
|
||||
buffer->out_info[starter].codepoint = composed;
|
||||
buffer->out_info[starter].glyph_index() = glyph;
|
||||
_hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
|
||||
_hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ hb_set_unicode_props (hb_buffer_t *buffer)
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
_hb_glyph_info_set_unicode_props (&info[i], buffer);
|
||||
_hb_glyph_info_set_unicode_props (&info[i], buffer->unicode);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -245,7 +245,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
||||
|
||||
hb_glyph_info_t dottedcircle = {0};
|
||||
dottedcircle.codepoint = 0x25CCu;
|
||||
_hb_glyph_info_set_unicode_props (&dottedcircle, buffer);
|
||||
_hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode);
|
||||
|
||||
buffer->clear_output ();
|
||||
|
||||
@ -254,7 +254,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
||||
info.cluster = buffer->cur().cluster;
|
||||
info.mask = buffer->cur().mask;
|
||||
buffer->output_info (info);
|
||||
while (buffer->idx < buffer->len && !buffer->in_error)
|
||||
while (buffer->idx < buffer->len)
|
||||
buffer->next_glyph ();
|
||||
|
||||
buffer->swap_buffers ();
|
||||
@ -263,8 +263,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
||||
static void
|
||||
hb_form_clusters (hb_buffer_t *buffer)
|
||||
{
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
|
||||
buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
return;
|
||||
|
||||
/* Loop duplicated in hb_ensure_native_direction(). */
|
||||
@ -347,8 +346,7 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c)
|
||||
static inline void
|
||||
hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
|
||||
{
|
||||
if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
|
||||
!c->plan->has_frac)
|
||||
if (!c->plan->has_frac)
|
||||
return;
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
@ -418,8 +416,7 @@ hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
|
||||
(buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
|
||||
if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
|
||||
return;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
@ -436,8 +433,7 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
|
||||
(buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
|
||||
if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
|
||||
return;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
@ -529,7 +525,7 @@ hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
hb_ot_layout_glyph_props_flags_t klass;
|
||||
hb_ot_layout_glyph_class_mask_t klass;
|
||||
|
||||
/* Never mark default-ignorables as marks.
|
||||
* They won't get in the way of lookups anyway,
|
||||
@ -553,6 +549,9 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
if (c->plan->shaper->preprocess_text)
|
||||
c->plan->shaper->preprocess_text (c->plan, buffer, c->font);
|
||||
|
||||
hb_ot_shape_initialize_masks (c);
|
||||
|
||||
hb_ot_mirror_chars (c);
|
||||
@ -577,6 +576,7 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
_hb_buffer_allocate_gsubgpos_vars (buffer);
|
||||
hb_ot_layout_substitute_start (c->font, buffer);
|
||||
|
||||
if (!hb_ot_layout_has_glyph_classes (c->face))
|
||||
@ -593,9 +593,6 @@ static inline void
|
||||
hb_ot_substitute (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_substitute_default (c);
|
||||
|
||||
_hb_buffer_allocate_gsubgpos_vars (c->buffer);
|
||||
|
||||
hb_ot_substitute_complex (c);
|
||||
}
|
||||
|
||||
@ -618,9 +615,6 @@ zero_mark_width (hb_glyph_position_t *pos)
|
||||
static inline void
|
||||
zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets)
|
||||
{
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
|
||||
return;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
@ -635,10 +629,6 @@ zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets)
|
||||
static inline void
|
||||
zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
|
||||
{
|
||||
/* This one is a hack; Technically GDEF can mark ASCII glyphs as marks, but we don't listen. */
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
|
||||
return;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
@ -657,29 +647,18 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
|
||||
unsigned int count = c->buffer->len;
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
hb_glyph_position_t *pos = c->buffer->pos;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
c->font->get_glyph_advance_for_direction (info[i].codepoint,
|
||||
direction,
|
||||
&pos[i].x_advance,
|
||||
&pos[i].y_advance);
|
||||
c->font->subtract_glyph_origin_for_direction (info[i].codepoint,
|
||||
direction,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
|
||||
if (c->font->has_glyph_h_origin_func ())
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->font->subtract_glyph_h_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
|
||||
if (c->font->has_glyph_v_origin_func ())
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->font->subtract_glyph_v_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
}
|
||||
if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
|
||||
_hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@ -724,21 +703,23 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
hb_glyph_position_t *pos = c->buffer->pos;
|
||||
|
||||
/* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
|
||||
/* Change glyph origin to what GPOS expects, apply GPOS, change it back. */
|
||||
|
||||
if (c->font->has_glyph_h_origin_func ())
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->font->add_glyph_h_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
c->font->add_glyph_origin_for_direction (info[i].codepoint,
|
||||
HB_DIRECTION_LTR,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
}
|
||||
|
||||
c->plan->position (c->font, c->buffer);
|
||||
|
||||
if (c->font->has_glyph_h_origin_func ())
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->font->subtract_glyph_h_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
c->font->subtract_glyph_origin_for_direction (info[i].codepoint,
|
||||
HB_DIRECTION_LTR,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
}
|
||||
|
||||
ret = true;
|
||||
}
|
||||
@ -797,12 +778,6 @@ static void
|
||||
hb_ot_shape_internal (hb_ot_shape_context_t *c)
|
||||
{
|
||||
c->buffer->deallocate_var_all ();
|
||||
c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
|
||||
if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_EXPANSION_FACTOR)))
|
||||
{
|
||||
c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_EXPANSION_FACTOR,
|
||||
(unsigned) HB_BUFFER_MAX_LEN_MIN);
|
||||
}
|
||||
|
||||
/* Save the original direction, we use it later. */
|
||||
c->target_direction = c->buffer->props.direction;
|
||||
@ -817,22 +792,15 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
|
||||
|
||||
hb_ensure_native_direction (c->buffer);
|
||||
|
||||
if (c->plan->shaper->preprocess_text)
|
||||
c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
|
||||
|
||||
hb_ot_substitute (c);
|
||||
hb_ot_position (c);
|
||||
|
||||
hb_ot_hide_default_ignorables (c);
|
||||
|
||||
if (c->plan->shaper->postprocess_glyphs)
|
||||
c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
|
||||
|
||||
_hb_buffer_deallocate_unicode_vars (c->buffer);
|
||||
|
||||
c->buffer->props.direction = c->target_direction;
|
||||
|
||||
c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
|
||||
c->buffer->deallocate_var_all ();
|
||||
}
|
||||
|
||||
|
@ -119,36 +119,6 @@ extern "C" void hb_free_impl(void *ptr);
|
||||
#define HB_FUNC __func__
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
|
||||
* HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
|
||||
* cases that fall through without a break or return statement. HB_FALLTHROUGH
|
||||
* is only needed on cases that have code:
|
||||
*
|
||||
* switch (foo) {
|
||||
* case 1: // These cases have no code. No fallthrough annotations are needed.
|
||||
* case 2:
|
||||
* case 3:
|
||||
* foo = 4; // This case has code, so a fallthrough annotation is needed:
|
||||
* HB_FALLTHROUGH;
|
||||
* default:
|
||||
* return foo;
|
||||
* }
|
||||
*/
|
||||
#if defined(__clang__) && __cplusplus >= 201103L
|
||||
/* clang's fallthrough annotations are only available starting in C++11. */
|
||||
# define HB_FALLTHROUGH [[clang::fallthrough]]
|
||||
#elif defined(_MSC_VER)
|
||||
/*
|
||||
* MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
|
||||
* https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
|
||||
*/
|
||||
# include <sal.h>
|
||||
# define HB_FALLTHROUGH __fallthrough
|
||||
#else
|
||||
# define HB_FALLTHROUGH /* FALLTHROUGH */
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
/* We need Windows Vista for both Uniscribe backend and for
|
||||
* MemoryBarrier. We don't support compiling on Windows XP,
|
||||
@ -240,9 +210,9 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
|
||||
#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
|
||||
#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
|
||||
|
||||
template <unsigned int cond> class hb_assert_constant_t {};
|
||||
|
||||
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
|
||||
/* Note: C++ allows sizeof() of variable-lengh arrays. So, if _cond is not
|
||||
* constant, it still compiles (ouch!), but at least we'll get a -Wvla warning. */
|
||||
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1]))
|
||||
|
||||
#define _PASTE1(a,b) a##b
|
||||
#define PASTE(a,b) _PASTE1(a,b)
|
||||
@ -891,34 +861,6 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
|
||||
}
|
||||
|
||||
|
||||
/* Enable bitwise ops on enums marked as flags_t */
|
||||
/* To my surprise, looks like the function resolver is happy to silently cast
|
||||
* one enum to another... So this doesn't provide the type-checking that I
|
||||
* originally had in mind... :(.
|
||||
*
|
||||
* On MSVC use DEFINE_ENUM_FLAG_OPERATORS. See:
|
||||
* https://github.com/behdad/harfbuzz/pull/163
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable:4200)
|
||||
# pragma warning(disable:4800)
|
||||
# define HB_MARK_AS_FLAG_T(flags_t) DEFINE_ENUM_FLAG_OPERATORS (##flags_t##);
|
||||
#else
|
||||
# define HB_MARK_AS_FLAG_T(flags_t) template <> class hb_mark_as_flags_t<flags_t> {};
|
||||
template <class T> class hb_mark_as_flags_t;
|
||||
template <class T> static inline T operator | (T l, T r)
|
||||
{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l | (unsigned int) r); }
|
||||
template <class T> static inline T operator & (T l, T r)
|
||||
{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T ((unsigned int) l & (unsigned int) r); }
|
||||
template <class T> static inline T operator ~ (T r)
|
||||
{ hb_mark_as_flags_t<T> unused HB_UNUSED; return T (~(unsigned int) r); }
|
||||
template <class T> static inline T& operator |= (T &l, T r)
|
||||
{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l | r; return l; }
|
||||
template <class T> static inline T& operator &= (T& l, T r)
|
||||
{ hb_mark_as_flags_t<T> unused HB_UNUSED; l = l & r; return l; }
|
||||
#endif
|
||||
|
||||
|
||||
/* Useful for set-operations on small enums.
|
||||
* For example, for testing "x ∈ {x1, x2, x3}" use:
|
||||
* (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
|
||||
|
@ -199,50 +199,6 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
}
|
||||
}
|
||||
|
||||
/* Space estimates based on:
|
||||
* http://www.unicode.org/charts/PDF/U2000.pdf
|
||||
* https://www.microsoft.com/typography/developers/fdsspec/spaces.aspx
|
||||
*/
|
||||
enum space_t {
|
||||
NOT_SPACE = 0,
|
||||
SPACE_EM = 1,
|
||||
SPACE_EM_2 = 2,
|
||||
SPACE_EM_3 = 3,
|
||||
SPACE_EM_4 = 4,
|
||||
SPACE_EM_5 = 5,
|
||||
SPACE_EM_6 = 6,
|
||||
SPACE_EM_16 = 16,
|
||||
SPACE_4_EM_18, /* 4/18th of an EM! */
|
||||
SPACE,
|
||||
SPACE_FIGURE,
|
||||
SPACE_PUNCTUATION,
|
||||
SPACE_NARROW,
|
||||
};
|
||||
static inline space_t
|
||||
space_fallback_type (hb_codepoint_t u)
|
||||
{
|
||||
switch (u)
|
||||
{
|
||||
/* All GC=Zs chars that can use a fallback. */
|
||||
default: return NOT_SPACE; /* Shouldn't happen. */
|
||||
case 0x0020u: return SPACE; /* U+0020 SPACE */
|
||||
case 0x00A0u: return SPACE; /* U+00A0 NO-BREAK SPACE */
|
||||
case 0x2000u: return SPACE_EM_2; /* U+2000 EN QUAD */
|
||||
case 0x2001u: return SPACE_EM; /* U+2001 EM QUAD */
|
||||
case 0x2002u: return SPACE_EM_2; /* U+2002 EN SPACE */
|
||||
case 0x2003u: return SPACE_EM; /* U+2003 EM SPACE */
|
||||
case 0x2004u: return SPACE_EM_3; /* U+2004 THREE-PER-EM SPACE */
|
||||
case 0x2005u: return SPACE_EM_4; /* U+2005 FOUR-PER-EM SPACE */
|
||||
case 0x2006u: return SPACE_EM_6; /* U+2006 SIX-PER-EM SPACE */
|
||||
case 0x2007u: return SPACE_FIGURE; /* U+2007 FIGURE SPACE */
|
||||
case 0x2008u: return SPACE_PUNCTUATION; /* U+2008 PUNCTUATION SPACE */
|
||||
case 0x2009u: return SPACE_EM_5; /* U+2009 THIN SPACE */
|
||||
case 0x200Au: return SPACE_EM_16; /* U+200A HAIR SPACE */
|
||||
case 0x202Fu: return SPACE_NARROW; /* U+202F NARROW NO-BREAK SPACE */
|
||||
case 0x205Fu: return SPACE_4_EM_18; /* U+205F MEDIUM MATHEMATICAL SPACE */
|
||||
case 0x3000u: return SPACE_EM; /* U+3000 IDEOGRAPHIC SPACE */
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
|
||||
@ -357,9 +313,5 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
|
||||
|
||||
#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK(gen_cat) \
|
||||
(FLAG_SAFE (gen_cat) & \
|
||||
(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
|
||||
|
||||
#endif /* HB_UNICODE_PRIVATE_HH */
|
||||
|
@ -146,11 +146,11 @@ struct hb_utf16_t
|
||||
return text;
|
||||
}
|
||||
|
||||
if (likely (c <= 0xDBFFu && text < end))
|
||||
if (likely (hb_in_range (c, 0xD800u, 0xDBFFu)))
|
||||
{
|
||||
/* High-surrogate in c */
|
||||
hb_codepoint_t l = *text;
|
||||
if (likely (hb_in_range (l, 0xDC00u, 0xDFFFu)))
|
||||
hb_codepoint_t l;
|
||||
if (text < end && ((l = *text), likely (hb_in_range (l, 0xDC00u, 0xDFFFu))))
|
||||
{
|
||||
/* Low-surrogate in l */
|
||||
*unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
|
||||
@ -170,7 +170,8 @@ struct hb_utf16_t
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
hb_codepoint_t c = *--text;
|
||||
const uint16_t *end = text--;
|
||||
hb_codepoint_t c = *text;
|
||||
|
||||
if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
{
|
||||
@ -178,22 +179,14 @@ struct hb_utf16_t
|
||||
return text;
|
||||
}
|
||||
|
||||
if (likely (c >= 0xDC00u && start < text))
|
||||
{
|
||||
/* Low-surrogate in c */
|
||||
hb_codepoint_t h = text[-1];
|
||||
if (likely (hb_in_range (h, 0xD800u, 0xDBFFu)))
|
||||
{
|
||||
/* High-surrogate in h */
|
||||
*unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
|
||||
text--;
|
||||
return text;
|
||||
}
|
||||
}
|
||||
if (likely (start < text && hb_in_range (c, 0xDC00u, 0xDFFFu)))
|
||||
text--;
|
||||
|
||||
if (likely (next (text, end, unicode, replacement) == end))
|
||||
return text;
|
||||
|
||||
/* Lonely / out-of-order surrogate. */
|
||||
*unicode = replacement;
|
||||
return text;
|
||||
return end - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -218,9 +211,14 @@ struct hb_utf32_t
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
hb_codepoint_t c = *unicode = *text++;
|
||||
if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
|
||||
*unicode = replacement;
|
||||
hb_codepoint_t c = *text++;
|
||||
if (validate && unlikely (c > 0x10FFFFu || hb_in_range (c, 0xD800u, 0xDFFFu)))
|
||||
goto error;
|
||||
*unicode = c;
|
||||
return text;
|
||||
|
||||
error:
|
||||
*unicode = replacement;
|
||||
return text;
|
||||
}
|
||||
|
||||
@ -230,10 +228,8 @@ struct hb_utf32_t
|
||||
hb_codepoint_t *unicode,
|
||||
hb_codepoint_t replacement)
|
||||
{
|
||||
hb_codepoint_t c = *unicode = *--text;
|
||||
if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
|
||||
*unicode = replacement;
|
||||
return text;
|
||||
next (text - 1, text, unicode, replacement);
|
||||
return text - 1;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
|
@ -37,10 +37,10 @@ HB_BEGIN_DECLS
|
||||
|
||||
|
||||
#define HB_VERSION_MAJOR 1
|
||||
#define HB_VERSION_MINOR 1
|
||||
#define HB_VERSION_MICRO 0
|
||||
#define HB_VERSION_MINOR 0
|
||||
#define HB_VERSION_MICRO 6
|
||||
|
||||
#define HB_VERSION_STRING "1.1.0"
|
||||
#define HB_VERSION_STRING "1.0.6"
|
||||
|
||||
#define HB_VERSION_ATLEAST(major,minor,micro) \
|
||||
((major)*10000+(minor)*100+(micro) <= \
|
||||
|
Loading…
Reference in New Issue
Block a user