8163238: Upgrade to harfbuzz 1.3.0 in JDK 9

Reviewed-by: vadim, serb
This commit is contained in:
Phil Race 2016-08-09 16:20:02 -07:00
parent 56b7589578
commit 9797ce7dcb
80 changed files with 8085 additions and 6008 deletions

View File

@ -104,7 +104,6 @@ hb_blob_create (const char *data,
if (!length ||
length >= 1u << 31 ||
data + length < data /* overflows */ ||
!(blob = hb_object_create<hb_blob_t> ())) {
if (destroy)
destroy (user_data);

View File

@ -64,7 +64,7 @@ typedef enum {
typedef struct hb_blob_t hb_blob_t;
hb_blob_t *
HB_EXTERN hb_blob_t *
hb_blob_create (const char *data,
unsigned int length,
hb_memory_mode_t mode,
@ -77,21 +77,21 @@ hb_blob_create (const char *data,
* modify the parent data as that data may be
* shared among multiple sub-blobs.
*/
hb_blob_t *
HB_EXTERN hb_blob_t *
hb_blob_create_sub_blob (hb_blob_t *parent,
unsigned int offset,
unsigned int length);
hb_blob_t *
HB_EXTERN hb_blob_t *
hb_blob_get_empty (void);
hb_blob_t *
HB_EXTERN hb_blob_t *
hb_blob_reference (hb_blob_t *blob);
void
HB_EXTERN void
hb_blob_destroy (hb_blob_t *blob);
hb_bool_t
HB_EXTERN hb_bool_t
hb_blob_set_user_data (hb_blob_t *blob,
hb_user_data_key_t *key,
void * data,
@ -99,25 +99,25 @@ hb_blob_set_user_data (hb_blob_t *blob,
hb_bool_t replace);
void *
HB_EXTERN void *
hb_blob_get_user_data (hb_blob_t *blob,
hb_user_data_key_t *key);
void
HB_EXTERN void
hb_blob_make_immutable (hb_blob_t *blob);
hb_bool_t
HB_EXTERN hb_bool_t
hb_blob_is_immutable (hb_blob_t *blob);
unsigned int
HB_EXTERN unsigned int
hb_blob_get_length (hb_blob_t *blob);
const char *
HB_EXTERN const char *
hb_blob_get_data (hb_blob_t *blob, unsigned int *length);
char *
HB_EXTERN char *
hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);

View File

@ -35,9 +35,36 @@
#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_ATTACHMENT = 0x00000008u,
/* 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
@ -52,6 +79,8 @@ 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;
@ -76,17 +105,13 @@ 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 - 1]; }
inline hb_glyph_info_t prev (void) const { return info[out_len - 1]; }
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 bool has_separate_output (void) const { return info != out_info; }
unsigned int serial;
/* These reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
uint8_t allocated_var_bytes[8];
const char *allocated_var_owner[8];
/* Text before / after the main buffer contents.
* Always in Unicode, and ordered outward.
* Index 0 is for "pre-context", 1 for "post-context". */
@ -94,6 +119,52 @@ struct hb_buffer_t {
hb_codepoint_t context[2][CONTEXT_LENGTH];
unsigned int context_len[2];
/* Debugging API */
hb_buffer_message_func_t message_func;
void *message_data;
hb_destroy_func_t message_destroy;
/* Internal debugging. */
/* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
#ifndef HB_NDEBUG
uint8_t allocated_var_bits;
#endif
inline void allocate_var (unsigned int start, unsigned int count)
{
#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1<<end) - (1<<start);
assert (0 == (allocated_var_bits & bits));
allocated_var_bits |= bits;
#endif
}
inline void deallocate_var (unsigned int start, unsigned int count)
{
#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1<<end) - (1<<start);
assert (bits == (allocated_var_bits & bits));
allocated_var_bits &= ~bits;
#endif
}
inline void assert_var (unsigned int start, unsigned int count)
{
#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1<<end) - (1<<start);
assert (bits == (allocated_var_bits & bits));
#endif
}
inline void deallocate_var_all (void)
{
#ifndef HB_NDEBUG
allocated_var_bits = 0;
#endif
}
/* Methods */
@ -106,11 +177,6 @@ struct hb_buffer_t {
{ return len - idx; }
inline unsigned int next_serial (void) { return serial++; }
HB_INTERNAL void allocate_var (unsigned int byte_i, unsigned int count, const char *owner);
HB_INTERNAL void deallocate_var (unsigned int byte_i, unsigned int count, const char *owner);
HB_INTERNAL void assert_var (unsigned int byte_i, unsigned int count, const char *owner);
HB_INTERNAL void deallocate_var_all (void);
HB_INTERNAL void add (hb_codepoint_t codepoint,
unsigned int cluster);
HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
@ -203,18 +269,28 @@ struct hb_buffer_t {
inline void clear_context (unsigned int side) { context_len[side] = 0; }
HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
inline bool messaging (void) { return unlikely (message_func); }
inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
{
if (!messaging ())
return true;
va_list ap;
va_start (ap, fmt);
bool ret = message_impl (font, fmt, ap);
va_end (ap);
return ret;
}
HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
};
#define HB_BUFFER_XALLOCATE_VAR(b, func, var, owner) \
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
sizeof (b->info[0].var), owner)
#define HB_BUFFER_ALLOCATE_VAR(b, var) \
HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var (), #var)
#define HB_BUFFER_DEALLOCATE_VAR(b, var) \
HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var (), #var)
#define HB_BUFFER_ASSERT_VAR(b, var) \
HB_BUFFER_XALLOCATE_VAR (b, assert_var, var (), #var)
sizeof (b->info[0].var))
#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
#endif /* HB_BUFFER_PRIVATE_HH */

View File

@ -36,11 +36,12 @@ static const char *serialize_formats[] = {
/**
* hb_buffer_serialize_list_formats:
*
*
* Returns a list of supported buffer serialization formats.
*
* Return value: (transfer none):
* A string array of buffer serialization formats. Should not be freed.
*
* Since: 0.9.2
* Since: 0.9.7
**/
const char **
hb_buffer_serialize_list_formats (void)
@ -50,14 +51,17 @@ hb_buffer_serialize_list_formats (void)
/**
* hb_buffer_serialize_format_from_string:
* @str:
* @len:
*
* @str: (array length=len) (element-type uint8_t): a string to parse
* @len: length of @str, or -1 if string is %NULL terminated
*
* Parses a string into an #hb_buffer_serialize_format_t. Does not check if
* @str is a valid buffer serialization format, use
* hb_buffer_serialize_list_formats() to get the list of supported formats.
*
* Return value:
* The parsed #hb_buffer_serialize_format_t.
*
* Since: 0.9.2
* Since: 0.9.7
**/
hb_buffer_serialize_format_t
hb_buffer_serialize_format_from_string (const char *str, int len)
@ -68,13 +72,15 @@ hb_buffer_serialize_format_from_string (const char *str, int len)
/**
* hb_buffer_serialize_format_to_string:
* @format:
* @format: an #hb_buffer_serialize_format_t to convert.
*
* Converts @format to the string corresponding it, or %NULL if it is not a valid
* #hb_buffer_serialize_format_t.
*
* Return value: (transfer none):
* A %NULL terminated string corresponding to @format. Should not be freed.
*
* Return value:
*
* Since: 0.9.2
* Since: 0.9.7
**/
const char *
hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
@ -242,24 +248,51 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
return end - start;
}
/* Returns number of items, starting at start, that were serialized. */
/**
* hb_buffer_serialize_glyphs:
* @buffer: a buffer.
* @start:
* @end:
* @buf: (array length=buf_size):
* @buf_size:
* @buf_consumed: (out):
* @font:
* @format:
* @flags:
* @buffer: an #hb_buffer_t buffer.
* @start: the first item in @buffer to serialize.
* @end: the last item in @buffer to serialize.
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
* @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf.
* @font: (allow-none): the #hb_font_t used to shape this buffer, needed to
* read glyph names and extents. If %NULL, and empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
*
* Serializes @buffer into a textual representation of its glyph content,
* useful for showing the contents of the buffer, for example during debugging.
* There are currently two supported serialization formats:
*
* ## text
* A human-readable, plain text format.
* The serialized glyphs will look something like:
*
* ```
* [uni0651=0@518,0+0|uni0628=0+1897]
* ```
* - The serialized glyphs are delimited with `[` and `]`.
* - Glyphs are separated with `|`
* - Each glyph starts with glyph name, or glyph index if
* #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then,
* - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster.
* - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format:
* - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then,
* - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then,
* - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the
* #hb_glyph_extents_t in the format
* `&lt;x_bearing,y_bearing,width,height&gt;`
*
* ## json
* TODO.
*
* Return value:
* The number of serialized items.
*
* Since: 0.9.2
* Since: 0.9.7
**/
unsigned int
hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
@ -267,8 +300,8 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
unsigned int end,
char *buf,
unsigned int buf_size,
unsigned int *buf_consumed, /* May be NULL */
hb_font_t *font, /* May be NULL */
unsigned int *buf_consumed,
hb_font_t *font,
hb_buffer_serialize_format_t format,
hb_buffer_serialize_flags_t flags)
{
@ -282,6 +315,9 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
if (!buffer->have_positions)
flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
if (unlikely (start == end))
return 0;
@ -355,7 +391,7 @@ parse_int (const char *pp, const char *end, int32_t *pv)
/**
* hb_buffer_deserialize_glyphs:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len):
* @buf_len:
* @end_ptr: (out):
@ -366,7 +402,7 @@ parse_int (const char *pp, const char *end, int32_t *pv)
*
* Return value:
*
* Since: 0.9.2
* Since: 0.9.7
**/
hb_bool_t
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,

View File

@ -35,8 +35,26 @@
#define HB_DEBUG_BUFFER (HB_DEBUG+0)
#endif
/**
* SECTION: hb-buffer
* @title: Buffers
* @short_description: Input and output buffers
* @include: hb.h
*
* Buffers serve dual role in HarfBuzz; they hold the input characters that are
* passed hb_shape(), and after shaping they hold the output glyphs.
**/
/**
* hb_segment_properties_equal:
* @a: first #hb_segment_properties_t to compare.
* @b: second #hb_segment_properties_t to compare.
*
* Checks the equality of two #hb_segment_properties_t's.
*
* Return value:
* %true if all properties of @a equal those of @b, false otherwise.
*
* Since: 0.9.7
**/
hb_bool_t
@ -52,6 +70,14 @@ hb_segment_properties_equal (const hb_segment_properties_t *a,
}
/**
* hb_segment_properties_hash:
* @p: #hb_segment_properties_t to hash.
*
* Creates a hash representing @p.
*
* Return value:
* A hash of @p.
*
* Since: 0.9.7
**/
unsigned int
@ -91,6 +117,11 @@ 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;
@ -152,6 +183,12 @@ hb_buffer_t::shift_forward (unsigned int count)
if (unlikely (!ensure (len + count))) return false;
memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0]));
if (idx + count > len)
{
/* Under memory failure we might expose this area. At least
* clean it up. Oh well... */
memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
}
len += count;
idx += count;
@ -198,6 +235,7 @@ 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;
@ -210,11 +248,11 @@ hb_buffer_t::clear (void)
out_info = info;
serial = 0;
memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
memset (allocated_var_owner, 0, sizeof allocated_var_owner);
memset (context, 0, sizeof context);
memset (context_len, 0, sizeof context_len);
deallocate_var_all ();
}
void
@ -375,6 +413,8 @@ hb_buffer_t::move_to (unsigned int i)
idx = i;
return true;
}
if (unlikely (in_error))
return false;
assert (i <= out_len + (len - idx));
@ -392,6 +432,8 @@ hb_buffer_t::move_to (unsigned int i)
/* Tricky part: rewinding... */
unsigned int count = out_len - i;
/* This will blow in our face if memory allocation fails later
* in this same lookup... */
if (unlikely (idx < count && !shift_forward (count + 32))) return false;
assert (idx >= count);
@ -627,82 +669,19 @@ hb_buffer_t::guess_segment_properties (void)
}
static inline void
dump_var_allocation (const hb_buffer_t *buffer)
{
char buf[80];
for (unsigned int i = 0; i < 8; i++)
buf[i] = '0' + buffer->allocated_var_bytes[7 - i];
buf[8] = '\0';
DEBUG_MSG (BUFFER, buffer,
"Current var allocation: %s",
buf);
}
void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner)
{
assert (byte_i < 8 && byte_i + count <= 8);
if (DEBUG_ENABLED (BUFFER))
dump_var_allocation (this);
DEBUG_MSG (BUFFER, this,
"Allocating var bytes %d..%d for %s",
byte_i, byte_i + count - 1, owner);
for (unsigned int i = byte_i; i < byte_i + count; i++) {
assert (!allocated_var_bytes[i]);
allocated_var_bytes[i]++;
allocated_var_owner[i] = owner;
}
}
void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
{
if (DEBUG_ENABLED (BUFFER))
dump_var_allocation (this);
DEBUG_MSG (BUFFER, this,
"Deallocating var bytes %d..%d for %s",
byte_i, byte_i + count - 1, owner);
assert (byte_i < 8 && byte_i + count <= 8);
for (unsigned int i = byte_i; i < byte_i + count; i++) {
assert (allocated_var_bytes[i]);
assert (0 == strcmp (allocated_var_owner[i], owner));
allocated_var_bytes[i]--;
}
}
void hb_buffer_t::assert_var (unsigned int byte_i, unsigned int count, const char *owner)
{
if (DEBUG_ENABLED (BUFFER))
dump_var_allocation (this);
DEBUG_MSG (BUFFER, this,
"Asserting var bytes %d..%d for %s",
byte_i, byte_i + count - 1, owner);
assert (byte_i < 8 && byte_i + count <= 8);
for (unsigned int i = byte_i; i < byte_i + count; i++) {
assert (allocated_var_bytes[i]);
assert (0 == strcmp (allocated_var_owner[i], owner));
}
}
void hb_buffer_t::deallocate_var_all (void)
{
memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes));
memset (allocated_var_owner, 0, sizeof (allocated_var_owner));
}
/* Public API */
/**
* hb_buffer_create: (Xconstructor)
*
* Creates a new #hb_buffer_t with all properties to defaults.
*
*
* Return value: (transfer full)
* Return value: (transfer full):
* A newly allocated #hb_buffer_t with a reference count of 1. The initial
* reference count should be released with hb_buffer_destroy() when you are done
* using the #hb_buffer_t. This function never returns %NULL. If memory cannot
* be allocated, a special #hb_buffer_t object will be returned on which
* hb_buffer_allocation_successful() returns %false.
*
* Since: 0.9.2
**/
@ -714,6 +693,8 @@ 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;
@ -738,6 +719,8 @@ 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,
@ -753,11 +736,13 @@ hb_buffer_get_empty (void)
/**
* hb_buffer_reference: (skip)
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* Increases the reference count on @buffer by one. This prevents @buffer from
* being destroyed until a matching call to hb_buffer_destroy() is made.
*
* Return value: (transfer full):
* The referenced #hb_buffer_t.
*
* Since: 0.9.2
**/
@ -769,9 +754,11 @@ hb_buffer_reference (hb_buffer_t *buffer)
/**
* hb_buffer_destroy: (skip)
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* Deallocate the @buffer.
* Decreases the reference count on @buffer by one. If the result is zero, then
* @buffer and all associated resources are freed. See hb_buffer_reference().
*
* Since: 0.9.2
**/
@ -784,13 +771,15 @@ hb_buffer_destroy (hb_buffer_t *buffer)
free (buffer->info);
free (buffer->pos);
if (buffer->message_destroy)
buffer->message_destroy (buffer->message_data);
free (buffer);
}
/**
* hb_buffer_set_user_data: (skip)
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
* @key:
* @data:
* @destroy:
@ -814,7 +803,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
/**
* hb_buffer_get_user_data: (skip)
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
* @key:
*
*
@ -833,10 +822,11 @@ hb_buffer_get_user_data (hb_buffer_t *buffer,
/**
* hb_buffer_set_content_type:
* @buffer: a buffer.
* @content_type:
*
* @buffer: an #hb_buffer_t.
* @content_type: the type of buffer contents to set
*
* Sets the type of @buffer contents, buffers are either empty, contain
* characters (before shaping) or glyphs (the result of shaping).
*
* Since: 0.9.5
**/
@ -849,11 +839,12 @@ hb_buffer_set_content_type (hb_buffer_t *buffer,
/**
* hb_buffer_get_content_type:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* see hb_buffer_set_content_type().
*
* Return value:
* The type of @buffer contents.
*
* Since: 0.9.5
**/
@ -866,7 +857,7 @@ hb_buffer_get_content_type (hb_buffer_t *buffer)
/**
* hb_buffer_set_unicode_funcs:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
* @unicode_funcs:
*
*
@ -891,7 +882,7 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
/**
* hb_buffer_get_unicode_funcs:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
*
*
*
@ -907,10 +898,16 @@ hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
/**
* hb_buffer_set_direction:
* @buffer: a buffer.
* @direction:
*
* @buffer: an #hb_buffer_t.
* @direction: the #hb_direction_t of the @buffer
*
* Set the text flow direction of the buffer. No shaping can happen without
* setting @buffer direction, and it controls the visual direction for the
* output glyphs; for RTL direction the glyphs will be reversed. Many layout
* features depend on the proper setting of the direction, for example,
* reversing RTL text before shaping, then shaping with LTR direction is not
* the same as keeping the text in logical order and shaping with RTL
* direction.
*
* Since: 0.9.2
**/
@ -927,11 +924,12 @@ hb_buffer_set_direction (hb_buffer_t *buffer,
/**
* hb_buffer_get_direction:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* See hb_buffer_set_direction()
*
* Return value:
* The direction of the @buffer.
*
* Since: 0.9.2
**/
@ -943,10 +941,18 @@ hb_buffer_get_direction (hb_buffer_t *buffer)
/**
* hb_buffer_set_script:
* @buffer: a buffer.
* @script:
* @buffer: an #hb_buffer_t.
* @script: an #hb_script_t to set.
*
* Sets the script of @buffer to @script.
*
* Script is crucial for choosing the proper shaping behaviour for scripts that
* require it (e.g. Arabic) and the which OpenType features defined in the font
* to be applied.
*
* You can pass one of the predefined #hb_script_t values, or use
* hb_script_from_string() or hb_script_from_iso15924_tag() to get the
* corresponding script from an ISO 15924 script tag.
*
* Since: 0.9.2
**/
@ -962,11 +968,12 @@ hb_buffer_set_script (hb_buffer_t *buffer,
/**
* hb_buffer_get_script:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* See hb_buffer_set_script().
*
* Return value:
* The #hb_script_t of the @buffer.
*
* Since: 0.9.2
**/
@ -978,10 +985,18 @@ hb_buffer_get_script (hb_buffer_t *buffer)
/**
* hb_buffer_set_language:
* @buffer: a buffer.
* @language:
* @buffer: an #hb_buffer_t.
* @language: an hb_language_t to set.
*
* Sets the language of @buffer to @language.
*
* Languages are crucial for selecting which OpenType feature to apply to the
* buffer which can result in applying language-specific behaviour. Languages
* are orthogonal to the scripts, and though they are related, they are
* different concepts and should not be confused with each other.
*
* Use hb_language_from_string() to convert from ISO 639 language codes to
* #hb_language_t.
*
* Since: 0.9.2
**/
@ -997,11 +1012,12 @@ hb_buffer_set_language (hb_buffer_t *buffer,
/**
* hb_buffer_get_language:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* See hb_buffer_set_language().
*
* Return value: (transfer none):
* The #hb_language_t of the buffer. Must not be freed by the caller.
*
* Since: 0.9.2
**/
@ -1013,10 +1029,12 @@ hb_buffer_get_language (hb_buffer_t *buffer)
/**
* hb_buffer_set_segment_properties:
* @buffer: a buffer.
* @props:
*
* @buffer: an #hb_buffer_t.
* @props: an #hb_segment_properties_t to use.
*
* Sets the segment properties of the buffer, a shortcut for calling
* hb_buffer_set_direction(), hb_buffer_set_script() and
* hb_buffer_set_language() individually.
*
* Since: 0.9.7
**/
@ -1032,10 +1050,10 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer,
/**
* hb_buffer_get_segment_properties:
* @buffer: a buffer.
* @props: (out):
*
* @buffer: an #hb_buffer_t.
* @props: (out): the output #hb_segment_properties_t.
*
* Sets @props to the #hb_segment_properties_t of @buffer.
*
* Since: 0.9.7
**/
@ -1049,10 +1067,10 @@ hb_buffer_get_segment_properties (hb_buffer_t *buffer,
/**
* hb_buffer_set_flags:
* @buffer: a buffer.
* @flags:
*
* @buffer: an #hb_buffer_t.
* @flags: the buffer flags to set.
*
* Sets @buffer flags to @flags. See #hb_buffer_flags_t.
*
* Since: 0.9.7
**/
@ -1068,11 +1086,12 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
/**
* hb_buffer_get_flags:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* See hb_buffer_set_flags().
*
* Return value:
* The @buffer flags.
*
* Since: 0.9.7
**/
@ -1084,7 +1103,7 @@ hb_buffer_get_flags (hb_buffer_t *buffer)
/**
* hb_buffer_set_cluster_level:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
* @cluster_level:
*
*
@ -1103,7 +1122,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer,
/**
* hb_buffer_get_cluster_level:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
*
*
*
@ -1120,10 +1139,13 @@ hb_buffer_get_cluster_level (hb_buffer_t *buffer)
/**
* hb_buffer_set_replacement_codepoint:
* @buffer: a buffer.
* @replacement:
* @buffer: an #hb_buffer_t.
* @replacement: the replacement #hb_codepoint_t
*
* Sets the #hb_codepoint_t that replaces invalid entries for a given encoding
* when adding text to @buffer.
*
* Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
*
* Since: 0.9.31
**/
@ -1139,11 +1161,12 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
/**
* hb_buffer_get_replacement_codepoint:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* See hb_buffer_set_replacement_codepoint().
*
* Return value:
* The @buffer replacement #hb_codepoint_t.
*
* Since: 0.9.31
**/
@ -1156,9 +1179,10 @@ hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer)
/**
* hb_buffer_reset:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* Resets the buffer to its initial status, as if it was just newly created
* with hb_buffer_create().
*
* Since: 0.9.2
**/
@ -1170,9 +1194,10 @@ hb_buffer_reset (hb_buffer_t *buffer)
/**
* hb_buffer_clear_contents:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* Similar to hb_buffer_reset(), but does not clear the Unicode functions and
* the replacement code point.
*
* Since: 0.9.11
**/
@ -1184,12 +1209,13 @@ hb_buffer_clear_contents (hb_buffer_t *buffer)
/**
* hb_buffer_pre_allocate:
* @buffer: a buffer.
* @size:
*
* @buffer: an #hb_buffer_t.
* @size: number of items to pre allocate.
*
* Pre allocates memory for @buffer to fit at least @size number of items.
*
* Return value:
* %true if @buffer memory allocation succeeded, %false otherwise.
*
* Since: 0.9.2
**/
@ -1201,11 +1227,12 @@ hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
/**
* hb_buffer_allocation_successful:
* @buffer: a buffer.
*
* @buffer: an #hb_buffer_t.
*
* Check if allocating memory for the buffer succeeded.
*
* Return value:
* %true if @buffer memory allocation succeeded, %false otherwise.
*
* Since: 0.9.2
**/
@ -1217,11 +1244,18 @@ hb_buffer_allocation_successful (hb_buffer_t *buffer)
/**
* hb_buffer_add:
* @buffer: a buffer.
* @codepoint:
* @cluster:
* @buffer: an #hb_buffer_t.
* @codepoint: a Unicode code point.
* @cluster: the cluster value of @codepoint.
*
* Appends a character with the Unicode value of @codepoint to @buffer, and
* gives it the initial cluster value of @cluster. Clusters can be any thing
* the client wants, they are usually used to refer to the index of the
* character in the input text stream and are output in
* #hb_glyph_info_t.cluster field.
*
* This function does not check the validity of @codepoint, it is up to the
* caller to ensure it is a valid Unicode code point.
*
* Since: 0.9.7
**/
@ -1236,12 +1270,14 @@ hb_buffer_add (hb_buffer_t *buffer,
/**
* hb_buffer_set_length:
* @buffer: a buffer.
* @length:
*
* @buffer: an #hb_buffer_t.
* @length: the new length of @buffer.
*
* Similar to hb_buffer_pre_allocate(), but clears any new items added at the
* end.
*
* Return value:
* %true if @buffer memory allocation succeeded, %false otherwise.
*
* Since: 0.9.2
**/
@ -1276,11 +1312,13 @@ hb_buffer_set_length (hb_buffer_t *buffer,
/**
* hb_buffer_get_length:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
*
* Returns the number of items in the buffer.
*
* Return value: buffer length.
* Return value:
* The @buffer length.
* The value valid as long as buffer has not been modified.
*
* Since: 0.9.2
**/
@ -1292,13 +1330,15 @@ hb_buffer_get_length (hb_buffer_t *buffer)
/**
* hb_buffer_get_glyph_infos:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
* @length: (out): output array length.
*
* Returns buffer glyph information array. Returned pointer
* is valid as long as buffer contents are not modified.
* Returns @buffer glyph information array. Returned pointer
* is valid as long as @buffer contents are not modified.
*
* Return value: (transfer none) (array length=length): buffer glyph information array.
* Return value: (transfer none) (array length=length):
* The @buffer glyph information array.
* The value valid as long as buffer has not been modified.
*
* Since: 0.9.2
**/
@ -1314,13 +1354,15 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
/**
* hb_buffer_get_glyph_positions:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
* @length: (out): output length.
*
* Returns buffer glyph position array. Returned pointer
* is valid as long as buffer contents are not modified.
* Returns @buffer glyph position array. Returned pointer
* is valid as long as @buffer contents are not modified.
*
* Return value: (transfer none) (array length=length): buffer glyph position array.
* Return value: (transfer none) (array length=length):
* The @buffer glyph position array.
* The value valid as long as buffer has not been modified.
*
* Since: 0.9.2
**/
@ -1339,7 +1381,7 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
/**
* hb_buffer_reverse:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
*
* Reverses buffer contents.
*
@ -1353,7 +1395,7 @@ hb_buffer_reverse (hb_buffer_t *buffer)
/**
* hb_buffer_reverse_range:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
* @start: start index.
* @end: end index.
*
@ -1370,7 +1412,7 @@ hb_buffer_reverse_range (hb_buffer_t *buffer,
/**
* hb_buffer_reverse_clusters:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
*
* Reverses buffer clusters. That is, the buffer contents are
* reversed, then each cluster (consecutive items having the
@ -1386,7 +1428,7 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer)
/**
* hb_buffer_guess_segment_properties:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
*
* Sets unset buffer segment properties based on buffer Unicode
* contents. If buffer is not empty, it must have content type
@ -1485,13 +1527,18 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
/**
* hb_buffer_add_utf8:
* @buffer: a buffer.
* @text: (array length=text_length) (element-type uint8_t):
* @text_length:
* @item_offset:
* @item_length:
* @buffer: an #hb_buffer_t.
* @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
* characters to append.
* @text_length: the length of the @text, or -1 if it is %NULL terminated.
* @item_offset: the offset of the first character to add to the @buffer.
* @item_length: the number of characters to add to the @buffer, or -1 for the
* end of @text (assuming it is %NULL terminated).
*
* See hb_buffer_add_codepoints().
*
* Replaces invalid UTF-8 characters with the @buffer replacement code point,
* see hb_buffer_set_replacement_codepoint().
*
* Since: 0.9.2
**/
@ -1507,13 +1554,17 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer,
/**
* hb_buffer_add_utf16:
* @buffer: a buffer.
* @text: (array length=text_length):
* @text_length:
* @item_offset:
* @item_length:
* @buffer: an #hb_buffer_t.
* @text: (array length=text_length): an array of UTF-16 characters to append.
* @text_length: the length of the @text, or -1 if it is %NULL terminated.
* @item_offset: the offset of the first character to add to the @buffer.
* @item_length: the number of characters to add to the @buffer, or -1 for the
* end of @text (assuming it is %NULL terminated).
*
* See hb_buffer_add_codepoints().
*
* Replaces invalid UTF-16 characters with the @buffer replacement code point,
* see hb_buffer_set_replacement_codepoint().
*
* Since: 0.9.2
**/
@ -1529,13 +1580,17 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer,
/**
* hb_buffer_add_utf32:
* @buffer: a buffer.
* @text: (array length=text_length):
* @text_length:
* @item_offset:
* @item_length:
* @buffer: an #hb_buffer_t.
* @text: (array length=text_length): an array of UTF-32 characters to append.
* @text_length: the length of the @text, or -1 if it is %NULL terminated.
* @item_offset: the offset of the first character to add to the @buffer.
* @item_length: the number of characters to add to the @buffer, or -1 for the
* end of @text (assuming it is %NULL terminated).
*
* See hb_buffer_add_codepoints().
*
* Replaces invalid UTF-32 characters with the @buffer replacement code point,
* see hb_buffer_set_replacement_codepoint().
*
* Since: 0.9.2
**/
@ -1551,13 +1606,18 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
/**
* hb_buffer_add_latin1:
* @buffer: a buffer.
* @text: (array length=text_length) (element-type uint8_t):
* @text_length:
* @item_offset:
* @item_length:
* @buffer: an #hb_buffer_t.
* @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
* characters to append.
* @text_length: the length of the @text, or -1 if it is %NULL terminated.
* @item_offset: the offset of the first character to add to the @buffer.
* @item_length: the number of characters to add to the @buffer, or -1 for the
* end of @text (assuming it is %NULL terminated).
*
* Similar to hb_buffer_add_codepoints(), but allows only access to first 256
* Unicode code points that can fit in 8-bit strings.
*
* <note>Has nothing to do with non-Unicode Latin-1 encoding.</note>
*
* Since: 0.9.39
**/
@ -1573,13 +1633,25 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer,
/**
* hb_buffer_add_codepoints:
* @buffer: a buffer.
* @text: (array length=text_length):
* @text_length:
* @item_offset:
* @item_length:
* @buffer: a #hb_buffer_t to append characters to.
* @text: (array length=text_length): an array of Unicode code points to append.
* @text_length: the length of the @text, or -1 if it is %NULL terminated.
* @item_offset: the offset of the first code point to add to the @buffer.
* @item_length: the number of code points to add to the @buffer, or -1 for the
* end of @text (assuming it is %NULL terminated).
*
* Appends characters from @text array to @buffer. The @item_offset is the
* position of the first character from @text that will be appended, and
* @item_length is the number of character. When shaping part of a larger text
* (e.g. a run of text from a paragraph), instead of passing just the substring
* corresponding to the run, it is preferable to pass the whole
* paragraph and specify the run start and length as @item_offset and
* @item_length, respectively, to give HarfBuzz the full context to be able,
* for example, to do cross-run Arabic shaping or properly handle combining
* marks at stat of run.
*
* This function does not check the validity of @text, it is up to the caller
* to ensure it contains a valid Unicode code points.
*
* Since: 0.9.31
**/
@ -1651,9 +1723,12 @@ normalize_glyphs_cluster (hb_buffer_t *buffer,
/**
* hb_buffer_normalize_glyphs:
* @buffer: a buffer.
* @buffer: an #hb_buffer_t.
*
* Reorders a glyph buffer to have canonical in-cluster glyph order / position.
* The resulting clusters should behave identical to pre-reordering clusters.
*
* <note>This has nothing to do with Unicode normalization.</note>
*
* Since: 0.9.2
**/
@ -1699,3 +1774,45 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g
}
}
}
/*
* Debugging.
*/
/**
* hb_buffer_set_message_func:
* @buffer: an #hb_buffer_t.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
* @destroy:
*
*
*
* Since: 1.1.3
**/
void
hb_buffer_set_message_func (hb_buffer_t *buffer,
hb_buffer_message_func_t func,
void *user_data, hb_destroy_func_t destroy)
{
if (buffer->message_destroy)
buffer->message_destroy (buffer->message_data);
if (func) {
buffer->message_func = func;
buffer->message_data = user_data;
buffer->message_destroy = destroy;
} else {
buffer->message_func = NULL;
buffer->message_data = NULL;
buffer->message_destroy = NULL;
}
}
bool
hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
{
char buf[100];
vsnprintf (buf, sizeof (buf), fmt, ap);
return (bool) this->message_func (this, font, buf, this->message_data);
}

View File

@ -40,7 +40,27 @@
HB_BEGIN_DECLS
/**
* hb_glyph_info_t:
* @codepoint: either a Unicode code point (before shaping) or a glyph index
* (after shaping).
* @mask:
* @cluster: the index of the character in the original text that corresponds
* to this #hb_glyph_info_t, or whatever the client passes to
* hb_buffer_add(). More than one #hb_glyph_info_t can have the same
* @cluster value, if they resulted from the same character (e.g. one
* to many glyph substitution), and when more than one character gets
* merged in the same glyph (e.g. many to one glyph substitution) the
* #hb_glyph_info_t will have the smallest cluster value of them.
* By default some characters are merged into the same cluster
* (e.g. combining marks have the same cluster as their bases)
* even if they are separate glyphs, hb_buffer_set_cluster_level()
* allow selecting more fine-grained cluster handling.
*
* The #hb_glyph_info_t is the structure that holds information about the
* glyphs and their relation to input text.
*
*/
typedef struct hb_glyph_info_t {
hb_codepoint_t codepoint;
hb_mask_t mask;
@ -51,6 +71,22 @@ typedef struct hb_glyph_info_t {
hb_var_int_t var2;
} hb_glyph_info_t;
/**
* hb_glyph_position_t:
* @x_advance: how much the line advances after drawing this glyph when setting
* text in horizontal direction.
* @y_advance: how much the line advances after drawing this glyph when setting
* text in vertical direction.
* @x_offset: how much the glyph moves on the X-axis before drawing it, this
* should not affect how much the line advances.
* @y_offset: how much the glyph moves on the Y-axis before drawing it, this
* should not affect how much the line advances.
*
* The #hb_glyph_position_t is the structure that holds the positions of the
* glyph in both horizontal and vertical directions. All positions in
* #hb_glyph_position_t are relative to the current point.
*
*/
typedef struct hb_glyph_position_t {
hb_position_t x_advance;
hb_position_t y_advance;
@ -61,7 +97,16 @@ typedef struct hb_glyph_position_t {
hb_var_int_t var;
} hb_glyph_position_t;
/**
* hb_segment_properties_t:
* @direction: the #hb_direction_t of the buffer, see hb_buffer_set_direction().
* @script: the #hb_script_t of the buffer, see hb_buffer_set_script().
* @language: the #hb_language_t of the buffer, see hb_buffer_set_language().
*
* The structure that holds various text properties of an #hb_buffer_t. Can be
* set and retrieved using hb_buffer_set_segment_properties() and
* hb_buffer_get_segment_properties(), respectively.
*/
typedef struct hb_segment_properties_t {
hb_direction_t direction;
hb_script_t script;
@ -77,101 +122,125 @@ typedef struct hb_segment_properties_t {
NULL, \
NULL}
hb_bool_t
HB_EXTERN hb_bool_t
hb_segment_properties_equal (const hb_segment_properties_t *a,
const hb_segment_properties_t *b);
unsigned int
HB_EXTERN unsigned int
hb_segment_properties_hash (const hb_segment_properties_t *p);
/*
* hb_buffer_t
/**
* hb_buffer_t:
*
* The main structure holding the input text and its properties before shaping,
* and output glyphs and their information after shaping.
*/
typedef struct hb_buffer_t hb_buffer_t;
hb_buffer_t *
HB_EXTERN hb_buffer_t *
hb_buffer_create (void);
hb_buffer_t *
HB_EXTERN hb_buffer_t *
hb_buffer_get_empty (void);
hb_buffer_t *
HB_EXTERN hb_buffer_t *
hb_buffer_reference (hb_buffer_t *buffer);
void
HB_EXTERN void
hb_buffer_destroy (hb_buffer_t *buffer);
hb_bool_t
HB_EXTERN hb_bool_t
hb_buffer_set_user_data (hb_buffer_t *buffer,
hb_user_data_key_t *key,
void * data,
hb_destroy_func_t destroy,
hb_bool_t replace);
void *
HB_EXTERN void *
hb_buffer_get_user_data (hb_buffer_t *buffer,
hb_user_data_key_t *key);
/**
* hb_buffer_content_type_t:
* @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
* @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping).
* @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping).
*/
typedef enum {
HB_BUFFER_CONTENT_TYPE_INVALID = 0,
HB_BUFFER_CONTENT_TYPE_UNICODE,
HB_BUFFER_CONTENT_TYPE_GLYPHS
} hb_buffer_content_type_t;
void
HB_EXTERN void
hb_buffer_set_content_type (hb_buffer_t *buffer,
hb_buffer_content_type_t content_type);
hb_buffer_content_type_t
HB_EXTERN hb_buffer_content_type_t
hb_buffer_get_content_type (hb_buffer_t *buffer);
void
HB_EXTERN void
hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
hb_unicode_funcs_t *unicode_funcs);
hb_unicode_funcs_t *
HB_EXTERN hb_unicode_funcs_t *
hb_buffer_get_unicode_funcs (hb_buffer_t *buffer);
void
HB_EXTERN void
hb_buffer_set_direction (hb_buffer_t *buffer,
hb_direction_t direction);
hb_direction_t
HB_EXTERN hb_direction_t
hb_buffer_get_direction (hb_buffer_t *buffer);
void
HB_EXTERN void
hb_buffer_set_script (hb_buffer_t *buffer,
hb_script_t script);
hb_script_t
HB_EXTERN hb_script_t
hb_buffer_get_script (hb_buffer_t *buffer);
void
HB_EXTERN void
hb_buffer_set_language (hb_buffer_t *buffer,
hb_language_t language);
hb_language_t
HB_EXTERN hb_language_t
hb_buffer_get_language (hb_buffer_t *buffer);
void
HB_EXTERN void
hb_buffer_set_segment_properties (hb_buffer_t *buffer,
const hb_segment_properties_t *props);
void
HB_EXTERN void
hb_buffer_get_segment_properties (hb_buffer_t *buffer,
hb_segment_properties_t *props);
void
HB_EXTERN void
hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
/*
/**
* hb_buffer_flags_t:
* @HB_BUFFER_FLAG_DEFAULT: the default buffer flag.
* @HB_BUFFER_FLAG_BOT: flag indicating that special handling of the beginning
* of text paragraph can be applied to this buffer. Should usually
* be set, unless you are passing to the buffer only part
* of the text without the full context.
* @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text
* paragraph can be applied to this buffer, similar to
* @HB_BUFFER_FLAG_EOT.
* @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES:
* flag indication that character with Default_Ignorable
* Unicode property should use the corresponding glyph
* from the font, instead of hiding them (currently done
* by replacing them with the space glyph and zeroing the
* advance width.)
*
* Since: 0.9.20
*/
typedef enum { /*< flags >*/
@ -181,11 +250,11 @@ typedef enum { /*< flags >*/
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u
} hb_buffer_flags_t;
void
HB_EXTERN void
hb_buffer_set_flags (hb_buffer_t *buffer,
hb_buffer_flags_t flags);
hb_buffer_flags_t
HB_EXTERN hb_buffer_flags_t
hb_buffer_get_flags (hb_buffer_t *buffer);
/*
@ -198,93 +267,92 @@ typedef enum {
HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
} hb_buffer_cluster_level_t;
void
HB_EXTERN void
hb_buffer_set_cluster_level (hb_buffer_t *buffer,
hb_buffer_cluster_level_t cluster_level);
hb_buffer_cluster_level_t
HB_EXTERN hb_buffer_cluster_level_t
hb_buffer_get_cluster_level (hb_buffer_t *buffer);
/**
* HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT:
*
* The default code point for replacing invalid characters in a given encoding.
* Set to U+FFFD REPLACEMENT CHARACTER.
*
* Since: 0.9.31
*/
#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
/* Sets codepoint used to replace invalid UTF-8/16/32 entries.
* Default is 0xFFFDu. */
void
HB_EXTERN void
hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
hb_codepoint_t replacement);
hb_codepoint_t
HB_EXTERN hb_codepoint_t
hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer);
/* Resets the buffer. Afterwards it's as if it was just created,
* except that it has a larger buffer allocated perhaps... */
void
HB_EXTERN void
hb_buffer_reset (hb_buffer_t *buffer);
/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */
void
HB_EXTERN void
hb_buffer_clear_contents (hb_buffer_t *buffer);
/* Returns false if allocation failed */
hb_bool_t
HB_EXTERN hb_bool_t
hb_buffer_pre_allocate (hb_buffer_t *buffer,
unsigned int size);
/* Returns false if allocation has failed before */
hb_bool_t
HB_EXTERN hb_bool_t
hb_buffer_allocation_successful (hb_buffer_t *buffer);
void
HB_EXTERN void
hb_buffer_reverse (hb_buffer_t *buffer);
void
HB_EXTERN void
hb_buffer_reverse_range (hb_buffer_t *buffer,
unsigned int start, unsigned int end);
void
HB_EXTERN void
hb_buffer_reverse_clusters (hb_buffer_t *buffer);
/* Filling the buffer in */
void
HB_EXTERN void
hb_buffer_add (hb_buffer_t *buffer,
hb_codepoint_t codepoint,
unsigned int cluster);
void
HB_EXTERN void
hb_buffer_add_utf8 (hb_buffer_t *buffer,
const char *text,
int text_length,
unsigned int item_offset,
int item_length);
void
HB_EXTERN void
hb_buffer_add_utf16 (hb_buffer_t *buffer,
const uint16_t *text,
int text_length,
unsigned int item_offset,
int item_length);
void
HB_EXTERN void
hb_buffer_add_utf32 (hb_buffer_t *buffer,
const uint32_t *text,
int text_length,
unsigned int item_offset,
int item_length);
/* Allows only access to first 256 Unicode codepoints. */
void
HB_EXTERN void
hb_buffer_add_latin1 (hb_buffer_t *buffer,
const uint8_t *text,
int text_length,
unsigned int item_offset,
int item_length);
/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */
void
HB_EXTERN void
hb_buffer_add_codepoints (hb_buffer_t *buffer,
const hb_codepoint_t *text,
int text_length,
@ -292,32 +360,25 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
int item_length);
/* Clears any new items added at the end */
hb_bool_t
HB_EXTERN hb_bool_t
hb_buffer_set_length (hb_buffer_t *buffer,
unsigned int length);
/* Return value valid as long as buffer not modified */
unsigned int
HB_EXTERN unsigned int
hb_buffer_get_length (hb_buffer_t *buffer);
/* Getting glyphs out of the buffer */
/* Return value valid as long as buffer not modified */
hb_glyph_info_t *
HB_EXTERN hb_glyph_info_t *
hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
unsigned int *length);
/* Return value valid as long as buffer not modified */
hb_glyph_position_t *
HB_EXTERN hb_glyph_position_t *
hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
unsigned int *length);
/* Reorders a glyph buffer to have canonical in-cluster glyph order / position.
* The resulting clusters should behave identical to pre-reordering clusters.
* NOTE: This has nothing to do with Unicode normalization. */
void
HB_EXTERN void
hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
@ -325,7 +386,16 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
* Serialize
*/
/*
/**
* hb_buffer_serialize_flags_t:
* @HB_BUFFER_SERIALIZE_FLAG_DEFAULT: serialize glyph names, clusters and positions.
* @HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS: do not serialize glyph cluster.
* @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information.
* @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name.
* @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents.
*
* Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
*
* Since: 0.9.20
*/
typedef enum { /*< flags >*/
@ -336,43 +406,67 @@ typedef enum { /*< flags >*/
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u
} hb_buffer_serialize_flags_t;
/**
* hb_buffer_serialize_format_t:
* @HB_BUFFER_SERIALIZE_FORMAT_TEXT: a human-readable, plain text format.
* @HB_BUFFER_SERIALIZE_FORMAT_JSON: a machine-readable JSON format.
* @HB_BUFFER_SERIALIZE_FORMAT_INVALID: invalid format.
*
* The buffer serialization and de-serialization format used in
* hb_buffer_serialize_glyphs() and hb_buffer_deserialize_glyphs().
*
* Since: 0.9.2
*/
typedef enum {
HB_BUFFER_SERIALIZE_FORMAT_TEXT = HB_TAG('T','E','X','T'),
HB_BUFFER_SERIALIZE_FORMAT_JSON = HB_TAG('J','S','O','N'),
HB_BUFFER_SERIALIZE_FORMAT_INVALID = HB_TAG_NONE
} hb_buffer_serialize_format_t;
/* len=-1 means str is NUL-terminated. */
hb_buffer_serialize_format_t
HB_EXTERN hb_buffer_serialize_format_t
hb_buffer_serialize_format_from_string (const char *str, int len);
const char *
HB_EXTERN const char *
hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format);
const char **
HB_EXTERN const char **
hb_buffer_serialize_list_formats (void);
/* Returns number of items, starting at start, that were serialized. */
unsigned int
HB_EXTERN unsigned int
hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
unsigned int start,
unsigned int end,
char *buf,
unsigned int buf_size,
unsigned int *buf_consumed, /* May be NULL */
hb_font_t *font, /* May be NULL */
unsigned int *buf_consumed,
hb_font_t *font,
hb_buffer_serialize_format_t format,
hb_buffer_serialize_flags_t flags);
hb_bool_t
HB_EXTERN hb_bool_t
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
const char *buf,
int buf_len, /* -1 means nul-terminated */
const char **end_ptr, /* May be NULL */
hb_font_t *font, /* May be NULL */
int buf_len,
const char **end_ptr,
hb_font_t *font,
hb_buffer_serialize_format_t format);
/*
* Debugging.
*/
typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer,
hb_font_t *font,
const char *message,
void *user_data);
HB_EXTERN void
hb_buffer_set_message_func (hb_buffer_t *buffer,
hb_buffer_message_func_t func,
void *user_data, hb_destroy_func_t destroy);
HB_END_DECLS
#endif /* HB_BUFFER_H */

View File

@ -88,7 +88,7 @@ hb_tag_from_string (const char *str, int len)
/**
* hb_tag_to_string:
* @tag:
* @buf: (array fixed-size=4):
* @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t):
*
*
*
@ -281,12 +281,15 @@ retry:
/**
* hb_language_from_string:
* @str: (array length=len) (element-type uint8_t):
* @len:
*
* @str: (array length=len) (element-type uint8_t): a string representing
* ISO 639 language code
* @len: length of the @str, or -1 if it is %NULL-terminated.
*
* Converts @str representing an ISO 639 language code to the corresponding
* #hb_language_t.
*
* Return value: (transfer none):
* The #hb_language_t corresponding to the ISO 639 language code.
*
* Since: 0.9.2
**/
@ -314,11 +317,13 @@ hb_language_from_string (const char *str, int len)
/**
* hb_language_to_string:
* @language:
*
* @language: an #hb_language_t to convert.
*
* See hb_language_from_string().
*
* Return value: (transfer none):
* A %NULL-terminated string representing the @language. Must not be freed by
* the caller.
*
* Since: 0.9.2
**/
@ -357,11 +362,12 @@ hb_language_get_default (void)
/**
* hb_script_from_iso15924_tag:
* @tag:
*
* @tag: an #hb_tag_t representing an ISO 15924 tag.
*
* Converts an ISO 15924 script tag to a corresponding #hb_script_t.
*
* Return value:
* An #hb_script_t corresponding to the ISO 15924 tag.
*
* Since: 0.9.2
**/
@ -401,28 +407,33 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
/**
* hb_script_from_string:
* @s: (array length=len) (element-type uint8_t):
* @len:
*
* @str: (array length=len) (element-type uint8_t): a string representing an
* ISO 15924 tag.
* @len: length of the @str, or -1 if it is %NULL-terminated.
*
* Converts a string @str representing an ISO 15924 script tag to a
* corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
* hb_script_from_iso15924_tag().
*
* Return value:
* An #hb_script_t corresponding to the ISO 15924 tag.
*
* Since: 0.9.2
**/
hb_script_t
hb_script_from_string (const char *s, int len)
hb_script_from_string (const char *str, int len)
{
return hb_script_from_iso15924_tag (hb_tag_from_string (s, len));
return hb_script_from_iso15924_tag (hb_tag_from_string (str, len));
}
/**
* hb_script_to_iso15924_tag:
* @script:
*
* @script: an #hb_script_ to convert.
*
* See hb_script_from_iso15924_tag().
*
* Return value:
* An #hb_tag_t representing an ISO 15924 script tag.
*
* Since: 0.9.2
**/
@ -496,6 +507,9 @@ hb_script_get_horizontal_direction (hb_script_t script)
/* Unicode-8.0 additions */
case HB_SCRIPT_OLD_HUNGARIAN:
/* Unicode-9.0 additions */
case HB_SCRIPT_ADLAM:
return HB_DIRECTION_RTL;
}
@ -521,7 +535,7 @@ hb_user_data_array_t::set (hb_user_data_key_t *key,
}
}
hb_user_data_item_t item = {key, data, destroy};
bool ret = !!items.replace_or_insert (item, lock, replace);
bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
return ret;
}
@ -529,7 +543,7 @@ hb_user_data_array_t::set (hb_user_data_key_t *key,
void *
hb_user_data_array_t::get (hb_user_data_key_t *key)
{
hb_user_data_item_t item = {NULL };
hb_user_data_item_t item = {NULL, NULL, NULL};
return items.find (key, &item, lock) ? item.data : NULL;
}

View File

@ -98,16 +98,22 @@ typedef uint32_t hb_tag_t;
#define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff)
/* len=-1 means str is NUL-terminated. */
hb_tag_t
HB_EXTERN hb_tag_t
hb_tag_from_string (const char *str, int len);
/* buf should have 4 bytes. */
void
HB_EXTERN void
hb_tag_to_string (hb_tag_t tag, char *buf);
/* hb_direction_t */
/**
* hb_direction_t:
* @HB_DIRECTION_INVALID: Initial, unset direction.
* @HB_DIRECTION_LTR: Text is set horizontally from left to right.
* @HB_DIRECTION_RTL: Text is set horizontally from right to left.
* @HB_DIRECTION_TTB: Text is set vertically from top to bottom.
* @HB_DIRECTION_BTT: Text is set vertically from bottom to top.
*/
typedef enum {
HB_DIRECTION_INVALID = 0,
HB_DIRECTION_LTR = 4,
@ -117,10 +123,10 @@ typedef enum {
} hb_direction_t;
/* len=-1 means str is NUL-terminated */
hb_direction_t
HB_EXTERN hb_direction_t
hb_direction_from_string (const char *str, int len);
const char *
HB_EXTERN const char *
hb_direction_to_string (hb_direction_t direction);
#define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4)
@ -136,16 +142,15 @@ hb_direction_to_string (hb_direction_t direction);
typedef const struct hb_language_impl_t *hb_language_t;
/* len=-1 means str is NUL-terminated */
hb_language_t
HB_EXTERN hb_language_t
hb_language_from_string (const char *str, int len);
const char *
HB_EXTERN const char *
hb_language_to_string (hb_language_t language);
#define HB_LANGUAGE_INVALID ((hb_language_t) NULL)
hb_language_t
HB_EXTERN hb_language_t
hb_language_get_default (void);
@ -306,6 +311,16 @@ typedef enum
/*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'),
/*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'),
/*
* Since 1.3.0
*/
/*9.0*/ HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'),
/*9.0*/ HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'),
/*9.0*/ HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'),
/*9.0*/ HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'),
/*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'),
/*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'),
/* No script set. */
HB_SCRIPT_INVALID = HB_TAG_NONE,
@ -324,18 +339,16 @@ typedef enum
/* Script functions */
hb_script_t
HB_EXTERN hb_script_t
hb_script_from_iso15924_tag (hb_tag_t tag);
/* sugar for tag_from_string() then script_from_iso15924_tag */
/* len=-1 means s is NUL-terminated */
hb_script_t
hb_script_from_string (const char *s, int len);
HB_EXTERN hb_script_t
hb_script_from_string (const char *str, int len);
hb_tag_t
HB_EXTERN hb_tag_t
hb_script_to_iso15924_tag (hb_script_t script);
hb_direction_t
HB_EXTERN hb_direction_t
hb_script_get_horizontal_direction (hb_script_t script);

View File

@ -27,7 +27,6 @@
*/
#define HB_SHAPER coretext
#define hb_coretext_shaper_face_data_t CGFont
#include "hb-shaper-impl-private.hh"
#include "hb-coretext.h"
@ -78,6 +77,29 @@ HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
* shaper face data
*/
static CTFontDescriptorRef
get_last_resort_font_desc (void)
{
// TODO Handle allocation failures?
CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
(const void **) &last_resort,
1,
&kCFTypeArrayCallBacks);
CFRelease (last_resort);
CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault,
(const void **) &kCTFontCascadeListAttribute,
(const void **) &cascade_list,
1,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFRelease (cascade_list);
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
CFRelease (attributes);
return font_desc;
}
static void
release_data (void *info, const void *data, size_t size)
{
@ -87,14 +109,13 @@ release_data (void *info, const void *data, size_t size)
hb_blob_destroy ((hb_blob_t *) info);
}
hb_coretext_shaper_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
static CGFontRef
create_cg_font (hb_face_t *face)
{
hb_coretext_shaper_face_data_t *data = NULL;
CGFontRef cg_font = NULL;
if (face->destroy == (hb_destroy_func_t) CGFontRelease)
{
data = CGFontRetain ((CGFontRef) face->user_data);
cg_font = CGFontRetain ((CGFontRef) face->user_data);
}
else
{
@ -107,13 +128,98 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face)
CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
if (likely (provider))
{
data = CGFontCreateWithDataProvider (provider);
cg_font = CGFontCreateWithDataProvider (provider);
if (unlikely (!cg_font))
DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
CGDataProviderRelease (provider);
}
}
return cg_font;
}
if (unlikely (!data)) {
DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
static CTFontRef
create_ct_font (CGFontRef cg_font, CGFloat font_size)
{
CTFontRef ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL);
if (unlikely (!ct_font)) {
DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
return NULL;
}
CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute);
/* Create font copy with cascade list that has LastResort first; this speeds up CoreText
* font fallback which we don't need anyway. */
{
CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, last_resort_font_desc);
CFRelease (last_resort_font_desc);
if (new_ct_font)
{
/* The CTFontCreateCopyWithAttributes call fails to stay on the same font
* when reconfiguring the cascade list and may switch to a different font
* when there are fonts that go by the same name, since the descriptor is
* just name and size.
*
* Avoid reconfiguring the cascade lists if the new font is outside the
* system locations that we cannot access from the sandboxed renderer
* process in Blink. This can be detected by the new file URL location
* that the newly found font points to. */
CFURLRef new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
// Keep reconfigured font if URL cannot be retrieved (seems to be the case
// on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
if (!original_url || !new_url || CFEqual (original_url, new_url)) {
CFRelease (ct_font);
ct_font = new_ct_font;
} else {
CFRelease (new_ct_font);
DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
}
if (new_url)
CFRelease (new_url);
}
else
DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
}
if (original_url)
CFRelease (original_url);
return ct_font;
}
struct hb_coretext_shaper_face_data_t {
CGFontRef cg_font;
CTFontRef ct_font;
};
hb_coretext_shaper_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
{
hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t));
if (unlikely (!data))
return NULL;
data->cg_font = create_cg_font (face);
if (unlikely (!data->cg_font))
{
DEBUG_MSG (CORETEXT, face, "CGFont creation failed..");
free (data);
return NULL;
}
/* We use 36pt size instead of UPEM, because CoreText implements the 'trak' table,
* which can make the font too tight at large sizes. 36pt should be a good semi-neutral
* size.
*
* Since we always create CTFont at a fixed size, our CTFont lives in face_data
* instead of font_data. Which is good, because when people change scale on
* hb_font_t, we won't need to update our CTFont. */
data->ct_font = create_ct_font (data->cg_font, 36.);
if (unlikely (!data->ct_font))
{
DEBUG_MSG (CORETEXT, face, "CTFont creation failed.");
CFRelease (data->cg_font);
free (data);
return NULL;
}
return data;
@ -122,7 +228,9 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face)
void
_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
{
CFRelease (data);
CFRelease (data->ct_font);
CFRelease (data->cg_font);
free (data);
}
/*
@ -133,7 +241,7 @@ hb_coretext_face_get_cg_font (hb_face_t *face)
{
if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL;
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
return face_data;
return face_data->cg_font;
}
@ -141,49 +249,17 @@ hb_coretext_face_get_cg_font (hb_face_t *face)
* shaper font data
*/
struct hb_coretext_shaper_font_data_t {
CTFontRef ct_font;
CGFloat x_mult, y_mult; /* From CT space to HB space. */
};
struct hb_coretext_shaper_font_data_t {};
hb_coretext_shaper_font_data_t *
_hb_coretext_shaper_font_data_create (hb_font_t *font)
_hb_coretext_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL;
hb_coretext_shaper_font_data_t *data = (hb_coretext_shaper_font_data_t *) calloc (1, sizeof (hb_coretext_shaper_font_data_t));
if (unlikely (!data))
return NULL;
hb_face_t *face = font->face;
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
/* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */
/* TODO: use upem instead of 36? */
CGFloat font_size = 36.; /* Default... */
/* No idea if the following is even a good idea. */
if (font->y_ppem)
font_size = font->y_ppem;
if (font_size < 0)
font_size = -font_size;
data->x_mult = (CGFloat) font->x_scale / font_size;
data->y_mult = (CGFloat) font->y_scale / font_size;
data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL);
if (unlikely (!data->ct_font)) {
DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
free (data);
return NULL;
}
return data;
return (hb_coretext_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
{
CFRelease (data->ct_font);
free (data);
}
@ -209,9 +285,10 @@ _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_
CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font)
{
if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL;
hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
return font_data->ct_font;
hb_face_t *face = font->face;
if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL;
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
return face_data->ct_font;
}
@ -444,7 +521,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
{
hb_face_t *face = font->face;
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
CGFloat ct_font_size = CTFontGetSize (face_data->ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
/* Attach marks to their bases, to match the 'ot' shaper.
* Adapted from hb-ot-shape:hb_form_clusters().
@ -453,6 +533,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
* B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
* continue pointing to B2 even though B2 was merged into B1's
* cluster... */
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
{
hb_unicode_funcs_t *unicode = buffer->unicode;
unsigned int count = buffer->len;
@ -575,7 +656,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
CFRelease (attributes);
range->font = CTFontCreateCopyWithAttributes (font_data->ct_font, 0.0, NULL, font_desc);
range->font = CTFontCreateCopyWithAttributes (face_data->ct_font, 0.0, NULL, font_desc);
CFRelease (font_desc);
}
else
@ -693,7 +774,6 @@ resize_and_retry:
scratch += old_scratch_used;
scratch_size -= old_scratch_used;
}
retry:
{
string_ref = CFStringCreateWithCharactersNoCopy (NULL,
pchars, chars_len,
@ -733,7 +813,7 @@ retry:
CFRelease (lang);
}
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
kCTFontAttributeName, font_data->ct_font);
kCTFontAttributeName, face_data->ct_font);
if (num_features)
{
@ -826,7 +906,7 @@ retry:
*/
CFDictionaryRef attributes = CTRunGetAttributes (run);
CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
if (!CFEqual (run_ct_font, font_data->ct_font))
if (!CFEqual (run_ct_font, face_data->ct_font))
{
/* The run doesn't use our main font instance. We have to figure out
* whether font fallback happened, or this is just CoreText giving us
@ -846,15 +926,11 @@ retry:
* backend.
*
* However, even that wouldn't work if we were passed in the CGFont to
* begin with.
*
* Webkit uses a slightly different approach: it installs LastResort
* as fallback chain, and then checks PS name of used font against
* LastResort. That one is safe for any font except for LastResort,
* as opposed to ours, which can fail if we are using any uninstalled
* font that has the same name as an installed font.
* construct a hb_face to begin with.
*
* See: http://github.com/behdad/harfbuzz/pull/36
*
* Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
*/
bool matched = false;
for (unsigned int i = 0; i < range_records.len; i++)
@ -868,13 +944,13 @@ retry:
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
if (run_cg_font)
{
matched = CFEqual (run_cg_font, face_data);
matched = CFEqual (run_cg_font, face_data->cg_font);
CFRelease (run_cg_font);
}
}
if (!matched)
{
CFStringRef font_ps_name = CTFontCopyName (font_data->ct_font, kCTFontPostScriptNameKey);
CFStringRef font_ps_name = CTFontCopyName (face_data->ct_font, kCTFontPostScriptNameKey);
CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey);
CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0);
CFRelease (run_ps_name);
@ -994,7 +1070,6 @@ retry:
positions = position_buf;
}
hb_glyph_info_t *info = run_info;
CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult;
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
{
hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
@ -1129,10 +1204,6 @@ fail:
* AAT shaper
*/
HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face)
HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font)
/*
* shaper face data
*/

View File

@ -44,14 +44,14 @@ HB_BEGIN_DECLS
#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
hb_face_t *
HB_EXTERN hb_face_t *
hb_coretext_face_create (CGFontRef cg_font);
CGFontRef
HB_EXTERN CGFontRef
hb_coretext_face_get_cg_font (hb_face_t *face);
CTFontRef
HB_EXTERN CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font);

View File

@ -44,6 +44,16 @@ HB_BEGIN_DECLS
#define HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_FLAG_DEFAULT
#define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAG_DEFAULT
typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data);
HB_EXTERN void
hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy);
#endif
HB_END_DECLS

View File

@ -43,28 +43,28 @@ HB_BEGIN_DECLS
typedef struct hb_face_t hb_face_t;
hb_face_t *
HB_EXTERN hb_face_t *
hb_face_create (hb_blob_t *blob,
unsigned int index);
typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data);
/* calls destroy() when not needing user_data anymore */
hb_face_t *
HB_EXTERN hb_face_t *
hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
void *user_data,
hb_destroy_func_t destroy);
hb_face_t *
HB_EXTERN hb_face_t *
hb_face_get_empty (void);
hb_face_t *
HB_EXTERN hb_face_t *
hb_face_reference (hb_face_t *face);
void
HB_EXTERN void
hb_face_destroy (hb_face_t *face);
hb_bool_t
HB_EXTERN hb_bool_t
hb_face_set_user_data (hb_face_t *face,
hb_user_data_key_t *key,
void * data,
@ -72,43 +72,43 @@ hb_face_set_user_data (hb_face_t *face,
hb_bool_t replace);
void *
HB_EXTERN void *
hb_face_get_user_data (hb_face_t *face,
hb_user_data_key_t *key);
void
HB_EXTERN void
hb_face_make_immutable (hb_face_t *face);
hb_bool_t
HB_EXTERN hb_bool_t
hb_face_is_immutable (hb_face_t *face);
hb_blob_t *
HB_EXTERN hb_blob_t *
hb_face_reference_table (hb_face_t *face,
hb_tag_t tag);
hb_blob_t *
HB_EXTERN hb_blob_t *
hb_face_reference_blob (hb_face_t *face);
void
HB_EXTERN void
hb_face_set_index (hb_face_t *face,
unsigned int index);
unsigned int
HB_EXTERN unsigned int
hb_face_get_index (hb_face_t *face);
void
HB_EXTERN void
hb_face_set_upem (hb_face_t *face,
unsigned int upem);
unsigned int
HB_EXTERN unsigned int
hb_face_get_upem (hb_face_t *face);
void
HB_EXTERN void
hb_face_set_glyph_count (hb_face_t *face,
unsigned int glyph_count);
unsigned int
HB_EXTERN unsigned int
hb_face_get_glyph_count (hb_face_t *face);

View File

@ -106,7 +106,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
*/
hb_codepoint_t space;
bool has_space = font->get_glyph (' ', 0, &space);
bool has_space = (bool) font->get_nominal_glyph (' ', &space);
buffer->clear_positions ();
@ -123,7 +123,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
pos[i].y_advance = 0;
continue;
}
font->get_glyph (info[i].codepoint, 0, &info[i].codepoint);
font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
font->get_glyph_advance_for_direction (info[i].codepoint,
direction,
&pos[i].x_advance,

View File

@ -42,7 +42,10 @@
*/
#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
HB_FONT_FUNC_IMPLEMENT (glyph) \
HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
@ -61,14 +64,6 @@ 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
@ -80,6 +75,16 @@ 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[VAR]) (void);
} get;
};
@ -144,95 +149,133 @@ struct hb_font_t {
/* Public getters */
inline hb_bool_t has_glyph (hb_codepoint_t unicode)
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 get_font_h_extents (hb_font_extents_t *extents)
{
hb_codepoint_t glyph;
return get_glyph (unicode, 0, &glyph);
memset (extents, 0, sizeof (*extents));
return klass->get.f.font_h_extents (this, user_data,
extents,
klass->user_data.font_h_extents);
}
inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
{
memset (extents, 0, sizeof (*extents));
return klass->get.f.font_v_extents (this, user_data,
extents,
klass->user_data.font_v_extents);
}
inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph)
inline bool has_glyph (hb_codepoint_t unicode)
{
hb_codepoint_t glyph;
return get_nominal_glyph (unicode, &glyph);
}
inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
hb_codepoint_t *glyph)
{
*glyph = 0;
return klass->get.glyph (this, user_data,
unicode, variation_selector, glyph,
klass->user_data.glyph);
return klass->get.f.nominal_glyph (this, user_data,
unicode, glyph,
klass->user_data.nominal_glyph);
}
inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph)
{
*glyph = 0;
return klass->get.f.variation_glyph (this, user_data,
unicode, variation_selector, glyph,
klass->user_data.variation_glyph);
}
inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
{
return klass->get.glyph_h_advance (this, user_data,
glyph,
klass->user_data.glyph_h_advance);
return klass->get.f.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.glyph_v_advance (this, user_data,
glyph,
klass->user_data.glyph_v_advance);
return klass->get.f.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.glyph_h_origin (this, user_data,
glyph, x, y,
klass->user_data.glyph_h_origin);
return klass->get.f.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.glyph_v_origin (this, user_data,
glyph, x, y,
klass->user_data.glyph_v_origin);
return klass->get.f.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.glyph_h_kerning (this, user_data,
left_glyph, right_glyph,
klass->user_data.glyph_h_kerning);
return klass->get.f.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.glyph_v_kerning (this, user_data,
top_glyph, bottom_glyph,
klass->user_data.glyph_v_kerning);
return klass->get.f.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.glyph_extents (this, user_data,
glyph,
extents,
klass->user_data.glyph_extents);
return klass->get.f.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.glyph_contour_point (this, user_data,
glyph, point_index,
x, y,
klass->user_data.glyph_contour_point);
return klass->get.f.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.glyph_name (this, user_data,
glyph,
name, size,
klass->user_data.glyph_name);
return klass->get.f.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 */
@ -240,15 +283,35 @@ struct hb_font_t {
{
*glyph = 0;
if (len == -1) len = strlen (name);
return klass->get.glyph_from_name (this, user_data,
name, len,
glyph,
klass->user_data.glyph_from_name);
return klass->get.f.glyph_from_name (this, user_data,
name, len,
glyph,
klass->user_data.glyph_from_name);
}
/* A bit higher-level, and with fallback */
inline void get_extents_for_direction (hb_direction_t direction,
hb_font_extents_t *extents)
{
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
if (!get_font_h_extents (extents))
{
extents->ascender = y_scale * .8;
extents->descender = y_scale - extents->ascender;
extents->line_gap = 0;
}
} else {
if (!get_font_v_extents (extents))
{
extents->ascender = x_scale / 2;
extents->descender = x_scale - extents->ascender;
extents->line_gap = 0;
}
}
}
inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
hb_direction_t direction,
hb_position_t *x, hb_position_t *y)
@ -268,7 +331,7 @@ struct hb_font_t {
{
*x = get_glyph_h_advance (glyph) / 2;
/* TODO use font_metrics.ascent */
/* TODO use font_extents.ascender */
*y = y_scale;
}
@ -298,6 +361,26 @@ 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)
@ -310,6 +393,26 @@ 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)
@ -394,7 +497,7 @@ struct hb_font_t {
hb_codepoint_t unichar;
if (0 == strncmp (s, "uni", 3) &&
hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
get_glyph (unichar, 0, glyph))
get_nominal_glyph (unichar, glyph))
return true;
}
@ -402,7 +505,13 @@ struct hb_font_t {
}
private:
inline hb_position_t em_scale (int16_t v, int scale) { return (hb_position_t) (v * (int64_t) scale / face->get_upem ()); }
inline hb_position_t em_scale (int16_t v, int scale)
{
int upem = face->get_upem ();
int64_t scaled = v * (int64_t) scale;
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
return (hb_position_t) (scaled / upem);
}
};
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS

View File

@ -45,130 +45,246 @@
*/
static hb_bool_t
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)
hb_font_get_font_h_extents_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
if (font->parent)
return font->parent->get_glyph (unicode, variation_selector, glyph);
memset (metrics, 0, sizeof (*metrics));
return false;
}
static hb_bool_t
hb_font_get_font_h_extents_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_font_h_extents (metrics);
if (ret) {
metrics->ascender = font->parent_scale_y_distance (metrics->ascender);
metrics->descender = font->parent_scale_y_distance (metrics->descender);
metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap);
}
return ret;
}
static hb_bool_t
hb_font_get_font_v_extents_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
memset (metrics, 0, sizeof (*metrics));
return false;
}
static hb_bool_t
hb_font_get_font_v_extents_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
hb_bool_t ret = font->parent->get_font_v_extents (metrics);
if (ret) {
metrics->ascender = font->parent_scale_x_distance (metrics->ascender);
metrics->descender = font->parent_scale_x_distance (metrics->descender);
metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap);
}
return ret;
}
static hb_bool_t
hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
*glyph = 0;
return false;
}
static hb_bool_t
hb_font_get_nominal_glyph_parent (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
return font->parent->get_nominal_glyph (unicode, glyph);
}
static hb_bool_t
hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
*glyph = 0;
return false;
}
static hb_bool_t
hb_font_get_variation_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_variation_glyph (unicode, variation_selector, glyph);
}
static hb_position_t
hb_font_get_glyph_h_advance_nil (hb_font_t *font,
hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
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_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
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));
/* TODO use font_extents.ascender+descender */
return font->y_scale;
}
static hb_bool_t
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)
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)
{
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;
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
}
static hb_bool_t
hb_font_get_glyph_v_origin_nil (hb_font_t *font,
hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
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 true;
}
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,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
{
*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_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
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_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
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_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
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_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
unsigned int point_index,
@ -176,45 +292,63 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font,
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_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
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_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
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 = {
HB_OBJECT_HEADER_STATIC,
@ -222,9 +356,44 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
true, /* immutable */
{
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
#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
}
}
};
@ -246,7 +415,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_nil.get;
ffuncs->get = _hb_font_funcs_parent.get;
return ffuncs;
}
@ -263,7 +432,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_nil);
return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
}
/**
@ -398,11 +567,11 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
ffuncs->destroy.name (ffuncs->user_data.name); \
\
if (func) { \
ffuncs->get.name = func; \
ffuncs->get.f.name = func; \
ffuncs->user_data.name = user_data; \
ffuncs->destroy.name = destroy; \
} else { \
ffuncs->get.name = hb_font_get_##name##_nil; \
ffuncs->get.f.name = hb_font_get_##name##_parent; \
ffuncs->user_data.name = NULL; \
ffuncs->destroy.name = NULL; \
} \
@ -411,9 +580,52 @@ 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 */
/**
* hb_font_get_h_extents:
* @font: a font.
* @extents: (out):
*
*
*
* Return value:
*
* Since: 1.1.3
**/
hb_bool_t
hb_font_get_h_extents (hb_font_t *font,
hb_font_extents_t *extents)
{
return font->get_font_h_extents (extents);
}
/**
* hb_font_get_v_extents:
* @font: a font.
* @extents: (out):
*
*
*
* Return value:
*
* Since: 1.1.3
**/
hb_bool_t
hb_font_get_v_extents (hb_font_t *font,
hb_font_extents_t *extents)
{
return font->get_font_v_extents (extents);
}
/**
* hb_font_get_glyph:
* @font: a font.
@ -432,7 +644,50 @@ hb_font_get_glyph (hb_font_t *font,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph)
{
return font->get_glyph (unicode, variation_selector, glyph);
if (unlikely (variation_selector))
return font->get_variation_glyph (unicode, variation_selector, glyph);
return font->get_nominal_glyph (unicode, glyph);
}
/**
* hb_font_get_nominal_glyph:
* @font: a font.
* @unicode:
* @glyph: (out):
*
*
*
* Return value:
*
* Since: 1.2.3
**/
hb_bool_t
hb_font_get_nominal_glyph (hb_font_t *font,
hb_codepoint_t unicode,
hb_codepoint_t *glyph)
{
return font->get_nominal_glyph (unicode, glyph);
}
/**
* hb_font_get_variation_glyph:
* @font: a font.
* @unicode:
* @variation_selector:
* @glyph: (out):
*
*
*
* Return value:
*
* Since: 1.2.3
**/
hb_bool_t
hb_font_get_variation_glyph (hb_font_t *font,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph)
{
return font->get_variation_glyph (unicode, variation_selector, glyph);
}
/**
@ -638,6 +893,23 @@ hb_font_get_glyph_from_name (hb_font_t *font,
/* A bit higher-level, and with fallback */
/**
* hb_font_get_extents_for_direction:
* @font: a font.
* @direction:
* @extents:
*
*
*
* Since: 1.1.3
**/
void
hb_font_get_extents_for_direction (hb_font_t *font,
hb_direction_t direction,
hb_font_extents_t *extents)
{
return font->get_extents_for_direction (direction, extents);
}
/**
* hb_font_get_glyph_advance_for_direction:
* @font: a font.
@ -858,6 +1130,7 @@ 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 ();
@ -917,8 +1190,8 @@ hb_font_get_empty (void)
NULL, /* parent */
const_cast<hb_face_t *> (&_hb_face_nil),
0, /* x_scale */
0, /* y_scale */
1000, /* x_scale */
1000, /* y_scale */
0, /* x_ppem */
0, /* y_ppem */
@ -1264,3 +1537,131 @@ hb_font_get_ppem (hb_font_t *font,
if (x_ppem) *x_ppem = font->x_ppem;
if (y_ppem) *y_ppem = font->y_ppem;
}
#ifndef HB_DISABLE_DEPRECATED
/*
* Deprecated get_glyph_func():
*/
struct hb_trampoline_closure_t
{
void *user_data;
hb_destroy_func_t destroy;
unsigned int ref_count;
};
template <typename FuncType>
struct hb_trampoline_t
{
hb_trampoline_closure_t closure; /* Must be first. */
FuncType func;
};
template <typename FuncType>
static hb_trampoline_t<FuncType> *
trampoline_create (FuncType func,
void *user_data,
hb_destroy_func_t destroy)
{
typedef hb_trampoline_t<FuncType> trampoline_t;
trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
if (unlikely (!trampoline))
return NULL;
trampoline->closure.user_data = user_data;
trampoline->closure.destroy = destroy;
trampoline->closure.ref_count = 1;
trampoline->func = func;
return trampoline;
}
static void
trampoline_reference (hb_trampoline_closure_t *closure)
{
closure->ref_count++;
}
static void
trampoline_destroy (void *user_data)
{
hb_trampoline_closure_t *closure = (hb_trampoline_closure_t *) user_data;
if (--closure->ref_count)
return;
if (closure->destroy)
closure->destroy (closure->user_data);
free (closure);
}
typedef hb_trampoline_t<hb_font_get_glyph_func_t> hb_font_get_glyph_trampoline_t;
static hb_bool_t
hb_font_get_nominal_glyph_trampoline (hb_font_t *font,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data)
{
hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
return trampoline->func (font, font_data, unicode, 0, glyph, trampoline->closure.user_data);
}
static hb_bool_t
hb_font_get_variation_glyph_trampoline (hb_font_t *font,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data)
{
hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
return trampoline->func (font, font_data, unicode, variation_selector, glyph, trampoline->closure.user_data);
}
/**
* hb_font_funcs_set_glyph_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
* @destroy:
*
* Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and
* hb_font_funcs_set_variation_glyph_func() instead.
*
* Since: 0.9.2
* Deprecated: 1.2.3
**/
void
hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy)
{
hb_font_get_glyph_trampoline_t *trampoline;
trampoline = trampoline_create (func, user_data, destroy);
if (unlikely (!trampoline))
{
if (destroy)
destroy (user_data);
return;
}
hb_font_funcs_set_nominal_glyph_func (ffuncs,
hb_font_get_nominal_glyph_trampoline,
trampoline,
trampoline_destroy);
trampoline_reference (&trampoline->closure);
hb_font_funcs_set_variation_glyph_func (ffuncs,
hb_font_get_variation_glyph_trampoline,
trampoline,
trampoline_destroy);
}
#endif /* HB_DISABLE_DEPRECATED */

View File

@ -46,19 +46,19 @@ typedef struct hb_font_t hb_font_t;
typedef struct hb_font_funcs_t hb_font_funcs_t;
hb_font_funcs_t *
HB_EXTERN hb_font_funcs_t *
hb_font_funcs_create (void);
hb_font_funcs_t *
HB_EXTERN hb_font_funcs_t *
hb_font_funcs_get_empty (void);
hb_font_funcs_t *
HB_EXTERN hb_font_funcs_t *
hb_font_funcs_reference (hb_font_funcs_t *ffuncs);
void
HB_EXTERN void
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
hb_user_data_key_t *key,
void * data,
@ -66,19 +66,37 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
hb_bool_t replace);
void *
HB_EXTERN void *
hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
hb_user_data_key_t *key);
void
HB_EXTERN void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
/* glyph extents */
/* font and glyph extents */
/* Note that typically ascender is positive and descender negative in coordinate systems that grow up. */
typedef struct hb_font_extents_t
{
hb_position_t ascender; /* typographic ascender. */
hb_position_t descender; /* typographic descender. */
hb_position_t line_gap; /* suggested line spacing gap. */
/*< private >*/
hb_position_t reserved9;
hb_position_t reserved8;
hb_position_t reserved7;
hb_position_t reserved6;
hb_position_t reserved5;
hb_position_t reserved4;
hb_position_t reserved3;
hb_position_t reserved2;
hb_position_t reserved1;
} hb_font_extents_t;
/* Note that height is negative in coordinate systems that grow up. */
typedef struct hb_glyph_extents_t
@ -89,13 +107,23 @@ typedef struct hb_glyph_extents_t
hb_position_t height; /* distance from top to bottom side. */
} hb_glyph_extents_t;
/* func types */
typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data);
typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
hb_font_extents_t *metrics,
void *user_data);
typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data);
typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data);
typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
@ -141,7 +169,7 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
/* func setters */
/**
* hb_font_funcs_set_glyph_func:
* hb_font_funcs_set_font_h_extents_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
@ -149,12 +177,60 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
*
*
*
* Since: 0.9.2
* Since: 1.1.2
**/
void
hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy);
HB_EXTERN void
hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs,
hb_font_get_font_h_extents_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_font_v_extents_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
* @destroy:
*
*
*
* Since: 1.1.2
**/
HB_EXTERN void
hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs,
hb_font_get_font_v_extents_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_nominal_glyph_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
* @destroy:
*
*
*
* Since: 1.2.3
**/
HB_EXTERN void
hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_get_nominal_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_variation_glyph_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
* @destroy:
*
*
*
* Since: 1.2.3
**/
HB_EXTERN void
hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs,
hb_font_get_variation_glyph_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_glyph_h_advance_func:
@ -167,7 +243,7 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_h_advance_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -183,7 +259,7 @@ hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_v_advance_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -199,7 +275,7 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_h_origin_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -215,7 +291,7 @@ hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_v_origin_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -231,7 +307,7 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_h_kerning_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -247,7 +323,7 @@ hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_v_kerning_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -263,7 +339,7 @@ hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_extents_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -279,7 +355,7 @@ hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_contour_point_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -295,7 +371,7 @@ hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_name_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -311,57 +387,67 @@ hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_from_name_func_t func,
void *user_data, hb_destroy_func_t destroy);
/* func dispatch */
hb_bool_t
hb_font_get_glyph (hb_font_t *font,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph);
HB_EXTERN hb_bool_t
hb_font_get_h_extents (hb_font_t *font,
hb_font_extents_t *extents);
HB_EXTERN hb_bool_t
hb_font_get_v_extents (hb_font_t *font,
hb_font_extents_t *extents);
hb_position_t
HB_EXTERN hb_bool_t
hb_font_get_nominal_glyph (hb_font_t *font,
hb_codepoint_t unicode,
hb_codepoint_t *glyph);
HB_EXTERN hb_bool_t
hb_font_get_variation_glyph (hb_font_t *font,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph);
HB_EXTERN hb_position_t
hb_font_get_glyph_h_advance (hb_font_t *font,
hb_codepoint_t glyph);
hb_position_t
HB_EXTERN hb_position_t
hb_font_get_glyph_v_advance (hb_font_t *font,
hb_codepoint_t glyph);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_get_glyph_h_origin (hb_font_t *font,
hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_get_glyph_v_origin (hb_font_t *font,
hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y);
hb_position_t
HB_EXTERN hb_position_t
hb_font_get_glyph_h_kerning (hb_font_t *font,
hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
hb_position_t
HB_EXTERN hb_position_t
hb_font_get_glyph_v_kerning (hb_font_t *font,
hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_get_glyph_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_get_glyph_contour_point (hb_font_t *font,
hb_codepoint_t glyph, unsigned int point_index,
hb_position_t *x, hb_position_t *y);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_get_glyph_name (hb_font_t *font,
hb_codepoint_t glyph,
char *name, unsigned int size);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_get_glyph_from_name (hb_font_t *font,
const char *name, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph);
@ -369,52 +455,63 @@ hb_font_get_glyph_from_name (hb_font_t *font,
/* high-level funcs, with fallback */
void
/* Calls either hb_font_get_nominal_glyph() if variation_selector is 0,
* otherwise callse hb_font_get_variation_glyph(). */
HB_EXTERN hb_bool_t
hb_font_get_glyph (hb_font_t *font,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph);
HB_EXTERN void
hb_font_get_extents_for_direction (hb_font_t *font,
hb_direction_t direction,
hb_font_extents_t *extents);
HB_EXTERN void
hb_font_get_glyph_advance_for_direction (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
hb_position_t *x, hb_position_t *y);
void
HB_EXTERN void
hb_font_get_glyph_origin_for_direction (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
hb_position_t *x, hb_position_t *y);
void
HB_EXTERN void
hb_font_add_glyph_origin_for_direction (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
hb_position_t *x, hb_position_t *y);
void
HB_EXTERN void
hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
hb_position_t *x, hb_position_t *y);
void
HB_EXTERN void
hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
hb_direction_t direction,
hb_position_t *x, hb_position_t *y);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_get_glyph_extents_for_origin (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
hb_glyph_extents_t *extents);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
hb_codepoint_t glyph, unsigned int point_index,
hb_direction_t direction,
hb_position_t *x, hb_position_t *y);
/* Generates gidDDD if glyph has no name. */
void
HB_EXTERN void
hb_font_glyph_to_string (hb_font_t *font,
hb_codepoint_t glyph,
char *s, unsigned int size);
/* Parses gidDDD and uniUUUU strings automatically. */
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_glyph_from_string (hb_font_t *font,
const char *s, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph);
@ -426,22 +523,22 @@ hb_font_glyph_from_string (hb_font_t *font,
/* Fonts are very light-weight objects */
hb_font_t *
HB_EXTERN hb_font_t *
hb_font_create (hb_face_t *face);
hb_font_t *
HB_EXTERN hb_font_t *
hb_font_create_sub_font (hb_font_t *parent);
hb_font_t *
HB_EXTERN hb_font_t *
hb_font_get_empty (void);
hb_font_t *
HB_EXTERN hb_font_t *
hb_font_reference (hb_font_t *font);
void
HB_EXTERN void
hb_font_destroy (hb_font_t *font);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_set_user_data (hb_font_t *font,
hb_user_data_key_t *key,
void * data,
@ -449,46 +546,46 @@ hb_font_set_user_data (hb_font_t *font,
hb_bool_t replace);
void *
HB_EXTERN void *
hb_font_get_user_data (hb_font_t *font,
hb_user_data_key_t *key);
void
HB_EXTERN void
hb_font_make_immutable (hb_font_t *font);
hb_bool_t
HB_EXTERN hb_bool_t
hb_font_is_immutable (hb_font_t *font);
void
HB_EXTERN void
hb_font_set_parent (hb_font_t *font,
hb_font_t *parent);
hb_font_t *
HB_EXTERN hb_font_t *
hb_font_get_parent (hb_font_t *font);
hb_face_t *
HB_EXTERN hb_face_t *
hb_font_get_face (hb_font_t *font);
void
HB_EXTERN void
hb_font_set_funcs (hb_font_t *font,
hb_font_funcs_t *klass,
void *font_data,
hb_destroy_func_t destroy);
/* Be *very* careful with this function! */
void
HB_EXTERN void
hb_font_set_funcs_data (hb_font_t *font,
void *font_data,
hb_destroy_func_t destroy);
void
HB_EXTERN void
hb_font_set_scale (hb_font_t *font,
int x_scale,
int y_scale);
void
HB_EXTERN void
hb_font_get_scale (hb_font_t *font,
int *x_scale,
int *y_scale);
@ -496,12 +593,12 @@ hb_font_get_scale (hb_font_t *font,
/*
* A zero value means "no hinting in that direction"
*/
void
HB_EXTERN void
hb_font_set_ppem (hb_font_t *font,
unsigned int x_ppem,
unsigned int y_ppem);
void
HB_EXTERN void
hb_font_get_ppem (hb_font_t *font,
unsigned int *x_ppem,
unsigned int *y_ppem);

View File

@ -70,11 +70,12 @@ struct hb_ft_font_t
{
FT_Face ft_face;
int load_flags;
bool symbol; /* Whether selected cmap is symbol cmap. */
bool unref; /* Whether to destroy ft_face when done. */
};
static hb_ft_font_t *
_hb_ft_font_create (FT_Face ft_face, bool unref)
_hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
{
hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t));
@ -82,6 +83,7 @@ _hb_ft_font_create (FT_Face ft_face, bool unref)
return NULL;
ft_font->ft_face = ft_face;
ft_font->symbol = symbol;
ft_font->unref = unref;
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
@ -89,11 +91,17 @@ _hb_ft_font_create (FT_Face ft_face, bool unref)
return ft_font;
}
static void
_hb_ft_face_destroy (FT_Face ft_face)
{
FT_Done_Face (ft_face);
}
static void
_hb_ft_font_destroy (hb_ft_font_t *ft_font)
{
if (ft_font->unref)
FT_Done_Face (ft_font->ft_face);
_hb_ft_face_destroy (ft_font->ft_face);
free (ft_font);
}
@ -155,21 +163,46 @@ hb_ft_font_get_face (hb_font_t *font)
static hb_bool_t
hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
unsigned int g;
unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
if (likely (!variation_selector))
g = FT_Get_Char_Index (ft_font->ft_face, unicode);
else
g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
if (unlikely (!g))
{
if (unlikely (ft_font->symbol) && unicode <= 0x00FFu)
{
/* For symbol-encoded OpenType fonts, we duplicate the
* U+F000..F0FF range at U+0000..U+00FF. That's what
* Windows seems to do, and that's hinted about at:
* http://www.microsoft.com/typography/otspec/recom.htm
* under "Non-Standard (Symbol) Fonts". */
g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
if (!g)
return false;
}
else
return false;
}
*glyph = g;
return true;
}
static hb_bool_t
hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
if (unlikely (!g))
return false;
@ -216,18 +249,6 @@ 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,
@ -272,17 +293,6 @@ 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,
@ -300,6 +310,16 @@ 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;
}
@ -379,25 +399,78 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
return *glyph != 0;
}
static hb_bool_t
hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
void *font_data,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
FT_Face ft_face = ft_font->ft_face;
metrics->ascender = ft_face->size->metrics.ascender;
metrics->descender = ft_face->size->metrics.descender;
metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender);
if (font->y_scale < 0)
{
metrics->ascender = -metrics->ascender;
metrics->descender = -metrics->descender;
metrics->line_gap = -metrics->line_gap;
}
return true;
}
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)
{
static const hb_font_funcs_t ft_ffuncs = {
HB_OBJECT_HEADER_STATIC,
retry:
hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
true, /* immutable */
if (unlikely (!funcs))
{
funcs = hb_font_funcs_create ();
{
#define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name,
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL);
//hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL);
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, NULL, NULL);
hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_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;
}
#ifdef HB_USE_ATEXIT
atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
#endif
};
bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
hb_font_set_funcs (font,
const_cast<hb_font_funcs_t *> (&ft_ffuncs),
_hb_ft_font_create (ft_face, unref),
funcs,
_hb_ft_font_create (ft_face, symbol, unref),
(hb_destroy_func_t) _hb_ft_font_destroy);
}
@ -477,7 +550,7 @@ hb_face_t *
hb_ft_face_create_referenced (FT_Face ft_face)
{
FT_Reference_Face (ft_face);
return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
return hb_ft_face_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy);
}
static void
@ -557,7 +630,7 @@ hb_font_t *
hb_ft_font_create_referenced (FT_Face ft_face)
{
FT_Reference_Face (ft_face);
return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
return hb_ft_font_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy);
}
@ -626,7 +699,8 @@ hb_ft_font_set_funcs (hb_font_t *font)
return;
}
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
if (FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE))
FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL);
FT_Set_Char_Size (ft_face,
abs (font->x_scale), abs (font->y_scale),

View File

@ -59,7 +59,7 @@ HB_BEGIN_DECLS
* probably should use (the more recent) hb_ft_face_create_referenced()
* instead.
*/
hb_face_t *
HB_EXTERN hb_face_t *
hb_ft_face_create (FT_Face ft_face,
hb_destroy_func_t destroy);
@ -71,7 +71,7 @@ hb_ft_face_create (FT_Face ft_face,
* Client is still responsible for making sure that ft-face is destroyed
* after hb-face is.
*/
hb_face_t *
HB_EXTERN hb_face_t *
hb_ft_face_create_cached (FT_Face ft_face);
/* This version is like hb_ft_face_create(), except that it calls
@ -81,7 +81,7 @@ hb_ft_face_create_cached (FT_Face ft_face);
* This is the most convenient version to use. Use it unless you have
* very good reasons not to.
*/
hb_face_t *
HB_EXTERN hb_face_t *
hb_ft_face_create_referenced (FT_Face ft_face);
@ -98,26 +98,26 @@ hb_ft_face_create_referenced (FT_Face ft_face);
/* See notes on hb_ft_face_create(). Same issues re lifecycle-management
* apply here. Use hb_ft_font_create_referenced() if you can. */
hb_font_t *
HB_EXTERN hb_font_t *
hb_ft_font_create (FT_Face ft_face,
hb_destroy_func_t destroy);
/* See notes on hb_ft_face_create_referenced() re lifecycle-management
* issues. */
hb_font_t *
HB_EXTERN hb_font_t *
hb_ft_font_create_referenced (FT_Face ft_face);
FT_Face
HB_EXTERN FT_Face
hb_ft_font_get_face (hb_font_t *font);
void
HB_EXTERN void
hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
int
HB_EXTERN int
hb_ft_font_get_load_flags (hb_font_t *font);
/* Makes an hb_font_t use FreeType internally to implement font functions. */
void
HB_EXTERN void
hb_ft_font_set_funcs (hb_font_t *font);

View File

@ -140,7 +140,7 @@ struct TTCHeaderVersion1
protected:
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
FixedVersion version; /* Version of the TTC Header (1.0),
FixedVersion<>version; /* Version of the TTC Header (1.0),
* 0x00010000u */
ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
table; /* Array of offsets to the OffsetTable for each font
@ -187,7 +187,7 @@ struct TTCHeader
union {
struct {
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
FixedVersion version; /* Version of the TTC Header (1.0 or 2.0),
FixedVersion<>version; /* Version of the TTC Header (1.0 or 2.0),
* 0x00010000u or 0x00020000u */
} header;
TTCHeaderVersion1 version1;

View File

@ -101,10 +101,8 @@ static inline Type& StructAfter(TObject &X)
#define DEFINE_SIZE_STATIC(size) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
static const unsigned int static_size = (size); \
static const unsigned int min_size = (size)
/* Size signifying variable-sized array */
#define VAR 1
static const unsigned int min_size = (size); \
inline unsigned int get_size (void) const { return (size); }
#define DEFINE_SIZE_UNION(size, _member) \
DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
@ -185,7 +183,7 @@ struct hb_dispatch_context_t
/* This limits sanitizing time on really broken fonts. */
#ifndef HB_SANITIZE_MAX_EDITS
#define HB_SANITIZE_MAX_EDITS 100
#define HB_SANITIZE_MAX_EDITS 32
#endif
struct hb_sanitize_context_t :
@ -399,9 +397,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 +493,10 @@ struct hb_serialize_context_t
return reinterpret_cast<Type *> (&obj);
}
inline void truncate (void *head)
inline void truncate (void *new_head)
{
assert (this->start < head && head <= this->head);
this->head = (char *) head;
assert (this->start < new_head && new_head <= this->head);
this->head = (char *) new_head;
}
unsigned int debug_depth;
@ -665,6 +663,24 @@ typedef SHORT FWORD;
/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
typedef USHORT UFWORD;
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
struct F2DOT14 : SHORT
{
//inline float to_float (void) const { return ???; }
//inline void set_float (float f) { v.set (f * ???); }
public:
DEFINE_SIZE_STATIC (2);
};
/* 32-bit signed fixed-point number (16.16). */
struct Fixed: LONG
{
//inline float to_float (void) const { return ???; }
//inline void set_float (float f) { v.set (f * ???); }
public:
DEFINE_SIZE_STATIC (4);
};
/* Date represented in number of seconds since 12:00 midnight, January 1,
* 1904. The value is represented as a signed 64-bit integer. */
struct LONGDATETIME
@ -742,9 +758,10 @@ struct CheckSum : ULONG
* Version Numbers
*/
template <typename FixedType=USHORT>
struct FixedVersion
{
inline uint32_t to_int (void) const { return (major << 16) + minor; }
inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
inline bool sanitize (hb_sanitize_context_t *c) const
{
@ -752,10 +769,10 @@ struct FixedVersion
return_trace (c->check_struct (this));
}
USHORT major;
USHORT minor;
FixedType major;
FixedType minor;
public:
DEFINE_SIZE_STATIC (4);
DEFINE_SIZE_STATIC (2 * sizeof(FixedType));
};

View File

@ -69,61 +69,78 @@ struct CmapSubtableFormat0
struct CmapSubtableFormat4
{
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
struct accelerator_t
{
unsigned int segCount;
inline void init (const CmapSubtableFormat4 *subtable)
{
segCount = subtable->segCountX2 / 2;
endCount = subtable->values;
startCount = endCount + segCount + 1;
idDelta = startCount + segCount;
idRangeOffset = idDelta + segCount;
glyphIdArray = idRangeOffset + segCount;
glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
}
static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
{
const accelerator_t *thiz = (const accelerator_t *) obj;
/* Custom two-array bsearch. */
int min = 0, max = (int) thiz->segCount - 1;
const USHORT *startCount = thiz->startCount;
const USHORT *endCount = thiz->endCount;
unsigned int i;
while (min <= max)
{
int mid = (min + max) / 2;
if (codepoint < startCount[mid])
max = mid - 1;
else if (codepoint > endCount[mid])
min = mid + 1;
else
{
i = mid;
goto found;
}
}
return false;
found:
hb_codepoint_t gid;
unsigned int rangeOffset = thiz->idRangeOffset[i];
if (rangeOffset == 0)
gid = codepoint + thiz->idDelta[i];
else
{
/* Somebody has been smoking... */
unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
if (unlikely (index >= thiz->glyphIdArrayLength))
return false;
gid = thiz->glyphIdArray[index];
if (unlikely (!gid))
return false;
gid += thiz->idDelta[i];
}
*glyph = gid & 0xFFFFu;
return true;
}
const USHORT *endCount;
const USHORT *startCount;
const USHORT *idDelta;
const USHORT *idRangeOffset;
const USHORT *glyphIdArray;
unsigned int segCount;
unsigned int glyphIdArrayLength;
};
segCount = this->segCountX2 / 2;
endCount = this->values;
startCount = endCount + segCount + 1;
idDelta = startCount + segCount;
idRangeOffset = idDelta + segCount;
glyphIdArray = idRangeOffset + segCount;
glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
/* Custom two-array bsearch. */
int min = 0, max = (int) segCount - 1;
unsigned int i;
while (min <= max)
{
int mid = (min + max) / 2;
if (codepoint < startCount[mid])
max = mid - 1;
else if (codepoint > endCount[mid])
min = mid + 1;
else
{
i = mid;
goto found;
}
}
return false;
found:
hb_codepoint_t gid;
unsigned int rangeOffset = idRangeOffset[i];
if (rangeOffset == 0)
gid = codepoint + idDelta[i];
else
{
/* Somebody has been smoking... */
unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
if (unlikely (index >= glyphIdArrayLength))
return false;
gid = glyphIdArray[index];
if (unlikely (!gid))
return false;
gid += idDelta[i];
}
*glyph = gid & 0xFFFFu;
return true;
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
accelerator_t accel;
accel.init (this);
return accel.get_glyph_func (&accel, codepoint, glyph);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@ -388,7 +405,7 @@ struct CmapSubtableFormat14
}
protected:
USHORT format; /* Format number is set to 0. */
USHORT format; /* Format number is set to 14. */
ULONG lengthZ; /* Byte length of this subtable. */
SortedArrayOf<VariationSelectorRecord, ULONG>
record; /* Variation selector records; sorted
@ -416,16 +433,6 @@ struct CmapSubtable
}
}
inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph) const
{
switch (u.format) {
case 14: return u.format14.get_glyph_variant(codepoint, variation_selector, glyph);
default: return GLYPH_VARIANT_NOT_FOUND;
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -442,7 +449,7 @@ struct CmapSubtable
}
}
protected:
public:
union {
USHORT format; /* Format identifier */
CmapSubtableFormat0 format0;

View File

@ -35,6 +35,8 @@
#include "hb-ot-head-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-os2-table.hh"
//#include "hb-ot-post-table.hh"
struct hb_ot_face_metrics_accelerator_t
@ -42,24 +44,58 @@ struct hb_ot_face_metrics_accelerator_t
unsigned int num_metrics;
unsigned int num_advances;
unsigned int default_advance;
unsigned short ascender;
unsigned short descender;
unsigned short line_gap;
const OT::_mtx *table;
hb_blob_t *blob;
inline void init (hb_face_t *face,
hb_tag_t _hea_tag, hb_tag_t _mtx_tag,
unsigned int default_advance_)
hb_tag_t _hea_tag,
hb_tag_t _mtx_tag,
hb_tag_t os2_tag)
{
this->default_advance = default_advance_;
this->num_metrics = face->get_num_glyphs ();
this->default_advance = face->get_upem ();
bool got_font_extents = false;
if (os2_tag)
{
hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>::sanitize (face->reference_table (os2_tag));
const OT::os2 *os2 = OT::Sanitizer<OT::os2>::lock_instance (os2_blob);
#define USE_TYPO_METRICS (1u<<7)
if (0 != (os2->fsSelection & USE_TYPO_METRICS))
{
this->ascender = os2->sTypoAscender;
this->descender = os2->sTypoDescender;
this->line_gap = os2->sTypoLineGap;
got_font_extents = (this->ascender | this->descender) != 0;
}
hb_blob_destroy (os2_blob);
}
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);
this->num_advances = _hea->numberOfLongMetrics;
if (!got_font_extents)
{
this->ascender = _hea->ascender;
this->descender = _hea->descender;
this->line_gap = _hea->lineGap;
}
hb_blob_destroy (_hea_blob);
this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag));
if (unlikely (!this->num_advances ||
2 * (this->num_advances + this->num_metrics) > hb_blob_get_length (this->blob)))
/* 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))
{
this->num_metrics = this->num_advances = 0;
hb_blob_destroy (this->blob);
@ -166,10 +202,48 @@ struct hb_ot_face_glyf_accelerator_t
}
};
typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph);
template <typename Type>
static inline bool get_glyph_from (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph)
{
const Type *typed_obj = (const Type *) obj;
return typed_obj->get_glyph (codepoint, glyph);
}
template <typename Type>
static inline bool get_glyph_from_symbol (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph)
{
const Type *typed_obj = (const Type *) obj;
if (likely (typed_obj->get_glyph (codepoint, glyph)))
return true;
if (codepoint <= 0x00FFu)
{
/* For symbol-encoded OpenType fonts, we duplicate the
* U+F000..F0FF range at U+0000..U+00FF. That's what
* Windows seems to do, and that's hinted about at:
* http://www.microsoft.com/typography/otspec/recom.htm
* under "Non-Standard (Symbol) Fonts". */
return typed_obj->get_glyph (0xF000u + codepoint, glyph);
}
return false;
}
struct hb_ot_face_cmap_accelerator_t
{
const OT::CmapSubtable *table;
const OT::CmapSubtable *uvs_table;
hb_cmap_get_glyph_func_t get_glyph_func;
const void *get_glyph_data;
OT::CmapSubtableFormat4::accelerator_t format4_accel;
const OT::CmapSubtableFormat14 *uvs_table;
hb_blob_t *blob;
inline void init (hb_face_t *face)
@ -177,8 +251,9 @@ struct hb_ot_face_cmap_accelerator_t
this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
const OT::CmapSubtable *subtable = NULL;
const OT::CmapSubtable *subtable_uvs = NULL;
const OT::CmapSubtableFormat14 *subtable_uvs = NULL;
bool symbol = false;
/* 32-bit subtables. */
if (!subtable) subtable = cmap->find_subtable (3, 10);
if (!subtable) subtable = cmap->find_subtable (0, 6);
@ -189,17 +264,38 @@ struct hb_ot_face_cmap_accelerator_t
if (!subtable) subtable = cmap->find_subtable (0, 2);
if (!subtable) subtable = cmap->find_subtable (0, 1);
if (!subtable) subtable = cmap->find_subtable (0, 0);
if (!subtable) subtable = cmap->find_subtable (3, 0);
if (!subtable)(subtable = cmap->find_subtable (3, 0)) && (symbol = true);
/* Meh. */
if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
/* UVS subtable. */
if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
if (!subtable_uvs)
{
const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
if (st && st->u.format == 14)
subtable_uvs = &st->u.format14;
}
/* Meh. */
if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14);
this->table = subtable;
this->uvs_table = subtable_uvs;
this->get_glyph_data = subtable;
if (unlikely (symbol))
this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
else
switch (subtable->u.format) {
/* Accelerate format 4 and format 12. */
default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>; break;
case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>; break;
case 4:
{
this->format4_accel.init (&subtable->u.format4);
this->get_glyph_data = &this->format4_accel;
this->get_glyph_func = this->format4_accel.get_glyph_func;
}
break;
}
}
inline void fini (void)
@ -207,33 +303,77 @@ struct hb_ot_face_cmap_accelerator_t
hb_blob_destroy (this->blob);
}
inline bool get_glyph (hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph) const
inline bool get_nominal_glyph (hb_codepoint_t unicode,
hb_codepoint_t *glyph) const
{
if (unlikely (variation_selector))
return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
}
inline bool get_variation_glyph (hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph) const
{
switch (this->uvs_table->get_glyph_variant (unicode,
variation_selector,
glyph))
{
switch (this->uvs_table->get_glyph_variant (unicode,
variation_selector,
glyph))
{
case OT::GLYPH_VARIANT_NOT_FOUND: return false;
case OT::GLYPH_VARIANT_FOUND: return true;
case OT::GLYPH_VARIANT_USE_DEFAULT: break;
}
case OT::GLYPH_VARIANT_NOT_FOUND: return false;
case OT::GLYPH_VARIANT_FOUND: return true;
case OT::GLYPH_VARIANT_USE_DEFAULT: break;
}
return this->table->get_glyph (unicode, glyph);
return get_nominal_glyph (unicode, glyph);
}
};
template <typename T>
struct hb_lazy_loader_t
{
inline void init (hb_face_t *face_)
{
face = face_;
instance = NULL;
}
inline void fini (void)
{
if (instance && instance != &OT::Null(T))
{
instance->fini();
free (instance);
}
}
inline const T* operator-> (void) const
{
retry:
T *p = (T *) hb_atomic_ptr_get (&instance);
if (unlikely (!p))
{
p = (T *) calloc (1, sizeof (T));
if (unlikely (!p))
return &OT::Null(T);
p->init (face);
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p)))
{
p->fini ();
goto retry;
}
}
return p;
}
private:
hb_face_t *face;
T *instance;
};
struct hb_ot_font_t
{
hb_ot_face_cmap_accelerator_t cmap;
hb_ot_face_metrics_accelerator_t h_metrics;
hb_ot_face_metrics_accelerator_t v_metrics;
hb_ot_face_glyf_accelerator_t glyf;
hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
};
@ -245,11 +385,9 @@ _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, 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->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2);
ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */
ot_font->glyf.init (face);
return ot_font;
@ -268,16 +406,27 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font)
static hb_bool_t
hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
return ot_font->cmap.get_nominal_glyph (unicode, glyph);
}
static hb_bool_t
hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
}
static hb_position_t
@ -300,52 +449,6 @@ 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,
@ -354,7 +457,7 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
bool ret = ot_font->glyf.get_extents (glyph, extents);
bool ret = ot_font->glyf->get_extents (glyph, extents);
extents->x_bearing = font->em_scale_x (extents->x_bearing);
extents->y_bearing = font->em_scale_y (extents->y_bearing);
extents->width = font->em_scale_x (extents->width);
@ -363,61 +466,85 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
}
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_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
void *font_data,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
/* TODO */
return false;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
return true;
}
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)
hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
void *font_data,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
/* TODO */
return false;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
return true;
}
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 *static_ot_funcs = NULL;
#ifdef HB_USE_ATEXIT
static
void free_static_ot_funcs (void)
{
hb_font_funcs_destroy (static_ot_funcs);
}
#endif
static hb_font_funcs_t *
_hb_ot_get_font_funcs (void)
{
static const hb_font_funcs_t ot_ffuncs = {
HB_OBJECT_HEADER_STATIC,
retry:
hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
true, /* immutable */
if (unlikely (!funcs))
{
funcs = hb_font_funcs_create ();
{
#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL);
hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL);
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, NULL, NULL);
hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_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;
}
#ifdef HB_USE_ATEXIT
atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
#endif
};
return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
return funcs;
}
/**
* hb_ot_font_set_funcs:
*
* Since: 0.9.28
**/
void

View File

@ -36,7 +36,7 @@
HB_BEGIN_DECLS
void
HB_EXTERN void
hb_ot_font_set_funcs (hb_font_t *font);

View File

@ -90,10 +90,10 @@ struct glyfGlyphHeader
* greater than or equal to zero,
* this is a simple glyph; if negative,
* this is a composite glyph. */
SHORT xMin; /* Minimum x for coordinate data. */
SHORT yMin; /* Minimum y for coordinate data. */
SHORT xMax; /* Maximum x for coordinate data. */
SHORT yMax; /* Maximum y for coordinate data. */
FWORD xMin; /* Minimum x for coordinate data. */
FWORD yMin; /* Minimum y for coordinate data. */
FWORD xMax; /* Maximum x for coordinate data. */
FWORD yMax; /* Maximum y for coordinate data. */
DEFINE_SIZE_STATIC (10);
};

View File

@ -55,13 +55,15 @@ struct head
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && likely (version.major == 1));
return_trace (c->check_struct (this) &&
version.major == 1 &&
magicNumber == 0x5F0F3CF5u);
}
protected:
FixedVersion version; /* Version of the head table--currently
FixedVersion<>version; /* Version of the head table--currently
* 0x00010000u for version 1.0. */
FixedVersion fontRevision; /* Set by font manufacturer. */
FixedVersion<>fontRevision; /* Set by font manufacturer. */
ULONG checkSumAdjustment; /* To compute: set it to 0, sum the
* entire font as ULONG, then store
* 0xB1B0AFBAu - sum. */

View File

@ -56,7 +56,7 @@ struct _hea
}
public:
FixedVersion version; /* 0x00010000u for version 1.0. */
FixedVersion<>version; /* 0x00010000u for version 1.0. */
FWORD ascender; /* Typographic ascent. */
FWORD descender; /* Typographic descent. */
FWORD lineGap; /* Typographic line gap. */

View File

@ -44,8 +44,8 @@ namespace OT {
struct LongMetric
{
USHORT advance; /* Advance width/height. */
SHORT lsb; /* Leading (left/top) side bearing. */
UFWORD advance; /* Advance width/height. */
FWORD lsb; /* Leading (left/top) side bearing. */
public:
DEFINE_SIZE_STATIC (4);
};
@ -74,7 +74,7 @@ struct _mtx
* be in the array, but that entry is
* required. The last entry applies to
* all subsequent glyphs. */
SHORT leadingBearingX[VAR]; /* Here the advance is assumed
FWORD leadingBearingX[VAR]; /* Here the advance is assumed
* to be the same as the advance
* for the last entry above. The
* number of entries in this array is

View File

@ -34,6 +34,14 @@
#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 {
@ -44,8 +52,6 @@ namespace OT {
#define NOT_COVERED ((unsigned int) -1)
#define MAX_NESTING_LEVEL 6
#define MAX_CONTEXT_LENGTH 64
@ -539,6 +545,9 @@ struct Feature
c->try_set (&featureParams, new_offset) &&
!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
return_trace (false);
if (c->edit_count > 1)
c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
}
return_trace (true);
@ -573,6 +582,11 @@ 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; }
@ -756,7 +770,11 @@ struct CoverageFormat2
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
if (unlikely (!num_glyphs)) return_trace (true);
if (unlikely (!num_glyphs))
{
rangeRecord.len.set (0);
return_trace (true);
}
unsigned int num_ranges = 1;
for (unsigned int i = 1; i < num_glyphs; i++)
@ -1156,6 +1174,21 @@ struct Device
inline hb_position_t get_y_delta (hb_font_t *font) const
{ return get_delta (font->y_ppem, font->y_scale); }
inline unsigned int get_size (void) const
{
unsigned int f = deltaFormat;
if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
}
private:
inline int get_delta (unsigned int ppem, int scale) const
{
if (!ppem) return 0;
@ -1166,8 +1199,6 @@ struct Device
return (int) (pixels * (int64_t) scale / ppem);
}
inline int get_delta_pixels (unsigned int ppem_size) const
{
unsigned int f = deltaFormat;
@ -1191,19 +1222,6 @@ struct Device
return delta;
}
inline unsigned int get_size (void) const
{
unsigned int f = deltaFormat;
if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
}
protected:
USHORT startSize; /* Smallest size to correct--in ppem */
USHORT endSize; /* Largest size to correct--in ppem */

View File

@ -409,7 +409,7 @@ struct GDEF
protected:
FixedVersion version; /* Version of the GDEF table--currently
FixedVersion<>version; /* Version of the GDEF table--currently
* 0x00010002u */
OffsetTo<ClassDef>
glyphClassDef; /* Offset to class definition table

View File

@ -36,8 +36,17 @@ namespace OT {
/* buffer **position** var allocations */
#define attach_lookback() var.u16[0] /* number of glyphs to go back to attach this glyph to its base */
#define cursive_chain() var.i16[1] /* character to which this connects, may be positive or negative */
#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
#define attach_type() var.u8[2] /* attachment type */
/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
enum attach_type_t {
ATTACH_TYPE_NONE = 0X00,
/* Each attachment should be either a mark or a cursive; can't be both. */
ATTACH_TYPE_MARK = 0X01,
ATTACH_TYPE_CURSIVE = 0X02,
};
/* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
@ -425,7 +434,9 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage ord
hb_glyph_position_t &o = buffer->cur_pos();
o.x_offset = base_x - mark_x;
o.y_offset = base_y - mark_y;
o.attach_lookback() = buffer->idx - glyph_pos;
o.attach_type() = ATTACH_TYPE_MARK;
o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
buffer->idx++;
return_trace (true);
@ -741,7 +752,7 @@ struct PairPosFormat2
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
TRACE_COLLECT_GLYPHS (this);
/* (this+coverage).add_coverage (c->input); // Don't need this. */
(this+coverage).add_coverage (c->input);
unsigned int count1 = class1Count;
const ClassDef &klass1 = this+classDef1;
@ -906,9 +917,6 @@ struct CursivePosFormat1
TRACE_APPLY (this);
hb_buffer_t *buffer = c->buffer;
/* We don't handle mark glyphs here. */
if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return_trace (false);
const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
if (!this_record.exitAnchor) return_trace (false);
@ -992,7 +1000,9 @@ struct CursivePosFormat1
*/
reverse_cursive_minor_offset (pos, child, c->direction, parent);
pos[child].cursive_chain() = parent - child;
pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
pos[child].attach_chain() = (int) parent - (int) child;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
pos[child].y_offset = y_offset;
else
@ -1067,7 +1077,7 @@ struct MarkBasePosFormat1
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
if (likely (mark_index == NOT_COVERED)) return_trace (false);
/* now we search backwards for a non-mark glyph */
/* Now we search backwards for a non-mark glyph */
hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
@ -1079,7 +1089,7 @@ struct MarkBasePosFormat1
} while (1);
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ }
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
if (base_index == NOT_COVERED) return_trace (false);
@ -1168,14 +1178,14 @@ struct MarkLigPosFormat1
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
if (likely (mark_index == NOT_COVERED)) return_trace (false);
/* now we search backwards for a non-mark glyph */
/* Now we search backwards for a non-mark glyph */
hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
if (!skippy_iter.prev ()) return_trace (false);
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return_trace (false);*/ }
//if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
unsigned int j = skippy_iter.idx;
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
@ -1499,7 +1509,8 @@ struct GPOS : GSUBGPOS
{ return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer);
static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
inline bool sanitize (hb_sanitize_context_t *c) const
{
@ -1516,13 +1527,13 @@ struct GPOS : GSUBGPOS
static void
reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
{
unsigned int j = pos[i].cursive_chain();
if (likely (!j))
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
return;
j += i;
pos[i].attach_chain() = 0;
pos[i].cursive_chain() = 0;
unsigned int j = (int) i + chain;
/* Stop if we see new parent in the chain. */
if (j == new_parent)
@ -1535,62 +1546,68 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc
else
pos[j].x_offset = -pos[i].x_offset;
pos[j].cursive_chain() = i - j;
pos[j].attach_chain() = -chain;
pos[j].attach_type() = type;
}
static void
fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
{
unsigned int j = pos[i].cursive_chain();
if (likely (!j))
/* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
* offset of glyph they are attached to. */
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
if (likely (!chain))
return;
j += i;
unsigned int j = (int) i + chain;
pos[i].cursive_chain() = 0;
pos[i].attach_chain() = 0;
fix_cursive_minor_offset (pos, j, direction);
propagate_attachment_offsets (pos, j, direction);
if (HB_DIRECTION_IS_HORIZONTAL (direction))
pos[i].y_offset += pos[j].y_offset;
else
assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
if (type & ATTACH_TYPE_CURSIVE)
{
if (HB_DIRECTION_IS_HORIZONTAL (direction))
pos[i].y_offset += pos[j].y_offset;
else
pos[i].x_offset += pos[j].x_offset;
}
else /*if (type & ATTACH_TYPE_MARK)*/
{
pos[i].x_offset += pos[j].x_offset;
}
pos[i].y_offset += pos[j].y_offset;
static void
fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
{
if (likely (!(pos[i].attach_lookback())))
return;
unsigned int j = i - pos[i].attach_lookback();
pos[i].x_offset += pos[j].x_offset;
pos[i].y_offset += pos[j].y_offset;
if (HB_DIRECTION_IS_FORWARD (direction))
for (unsigned int k = j; k < i; k++) {
pos[i].x_offset -= pos[k].x_advance;
pos[i].y_offset -= pos[k].y_advance;
}
else
for (unsigned int k = j + 1; k < i + 1; k++) {
pos[i].x_offset += pos[k].x_advance;
pos[i].y_offset += pos[k].y_advance;
}
assert (j < i);
if (HB_DIRECTION_IS_FORWARD (direction))
for (unsigned int k = j; k < i; k++) {
pos[i].x_offset -= pos[k].x_advance;
pos[i].y_offset -= pos[k].y_advance;
}
else
for (unsigned int k = j + 1; k < i + 1; k++) {
pos[i].x_offset += pos[k].x_advance;
pos[i].y_offset += pos[k].y_advance;
}
}
}
void
GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
{
buffer->clear_positions ();
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0;
buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
}
void
GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
{
//_hb_buffer_assert_gsubgpos_vars (buffer);
}
void
GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
{
_hb_buffer_assert_gsubgpos_vars (buffer);
@ -1598,13 +1615,10 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
hb_direction_t direction = buffer->props.direction;
/* Handle cursive connections */
for (unsigned int i = 0; i < len; i++)
fix_cursive_minor_offset (pos, i, direction);
/* Handle attachments */
for (unsigned int i = 0; i < len; i++)
fix_mark_attachment (pos, i, direction);
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
for (unsigned int i = 0; i < len; i++)
propagate_attachment_offsets (pos, i, direction);
}
@ -1633,8 +1647,8 @@ template <typename context_t>
}
#undef attach_lookback
#undef cursive_chain
#undef attach_chain
#undef attach_type
} /* namespace OT */

View File

@ -265,16 +265,6 @@ struct Sequence
TRACE_APPLY (this);
unsigned int count = substitute.len;
/* TODO:
* Testing shows that Uniscribe actually allows zero-len susbstitute,
* which essentially deletes a glyph. We don't allow for now. It
* can be confusing to the client since the cluster from the deleted
* glyph won't be merged with any output cluster... Also, currently
* buffer->move_to() makes assumptions about this too. Perhaps fix
* in the future after figuring out what to do with the clusters.
*/
if (unlikely (!count)) return_trace (false);
/* Special-case to make it in-place and not consider this
* as a "multiplied" substitution. */
if (unlikely (count == 1))
@ -282,6 +272,13 @@ struct Sequence
c->replace_glyph (substitute.array[0]);
return_trace (true);
}
/* Spec disallows this, but Uniscribe allows it.
* https://github.com/behdad/harfbuzz/issues/253 */
else if (unlikely (count == 0))
{
c->buffer->delete_glyph ();
return_trace (true);
}
unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
@ -630,7 +627,7 @@ struct Ligature
unsigned int total_component_count = 0;
unsigned int match_length = 0;
unsigned int match_positions[MAX_CONTEXT_LENGTH];
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
if (likely (!match_input (c, count,
&component[1],
@ -970,7 +967,7 @@ struct ReverseChainSingleSubstFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY (this);
if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL))
if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
return_trace (false); /* No chaining to this type */
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@ -1268,7 +1265,6 @@ struct GSUB : GSUBGPOS
{ return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer);
inline bool sanitize (hb_sanitize_context_t *c) const
{
@ -1289,19 +1285,32 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
{
_hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
_hb_glyph_info_clear_lig_props (&buffer->info[i]);
unsigned int props = gdef.get_glyph_props (info[i].codepoint);
if (!props)
{
/* Never mark default-ignorables as marks.
* They won't get in the way of lookups anyway,
* but having them as mark will cause them to be skipped
* over if the lookup-flag says so, but at least for the
* Mongolian variation selectors, looks like Uniscribe
* marks them as non-mark. Some Mongolian fonts without
* GDEF rely on this. Another notable character that
* this applies to is COMBINING GRAPHEME JOINER. */
props = (_hb_glyph_info_get_general_category (&info[i]) !=
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
_hb_glyph_info_is_default_ignorable (&info[i])) ?
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
HB_OT_LAYOUT_GLYPH_PROPS_MARK;
}
_hb_glyph_info_set_glyph_props (&info[i], props);
_hb_glyph_info_clear_lig_props (&info[i]);
buffer->info[i].syllable() = 0;
}
}
void
GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
{
}
/* Out-of-class implementation for methods recursing */

View File

@ -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_ = MAX_NESTING_LEVEL) :
unsigned int nesting_level_left_ = HB_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_ = MAX_NESTING_LEVEL) :
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
face (face_),
before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
input (glyphs_input ? glyphs_input : hb_set_get_empty ()),
@ -319,7 +319,7 @@ struct hb_apply_context_t :
if (!c->check_glyph_property (&info, lookup_props))
return SKIP_YES;
if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_fvs (&info) &&
(ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
(ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
return SKIP_MAYBE;
@ -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 (MAX_NESTING_LEVEL),
nesting_level_left (HB_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[MAX_CONTEXT_LENGTH],
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
bool *p_is_mark_ligature = NULL,
unsigned int *p_total_component_count = NULL)
{
TRACE_APPLY (NULL);
if (unlikely (count > MAX_CONTEXT_LENGTH)) return_trace (false);
if (unlikely (count > HB_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[MAX_CONTEXT_LENGTH], /* Including the first glyph */
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
unsigned int match_length,
hb_codepoint_t lig_glyph,
bool is_mark_ligature,
@ -836,19 +836,21 @@ 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])
while (buffer->idx < match_positions[i] && !buffer->in_error)
{
if (!is_mark_ligature) {
unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
if (this_comp == 0)
this_comp = last_num_components;
unsigned int new_lig_comp = components_so_far - last_num_components +
MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components);
_hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
MIN (this_comp, last_num_components);
_hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
}
buffer->next_glyph ();
}
@ -865,8 +867,11 @@ static inline bool ligate_input (hb_apply_context_t *c,
/* Re-adjust components for any marks following. */
for (unsigned int i = buffer->idx; i < buffer->len; i++) {
if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
if (!this_comp)
break;
unsigned int new_lig_comp = components_so_far - last_num_components +
MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components);
MIN (this_comp, last_num_components);
_hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
} else
break;
@ -944,7 +949,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[MAX_CONTEXT_LENGTH], /* Including the first glyph */
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
unsigned int match_length)
@ -966,12 +971,17 @@ static inline bool apply_lookup (hb_apply_context_t *c,
match_positions[j] += delta;
}
for (unsigned int i = 0; i < lookupCount; i++)
for (unsigned int i = 0; i < lookupCount && !buffer->in_error; i++)
{
unsigned int idx = lookupRecord[i].sequenceIndex;
if (idx >= count)
continue;
/* Don't recurse to ourself at same position.
* Note that this test is too naive, it doesn't catch longer loops. */
if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
continue;
buffer->move_to (match_positions[idx]);
unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
@ -986,16 +996,19 @@ static inline bool apply_lookup (hb_apply_context_t *c,
/* Recursed lookup changed buffer len. Adjust. */
/* 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 ((int) match_positions[idx] + 1, int (end) + delta);
end = int (end) + delta;
if (end <= match_positions[idx])
{
/* There can't be any further changes. */
assert (end == match_positions[idx]);
break;
}
unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
if (delta > 0)
{
if (unlikely (delta + count > MAX_CONTEXT_LENGTH))
if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
break;
}
else
@ -1094,7 +1107,7 @@ static inline bool context_apply_lookup (hb_apply_context_t *c,
ContextApplyLookupContext &lookup_context)
{
unsigned int match_length = 0;
unsigned int match_positions[MAX_CONTEXT_LENGTH];
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
return match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data,
@ -1621,7 +1634,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[MAX_CONTEXT_LENGTH];
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
return match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data[1],
@ -2267,7 +2280,7 @@ struct GSUBGPOS
}
protected:
FixedVersion version; /* Version of the GSUB/GPOS table--initially set
FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
* to 0x00010000u */
OffsetTo<ScriptList>
scriptList; /* ScriptList table */

View File

@ -218,7 +218,7 @@ struct JSTF
}
protected:
FixedVersion version; /* Version of the JSTF table--initially set
FixedVersion<>version; /* Version of the JSTF table--initially set
* to 0x00010000u */
RecordArrayOf<JstfScript>
scriptList; /* Array of JstfScripts--listed

View File

@ -49,7 +49,7 @@ hb_ot_layout_table_find_feature (hb_face_t *face,
* GDEF
*/
typedef enum
enum hb_ot_layout_glyph_props_flags_t
{
/* The following three match LookupFlags::Ignore* numbers. */
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 0x02u,
@ -64,7 +64,8 @@ typedef enum
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_ot_layout_glyph_class_mask_t;
};
HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
/*
@ -98,21 +99,20 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
const hb_ot_layout_lookup_accelerator_t &accel);
/* Should be called after all the substitute_lookup's are done */
HB_INTERNAL void
hb_ot_layout_substitute_finish (hb_font_t *font,
hb_buffer_t *buffer);
/* Should be called before all the position_lookup's are done. Resets positions to zero. */
/* Should be called before all the position_lookup's are done. */
HB_INTERNAL void
hb_ot_layout_position_start (hb_font_t *font,
hb_buffer_t *buffer);
/* Should be called after all the position_lookup's are done */
/* Should be called after all the position_lookup's are done, to finish advances. */
HB_INTERNAL void
hb_ot_layout_position_finish (hb_font_t *font,
hb_buffer_t *buffer);
hb_ot_layout_position_finish_advances (hb_font_t *font,
hb_buffer_t *buffer);
/* Should be called after hb_ot_layout_position_finish_advances, to finish offsets. */
HB_INTERNAL void
hb_ot_layout_position_finish_offsets (hb_font_t *font,
hb_buffer_t *buffer);
@ -180,8 +180,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout);
*/
/* buffer var allocations, used during the entire shaping process */
#define unicode_props0() var2.u8[0]
#define unicode_props1() var2.u8[1]
#define unicode_props() var2.u16[0]
/* buffer var allocations, used during the GSUB/GPOS processing */
#define glyph_props() var1.u16[0] /* GDEF glyph properties */
@ -214,48 +213,146 @@ _next_syllable (hb_buffer_t *buffer, unsigned int start)
/* unicode_props */
enum {
MASK0_ZWJ = 0x20u,
MASK0_ZWNJ = 0x40u,
MASK0_IGNORABLE = 0x80u,
MASK0_GEN_CAT = 0x1Fu
/* 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().
* * Whether it's one of the three Mongolian Free Variation Selectors.
* * One free bit right now.
*
* The high-byte has different meanings, switched by the Gen-Cat:
* - For Mn,Mc,Me: the modified Combining_Class.
* - For Cf: whether it's ZWJ, ZWNJ, or something else.
* - 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.
*/
enum hb_unicode_props_flags_t {
UPROPS_MASK_GEN_CAT = 0x001Fu,
UPROPS_MASK_IGNORABLE = 0x0020u,
UPROPS_MASK_FVS = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3 */
/* If GEN_CAT=FORMAT, top byte masks: */
UPROPS_MASK_Cf_ZWJ = 0x0100u,
UPROPS_MASK_Cf_ZWNJ = 0x0200u
};
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_unicode_funcs_t *unicode)
_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
{
/* 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);
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_Cf_ZWNJ;
if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
/* Mongolian Free Variation Selectors need to be remembered
* because although we need to hide them like default-ignorables,
* they need to non-ignorable during shaping. This is similar to
* what we do for joiners in Indic-like shapers, but since the
* FVSes are GC=Mn, we have use a separate bit to remember them.
* Fixes:
* https://github.com/behdad/harfbuzz/issues/234
*/
if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_FVS;
}
else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
{
/* The above check is just an optimization to let in only things we need further
* processing on. */
/* 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;
/* Recategorize emoji skin-tone modifiers as Unicode mark, so they
* behave correctly in non-native directionality. They originally
* are MODIFIER_SYMBOL. Fixes:
* https://github.com/behdad/harfbuzz/issues/169
*/
if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
{
props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
}
}
}
info->unicode_props() = props;
}
static inline void
_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
hb_unicode_general_category_t gen_cat)
{
info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT);
/* Clears top-byte. */
info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_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_props0() & MASK0_GEN_CAT);
return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_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)
{
info->unicode_props1() = modified_class;
if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
return;
info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
}
static inline unsigned int
_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
{
return info->unicode_props1();
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;
}
static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
@ -263,25 +360,44 @@ 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_props0() & MASK0_IGNORABLE) && !_hb_glyph_info_ligated (info);
return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
!_hb_glyph_info_ligated (info);
}
static inline hb_bool_t
_hb_glyph_info_is_default_ignorable_and_not_fvs (const hb_glyph_info_t *info)
{
return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_FVS))
== UPROPS_MASK_IGNORABLE) &&
!_hb_glyph_info_ligated (info);
}
static inline bool
_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
{
return _hb_glyph_info_get_general_category (info) ==
HB_UNICODE_GENERAL_CATEGORY_FORMAT;
}
static inline hb_bool_t
_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
{
return !!(info->unicode_props0() & MASK0_ZWNJ);
return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
}
static inline hb_bool_t
_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
{
return !!(info->unicode_props0() & MASK0_ZWJ);
return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
}
static inline hb_bool_t
_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
{
return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
}
static inline void
_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
{
info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ;
if (!_hb_glyph_info_is_unicode_format (info))
return;
info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
}
/* lig_props: aka lig_id / lig_comp
@ -442,11 +558,9 @@ _hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
}
static inline void
_hb_glyph_info_clear_substituted_and_ligated_and_multiplied (hb_glyph_info_t *info)
_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
{
info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
}
@ -455,22 +569,19 @@ _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_props0);
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1);
HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
}
static inline void
_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
{
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0);
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1);
HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
}
static inline void
_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ASSERT_VAR (buffer, unicode_props0);
HB_BUFFER_ASSERT_VAR (buffer, unicode_props1);
HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
}
static inline void

View File

@ -60,6 +60,80 @@ _hb_ot_layout_create (hb_face_t *face)
layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
{
/*
* The ugly business of blacklisting individual fonts' tables happen here!
* See this thread for why we finally had to bend in and do this:
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
*/
unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob);
unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob);
unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob);
if (0
/* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
|| (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
/* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
|| (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len)
/* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
|| (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len)
/* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
|| (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len)
/* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
|| (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len)
/* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
|| (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len)
)
{
/* In certain versions of Times New Roman Italic and Bold Italic,
* ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
* glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width
* double-quote. See:
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
*/
if (3 == layout->gdef->get_glyph_class (5))
layout->gdef = &OT::Null(OT::GDEF);
}
else if (0
/* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */
|| (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len)
/* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */
|| (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len)
/* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */
|| (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
/* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */
|| (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
/* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */
|| (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
/* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */
|| (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
/* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */
|| (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len)
/* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */
|| (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len)
/* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */
|| (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len)
/* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */
|| (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
/* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
/* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
|| (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
/* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
/* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
|| (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
)
{
/* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
* such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
* and the version of Cantarell shipped by Ubuntu 16.04.
* Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
*/
layout->gdef = &OT::Null(OT::GDEF);
}
}
layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
@ -130,6 +204,8 @@ hb_ot_layout_has_glyph_classes (hb_face_t *face)
}
/**
* hb_ot_layout_get_glyph_class:
*
* Since: 0.9.7
**/
hb_ot_layout_glyph_class_t
@ -140,6 +216,8 @@ hb_ot_layout_get_glyph_class (hb_face_t *face,
}
/**
* hb_ot_layout_get_glyphs_in_class:
*
* Since: 0.9.7
**/
void
@ -365,6 +443,8 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
}
/**
* hb_ot_layout_language_get_required_feature:
*
* Since: 0.9.30
**/
hb_bool_t
@ -452,6 +532,8 @@ hb_ot_layout_language_find_feature (hb_face_t *face,
}
/**
* hb_ot_layout_feature_get_lookups:
*
* Since: 0.9.7
**/
unsigned int
@ -469,6 +551,8 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face,
}
/**
* hb_ot_layout_table_get_lookup_count:
*
* Since: 0.9.22
**/
unsigned int
@ -629,6 +713,8 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face,
}
/**
* hb_ot_layout_collect_lookups:
*
* Since: 0.9.8
**/
void
@ -673,6 +759,8 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
}
/**
* hb_ot_layout_lookup_collect_glyphs:
*
* Since: 0.9.7
**/
void
@ -721,6 +809,8 @@ hb_ot_layout_has_substitution (hb_face_t *face)
}
/**
* hb_ot_layout_lookup_would_substitute:
*
* Since: 0.9.7
**/
hb_bool_t
@ -742,7 +832,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
hb_bool_t zero_context)
{
if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context);
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
@ -755,13 +845,9 @@ hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
OT::GSUB::substitute_start (font, buffer);
}
void
hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
{
OT::GSUB::substitute_finish (font, buffer);
}
/**
* hb_ot_layout_lookup_substitute_closure:
*
* Since: 0.9.7
**/
void
@ -793,12 +879,20 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
}
void
hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
{
OT::GPOS::position_finish (font, buffer);
OT::GPOS::position_finish_advances (font, buffer);
}
void
hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
{
OT::GPOS::position_finish_offsets (font, buffer);
}
/**
* hb_ot_layout_get_size_params:
*
* Since: 0.9.10
**/
hb_bool_t
@ -882,20 +976,79 @@ struct GPOSProxy
};
template <typename Obj>
struct hb_get_subtables_context_t :
OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
{
template <typename Type>
static inline bool apply_to (const void *obj, OT::hb_apply_context_t *c)
{
const Type *typed_obj = (const Type *) obj;
return typed_obj->apply (c);
}
typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_apply_context_t *c);
struct hb_applicable_t
{
inline void init (const void *obj_, hb_apply_func_t apply_func_)
{
obj = obj_;
apply_func = apply_func_;
}
inline bool apply (OT::hb_apply_context_t *c) const { return apply_func (obj, c); }
private:
const void *obj;
hb_apply_func_t apply_func;
};
typedef hb_auto_array_t<hb_applicable_t> array_t;
/* Dispatch interface. */
inline const char *get_name (void) { return "GET_SUBTABLES"; }
template <typename T>
inline return_t dispatch (const T &obj)
{
hb_applicable_t *entry = array.push();
if (likely (entry))
entry->init (&obj, apply_to<T>);
return HB_VOID;
}
static return_t default_return_value (void) { return HB_VOID; }
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
hb_get_subtables_context_t (array_t &array_) :
array (array_),
debug_depth (0) {}
array_t &array;
unsigned int debug_depth;
};
static inline bool
apply_forward (OT::hb_apply_context_t *c,
const Obj &obj,
const hb_ot_layout_lookup_accelerator_t &accel)
const hb_ot_layout_lookup_accelerator_t &accel,
const hb_get_subtables_context_t::array_t &subtables)
{
bool ret = false;
hb_buffer_t *buffer = c->buffer;
while (buffer->idx < buffer->len)
while (buffer->idx < buffer->len && !buffer->in_error)
{
bool applied = false;
if (accel.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props) &&
obj.apply (c))
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
for (unsigned int i = 0; i < subtables.len; i++)
if (subtables[i].apply (c))
{
applied = true;
break;
}
}
if (applied)
ret = true;
else
buffer->next_glyph ();
@ -903,11 +1056,10 @@ apply_forward (OT::hb_apply_context_t *c,
return ret;
}
template <typename Obj>
static inline bool
apply_backward (OT::hb_apply_context_t *c,
const Obj &obj,
const hb_ot_layout_lookup_accelerator_t &accel)
const hb_ot_layout_lookup_accelerator_t &accel,
const hb_get_subtables_context_t::array_t &subtables)
{
bool ret = false;
hb_buffer_t *buffer = c->buffer;
@ -915,9 +1067,15 @@ apply_backward (OT::hb_apply_context_t *c,
{
if (accel.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props) &&
obj.apply (c))
ret = true;
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
for (unsigned int i = 0; i < subtables.len; i++)
if (subtables[i].apply (c))
{
ret = true;
break;
}
}
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
@ -926,26 +1084,6 @@ apply_backward (OT::hb_apply_context_t *c,
return ret;
}
struct hb_apply_forward_context_t :
OT::hb_dispatch_context_t<hb_apply_forward_context_t, bool, HB_DEBUG_APPLY>
{
inline const char *get_name (void) { return "APPLY_FWD"; }
template <typename T>
inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); }
static return_t default_return_value (void) { return false; }
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; }
hb_apply_forward_context_t (OT::hb_apply_context_t *c_,
const hb_ot_layout_lookup_accelerator_t &accel_) :
c (c_),
accel (accel_),
debug_depth (0) {}
OT::hb_apply_context_t *c;
const hb_ot_layout_lookup_accelerator_t &accel;
unsigned int debug_depth;
};
template <typename Proxy>
static inline void
apply_string (OT::hb_apply_context_t *c,
@ -959,6 +1097,10 @@ apply_string (OT::hb_apply_context_t *c,
c->set_lookup_props (lookup.get_props ());
hb_get_subtables_context_t::array_t subtables;
hb_get_subtables_context_t c_get_subtables (subtables);
lookup.dispatch (&c_get_subtables);
if (likely (!lookup.is_reverse ()))
{
/* in/out forward substitution/positioning */
@ -967,13 +1109,7 @@ apply_string (OT::hb_apply_context_t *c,
buffer->idx = 0;
bool ret;
if (lookup.get_subtable_count () == 1)
{
hb_apply_forward_context_t c_forward (c, accel);
ret = lookup.dispatch (&c_forward);
}
else
ret = apply_forward (c, lookup, accel);
ret = apply_forward (c, accel, subtables);
if (ret)
{
if (!Proxy::inplace)
@ -989,7 +1125,7 @@ apply_string (OT::hb_apply_context_t *c,
buffer->remove_output ();
buffer->idx = buffer->len - 1;
apply_backward (c, lookup, accel);
apply_backward (c, accel, subtables);
}
}
@ -1008,25 +1144,15 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
const stage_map_t *stage = &stages[table_index][stage_index];
for (; i < stage->last_lookup; i++)
{
#if 0
char buf[4096];
hb_buffer_serialize_glyphs (buffer, 0, buffer->len,
buf, sizeof (buf), NULL,
font,
HB_BUFFER_SERIALIZE_FORMAT_TEXT,
Proxy::table_index == 0 ?
HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS :
HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
printf ("buf: [%s]\n", buf);
#endif
unsigned int lookup_index = lookups[table_index][i].index;
if (!buffer->message (font, "start lookup %d", lookup_index)) continue;
c.set_lookup_index (lookup_index);
c.set_lookup_mask (lookups[table_index][i].mask);
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
apply_string<Proxy> (&c,
proxy.table.get_lookup (lookup_index),
proxy.accels[lookup_index]);
(void) buffer->message (font, "end lookup %d", lookup_index);
}
if (stage->pause_func)

View File

@ -48,7 +48,7 @@ HB_BEGIN_DECLS
* GDEF
*/
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_has_glyph_classes (hb_face_t *face);
typedef enum {
@ -59,11 +59,11 @@ typedef enum {
HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT = 4
} hb_ot_layout_glyph_class_t;
hb_ot_layout_glyph_class_t
HB_EXTERN hb_ot_layout_glyph_class_t
hb_ot_layout_get_glyph_class (hb_face_t *face,
hb_codepoint_t glyph);
void
HB_EXTERN void
hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
hb_ot_layout_glyph_class_t klass,
hb_set_t *glyphs /* OUT */);
@ -71,7 +71,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
/* Not that useful. Provides list of attach points for a glyph that a
* client may want to cache */
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_get_attach_points (hb_face_t *face,
hb_codepoint_t glyph,
unsigned int start_offset,
@ -79,7 +79,7 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
unsigned int *point_array /* OUT */);
/* Ligature caret positions */
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_get_ligature_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph,
@ -96,35 +96,35 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
#define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_table_get_script_tags (hb_face_t *face,
hb_tag_t table_tag,
unsigned int start_offset,
unsigned int *script_count /* IN/OUT */,
hb_tag_t *script_tags /* OUT */);
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_table_find_script (hb_face_t *face,
hb_tag_t table_tag,
hb_tag_t script_tag,
unsigned int *script_index);
/* Like find_script, but takes zero-terminated array of scripts to test */
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_table_choose_script (hb_face_t *face,
hb_tag_t table_tag,
const hb_tag_t *script_tags,
unsigned int *script_index,
hb_tag_t *chosen_script);
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_table_get_feature_tags (hb_face_t *face,
hb_tag_t table_tag,
unsigned int start_offset,
unsigned int *feature_count /* IN/OUT */,
hb_tag_t *feature_tags /* OUT */);
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_script_get_language_tags (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
@ -132,21 +132,21 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
unsigned int *language_count /* IN/OUT */,
hb_tag_t *language_tags /* OUT */);
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_script_find_language (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
hb_tag_t language_tag,
unsigned int *language_index);
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
unsigned int language_index,
unsigned int *feature_index);
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_language_get_required_feature (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
@ -154,7 +154,7 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
unsigned int *feature_index,
hb_tag_t *feature_tag);
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
@ -163,7 +163,7 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
unsigned int *feature_count /* IN/OUT */,
unsigned int *feature_indexes /* OUT */);
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_language_get_feature_tags (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
@ -172,7 +172,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
unsigned int *feature_count /* IN/OUT */,
hb_tag_t *feature_tags /* OUT */);
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_language_find_feature (hb_face_t *face,
hb_tag_t table_tag,
unsigned int script_index,
@ -180,7 +180,7 @@ hb_ot_layout_language_find_feature (hb_face_t *face,
hb_tag_t feature_tag,
unsigned int *feature_index);
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_feature_get_lookups (hb_face_t *face,
hb_tag_t table_tag,
unsigned int feature_index,
@ -188,12 +188,12 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face,
unsigned int *lookup_count /* IN/OUT */,
unsigned int *lookup_indexes /* OUT */);
unsigned int
HB_EXTERN unsigned int
hb_ot_layout_table_get_lookup_count (hb_face_t *face,
hb_tag_t table_tag);
void
HB_EXTERN void
hb_ot_layout_collect_lookups (hb_face_t *face,
hb_tag_t table_tag,
const hb_tag_t *scripts,
@ -201,7 +201,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
const hb_tag_t *features,
hb_set_t *lookup_indexes /* OUT */);
void
HB_EXTERN void
hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
hb_tag_t table_tag,
unsigned int lookup_index,
@ -228,7 +228,7 @@ typedef hb_bool_t
const hb_ot_layout_glyph_sequence_t *sequence,
void *user_data);
void
HB_EXTERN void
Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face,
hb_tag_t table_tag,
unsigned int lookup_index,
@ -241,17 +241,17 @@ Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face,
* GSUB
*/
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_has_substitution (hb_face_t *face);
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_lookup_would_substitute (hb_face_t *face,
unsigned int lookup_index,
const hb_codepoint_t *glyphs,
unsigned int glyphs_length,
hb_bool_t zero_context);
void
HB_EXTERN void
hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
unsigned int lookup_index,
hb_set_t *glyphs
@ -259,7 +259,7 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
#ifdef HB_NOT_IMPLEMENTED
/* Note: You better have GDEF when using this API, or marks won't do much. */
hb_bool_t
HB_EXTERN hb_bool_t
Xhb_ot_layout_lookup_substitute (hb_font_t *font,
unsigned int lookup_index,
const hb_ot_layout_glyph_sequence_t *sequence,
@ -274,12 +274,12 @@ Xhb_ot_layout_lookup_substitute (hb_font_t *font,
* GPOS
*/
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face);
#ifdef HB_NOT_IMPLEMENTED
/* Note: You better have GDEF when using this API, or marks won't do much. */
hb_bool_t
HB_EXTERN hb_bool_t
Xhb_ot_layout_lookup_position (hb_font_t *font,
unsigned int lookup_index,
const hb_ot_layout_glyph_sequence_t *sequence,
@ -288,7 +288,7 @@ Xhb_ot_layout_lookup_position (hb_font_t *font,
/* Optical 'size' feature info. Returns true if found.
* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
hb_bool_t
HB_EXTERN hb_bool_t
hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *design_size, /* OUT. May be NULL */
unsigned int *subfamily_id, /* OUT. May be NULL */

View File

@ -159,23 +159,9 @@ 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
@ -217,7 +203,8 @@ struct hb_ot_map_builder_t
unsigned int stage[2]; /* GSUB/GPOS */
static int cmp (const feature_info_t *a, const feature_info_t *b)
{ return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); }
{ return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) :
(a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); }
};
struct stage_info_t {

View File

@ -89,7 +89,7 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
for (unsigned int table_index = 0; table_index < 2; table_index++) {
hb_tag_t table_tag = table_tags[table_index];
found_script[table_index] = hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
}
}
@ -204,11 +204,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
if (required_feature_tag[table_index] == info->tag)
{
required_feature_stage[table_index] = info->stage[table_index];
found = true;
continue;
}
found |= hb_ot_layout_language_find_feature (face,
table_tags[table_index],
script_index[table_index],

View File

@ -58,7 +58,7 @@ struct maxp
/* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
protected:
FixedVersion version; /* Version of the maxp table (0.5 or 1.0),
FixedVersion<>version; /* Version of the maxp table (0.5 or 1.0),
* 0x00005000u or 0x00010000u. */
USHORT numGlyphs; /* The number of glyphs in the font. */
public:

View File

@ -0,0 +1,105 @@
/*
* Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_OS2_TABLE_HH
#define HB_OT_OS2_TABLE_HH
#include "hb-open-type-private.hh"
namespace OT {
/*
* OS/2 and Windows Metrics
* http://www.microsoft.com/typography/otspec/os2.htm
*/
#define HB_OT_TAG_os2 HB_TAG('O','S','/','2')
struct os2
{
static const hb_tag_t tableTag = HB_OT_TAG_os2;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
public:
USHORT version;
/* Version 0 */
SHORT xAvgCharWidth;
USHORT usWeightClass;
USHORT usWidthClass;
USHORT fsType;
SHORT ySubscriptXSize;
SHORT ySubscriptYSize;
SHORT ySubscriptXOffset;
SHORT ySubscriptYOffset;
SHORT ySuperscriptXSize;
SHORT ySuperscriptYSize;
SHORT ySuperscriptXOffset;
SHORT ySuperscriptYOffset;
SHORT yStrikeoutSize;
SHORT yStrikeoutPosition;
SHORT sFamilyClass;
BYTE panose[10];
ULONG ulUnicodeRange[4];
Tag achVendID;
USHORT fsSelection;
USHORT usFirstCharIndex;
USHORT usLastCharIndex;
SHORT sTypoAscender;
SHORT sTypoDescender;
SHORT sTypoLineGap;
USHORT usWinAscent;
USHORT usWinDescent;
/* Version 1 */
//ULONG ulCodePageRange1;
//ULONG ulCodePageRange2;
/* Version 2 */
//SHORT sxHeight;
//SHORT sCapHeight;
//USHORT usDefaultChar;
//USHORT usBreakChar;
//USHORT usMaxContext;
/* Version 5 */
//USHORT usLowerOpticalPointSize;
//USHORT usUpperOpticalPointSize;
public:
DEFINE_SIZE_STATIC (78);
};
} /* namespace OT */
#endif /* HB_OT_OS2_TABLE_HH */

View File

@ -6,10 +6,10 @@
*
* on files with these headers:
*
* # ArabicShaping-8.0.0.txt
* # Date: 2015-02-17, 23:33:00 GMT [RP]
* # Blocks-8.0.0.txt
* # Date: 2014-11-10, 23:04:00 GMT [KW]
* # ArabicShaping-9.0.0.txt
* # Date: 2016-02-24, 22:25:00 GMT [RP]
* # Blocks-9.0.0.txt
* # Date: 2016-02-05, 23:48:00 GMT [KW]
* UnicodeData.txt does not have a header.
*/
@ -19,6 +19,7 @@
#define X JOINING_TYPE_X
#define R JOINING_TYPE_R
#define T JOINING_TYPE_T
#define U JOINING_TYPE_U
#define A JOINING_GROUP_ALAPH
#define DR JOINING_GROUP_DALATH_RISH
@ -76,9 +77,11 @@ static const uint8_t joining_table[] =
/* Arabic Extended-A */
/* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,
/* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,X,D,D,D,R,D,D,D,D,X,X,
/* 08C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 08E0 */ X,X,U,
#define joining_offset_0x1806u 693
#define joining_offset_0x1806u 739
/* Mongolian */
@ -86,43 +89,48 @@ static const uint8_t joining_table[] =
/* 1820 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 1840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,
/* 1880 */ U,U,U,U,U,U,U,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 1880 */ U,U,U,U,U,T,T,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 18A0 */ D,D,D,D,D,D,D,D,D,X,D,
#define joining_offset_0x200cu 858
#define joining_offset_0x200cu 904
/* General Punctuation */
/* 2000 */ U,C,
/* 2000 */ U,C,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 2020 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 2040 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 2060 */ X,X,X,X,X,X,U,U,U,U,
#define joining_offset_0x2066u 860
/* General Punctuation */
/* 2060 */ U,U,U,U,
#define joining_offset_0xa840u 864
#define joining_offset_0xa840u 998
/* Phags-pa */
/* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U,
#define joining_offset_0x10ac0u 916
#define joining_offset_0x10ac0u 1050
/* Manichaean */
/* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D,
/* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R,
#define joining_offset_0x10b80u 964
#define joining_offset_0x10b80u 1098
/* Psalter Pahlavi */
/* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
/* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U,
}; /* Table items: 1012; occupancy: 57% */
#define joining_offset_0x1e900u 1146
/* Adlam */
/* 1E900 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
/* 1E940 */ D,D,D,D,
}; /* Table items: 1214; occupancy: 54% */
static unsigned int
@ -131,7 +139,7 @@ joining_type (hb_codepoint_t u)
switch (u >> 12)
{
case 0x0u:
if (hb_in_range (u, 0x0600u, 0x08B4u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
if (hb_in_range (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
break;
case 0x1u:
@ -139,8 +147,7 @@ joining_type (hb_codepoint_t u)
break;
case 0x2u:
if (hb_in_range (u, 0x200Cu, 0x200Du)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
if (hb_in_range (u, 0x2066u, 0x2069u)) return joining_table[u - 0x2066u + joining_offset_0x2066u];
if (hb_in_range (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
break;
case 0xAu:
@ -152,6 +159,10 @@ joining_type (hb_codepoint_t u)
if (hb_in_range (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
break;
case 0x1Eu:
if (hb_in_range (u, 0x1E900u, 0x1E943u)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u];
break;
default:
break;
}
@ -160,6 +171,7 @@ joining_type (hb_codepoint_t u)
#undef X
#undef R
#undef T
#undef U
#undef A
#undef DR

View File

@ -28,9 +28,38 @@
#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:
@ -84,7 +113,7 @@ static const hb_tag_t arabic_features[] =
/* Same order as the feature array */
enum {
enum arabic_action_t {
ISOL,
FINA,
FIN2,
@ -95,7 +124,11 @@ enum {
NONE,
ARABIC_NUM_FEATURES = NONE
ARABIC_NUM_FEATURES = NONE,
/* We abuse the same byte for other things... */
STCH_FIXED,
STCH_REPEATING,
};
static const struct arabic_state_table_entry {
@ -139,6 +172,11 @@ 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)
{
@ -165,6 +203,9 @@ 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'));
@ -182,7 +223,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
map->add_gsub_pause (arabic_fallback_shape);
map->add_global_bool_feature (HB_TAG('c','a','l','t'));
map->add_gsub_pause (NULL);
/* The spec includes 'cswh'. Earlier versions of Windows
* used to enable this by default, but testing suggests
@ -192,6 +232,7 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
* Note that IranNastaliq uses this feature extensively
* to fixup broken glyph sequences. Oh well...
* Test case: U+0643,U+0640,U+0631. */
//map->add_gsub_pause (NULL);
//map->add_global_bool_feature (HB_TAG('c','s','w','h'));
map->add_global_bool_feature (HB_TAG('m','s','e','t'));
}
@ -208,8 +249,10 @@ 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 *
@ -220,6 +263,7 @@ 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 &&
@ -320,8 +364,6 @@ 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
@ -371,6 +413,197 @@ 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.
*/
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_position_t width = font->get_glyph_h_advance (info[i].codepoint);
if (info[i].arabic_shaping_action() == STCH_FIXED)
{
w_fixed += width;
n_fixed++;
}
else
{
w_repeating += 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;
if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
n_copies = (sign * w_remaining) / (sign * w_repeating) - 1;
/* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
hb_position_t extra_repeat_overlap = 0;
hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
if (shortfall > 0)
{
++n_copies;
hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
if (excess > 0)
extra_repeat_overlap = excess / (n_copies * n_repeating);
}
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 = 0;
for (unsigned int k = end; k > start; k--)
{
hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint);
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 -= width;
if (n > 0)
x_offset += extra_repeat_overlap;
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 =
{
@ -379,7 +612,8 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
NULL, /* override_features */
data_create_arabic,
data_destroy_arabic,
NULL, /* preprocess_text_arabic */
NULL, /* preprocess_text */
postprocess_glyphs_arabic,
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
NULL, /* decompose */
NULL, /* compose */

View File

@ -35,10 +35,11 @@ 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 */
NULL, /* setup_masks */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};

View File

@ -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;)
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
{
hb_codepoint_t u = buffer->cur().codepoint;
@ -411,13 +411,14 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
"hangul",
collect_features_hangul,
override_features_hangul,
data_create_hangul, /* data_create */
data_destroy_hangul, /* data_destroy */
data_create_hangul,
data_destroy_hangul,
preprocess_text_hangul,
NULL, /* postprocess_glyphs */
HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
NULL, /* decompose */
NULL, /* compose */
setup_masks_hangul, /* setup_masks */
setup_masks_hangul,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};

View File

@ -68,7 +68,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
0xFB4Au /* TAV */
};
bool found = c->unicode->compose (a, b, ab);
bool found = (bool) c->unicode->compose (a, b, ab);
if (!found && !c->plan->has_mark)
{
@ -163,6 +163,7 @@ 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,

View File

@ -60,11 +60,10 @@ enum indic_category_t {
OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
OT_Ra = 16,
OT_CM = 17, /* Consonant-Medial. */
OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
OT_CM2 = 31 /* Consonant-Medial, second slot. */
OT_Symbol = 18 /* Avagraha, etc that take marks (SM,A,VD). */
};
#define MEDIAL_FLAGS (FLAG (OT_CM) | FLAG (OT_CM2))
#define MEDIAL_FLAGS (FLAG (OT_CM))
/* Note:
*
@ -109,27 +108,31 @@ enum indic_syllabic_category_t {
INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol,
INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* TODO */
INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* Don't care. */
INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A,
INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM,
INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER = OT_M, /* U+17CD only. */
INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM,
INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER,
INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha,
INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */
INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM,
INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N,
INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_Repha, /* TODO */
INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM,
INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_H, /* TODO */
INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng,
INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ,
INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ,
INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER,
INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* TODO */
INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_H, /* TODO */
INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */
INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */
INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS,
INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_M, /* Misc Khmer signs. */
INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N,
INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
@ -162,17 +165,23 @@ enum indic_matra_category_t {
};
#define INDIC_COMBINE_CATEGORIES(S,M) \
(ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || \
( \
S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
false)) + \
ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
((M << 8) | S))
( \
ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
( S | \
( \
( \
S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
false \
? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
) << 8 \
) \
) \
)
HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
hb_indic_get_categories (hb_codepoint_t u);

View File

@ -2,67 +2,71 @@
/*
* The following table is generated by running:
*
* ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt
* ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
*
* on files with these headers:
*
* # IndicSyllabicCategory-7.0.0.txt
* # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP]
* # IndicMatraCategory-7.0.0.txt
* # Date: 2014-06-03, 07:00:00 GMT [KW, LI, AG, RP]
* # Blocks-7.0.0.txt
* # Date: 2014-04-03, 23:23:00 GMT [RP, KW]
* # IndicSyllabicCategory-9.0.0.txt
* # Date: 2016-05-21, 02:46:00 GMT [RP]
* # IndicPositionalCategory-9.0.0.txt
* # Date: 2016-02-25, 00:48:00 GMT [RP]
* # Blocks-9.0.0.txt
* # Date: 2016-02-05, 23:48:00 GMT [KW]
*/
#include "hb-ot-shape-complex-indic-private.hh"
#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 13 chars; Avagraha */
#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 59 chars; Bindu */
#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 15 chars; Avagraha */
#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 67 chars; Bindu */
#define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */
#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 30 chars; Cantillation_Mark */
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1744 chars; Consonant */
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 7 chars; Consonant_Dead */
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 61 chars; Consonant_Final */
#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 53 chars; Cantillation_Mark */
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1907 chars; Consonant */
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 10 chars; Consonant_Dead */
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 62 chars; Consonant_Final */
#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */
#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 19 chars; Consonant_Medial */
#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 11 chars; Consonant_Placeholder */
#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */
#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 22 chars; Consonant_Medial */
#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 16 chars; Consonant_Placeholder */
#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 1 chars; Consonant_Preceding_Repha */
#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 61 chars; Consonant_Subjoined */
#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 2 chars; Consonant_Prefixed */
#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 90 chars; Consonant_Subjoined */
#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */
#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 4 chars; Consonant_With_Stacker */
#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 2 chars; Gemination_Mark */
#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 7 chars; Invisible_Stacker */
#define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */
#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 18 chars; Nukta */
#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 408 chars; Number */
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 24 chars; Nukta */
#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 459 chars; Number */
#define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */
#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 15 chars; Pure_Killer */
#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 3 chars; Register_Shifter */
#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 16 chars; Pure_Killer */
#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */
#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 22 chars; Syllable_Modifier */
#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */
#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 62 chars; Tone_Mark */
#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 22 chars; Virama */
#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 29 chars; Visarga */
#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */
#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 24 chars; Virama */
#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 31 chars; Visarga */
#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 553 chars; Vowel_Dependent */
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 395 chars; Vowel_Independent */
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 602 chars; Vowel_Dependent */
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 431 chars; Vowel_Independent */
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 142 chars; Bottom */
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 300 chars; Bottom */
#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */
#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 57 chars; Left */
#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 21 chars; Left_And_Right */
#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 2 chars; Overstruck */
#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 163 chars; Right */
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 169 chars; Top */
#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */
#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 258 chars; Right */
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 342 chars; Top */
#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */
#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */
#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */
#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */
#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 15 chars; Visual_Order_Left */
#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 19 chars; Visual_Order_Left */
#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
@ -79,29 +83,33 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0038 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x00d0u 24
#define indic_offset_0x00b0u 24
/* Latin-1 Supplement */
/* 00B0 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 00B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 00C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 00C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 00D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x),
#define indic_offset_0x0900u 32
#define indic_offset_0x0900u 64
/* Devanagari */
/* 0900 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0920 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0928 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,x), _(A,x), _(M,R), _(M,L),
/* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,B), _(A,x), _(M,R), _(M,L),
/* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T),
/* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R),
/* 0950 */ _(x,x), _(TM,x), _(TM,x), _(x,x), _(x,x), _(M,T), _(M,B), _(M,B),
/* 0950 */ _(x,x), _(Ca,T), _(Ca,B), _(x,T), _(x,T), _(M,T), _(M,B), _(M,B),
/* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
@ -110,14 +118,14 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* Bengali */
/* 0980 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0980 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
/* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 09A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 09A8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 09B0 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
/* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L),
/* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L),
/* 09C0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
/* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x),
/* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
@ -129,33 +137,33 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* Gurmukhi */
/* 0A00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0A00 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
/* 0A10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0A18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0A28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0A30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x),
/* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(x,x), _(M,R), _(M,L),
/* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(x,x), _(M,R), _(M,L),
/* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T),
/* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x),
/* 0A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x),
/* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0A70 */ _(Bi,x), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,x), _(x,x), _(x,x),
/* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,B), _(x,x), _(x,x),
/* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Gujarati */
/* 0A80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0A80 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x),
/* 0A90 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0A98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0AA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0AA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0AB0 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
/* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L),
/* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L),
/* 0AC0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(x,x), _(M,T),
/* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x),
/* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
@ -163,18 +171,18 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0AF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0AF8 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Oriya */
/* 0B00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0B00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
/* 0B10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0B28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0B30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
/* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T),
/* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T),
/* 0B40 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
/* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x),
/* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,TR),
@ -186,7 +194,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* Tamil */
/* 0B80 */ _(x,x), _(x,x), _(Bi,x), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0B80 */ _(x,x), _(x,x), _(Bi,T), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x),
/* 0B90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(x,x), _(x,x),
/* 0B98 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x), _(C,x),
@ -194,7 +202,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0BA8 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
/* 0BB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0BB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R),
/* 0BC0 */ _(M,T), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L),
/* 0BC0 */ _(M,T), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L),
/* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x),
/* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
/* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
@ -205,7 +213,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* Telugu */
/* 0C00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
/* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@ -216,7 +224,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T),
/* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x),
/* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x),
/* 0C58 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
@ -224,26 +232,26 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* Kannada */
/* 0C80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0C80 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
/* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0CA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0CA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0CB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
/* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T),
/* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T),
/* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR),
/* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x),
/* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x),
/* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(x,x),
/* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0CF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Malayalam */
/* 0D00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0D00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
/* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@ -253,8 +261,8 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0D38 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(A,x), _(M,R), _(M,R),
/* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L),
/* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,x), _(x,x),
/* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
/* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(M,R),
/* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
/* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
@ -262,7 +270,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* Sinhala */
/* 0D80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0D80 */ _(x,x), _(x,x), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x),
/* 0D98 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@ -278,7 +286,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x1000u 1304
#define indic_offset_0x1000u 1336
/* Myanmar */
@ -289,52 +297,24 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 1018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B),
/* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(TM,x),
/* 1038 */ _(Vs,x), _(IS,x), _(PK,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(C,x),
/* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,T), _(TM,B),
/* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R), _(CM,x), _(CM,B), _(CM,B), _(C,x),
/* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x),
/* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R),
/* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,x), _(CM,x),
/* 1060 */ _(CM,x), _(C,x), _(M,R), _(TM,x), _(TM,x), _(C,x), _(C,x), _(M,R),
/* 1068 */ _(M,R), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x),
/* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,B), _(CM,B),
/* 1060 */ _(CM,B), _(C,x), _(M,R), _(TM,R), _(TM,R), _(C,x), _(C,x), _(M,R),
/* 1068 */ _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(C,x), _(C,x),
/* 1070 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(C,x), _(C,x), _(C,x),
/* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1080 */ _(C,x), _(C,x), _(CM,x), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,x),
/* 1088 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(TM,x),
/* 1080 */ _(C,x), _(C,x), _(CM,B), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,R),
/* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B), _(C,x), _(TM,R),
/* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 1098 */ _(Nd,x), _(Nd,x), _(TM,x), _(TM,x), _(M,R), _(M,T), _(x,x), _(x,x),
/* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R), _(M,R), _(M,T), _(x,x), _(x,x),
#define indic_offset_0x1700u 1464
#define indic_offset_0x1780u 1496
/* Tagalog */
/* 1700 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1708 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x),
/* 1710 */ _(C,x), _(C,x), _(M,T), _(M,B), _(PK,B), _(x,x), _(x,x), _(x,x),
/* 1718 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Hanunoo */
/* 1720 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1728 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1730 */ _(C,x), _(C,x), _(M,T), _(M,B), _(PK,B), _(x,x), _(x,x), _(x,x),
/* 1738 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Buhid */
/* 1740 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1748 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1750 */ _(C,x), _(C,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1758 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Tagbanwa */
/* 1760 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1768 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x),
/* 1770 */ _(C,x), _(x,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1778 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Khmer */
/* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
@ -345,515 +325,72 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
/* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T),
/* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR),
/* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,x), _(Vs,x),
/* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(RS,T),_(CSR,T), _(M,T), _(M,T), _(M,T),
/* 17D0 */ _(M,T), _(PK,T), _(IS,x), _(M,T), _(x,x), _(x,x), _(x,x), _(x,x),
/* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(x,x), _(x,x), _(x,x),
/* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R),
/* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T),
/* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T), _(x,x), _(x,x), _(x,x), _(x,x),
/* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(SM,T), _(x,x), _(x,x),
/* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 17E8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x1900u 1704
/* Limbu */
/* 1900 */ _(CP,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1908 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
/* 1920 */ _(M,T), _(M,T), _(M,B), _(M,R), _(M,R), _(M,TR), _(M,TR), _(M,T),
/* 1928 */ _(M,T), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1930 */ _(CF,x), _(CF,x), _(Bi,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* 1938 */ _(CF,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1940 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
/* 1948 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* Tai Le */
/* 1950 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1960 */ _(C,x), _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x),
/* 1968 */ _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(x,x), _(x,x),
/* 1970 */ _(TL,x), _(TL,x), _(TL,x), _(TL,x), _(TL,x), _(x,x), _(x,x), _(x,x),
/* 1978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* New Tai Lue */
/* 1980 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1988 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 19A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 19A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19B0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,L), _(M,L), _(M,L),
/* 19B8 */ _(M,R), _(M,R), _(M,L), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R),
/* 19C0 */ _(M,R), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* 19C8 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 19D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Buginese */
/* 1A00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T),
/* 1A18 */ _(M,B), _(M,L), _(M,R), _(M,T), _(x,x), _(x,x), _(x,x), _(x,x),
/* Tai Tham */
/* 1A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A38 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1A48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x),
/* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,L), _(CM,x), _(CF,x),
/* 1A58 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x),
/* 1A60 */ _(IS,x), _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T),
/* 1A68 */ _(M,T), _(M,B), _(M,B), _(M,T), _(M,B), _(M,R), _(M,L), _(M,L),
/* 1A70 */ _(M,L), _(M,L), _(M,L), _(M,T), _(M,T), _(TM,x), _(TM,x), _(TM,x),
/* 1A78 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1A80 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 1A88 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1A90 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 1A98 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x1b00u 2120
/* Balinese */
/* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x),
/* 1B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 1B10 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,T), _(M,T),
/* 1B38 */ _(M,B), _(M,B), _(M,B), _(M,BR), _(M,TB),_(M,TBR), _(M,L), _(M,L),
/* 1B40 */ _(M,LR), _(M,LR), _(M,T), _(M,TR), _(V,R), _(C,x), _(C,x), _(C,x),
/* 1B48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 1B58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Sundanese */
/* 1B80 */ _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 1B88 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BA0 */ _(C,x), _(CS,x), _(CS,x), _(CS,x), _(M,T), _(M,B), _(M,L), _(M,R),
/* 1BA8 */ _(M,T), _(M,T), _(PK,R), _(IS,x), _(CS,x), _(CS,x), _(C,x), _(C,x),
/* 1BB0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 1BB8 */ _(Nd,x), _(Nd,x), _(A,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x),
/* Batak */
/* 1BC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BD0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BD8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,x), _(M,R),
/* 1BE8 */ _(M,T), _(M,T), _(M,R), _(M,R), _(M,R), _(M,T), _(M,R), _(M,T),
/* 1BF0 */ _(CF,x), _(CF,x), _(PK,R), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Lepcha */
/* 1C00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1C08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1C10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CS,x), _(CS,x), _(M,R), _(M,L),
/* 1C28 */ _(M,L), _(M,TL), _(M,R), _(M,R), _(M,B), _(CF,x), _(CF,x), _(CF,x),
/* 1C30 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(Bi,L), _(Bi,L), _(x,x), _(N,x),
/* 1C38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1C40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 1C48 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x),
#define indic_offset_0x1cd0u 2456
#define indic_offset_0x1cd0u 1608
/* Vedic Extensions */
/* 1CD0 */ _(TM,x), _(TM,x), _(TM,x), _(x,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x),
/* 1CD8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x),
/* 1CE0 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(TM,x), _(x,x), _(x,x), _(x,x),
/* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B),
/* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B),
/* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O),
/* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x),
/* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(x,x),
/* 1CF8 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x2008u 2496
#define indic_offset_0x2008u 1656
/* General Punctuation */
/* 2008 */ _(x,x), _(x,x), _(x,x), _(x,x),_(ZWNJ,x),_(ZWJ,x), _(x,x), _(x,x),
/* 2010 */ _(x,x), _(x,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x),
/* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0xa800u 2512
#define indic_offset_0x2070u 1672
/* Syloti Nagri */
/* Superscripts and Subscripts */
/* A800 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(PK,T), _(C,x),
/* A808 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A810 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A818 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A820 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,B), _(M,T), _(M,R),
/* A828 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A830 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A838 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 2070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(SM,x), _(x,x), _(x,x), _(x,x),
/* 2078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 2080 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x),
/* Phags-pa */
#define indic_offset_0xa8e0u 1696
/* A840 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A848 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A850 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A858 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Vo,x), _(Vo,x),
/* A860 */ _(Vo,x), _(Vo,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Vo,x), _(CS,x),
/* A868 */ _(CS,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A870 */ _(C,x), _(CS,x), _(C,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A878 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Saurashtra */
/* A880 */ _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* A888 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* A890 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A898 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A8A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A8A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A8B0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(M,R), _(M,R), _(M,R),
/* A8B8 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R),
/* A8C0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), _(x,x),
/* A8C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A8D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* A8D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Devanagari Extended */
/* A8E0 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x),
/* A8E8 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x),
/* A8F0 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
/* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
/* A8F0 */ _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Kayah Li */
#define indic_offset_0xa9e0u 1720
/* A900 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* A908 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A920 */ _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x),
/* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(x,x),
/* Rejang */
/* A930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A938 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A940 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,B),
/* A948 */ _(M,B), _(M,B), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), _(CF,x),
/* A950 */ _(CF,x), _(CF,x), _(CF,x), _(PK,R), _(x,x), _(x,x), _(x,x), _(x,x),
/* A958 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A960 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A970 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Javanese */
/* A980 */ _(Bi,x), _(Bi,x),_(CSR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* A988 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(C,x),
/* A990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A9A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A9A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A9B0 */ _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,R), _(M,T), _(M,T),
/* A9B8 */ _(M,B), _(M,B), _(M,L), _(M,L), _(M,T), _(CS,x), _(CM,x), _(CM,x),
/* A9C0 */ _(V,BR), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A9C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A9D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* A9D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Myanmar Extended-B */
/* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(C,x),
/* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), _(x,x), _(C,x),
/* A9E8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
/* Cham */
#define indic_offset_0xaa60u 1752
/* AA00 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x),
/* AA08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA28 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,T), _(M,L),
/* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,x), _(CM,L), _(CM,x), _(CM,x), _(x,x),
/* AA38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), _(x,x),
/* AA50 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* AA58 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Myanmar Extended-A */
/* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x),
/* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x),
/* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x),
/* Tai Viet */
/* AA80 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA88 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AA98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AAA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AAA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AAB0 */ _(M,T), _(M,R), _(M,T), _(M,T), _(M,B),_(M,VOL),_(M,VOL), _(M,T),
/* AAB8 */ _(M,T),_(M,VOL), _(M,R),_(M,VOL),_(M,VOL), _(M,R), _(M,T), _(TM,x),
/* AAC0 */ _(TL,x), _(TM,x), _(TL,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AAC8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AAD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AAD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Meetei Mayek Extensions */
/* AAE0 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* AAE8 */ _(C,x), _(C,x), _(C,x), _(M,L), _(M,B), _(M,T), _(M,L), _(M,R),
/* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,x), _(IS,x), _(x,x),
#define indic_offset_0xabc0u 3272
/* Meetei Mayek */
/* ABC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* ABC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x),
/* ABD0 */ _(C,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* ABD8 */ _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* ABE0 */ _(CF,x), _(CF,x), _(CF,x), _(M,R), _(M,R), _(M,T), _(M,R), _(M,R),
/* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,x), _(PK,B), _(x,x), _(x,x),
/* ABF0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* ABF8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x10a00u 3336
/* Kharoshthi */
/* 10A00 */ _(C,x), _(M,O), _(M,B), _(M,B), _(x,x), _(M,T), _(M,O), _(x,x),
/* 10A08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(M,B), _(x,x), _(Bi,x), _(Vs,x),
/* 10A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
/* 10A18 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 10A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 10A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 10A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 10A38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(IS,x),
/* 10A40 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
#define indic_offset_0x11000u 3408
/* Brahmi */
/* 11000 */ _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 11008 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11010 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11020 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11028 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11030 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11038 */ _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B),
/* 11040 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x),
/* 11048 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11050 */ _(x,x), _(x,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),
/* 11058 */_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),
/* 11060 */_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x),_(BJN,x), _(Nd,x), _(Nd,x),
/* 11068 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 11070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(NJ,x),
/* Kaithi */
/* 11080 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11088 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 11090 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11098 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 110A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 110A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 110B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,R),
/* 110B8 */ _(M,R), _(V,B), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x11100u 3600
/* Chakma */
/* 11100 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x),
/* 11108 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11110 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11118 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11120 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T),
/* 11128 */ _(M,T), _(M,T), _(M,B), _(M,B), _(M,L), _(M,T), _(M,TB), _(M,TB),
/* 11130 */ _(M,T), _(M,B), _(M,B), _(IS,x), _(PK,T), _(x,x), _(Nd,x), _(Nd,x),
/* 11138 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 11140 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11148 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Mahajani */
/* 11150 */ _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(C,x), _(C,x), _(C,x),
/* 11158 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11160 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11168 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11170 */ _(C,x), _(C,x), _(C,x), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11178 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Sharada */
/* 11180 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11188 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11190 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11198 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 111A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 111A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 111B0 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,L), _(M,R), _(M,B), _(M,B),
/* 111B8 */ _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,TR),
/* 111C0 */ _(V,R), _(A,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 111C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 111D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 111D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Sinhala Archaic Numbers */
/* 111E0 */ _(x,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 111E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 111F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x),
/* 111F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Khojki */
/* 11200 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11208 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11210 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11218 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11220 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11228 */ _(C,x), _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,R), _(M,B),
/* 11230 */ _(M,T), _(M,T), _(M,TR), _(M,TR), _(Bi,x), _(V,R), _(N,x), _(GM,T),
#define indic_offset_0x112b0u 3912
/* Khudawadi */
/* 112B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 112B8 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 112C0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 112C8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 112D0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 112D8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Bi,x),
/* 112E0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T),
/* 112E8 */ _(M,T), _(N,x), _(PK,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 112F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 112F8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Grantha */
/* 11300 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
/* 11308 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
/* 11310 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
/* 11318 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11320 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11328 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11330 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
/* 11338 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,R),
/* 11340 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(x,x), _(M,L),
/* 11348 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,R), _(x,x), _(x,x),
/* 11350 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
/* 11358 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11360 */ _(VI,x), _(VI,x), _(M,R), _(M,R), _(x,x), _(x,x), _(Ca,x), _(Ca,x),
/* 11368 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x),
/* 11370 */ _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x11480u 4112
/* Tirhuta */
/* 11480 */ _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11488 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x),
/* 11490 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11498 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 114A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 114A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 114B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B),
/* 114B8 */ _(M,B), _(M,L), _(M,T), _(M,TL), _(M,LR), _(M,R), _(M,LR), _(Bi,x),
/* 114C0 */ _(Bi,x), _(Vs,x), _(V,B), _(N,x), _(A,x), _(x,x), _(x,x), _(x,x),
/* 114C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 114D0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 114D8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x11580u 4208
/* Siddham */
/* 11580 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11588 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x),
/* 11590 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11598 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 115A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 115A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,R),
/* 115B0 */ _(M,L), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x),
/* 115B8 */ _(M,L), _(M,TL), _(M,LR),_(M,TLR), _(Bi,x), _(Bi,x), _(Vs,x), _(V,B),
/* 115C0 */ _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x11600u 4280
/* Modi */
/* 11600 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11608 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x),
/* 11610 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11618 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11620 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11628 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11630 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,B),
/* 11638 */ _(M,B), _(M,T), _(M,T), _(M,R), _(M,R), _(Bi,x), _(Vs,x), _(V,B),
/* 11640 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11648 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11650 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 11658 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11660 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11668 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11670 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11678 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Takri */
/* 11680 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 11688 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11690 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 11698 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 116A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 116A8 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(Vs,x), _(M,T), _(M,L), _(M,R),
/* 116B0 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(N,x),
/* 116B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 116C0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
/* 116C8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
}; /* Table items: 4488; occupancy: 73% */
}; /* Table items: 1784; occupancy: 69% */
INDIC_TABLE_ELEMENT_TYPE
hb_indic_get_categories (hb_codepoint_t u)
@ -862,40 +399,27 @@ hb_indic_get_categories (hb_codepoint_t u)
{
case 0x0u:
if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
if (hb_in_range (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
if (unlikely (u == 0x00A0u)) return _(CP,x);
break;
case 0x1u:
if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
if (hb_in_range (u, 0x1CD0u, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
if (hb_in_range (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
break;
case 0x2u:
if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
if (hb_in_range (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
if (unlikely (u == 0x25CCu)) return _(CP,x);
break;
case 0xAu:
if (hb_in_range (u, 0xA800u, 0xAAF7u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
if (hb_in_range (u, 0xABC0u, 0xABFFu)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
break;
case 0x10u:
if (hb_in_range (u, 0x10A00u, 0x10A47u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
break;
case 0x11u:
if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
if (hb_in_range (u, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
if (hb_in_range (u, 0x11580u, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
if (hb_in_range (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
if (hb_in_range (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
if (hb_in_range (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
break;
default:
@ -914,11 +438,14 @@ hb_indic_get_categories (hb_codepoint_t u)
#undef ISC_CD
#undef ISC_CF
#undef ISC_CHL
#undef ISC_CK
#undef ISC_CM
#undef ISC_CP
#undef ISC_CPR
#undef ISC_CPrf
#undef ISC_CS
#undef ISC_CSR
#undef ISC_CWS
#undef ISC_GM
#undef ISC_IS
#undef ISC_ZWJ
@ -930,6 +457,7 @@ hb_indic_get_categories (hb_codepoint_t u)
#undef ISC_x
#undef ISC_PK
#undef ISC_RS
#undef ISC_SM
#undef ISC_TL
#undef ISC_TM
#undef ISC_V

View File

@ -176,24 +176,8 @@ set_indic_properties (hb_glyph_info_t &info)
* Re-assign category
*/
/* The spec says U+0952 is OT_A. However, testing shows that Uniscribe
* treats a whole bunch of characters similarly.
* TESTS: For example, for U+0951:
* U+092E,U+0947,U+0952
* U+092E,U+0952,U+0947
* U+092E,U+0947,U+0951
* U+092E,U+0951,U+0947
* U+092E,U+0951,U+0952
* U+092E,U+0952,U+0951
*/
if (unlikely (hb_in_ranges (u, 0x0951u, 0x0952u,
0x1CD0u, 0x1CD2u,
0x1CD4u, 0x1CE1u) ||
u == 0x1CF4u))
cat = OT_A;
/* The following act more like the Bindus. */
else if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
cat = OT_SM;
/* The following act like consonants. */
else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u,
@ -216,21 +200,10 @@ set_indic_properties (hb_glyph_info_t &info)
cat = OT_Symbol;
ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol);
}
else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) ||
u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
{
/* These are like Top Matras. */
cat = OT_M;
pos = POS_ABOVE_C;
}
else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
else if (unlikely (u == 0x17D2u)) cat = OT_Coeng; /* Khmer coeng */
else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u)))
cat = OT_PLACEHOLDER;
else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
else if (unlikely (u == 0xA982u)) cat = OT_SM; /* Javanese repha. */
else if (unlikely (u == 0xA9BEu)) cat = OT_CM2; /* Javanese medial ya. */
else if (unlikely (u == 0xA9BDu)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */
/*
@ -296,11 +269,6 @@ enum blwf_mode_t {
BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-base. */
BLWF_MODE_POST_ONLY /* Below-forms feature applied to post-base only. */
};
enum pref_len_t {
PREF_LEN_1 = 1,
PREF_LEN_2 = 2,
PREF_LEN_DONT_CARE = PREF_LEN_2
};
struct indic_config_t
{
hb_script_t script;
@ -310,26 +278,24 @@ struct indic_config_t
reph_position_t reph_pos;
reph_mode_t reph_mode;
blwf_mode_t blwf_mode;
pref_len_t pref_len;
};
static const indic_config_t indic_configs[] =
{
/* Default. Should be first. */
{HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
{HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
{HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
{HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
{HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
{HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
{HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
{HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
{HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2},
{HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
{HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY},
{HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
{HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA,
REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE},
{HB_SCRIPT_KHMER, false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2},
{HB_SCRIPT_JAVANESE, false,0xA9C0u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1},
REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST},
{HB_SCRIPT_KHMER, false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST},
};
@ -512,12 +478,12 @@ struct indic_shape_plan_t
hb_codepoint_t glyph = virama_glyph;
if (unlikely (virama_glyph == (hb_codepoint_t) -1))
{
if (!config->virama || !font->get_glyph (config->virama, 0, &glyph))
if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
glyph = 0;
/* Technically speaking, the spec says we should apply 'locl' to virama too.
* Maybe one day... */
/* Our get_glyph() function needs a font, so we can't get the virama glyph
/* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
* during shape planning... Instead, overwrite it here. It's safe. Don't worry! */
(const_cast<indic_shape_plan_t *> (this))->virama_glyph = glyph;
}
@ -557,8 +523,15 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
indic_plan->virama_glyph = (hb_codepoint_t) -1;
/* Use zero-context would_substitute() matching for new-spec of the main
* Indic scripts, and scripts with one spec only, but not for old-specs. */
bool zero_context = !indic_plan->is_old_spec;
* Indic scripts, and scripts with one spec only, but not for old-specs.
* The new-spec for all dual-spec scripts says zero-context matching happens.
*
* However, testing with Malayalam shows that old and new spec both allow
* context. Testing with Bengali new-spec however shows that it doesn't.
* So, the heuristic here is the way it is. It should *only* be changed,
* as we discover more cases of what Windows does. DON'T TOUCH OTHERWISE.
*/
bool zero_context = !indic_plan->is_old_spec && plan->props.script != HB_SCRIPT_MALAYALAM;
indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context);
indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
@ -600,12 +573,8 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan,
if (indic_plan->pstf.would_substitute (glyphs , 2, face) ||
indic_plan->pstf.would_substitute (glyphs+1, 2, face))
return POS_POST_C;
unsigned int pref_len = indic_plan->config->pref_len;
if ((pref_len == PREF_LEN_2 &&
(indic_plan->pref.would_substitute (glyphs , 2, face) ||
indic_plan->pref.would_substitute (glyphs+1, 2, face)))
|| (pref_len == PREF_LEN_1 &&
indic_plan->pref.would_substitute (glyphs+1, 1, face)))
if (indic_plan->pref.would_substitute (glyphs , 2, face) ||
indic_plan->pref.would_substitute (glyphs+1, 2, face))
return POS_POST_C;
return POS_BASE_C;
}
@ -754,10 +723,6 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
switch (indic_plan->config->base_pos)
{
default:
assert (false);
/* fallthrough */
case BASE_POS_LAST:
{
/* -> starting from the end of the syllable, move backwards */
@ -1115,10 +1080,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
}
}
unsigned int pref_len = indic_plan->config->pref_len;
unsigned int pref_len = 2;
if (indic_plan->mask_array[PREF] && base + pref_len < end)
{
assert (1 <= pref_len && pref_len <= 2);
/* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */
for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
hb_codepoint_t glyphs[2];
@ -1231,7 +1195,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t dottedcircle_glyph;
if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
@ -1243,7 +1207,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)
while (buffer->idx < buffer->len && !buffer->in_error)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
@ -1251,19 +1215,19 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
{
last_syllable = syllable;
hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
info.syllable() = buffer->cur().syllable();
hb_glyph_info_t ginfo = dottedcircle;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
/* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len &&
while (buffer->idx < buffer->len && !buffer->in_error &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().indic_category() == OT_Repha)
buffer->next_glyph ();
buffer->output_info (info);
buffer->output_info (ginfo);
}
else
buffer->next_glyph ();
@ -1328,7 +1292,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
for (base = start; base < end; base++)
if (info[base].indic_position() >= POS_BASE_C)
{
if (try_pref && base + 1 < end && indic_plan->config->pref_len == 2)
if (try_pref && base + 1 < end)
{
for (unsigned int i = base + 1; i < end; i++)
if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
@ -1348,6 +1312,25 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
break;
}
}
/* For Malayalam, skip over unformed below- (but NOT post-) forms. */
if (buffer->props.script == HB_SCRIPT_MALAYALAM)
{
for (unsigned int i = base + 1; i < end; i++)
{
while (i < end && is_joiner (info[i]))
i++;
if (i == end || !is_halant_or_coeng (info[i]))
break;
i++; /* Skip halant. */
while (i < end && is_joiner (info[i]))
i++;
if (i < end && is_consonant (info[i]) && info[i].indic_position() == POS_BELOW_C)
{
base = i;
info[base].indic_position() = POS_BASE_C;
}
}
}
if (start < base && info[base].indic_position() > POS_BASE_C)
base--;
@ -1591,7 +1574,6 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */
{
unsigned int pref_len = indic_plan->config->pref_len;
for (unsigned int i = base + 1; i < end; i++)
if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
{
@ -1602,10 +1584,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
/* Note: We just check that something got substituted. We don't check that
* the <pref> feature actually did it...
*
* If pref len is longer than one, then only reorder if it ligated. If
* pref len is one, only reorder if it didn't ligate with other things. */
if (_hb_glyph_info_substituted (&info[i]) &&
((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
* Reorder pref only if it ligated. */
if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
{
/*
* 2. Try to find a target position the same way as for pre-base matra.
@ -1631,8 +1611,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 i = base + 1; i < old_pos; i++)
if (info[i].indic_category() == OT_M)
for (unsigned int j = base + 1; j < old_pos; j++)
if (info[j].indic_category() == OT_M)
{
new_pos--;
break;
@ -1796,7 +1776,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t glyph;
if (hb_options ().uniscribe_bug_compatible ||
(c->font->get_glyph (ab, 0, &glyph) &&
(c->font->get_nominal_glyph (ab, &glyph) &&
indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
{
/* Ok, safe to use Uniscribe-style decomposition. */
@ -1806,7 +1786,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
}
}
return c->unicode->decompose (ab, a, b);
return (bool) c->unicode->decompose (ab, a, b);
}
static bool
@ -1822,7 +1802,7 @@ compose_indic (const hb_ot_shape_normalize_context_t *c,
/* Composition-exclusion exceptions that we want to recompose. */
if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; }
return c->unicode->compose (a, b, ab);
return (bool) c->unicode->compose (a, b, ab);
}
@ -1834,6 +1814,7 @@ 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,

View File

@ -1,5 +1,5 @@
#line 1 "hb-ot-shape-complex-myanmar-machine.rl"
#line 1 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
/*
* Copyright © 2011,2012 Google, Inc.
*
@ -32,7 +32,7 @@
#include "hb-private.hh"
#line 36 "hb-ot-shape-complex-myanmar-machine.hh"
#line 36 "../../src/hb-ot-shape-complex-myanmar-machine.hh.tmp"
static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
1u, 31u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u,
@ -261,11 +261,11 @@ static const int myanmar_syllable_machine_error = -1;
static const int myanmar_syllable_machine_en_main = 0;
#line 36 "hb-ot-shape-complex-myanmar-machine.rl"
#line 36 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
#line 93 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
#define found_syllable(syllable_type) \
@ -285,7 +285,7 @@ find_syllables (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
#line 289 "hb-ot-shape-complex-myanmar-machine.hh"
#line 289 "../../src/hb-ot-shape-complex-myanmar-machine.hh.tmp"
{
cs = myanmar_syllable_machine_start;
ts = 0;
@ -293,7 +293,7 @@ find_syllables (hb_buffer_t *buffer)
act = 0;
}
#line 114 "hb-ot-shape-complex-myanmar-machine.rl"
#line 114 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
p = 0;
@ -302,7 +302,7 @@ find_syllables (hb_buffer_t *buffer)
unsigned int last = 0;
unsigned int syllable_serial = 1;
#line 306 "hb-ot-shape-complex-myanmar-machine.hh"
#line 306 "../../src/hb-ot-shape-complex-myanmar-machine.hh.tmp"
{
int _slen;
int _trans;
@ -316,7 +316,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
#line 320 "hb-ot-shape-complex-myanmar-machine.hh"
#line 320 "../../src/hb-ot-shape-complex-myanmar-machine.hh.tmp"
}
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@ -335,38 +335,38 @@ _eof_trans:
switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
case 7:
#line 85 "hb-ot-shape-complex-myanmar-machine.rl"
#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (consonant_syllable); }}
break;
case 5:
#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
#line 86 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (non_myanmar_cluster); }}
break;
case 10:
#line 87 "hb-ot-shape-complex-myanmar-machine.rl"
#line 87 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (punctuation_cluster); }}
break;
case 4:
#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
#line 88 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (broken_cluster); }}
break;
case 3:
#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
#line 89 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (non_myanmar_cluster); }}
break;
case 6:
#line 85 "hb-ot-shape-complex-myanmar-machine.rl"
#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }}
break;
case 8:
#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
#line 88 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }}
break;
case 9:
#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
#line 89 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
break;
#line 370 "hb-ot-shape-complex-myanmar-machine.hh"
#line 370 "../../src/hb-ot-shape-complex-myanmar-machine.hh.tmp"
}
_again:
@ -375,7 +375,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
#line 379 "hb-ot-shape-complex-myanmar-machine.hh"
#line 379 "../../src/hb-ot-shape-complex-myanmar-machine.hh.tmp"
}
if ( ++p != pe )
@ -391,7 +391,7 @@ _again:
}
#line 123 "hb-ot-shape-complex-myanmar-machine.rl"
#line 123 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
}

View File

@ -199,6 +199,10 @@ set_myanmar_properties (hb_glyph_info_t &info)
cat = (indic_category_t) OT_A;
break;
case 0x1039u:
cat = (indic_category_t) OT_H;
break;
case 0x103Au:
cat = (indic_category_t) OT_As;
break;
@ -245,6 +249,11 @@ set_myanmar_properties (hb_glyph_info_t &info)
case 0x104Au: case 0x104Bu:
cat = (indic_category_t) OT_P;
break;
case 0xAA74u: case 0xAA75u: case 0xAA76u:
/* https://github.com/roozbehp/unicode-data/issues/3 */
cat = (indic_category_t) OT_C;
break;
}
if (cat == OT_M)
@ -435,7 +444,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t dottedcircle_glyph;
if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
@ -447,7 +456,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)
while (buffer->idx < buffer->len && !buffer->in_error)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
@ -455,12 +464,12 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
{
last_syllable = syllable;
hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
info.syllable() = buffer->cur().syllable();
hb_glyph_info_t ginfo = dottedcircle;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
buffer->output_info (info);
buffer->output_info (ginfo);
}
else
buffer->next_glyph ();
@ -507,6 +516,7 @@ 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 */
@ -523,6 +533,7 @@ 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 */

View File

@ -41,12 +41,8 @@
enum hb_ot_shape_zero_width_marks_type_t {
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
// HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
};
@ -110,6 +106,15 @@ 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;
@ -236,9 +241,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-3.0 additions */
case HB_SCRIPT_SINHALA:
/* Unicode-5.2 additions */
case HB_SCRIPT_JAVANESE:
/* If the designer designed the font for the 'DFLT' script,
* use the default shaper. Otherwise, use the specific shaper.
* Note that for some simple scripts, there may not be *any*
@ -311,7 +313,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-5.2 additions */
case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
//case HB_SCRIPT_JAVANESE:
case HB_SCRIPT_JAVANESE:
case HB_SCRIPT_KAITHI:
case HB_SCRIPT_MEETEI_MAYEK:
case HB_SCRIPT_TAI_THAM:
@ -340,6 +342,15 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_SIDDHAM:
case HB_SCRIPT_TIRHUTA:
/* Unicode-8.0 additions */
case HB_SCRIPT_AHOM:
//case HB_SCRIPT_MULTANI:
/* Unicode-9.0 additions */
case HB_SCRIPT_BHAIKSUKI:
case HB_SCRIPT_MARCHEN:
case HB_SCRIPT_NEWA:
/* If the designer designed the font for the 'DFLT' script,
* use the default shaper. Otherwise, use the specific shaper.
* Note that for some simple scripts, there may not be *any*

View File

@ -139,7 +139,6 @@ thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
};
switch (action) {
default: assert (false); /* Fallthrough */
case NOP: return u;
case SD: pua_mappings = SD_mappings; break;
case SDL: pua_mappings = SDL_mappings; break;
@ -315,7 +314,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;)
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
{
hb_codepoint_t u = buffer->cur().codepoint;
if (likely (!IS_SARA_AM (u))) {
@ -330,7 +329,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
if (unlikely (buffer->in_error))
return;
/* Make Nikhahit be recognized as a mark when zeroing widths. */
/* Make Nikhahit be recognized as a ccc=0 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,10 +371,11 @@ 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 */
NULL, /* setup_masks */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
false,/* fallback_position */
};

View File

@ -52,10 +52,11 @@ 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 */
NULL, /* setup_masks */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
true, /* fallback_position */
};

View File

@ -36,291 +36,222 @@
#line 38 "hb-ot-shape-complex-use-machine.hh"
static const unsigned char _use_syllable_machine_trans_keys[] = {
0u, 0u, 4u, 4u, 1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u,
8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u,
8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u,
1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u,
8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 13u, 21u,
4u, 4u, 13u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u,
8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
8u, 39u, 12u, 21u, 12u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u,
8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u,
8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u,
42u, 42u, 0
};
static const char _use_syllable_machine_key_spans[] = {
0, 1, 1, 40, 1, 32, 32, 1,
32, 32, 32, 19, 19, 19, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 1, 32, 32, 19, 19,
1, 40, 1, 32, 32, 1, 32, 32,
32, 19, 19, 19, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 9,
1, 1, 32, 32, 32, 32, 19, 19,
19, 32, 32, 32, 32, 32, 32, 32,
32, 10, 2, 32, 32, 32, 32, 19,
19, 19, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 39, 32, 22, 2,
32, 32, 32, 1, 39, 32, 22, 2,
1
};
static const short _use_syllable_machine_index_offsets[] = {
0, 0, 2, 4, 45, 47, 80, 113,
115, 148, 181, 214, 234, 254, 274, 307,
340, 373, 406, 439, 472, 505, 538, 571,
604, 637, 670, 703, 705, 738, 771, 791,
811, 831, 864, 897, 930, 963, 996, 1029,
1062, 1095, 1106, 1109, 1142, 1175, 1208, 1241,
1261, 1281, 1301, 1334, 1367, 1400, 1433, 1466,
1499, 1532, 1565, 1598, 1631, 1671, 1704, 1727,
1730
0, 2, 43, 45, 78, 111, 113, 146,
179, 212, 232, 252, 272, 305, 338, 371,
404, 437, 470, 503, 536, 569, 602, 635,
645, 647, 649, 682, 715, 748, 781, 801,
821, 841, 874, 907, 940, 973, 1006, 1039,
1072, 1105, 1138, 1171, 1173, 1213, 1246, 1269,
1272
};
static const char _use_syllable_machine_indicies[] = {
1, 0, 3, 2, 4, 5, 6,
4, 1, 5, 8, 8, 7, 8, 8,
3, 9, 8, 8, 8, 4, 4, 10,
11, 8, 8, 12, 13, 14, 15, 16,
17, 18, 12, 19, 20, 21, 22, 23,
24, 8, 25, 26, 27, 8, 29, 28,
31, 30, 30, 32, 33, 30, 30, 30,
30, 30, 30, 30, 30, 34, 35, 36,
37, 38, 39, 40, 41, 35, 42, 34,
43, 44, 45, 46, 30, 47, 48, 49,
30, 31, 30, 30, 32, 33, 30, 30,
30, 30, 30, 30, 30, 30, 50, 35,
36, 37, 38, 39, 40, 41, 35, 42,
43, 43, 44, 45, 46, 30, 47, 48,
49, 30, 32, 51, 31, 30, 30, 32,
33, 30, 30, 30, 30, 30, 30, 30,
30, 30, 35, 36, 37, 38, 39, 40,
41, 35, 42, 43, 43, 44, 45, 46,
30, 47, 48, 49, 30, 31, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 35, 36, 37, 38, 39,
30, 30, 30, 30, 30, 30, 44, 45,
46, 30, 47, 48, 49, 30, 31, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 36, 37, 38,
39, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 47, 48, 49, 30, 31,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 37,
38, 39, 30, 31, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 38, 39, 30, 31,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 39, 30, 31, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 37, 38, 39, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
47, 48, 49, 30, 31, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 37, 38, 39, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 48, 49, 30, 31, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 37, 38, 39,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 49, 30, 31, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 36, 37, 38,
39, 30, 30, 30, 30, 30, 30, 44,
45, 46, 30, 47, 48, 49, 30, 31,
30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 36, 37,
38, 39, 30, 30, 30, 30, 30, 30,
30, 45, 46, 30, 47, 48, 49, 30,
31, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 36,
37, 38, 39, 30, 30, 30, 30, 30,
30, 30, 30, 46, 30, 47, 48, 49,
30, 31, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 35,
36, 37, 38, 39, 30, 41, 35, 30,
30, 30, 44, 45, 46, 30, 47, 48,
49, 30, 31, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
35, 36, 37, 38, 39, 30, 30, 35,
30, 30, 30, 44, 45, 46, 30, 47,
48, 49, 30, 31, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30,
30, 35, 36, 37, 38, 39, 40, 41,
35, 30, 30, 30, 44, 45, 46, 30,
47, 48, 49, 30, 31, 30, 30, 32,
33, 30, 30, 30, 30, 30, 30, 30,
30, 30, 35, 36, 37, 38, 39, 40,
41, 35, 42, 30, 43, 44, 45, 46,
30, 47, 48, 49, 30, 31, 30, 30,
32, 33, 30, 30, 30, 30, 30, 30,
30, 30, 30, 35, 36, 37, 38, 39,
40, 41, 35, 42, 34, 43, 44, 45,
46, 30, 47, 48, 49, 30, 53, 52,
52, 54, 55, 52, 52, 52, 52, 52,
52, 52, 52, 56, 52, 57, 58, 59,
60, 61, 62, 57, 63, 56, 64, 52,
52, 52, 52, 65, 66, 67, 52, 53,
52, 52, 54, 55, 52, 52, 52, 52,
52, 52, 52, 52, 68, 52, 57, 58,
59, 60, 61, 62, 57, 63, 64, 64,
52, 52, 52, 52, 65, 66, 67, 52,
54, 51, 53, 52, 52, 54, 55, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 57, 58, 59, 60, 61, 62, 57,
63, 64, 64, 52, 52, 52, 52, 65,
66, 67, 52, 53, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 57, 58, 59, 60, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
65, 66, 67, 52, 53, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 58, 59, 60, 52,
53, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 59, 60, 52, 53, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 60, 52,
53, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
58, 59, 60, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 65, 66, 67,
52, 53, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 58, 59, 60, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 66,
67, 52, 53, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 58, 59, 60, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 67, 52, 53, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 57, 58, 59, 60, 52, 62,
57, 52, 52, 52, 52, 52, 52, 52,
65, 66, 67, 52, 53, 52, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 57, 58, 59, 60, 52,
52, 57, 52, 52, 52, 52, 52, 52,
52, 65, 66, 67, 52, 53, 52, 52,
52, 52, 52, 52, 52, 52, 52, 52,
52, 52, 52, 52, 57, 58, 59, 60,
61, 62, 57, 52, 52, 52, 52, 52,
52, 52, 65, 66, 67, 52, 53, 52,
52, 54, 55, 52, 52, 52, 52, 52,
52, 52, 52, 52, 52, 57, 58, 59,
60, 61, 62, 57, 63, 52, 64, 52,
52, 52, 52, 65, 66, 67, 52, 53,
52, 52, 54, 55, 52, 52, 52, 52,
52, 52, 52, 52, 52, 52, 57, 58,
59, 60, 61, 62, 57, 63, 56, 64,
52, 52, 52, 52, 65, 66, 67, 52,
70, 71, 69, 69, 69, 69, 69, 69,
69, 72, 69, 70, 71, 69, 7, 73,
73, 3, 9, 73, 73, 73, 73, 73,
73, 73, 73, 74, 12, 13, 14, 15,
16, 17, 18, 12, 19, 21, 21, 22,
23, 24, 73, 25, 26, 27, 73, 7,
73, 73, 3, 9, 73, 73, 73, 73,
73, 73, 73, 73, 73, 12, 13, 14,
15, 16, 17, 18, 12, 19, 21, 21,
22, 23, 24, 73, 25, 26, 27, 73,
7, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 12, 13,
14, 15, 16, 73, 73, 73, 73, 73,
73, 22, 23, 24, 73, 25, 26, 27,
73, 7, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
13, 14, 15, 16, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 25, 26,
27, 73, 7, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 14, 15, 16, 73, 7, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 15,
16, 73, 7, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 16, 73, 7, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 14, 15,
16, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 25, 26, 27, 73, 7,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 14,
15, 16, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 26, 27, 73,
7, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
14, 15, 16, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 27,
73, 7, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
13, 14, 15, 16, 73, 73, 73, 73,
73, 73, 22, 23, 24, 73, 25, 26,
27, 73, 7, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 13, 14, 15, 16, 73, 73, 73,
73, 73, 73, 73, 23, 24, 73, 25,
26, 27, 73, 7, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 13, 14, 15, 16, 73, 73,
73, 73, 73, 73, 73, 73, 24, 73,
25, 26, 27, 73, 7, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 12, 13, 14, 15, 16, 73,
18, 12, 73, 73, 73, 22, 23, 24,
73, 25, 26, 27, 73, 7, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 12, 13, 14, 15, 16,
73, 73, 12, 73, 73, 73, 22, 23,
24, 73, 25, 26, 27, 73, 7, 73,
73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 12, 13, 14, 15,
16, 17, 18, 12, 73, 73, 73, 22,
23, 24, 73, 25, 26, 27, 73, 7,
73, 73, 3, 9, 73, 73, 73, 73,
73, 73, 73, 73, 73, 12, 13, 14,
15, 16, 17, 18, 12, 19, 73, 21,
22, 23, 24, 73, 25, 26, 27, 73,
5, 6, 73, 73, 5, 73, 73, 7,
73, 73, 3, 9, 73, 73, 73, 73,
73, 73, 73, 73, 73, 12, 13, 14,
15, 16, 17, 18, 12, 19, 20, 21,
22, 23, 24, 73, 25, 26, 27, 73,
7, 73, 73, 3, 9, 73, 73, 73,
73, 73, 73, 73, 73, 73, 12, 13,
14, 15, 16, 17, 18, 12, 19, 20,
21, 22, 23, 24, 73, 25, 26, 27,
73, 76, 75, 75, 75, 75, 75, 75,
75, 75, 75, 75, 75, 75, 75, 75,
75, 75, 75, 75, 75, 76, 77, 75,
76, 77, 75, 77, 75, 0
1, 0, 2, 3, 4, 2, 5, 3,
4, 4, 6, 4, 4, 1, 7, 4,
4, 4, 2, 2, 8, 9, 4, 4,
10, 11, 12, 13, 14, 15, 16, 10,
17, 18, 19, 20, 21, 22, 4, 23,
24, 25, 4, 27, 26, 29, 28, 28,
30, 31, 28, 28, 28, 28, 28, 28,
28, 28, 32, 33, 34, 35, 36, 37,
38, 39, 33, 40, 32, 41, 42, 43,
44, 28, 45, 46, 47, 28, 29, 28,
28, 30, 31, 28, 28, 28, 28, 28,
28, 28, 28, 48, 33, 34, 35, 36,
37, 38, 39, 33, 40, 41, 41, 42,
43, 44, 28, 45, 46, 47, 28, 30,
49, 29, 28, 28, 30, 31, 28, 28,
28, 28, 28, 28, 28, 28, 28, 33,
34, 35, 36, 37, 38, 39, 33, 40,
41, 41, 42, 43, 44, 28, 45, 46,
47, 28, 29, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
33, 34, 35, 36, 37, 28, 28, 28,
28, 28, 28, 42, 43, 44, 28, 45,
46, 47, 28, 29, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 34, 35, 36, 37, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
45, 46, 47, 28, 29, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 35, 36, 37, 28,
29, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 36, 37, 28, 29, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 37, 28,
29, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
35, 36, 37, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 45, 46, 47,
28, 29, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 35, 36, 37, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 46,
47, 28, 29, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 35, 36, 37, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 47, 28, 29, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 34, 35, 36, 37, 28, 28,
28, 28, 28, 28, 42, 43, 44, 28,
45, 46, 47, 28, 29, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 34, 35, 36, 37, 28,
28, 28, 28, 28, 28, 28, 43, 44,
28, 45, 46, 47, 28, 29, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 34, 35, 36, 37,
28, 28, 28, 28, 28, 28, 28, 28,
44, 28, 45, 46, 47, 28, 29, 28,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 33, 34, 35, 36,
37, 28, 39, 33, 28, 28, 28, 42,
43, 44, 28, 45, 46, 47, 28, 29,
28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 33, 34, 35,
36, 37, 28, 28, 33, 28, 28, 28,
42, 43, 44, 28, 45, 46, 47, 28,
29, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 33, 34,
35, 36, 37, 38, 39, 33, 28, 28,
28, 42, 43, 44, 28, 45, 46, 47,
28, 29, 28, 28, 30, 31, 28, 28,
28, 28, 28, 28, 28, 28, 28, 33,
34, 35, 36, 37, 38, 39, 33, 40,
28, 41, 42, 43, 44, 28, 45, 46,
47, 28, 29, 28, 28, 30, 31, 28,
28, 28, 28, 28, 28, 28, 28, 28,
33, 34, 35, 36, 37, 38, 39, 33,
40, 32, 41, 42, 43, 44, 28, 45,
46, 47, 28, 51, 50, 50, 50, 50,
50, 50, 50, 52, 50, 5, 53, 51,
50, 6, 54, 54, 1, 55, 54, 54,
54, 54, 54, 54, 54, 54, 56, 10,
11, 12, 13, 14, 15, 16, 10, 17,
19, 19, 20, 21, 22, 54, 23, 24,
25, 54, 6, 54, 54, 1, 55, 54,
54, 54, 54, 54, 54, 54, 54, 54,
10, 11, 12, 13, 14, 15, 16, 10,
17, 19, 19, 20, 21, 22, 54, 23,
24, 25, 54, 6, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 10, 11, 12, 13, 14, 54, 54,
54, 54, 54, 54, 20, 21, 22, 54,
23, 24, 25, 54, 6, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 11, 12, 13, 14, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 23, 24, 25, 54, 6, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 12, 13, 14,
54, 6, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 13, 14, 54, 6, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 14,
54, 6, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 12, 13, 14, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 23, 24,
25, 54, 6, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 12, 13, 14, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
24, 25, 54, 6, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 12, 13, 14, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 25, 54, 6, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 11, 12, 13, 14, 54,
54, 54, 54, 54, 54, 20, 21, 22,
54, 23, 24, 25, 54, 6, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 11, 12, 13, 14,
54, 54, 54, 54, 54, 54, 54, 21,
22, 54, 23, 24, 25, 54, 6, 54,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 11, 12, 13,
14, 54, 54, 54, 54, 54, 54, 54,
54, 22, 54, 23, 24, 25, 54, 6,
54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 10, 11, 12,
13, 14, 54, 16, 10, 54, 54, 54,
20, 21, 22, 54, 23, 24, 25, 54,
6, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 10, 11,
12, 13, 14, 54, 54, 10, 54, 54,
54, 20, 21, 22, 54, 23, 24, 25,
54, 6, 54, 54, 54, 54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 10,
11, 12, 13, 14, 15, 16, 10, 54,
54, 54, 20, 21, 22, 54, 23, 24,
25, 54, 6, 54, 54, 1, 55, 54,
54, 54, 54, 54, 54, 54, 54, 54,
10, 11, 12, 13, 14, 15, 16, 10,
17, 54, 19, 20, 21, 22, 54, 23,
24, 25, 54, 1, 57, 3, 54, 54,
54, 3, 54, 54, 6, 54, 54, 1,
55, 54, 54, 54, 54, 54, 54, 54,
54, 54, 10, 11, 12, 13, 14, 15,
16, 10, 17, 18, 19, 20, 21, 22,
54, 23, 24, 25, 54, 6, 54, 54,
1, 55, 54, 54, 54, 54, 54, 54,
54, 54, 54, 10, 11, 12, 13, 14,
15, 16, 10, 17, 18, 19, 20, 21,
22, 54, 23, 24, 25, 54, 59, 58,
58, 58, 58, 58, 58, 58, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58,
58, 58, 59, 60, 58, 59, 60, 58,
60, 58, 0
};
static const char _use_syllable_machine_trans_targs[] = {
3, 41, 3, 43, 4, 5, 25, 3,
0, 2, 60, 62, 45, 46, 47, 48,
49, 56, 57, 58, 61, 59, 53, 54,
55, 50, 51, 52, 3, 3, 3, 3,
6, 7, 24, 9, 10, 11, 12, 13,
20, 21, 22, 23, 17, 18, 19, 14,
15, 16, 8, 3, 3, 3, 26, 27,
40, 29, 30, 31, 32, 36, 37, 38,
39, 33, 34, 35, 28, 3, 3, 1,
42, 3, 44, 3, 63, 64
1, 26, 2, 3, 1, 23, 1, 43,
44, 46, 28, 29, 30, 31, 32, 39,
40, 41, 45, 42, 36, 37, 38, 33,
34, 35, 1, 1, 1, 1, 4, 5,
22, 7, 8, 9, 10, 11, 18, 19,
20, 21, 15, 16, 17, 12, 13, 14,
6, 1, 1, 24, 25, 1, 1, 0,
27, 1, 1, 47, 48
};
static const char _use_syllable_machine_trans_actions[] = {
1, 2, 3, 4, 0, 0, 0, 7,
0, 0, 4, 0, 0, 0, 0, 0,
0, 0, 0, 0, 4, 4, 0, 0,
0, 0, 0, 0, 8, 9, 10, 11,
1, 2, 0, 0, 5, 0, 6, 0,
2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 2, 0, 0, 0, 0,
0, 0, 7, 8, 9, 10, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 12, 13, 14, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 15, 16, 0,
2, 17, 4, 18, 0, 0
0, 11, 12, 0, 0, 13, 14, 0,
2, 15, 16, 0, 0
};
static const char _use_syllable_machine_to_state_actions[] = {
0, 0, 0, 5, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 3, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@ -330,9 +261,7 @@ static const char _use_syllable_machine_to_state_actions[] = {
};
static const char _use_syllable_machine_from_state_actions[] = {
0, 0, 0, 6, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 4, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@ -342,29 +271,27 @@ static const char _use_syllable_machine_from_state_actions[] = {
};
static const short _use_syllable_machine_eof_trans[] = {
0, 1, 3, 0, 29, 31, 31, 52,
31, 31, 31, 31, 31, 31, 31, 31,
31, 31, 31, 31, 31, 31, 31, 31,
31, 53, 53, 52, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53,
53, 70, 70, 74, 74, 74, 74, 74,
74, 74, 74, 74, 74, 74, 74, 74,
74, 74, 74, 74, 74, 74, 76, 76,
76
1, 0, 27, 29, 29, 50, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 51,
54, 51, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 58, 55, 55, 59, 59,
59
};
static const int use_syllable_machine_start = 3;
static const int use_syllable_machine_first_final = 3;
static const int use_syllable_machine_error = 0;
static const int use_syllable_machine_start = 1;
static const int use_syllable_machine_first_final = 1;
static const int use_syllable_machine_error = -1;
static const int use_syllable_machine_en_main = 3;
static const int use_syllable_machine_en_main = 1;
#line 38 "hb-ot-shape-complex-use-machine.rl"
#line 145 "hb-ot-shape-complex-use-machine.rl"
#line 138 "hb-ot-shape-complex-use-machine.rl"
#define found_syllable(syllable_type) \
@ -384,7 +311,7 @@ find_syllables (hb_buffer_t *buffer)
int cs;
hb_glyph_info_t *info = buffer->info;
#line 388 "hb-ot-shape-complex-use-machine.hh"
#line 315 "hb-ot-shape-complex-use-machine.hh"
{
cs = use_syllable_machine_start;
ts = 0;
@ -392,7 +319,7 @@ find_syllables (hb_buffer_t *buffer)
act = 0;
}
#line 166 "hb-ot-shape-complex-use-machine.rl"
#line 159 "hb-ot-shape-complex-use-machine.rl"
p = 0;
@ -401,7 +328,7 @@ find_syllables (hb_buffer_t *buffer)
unsigned int last = 0;
unsigned int syllable_serial = 1;
#line 405 "hb-ot-shape-complex-use-machine.hh"
#line 332 "hb-ot-shape-complex-use-machine.hh"
{
int _slen;
int _trans;
@ -409,15 +336,13 @@ find_syllables (hb_buffer_t *buffer)
const char *_inds;
if ( p == pe )
goto _test_eof;
if ( cs == 0 )
goto _out;
_resume:
switch ( _use_syllable_machine_from_state_actions[cs] ) {
case 6:
case 4:
#line 1 "NONE"
{ts = p;}
break;
#line 421 "hb-ot-shape-complex-use-machine.hh"
#line 346 "hb-ot-shape-complex-use-machine.hh"
}
_keys = _use_syllable_machine_trans_keys + (cs<<1);
@ -439,92 +364,70 @@ _eof_trans:
#line 1 "NONE"
{te = p+1;}
break;
case 9:
#line 134 "hb-ot-shape-complex-use-machine.rl"
case 8:
#line 127 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (independent_cluster); }}
break;
case 11:
#line 136 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (consonant_cluster); }}
case 10:
#line 129 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (standard_cluster); }}
break;
case 14:
#line 137 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (vowel_cluster); }}
break;
case 16:
#line 138 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (number_joiner_terminated_cluster); }}
break;
case 7:
#line 141 "hb-ot-shape-complex-use-machine.rl"
case 6:
#line 133 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (broken_cluster); }}
break;
case 8:
case 5:
#line 134 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (non_cluster); }}
break;
case 7:
#line 127 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (independent_cluster); }}
break;
case 12:
#line 135 "hb-ot-shape-complex-use-machine.rl"
case 11:
#line 128 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (virama_terminated_cluster); }}
break;
case 10:
#line 136 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (consonant_cluster); }}
case 9:
#line 129 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (standard_cluster); }}
break;
case 13:
#line 137 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (vowel_cluster); }}
#line 130 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
break;
case 15:
#line 139 "hb-ot-shape-complex-use-machine.rl"
case 12:
#line 131 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (numeral_cluster); }}
break;
case 18:
#line 140 "hb-ot-shape-complex-use-machine.rl"
case 16:
#line 132 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (symbol_cluster); }}
break;
case 17:
#line 141 "hb-ot-shape-complex-use-machine.rl"
case 14:
#line 133 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }}
break;
case 15:
#line 134 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (non_cluster); }}
break;
case 1:
#line 139 "hb-ot-shape-complex-use-machine.rl"
{{p = ((te))-1;}{ found_syllable (numeral_cluster); }}
#line 133 "hb-ot-shape-complex-use-machine.rl"
{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
break;
case 3:
#line 1 "NONE"
{ switch( act ) {
case 0:
{{cs = 0; goto _again;}}
break;
case 8:
{{p = ((te))-1;} found_syllable (broken_cluster); }
break;
}
}
break;
case 4:
#line 1 "NONE"
{te = p+1;}
#line 141 "hb-ot-shape-complex-use-machine.rl"
{act = 8;}
break;
#line 513 "hb-ot-shape-complex-use-machine.hh"
#line 420 "hb-ot-shape-complex-use-machine.hh"
}
_again:
switch ( _use_syllable_machine_to_state_actions[cs] ) {
case 5:
case 3:
#line 1 "NONE"
{ts = 0;}
#line 1 "NONE"
{act = 0;}
break;
#line 524 "hb-ot-shape-complex-use-machine.hh"
#line 429 "hb-ot-shape-complex-use-machine.hh"
}
if ( cs == 0 )
goto _out;
if ( ++p != pe )
goto _resume;
_test_eof: {}
@ -536,10 +439,9 @@ _again:
}
}
_out: {}
}
#line 175 "hb-ot-shape-complex-use-machine.rl"
#line 168 "hb-ot-shape-complex-use-machine.rl"
}

View File

@ -46,7 +46,6 @@ enum use_category_t {
USE_O = 0, /* OTHER */
USE_B = 1, /* BASE */
USE_IV = 2, /* BASE_VOWEL */
USE_IND = 3, /* BASE_IND */
USE_N = 4, /* BASE_NUM */
USE_GB = 5, /* BASE_OTHER */

View File

@ -6,12 +6,12 @@
*
* on files with these headers:
*
* # IndicSyllabicCategory-8.0.0.txt
* # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI]
* # IndicPositionalCategory-8.0.0.txt
* # Date: 2015-05-12, 10:00:00 GMT [RP, KW, LI]
* # Blocks-8.0.0.txt
* # Date: 2014-11-10, 23:04:00 GMT [KW]
* # IndicSyllabicCategory-9.0.0.txt
* # Date: 2016-05-21, 02:46:00 GMT [RP]
* # IndicPositionalCategory-9.0.0.txt
* # Date: 2016-02-25, 00:48:00 GMT [RP]
* # Blocks-9.0.0.txt
* # Date: 2016-02-05, 23:48:00 GMT [KW]
* UnicodeData.txt does not have a header.
*/
@ -24,7 +24,6 @@
#define H USE_H /* HALANT */
#define HN USE_HN /* HALANT_NUM */
#define IND USE_IND /* BASE_IND */
#define IV USE_IV /* BASE_VOWEL */
#define N USE_N /* BASE_NUM */
#define O USE_O /* OTHER */
#define R USE_R /* REPHA */
@ -80,30 +79,30 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Devanagari */
/* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 0910 */ IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0930 */ B, B, B, B, B, B, B, B, B, B, VAbv, VPst, CMBlw, B, VPst, VPre,
/* 0940 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst,
/* 0950 */ O, VMAbv, VMBlw, O, O, VAbv, VBlw, VBlw, B, B, B, B, B, B, B, B,
/* 0960 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0970 */ O, O, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B,
/* 0960 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0970 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* Bengali */
/* 0980 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV,
/* 0990 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0980 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
/* 0990 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
/* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, IND, O,
/* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B,
/* 09E0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Gurmukhi */
/* 0A00 */ O, VMAbv, VMAbv, VMPst, O, IV, IV, IV, IV, IV, IV, O, O, O, O, IV,
/* 0A10 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0A00 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, O, O, O, O, B,
/* 0A10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0A20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0A30 */ B, O, B, B, O, B, B, O, B, B, O, O, CMBlw, O, VPst, VPre,
/* 0A40 */ VPst, VBlw, VBlw, O, O, O, O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O,
@ -113,30 +112,30 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Gujarati */
/* 0A80 */ O, VMAbv, VMAbv, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, IV, O, IV,
/* 0A90 */ IV, IV, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0A80 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, B, B, B, O, B,
/* 0A90 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0AA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0AB0 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
/* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O,
/* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 0AE0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0AE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0AF0 */ O, O, O, O, O, O, O, O, O, B, O, O, O, O, O, O,
/* Oriya */
/* 0B00 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV,
/* 0B10 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0B00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
/* 0B10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0B20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0B30 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv,
/* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
/* 0B50 */ O, O, O, O, O, O, VAbv, VAbv, O, O, O, O, B, B, O, B,
/* 0B60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0B60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0B70 */ O, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Tamil */
/* 0B80 */ O, O, VMAbv, IND, O, IV, IV, IV, IV, IV, IV, O, O, O, IV, IV,
/* 0B90 */ IV, O, IV, IV, IV, B, O, O, O, B, B, O, B, O, B, B,
/* 0B80 */ O, O, VMAbv, IND, O, B, B, B, B, B, B, O, O, O, B, B,
/* 0B90 */ B, O, B, B, B, B, O, O, O, B, B, O, B, O, B, B,
/* 0BA0 */ O, O, O, B, B, O, O, O, B, B, B, O, O, O, B, B,
/* 0BB0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, VPst, VPst,
/* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, O, O,
@ -146,41 +145,41 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Telugu */
/* 0C00 */ VMAbv, VMPst, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV,
/* 0C10 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0C00 */ VMAbv, VMPst, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B,
/* 0C10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, VAbv, VAbv,
/* 0C40 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
/* 0C50 */ O, O, O, O, O, VAbv, VBlw, O, B, B, B, O, O, O, O, O,
/* 0C60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0C60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0C70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Kannada */
/* 0C80 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV,
/* 0C90 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0C80 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B,
/* 0C90 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0CA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 0CB0 */ B, B, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv,
/* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
/* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O,
/* 0CE0 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0CE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0CF0 */ O, R, R, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Malayalam */
/* 0D00 */ O, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, IV, IV,
/* 0D10 */ IV, O, IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 0D00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B,
/* 0D10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, O, O, B, VPst, VPst,
/* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O,
/* 0D50 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, IV,
/* 0D60 */ IV, IV, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0D50 */ O, O, O, O, IND, IND, IND, VPst, O, O, O, O, O, O, O, B,
/* 0D60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
/* 0D70 */ O, O, O, O, O, O, O, O, O, O, IND, IND, IND, IND, IND, IND,
/* Sinhala */
/* 0D80 */ O, O, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 0D90 */ IV, IV, IV, IV, IV, IV, IV, O, O, O, B, B, B, B, B, B,
/* 0D80 */ O, O, VMPst, VMPst, O, B, B, B, B, B, B, B, B, B, B, B,
/* 0D90 */ B, B, B, B, B, B, B, O, O, O, B, B, B, B, B, B,
/* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0DB0 */ B, B, O, B, B, B, B, B, B, B, B, B, O, B, O, O,
/* 0DC0 */ B, B, B, B, B, B, B, O, O, O, H, O, O, O, O, VPst,
@ -195,10 +194,10 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1020 */ B, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, VPst, VPst, VAbv, VAbv, VBlw,
/* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw,
/* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, H, VAbv, MPst, MPre, MBlw, MBlw, B,
/* 1040 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, GB, O,
/* 1050 */ B, B, IV, IV, IV, IV, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
/* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
/* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B,
/* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B,
/* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst,
@ -209,30 +208,30 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Tagalog */
/* 1700 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, O, B, B,
/* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, B,
/* 1710 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O,
/* Hanunoo */
/* 1720 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1730 */ B, B, VAbv, VBlw, VBlw, O, O, O, O, O, O, O, O, O, O, O,
/* Buhid */
/* 1740 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1740 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1750 */ B, B, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O,
/* Tagbanwa */
/* 1760 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, O, B, B,
/* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, B,
/* 1770 */ B, O, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O,
/* Khmer */
/* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 17A0 */ B, B, B, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 17B0 */ IV, IV, IV, IV, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre,
/* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 17B0 */ B, B, B, B, O, O, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre,
/* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FM, FAbv, CMAbv, FM, FM,
/* 17D0 */ FM, VAbv, H, FM, O, O, O, O, O, O, O, O, B, VAbv, O, O,
/* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
@ -274,8 +273,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, IV, IV, IV,
/* 1A50 */ IV, IV, IV, B, B, MPre, MBlw, FPst, FAbv, FAbv, FAbv, FBlw, FBlw, FBlw, FBlw, O,
/* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1A50 */ B, B, B, B, B, MPre, MBlw, FPst, FAbv, FAbv, FAbv, FBlw, FBlw, FBlw, FBlw, O,
/* 1A60 */ H, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre,
/* 1A70 */ VPre, VPre, VPre, VAbv, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, FM, FM, FM, O, O, FM,
/* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
@ -286,8 +285,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Balinese */
/* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 1B10 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B,
/* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre,
/* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, O, O, O, O,
@ -297,7 +296,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Sundanese */
/* 1B80 */ VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B,
/* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, H, SUB, SUB, B, B,
/* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
@ -306,7 +305,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 1BE0 */ B, B, B, B, IV, IV, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv,
/* 1BE0 */ B, B, B, B, B, B, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv,
/* 1BF0 */ FAbv, FAbv, VPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O,
/* Lepcha */
@ -326,14 +325,20 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O,
/* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, O, VMAbv, VMAbv, O, O, O, O, O, O,
#define use_offset_0x2008u 2552
#define use_offset_0x1df8u 2552
/* Combining Diacritical Marks Supplement */
O, O, O, FM, O, O, O, O,
#define use_offset_0x2008u 2560
/* General Punctuation */
O, O, O, O, ZWNJ, ZWJ, O, O,
/* 2010 */ GB, GB, GB, GB, GB, O, O, O,
#define use_offset_0x2060u 2568
#define use_offset_0x2060u 2576
/* 2060 */ WJ, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
@ -342,12 +347,12 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 2070 */ O, O, O, O, FM, O, O, O, O, O, O, O, O, O, O, O,
/* 2080 */ O, O, FM, FM, FM, O, O, O,
#define use_offset_0xa800u 2608
#define use_offset_0xa800u 2616
/* Syloti Nagri */
/* A800 */ IV, IV, O, IV, IV, IV, VAbv, B, B, B, B, VMAbv, B, B, B, B,
/* A800 */ B, B, O, B, B, B, VAbv, B, B, B, B, VMAbv, B, B, B, B,
/* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, O, O, O, O,
/* A830 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
@ -361,11 +366,11 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Saurashtra */
/* A880 */ VMPst, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* A890 */ IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A880 */ VMPst, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A8B0 */ B, B, B, B, FPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst,
/* A8C0 */ VPst, VPst, VPst, VPst, H, O, O, O, O, O, O, O, O, O, O, O,
/* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, O, O, O, O, O, O, O, O, O, O,
/* A8D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* Devanagari Extended */
@ -389,7 +394,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Javanese */
/* A980 */ VMAbv, VMAbv, FAbv, VMPst, IV, IV, IV, IV, IV, B, B, B, IV, IV, IV, B,
/* A980 */ VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B,
/* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, SUB, MPst, MPst,
@ -403,7 +408,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Cham */
/* AA00 */ IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B, B,
/* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AA20 */ B, B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre,
/* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MBlw, MBlw, O, O, O, O, O, O, O, O, O,
@ -413,7 +418,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Myanmar Extended-A */
/* AA60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* AA70 */ O, B, B, B, O, O, O, O, O, O, B, VMPst, VMAbv, VMPst, B, B,
/* AA70 */ O, B, B, B, GB, GB, GB, O, O, O, B, VMPst, VMAbv, VMPst, B, B,
/* Tai Viet */
@ -426,27 +431,27 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Meetei Mayek Extensions */
/* AAE0 */ IV, IV, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst,
/* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst,
/* AAF0 */ O, O, O, O, O, VMPst, H, O,
#define use_offset_0xabc0u 3368
#define use_offset_0xabc0u 3376
/* Meetei Mayek */
/* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, IV, IV,
/* ABD0 */ B, IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* ABD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O,
/* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0xfe00u 3432
#define use_offset_0xfe00u 3440
/* Variation Selectors */
/* FE00 */ VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS,
#define use_offset_0x10a00u 3448
#define use_offset_0x10a00u 3456
/* Kharoshthi */
@ -457,13 +462,13 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 10A30 */ B, B, B, B, O, O, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H,
/* 10A40 */ B, B, B, B, B, B, B, B,
#define use_offset_0x11000u 3520
#define use_offset_0x11000u 3528
/* Brahmi */
/* 11000 */ VMPst, VMAbv, VMPst, R, R, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 11010 */ IV, IV, IV, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11000 */ VMPst, VMAbv, VMPst, R, R, B, B, B, B, B, B, B, B, B, B, B,
/* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw,
/* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, O, O,
@ -473,17 +478,17 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Kaithi */
/* 11080 */ VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B,
/* 11080 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O,
#define use_offset_0x11100u 3712
#define use_offset_0x11100u 3720
/* Chakma */
/* 11100 */ VMAbv, VMAbv, VMAbv, IV, IV, IV, IV, B, B, B, B, B, B, B, B, B,
/* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11120 */ B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VAbv, VAbv,
/* 11130 */ VAbv, VBlw, VBlw, H, VAbv, O, B, B, B, B, B, B, B, B, B, B,
@ -497,8 +502,8 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Sharada */
/* 11180 */ VMAbv, VMAbv, VMPst, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
/* 11190 */ IV, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11180 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
/* 111C0 */ H, B, R, R, O, O, O, O, O, O, CMBlw, VAbv, VBlw, O, O, O,
@ -511,23 +516,23 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Khojki */
/* 11200 */ IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B, B, B,
/* 11200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11210 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw,
/* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv,
/* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O,
#define use_offset_0x11280u 4024
#define use_offset_0x11280u 4040
/* Multani */
/* 11280 */ IV, IV, IV, IV, B, B, B, O, B, O, B, B, B, B, O, B,
/* 11280 */ B, B, B, B, B, B, B, O, B, O, B, B, B, B, O, B,
/* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, B,
/* 112A0 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
/* Khudawadi */
/* 112B0 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B,
/* 112B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv,
/* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, O, O, O, O, O,
@ -535,44 +540,55 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Grantha */
/* 11300 */ VMAbv, VMAbv, VMPst, VMPst, O, IV, IV, IV, IV, IV, IV, IV, IV, O, O, IV,
/* 11310 */ IV, O, O, IV, IV, B, B, B, B, B, B, B, B, B, B, B,
/* 11300 */ VMAbv, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
/* 11310 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 11330 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPst,
/* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
/* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O,
/* 11360 */ IV, IV, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
/* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
/* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
#define use_offset_0x11480u 4272
#define use_offset_0x11400u 4288
/* Newa */
/* 11400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv,
/* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O,
/* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* 11460 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 11470 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Tirhuta */
/* 11480 */ O, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B,
/* 11480 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv,
/* 114C0 */ VMAbv, VMPst, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O,
/* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
#define use_offset_0x11580u 4368
#define use_offset_0x11580u 4512
/* Siddham */
/* 11580 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B,
/* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
/* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H,
/* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 115D0 */ O, O, O, O, O, O, O, O, IV, IV, IV, IV, VBlw, VBlw, O, O,
/* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, O, O,
/* 115E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 115F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* Modi */
/* 11600 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B,
/* 11600 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H,
@ -583,7 +599,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* Takri */
/* 11680 */ IV, IV, IV, IV, IV, IV, IV, IV, IV, IV, B, B, B, B, B, B,
/* 11680 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst,
/* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, O, O, O, O, O, O, O, O,
@ -599,7 +615,28 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O,
/* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
}; /* Table items: 4816; occupancy: 72% */
#define use_offset_0x11c00u 4960
/* Bhaiksuki */
/* 11C00 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
/* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
/* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, O, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H,
/* 11C40 */ B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
/* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
/* Marchen */
/* 11C70 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11C90 */ O, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
/* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
/* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O,
}; /* Table items: 5144; occupancy: 72% */
USE_TABLE_ELEMENT_TYPE
hb_use_get_categories (hb_codepoint_t u)
@ -619,6 +656,7 @@ hb_use_get_categories (hb_codepoint_t u)
if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u];
if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
if (hb_in_range (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u];
break;
case 0x2u:
@ -642,10 +680,11 @@ hb_use_get_categories (hb_codepoint_t u)
case 0x11u:
if (hb_in_range (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u];
if (hb_in_range (u, 0x11100u, 0x11237u)) return use_table[u - 0x11100u + use_offset_0x11100u];
if (hb_in_range (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
if (hb_in_range (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
if (hb_in_range (u, 0x11480u, 0x114DFu)) return use_table[u - 0x11480u + use_offset_0x11480u];
if (hb_in_range (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
if (hb_in_range (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u];
if (hb_in_range (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
if (unlikely (u == 0x1107Fu)) return HN;
break;
@ -662,7 +701,6 @@ hb_use_get_categories (hb_codepoint_t u)
#undef H
#undef HN
#undef IND
#undef IV
#undef N
#undef O
#undef R

View File

@ -184,6 +184,9 @@ has_arabic_joining (hb_script_t script)
case HB_SCRIPT_MANICHAEAN:
case HB_SCRIPT_PSALTER_PAHLAVI:
/* Unicode-9.0 additions */
case HB_SCRIPT_ADLAM:
return true;
default:
@ -227,12 +230,12 @@ data_destroy_use (void *data)
enum syllable_type_t {
independent_cluster,
virama_terminated_cluster,
consonant_cluster,
vowel_cluster,
standard_cluster,
number_joiner_terminated_cluster,
numeral_cluster,
symbol_cluster,
broken_cluster,
non_cluster,
};
#include "hb-ot-shape-complex-use-machine.hh"
@ -285,6 +288,9 @@ static void
setup_topographical_masks (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer)
{
const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
if (use_plan->arabic_plan)
return;
ASSERT_STATIC (INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4);
hb_mask_t masks[4], all_masks = 0;
@ -309,13 +315,13 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
{
case independent_cluster:
case symbol_cluster:
case non_cluster:
/* These don't join. Nothing to do. */
last_form = _NONE;
break;
case virama_terminated_cluster:
case consonant_cluster:
case vowel_cluster:
case standard_cluster:
case number_joiner_terminated_cluster:
case numeral_cluster:
case broken_cluster:
@ -360,7 +366,7 @@ clear_substitution_flags (const hb_ot_shape_plan_t *plan,
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
_hb_glyph_info_clear_substituted_and_ligated_and_multiplied (&info[i]);
_hb_glyph_info_clear_substituted (&info[i]);
}
static void
@ -405,6 +411,12 @@ record_pref (const hb_ot_shape_plan_t *plan,
}
}
static inline bool
is_halant (const hb_glyph_info_t &info)
{
return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
}
static void
reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
{
@ -412,28 +424,26 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
/* Only a few syllable types need reordering. */
if (unlikely (!(FLAG_SAFE (syllable_type) &
(FLAG (virama_terminated_cluster) |
FLAG (consonant_cluster) |
FLAG (vowel_cluster) |
FLAG (standard_cluster) |
FLAG (broken_cluster) |
0))))
return;
hb_glyph_info_t *info = buffer->info;
#define HALANT_FLAGS FLAG(USE_H)
#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB) | FLAG (USE_IV))
#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB))
/* Move things forward. */
if (info[start].use_category() == USE_R && end - start > 1)
{
/* Got a repha. Reorder it to after first base, before first halant. */
for (unsigned int i = start + 1; i < end; i++)
if (FLAG_UNSAFE (info[i].use_category()) & (HALANT_FLAGS | BASE_FLAGS))
if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
{
/* If we hit a halant, move before it; otherwise it's a base: move to it's
* place, and shift things in between backward. */
if (info[i].use_category() == USE_H)
if (is_halant (info[i]))
i--;
buffer->merge_clusters (start, i + 1);
@ -450,11 +460,11 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
for (unsigned int i = start; i < end; i++)
{
uint32_t flag = FLAG_UNSAFE (info[i].use_category());
if (flag & (HALANT_FLAGS | BASE_FLAGS))
if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
{
/* If we hit a halant, move before it; otherwise it's a base: move to it's
/* If we hit a halant, move after it; otherwise it's a base: move to it's
* place, and shift things in between backward. */
if (info[i].use_category() == USE_H)
if (is_halant (info[i]))
j = i + 1;
else
j = i;
@ -490,22 +500,16 @@ 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))
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint))
return;
dottedcircle.use_category() = hb_use_get_categories (0x25CC);
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len)
while (buffer->idx < buffer->len && !buffer->in_error)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
@ -513,19 +517,19 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
{
last_syllable = syllable;
hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
info.syllable() = buffer->cur().syllable();
hb_glyph_info_t ginfo = dottedcircle;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
/* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len &&
while (buffer->idx < buffer->len && !buffer->in_error &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().use_category() == USE_R)
buffer->next_glyph ();
buffer->output_info (info);
buffer->output_info (ginfo);
}
else
buffer->next_glyph ();
@ -564,7 +568,7 @@ compose_use (const hb_ot_shape_normalize_context_t *c,
if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
return false;
return c->unicode->compose (a, b, ab);
return (bool)c->unicode->compose (a, b, ab);
}
@ -576,10 +580,11 @@ 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,
setup_masks_use,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
false, /* fallback_position */
};

View File

@ -45,5 +45,9 @@ 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 */

View File

@ -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;
}
/* Fall through */
HB_FALLTHROUGH;
default:
case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
@ -259,6 +259,7 @@ 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:
@ -279,6 +280,7 @@ 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:
@ -482,3 +484,70 @@ _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_nominal_glyph (u, &glyph))
{
pos[i].x_advance = font->get_glyph_h_advance (glyph);
break;
}
break;
case t::SPACE_PUNCTUATION:
if (font->get_nominal_glyph ('.', &glyph))
pos[i].x_advance = font->get_glyph_h_advance (glyph);
else if (font->get_nominal_glyph (',', &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;
}
}
}

View File

@ -62,24 +62,12 @@
* 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 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.
* - When a font does not support a character but supports its canonical
* decomposition, well, use the decomposition.
*
* - 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
@ -88,7 +76,7 @@ decompose_unicode (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t *a,
hb_codepoint_t *b)
{
return c->unicode->decompose (ab, a, b);
return (bool) c->unicode->decompose (ab, a, b);
}
static bool
@ -97,21 +85,21 @@ compose_unicode (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t b,
hb_codepoint_t *ab)
{
return c->unicode->compose (a, b, ab);
return (bool) c->unicode->compose (a, b, ab);
}
static inline void
set_glyph (hb_glyph_info_t &info, hb_font_t *font)
{
font->get_glyph (info.codepoint, 0, &info.glyph_index());
font->get_nominal_glyph (info.codepoint, &info.glyph_index());
}
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);
_hb_glyph_info_set_unicode_props (&buffer->prev(), buffer->unicode);
buffer->output_glyph (unichar); /* This is very confusing indeed. */
_hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
}
static inline void
@ -136,10 +124,10 @@ decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint
hb_font_t * const font = c->font;
if (!c->decompose (c, ab, &a, &b) ||
(b && !font->get_glyph (b, 0, &b_glyph)))
(b && !font->get_nominal_glyph (b, &b_glyph)))
return 0;
bool has_a = font->get_glyph (a, 0, &a_glyph);
bool has_a = (bool) font->get_nominal_glyph (a, &a_glyph);
if (shortest && has_a) {
/* Output a and b */
output_char (buffer, a, a_glyph);
@ -171,28 +159,6 @@ 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)
{
@ -200,17 +166,50 @@ 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))
if (shortest && c->font->get_nominal_glyph (u, &glyph))
{
next_char (buffer, glyph);
else if (decompose (c, shortest, u))
return;
}
if (decompose (c, shortest, u))
{
skip_char (buffer);
else if (!shortest && c->font->get_glyph (u, 0, &glyph))
return;
}
if (!shortest && c->font->get_nominal_glyph (u, &glyph))
{
next_char (buffer, glyph);
else if (decompose_compatibility (c, u))
skip_char (buffer);
else
next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
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_nominal_glyph (0x0020u, &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_nominal_glyph (0x2010u, &other_glyph))
{
next_char (buffer, other_glyph);
return;
}
}
next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
}
static inline void
@ -219,10 +218,10 @@ 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;) {
for (; buffer->idx < end - 1 && !buffer->in_error;) {
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()))
if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
{
buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
}
@ -255,13 +254,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; i++)
for (unsigned int i = buffer->idx; i < end && !buffer->in_error; 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)
while (buffer->idx < end && !buffer->in_error)
decompose_current_character (c, short_circuit);
}
@ -321,7 +320,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;)
for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;)
{
unsigned int end;
for (end = buffer->idx + 1; end < count; end++)
@ -371,7 +370,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)
while (buffer->idx < count && !buffer->in_error)
{
hb_codepoint_t composed, glyph;
if (/* We don't try to compose a non-mark character with it's preceding starter.
@ -389,7 +388,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
buffer->cur().codepoint,
&composed) &&
/* And the font has glyph for the composite. */
font->get_glyph (composed, 0, &glyph))
font->get_nominal_glyph (composed, &glyph))
{
/* Composes. */
buffer->next_glyph (); /* Copy to out-buffer. */
@ -400,7 +399,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->unicode);
_hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
continue;
}

View File

@ -145,7 +145,7 @@ _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
struct hb_ot_shaper_font_data_t {};
hb_ot_shaper_font_data_t *
_hb_ot_shaper_font_data_create (hb_font_t *font)
_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
{
return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
@ -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->unicode);
_hb_glyph_info_set_unicode_props (&info[i], buffer);
}
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->unicode);
_hb_glyph_info_set_unicode_props (&dottedcircle, buffer);
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)
while (buffer->idx < buffer->len && !buffer->in_error)
buffer->next_glyph ();
buffer->swap_buffers ();
@ -263,16 +263,18 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
static void
hb_form_clusters (hb_buffer_t *buffer)
{
if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
return;
/* Loop duplicated in hb_ensure_native_direction(). */
/* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */
unsigned int base = 0;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
{
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) &&
!_hb_glyph_info_is_joiner (&info[i])))
{
buffer->merge_clusters (base, i);
base = i;
@ -346,7 +348,8 @@ 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->plan->has_frac)
if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
!c->plan->has_frac)
return;
hb_buffer_t *buffer = c->buffer;
@ -416,7 +419,8 @@ hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
(buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
return;
unsigned int count = buffer->len;
@ -433,7 +437,8 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
(buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
return;
unsigned int count = buffer->len;
@ -451,7 +456,7 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
return;
hb_codepoint_t space;
if (c->font->get_glyph (' ', 0, &space))
if (c->font->get_nominal_glyph (' ', &space))
{
/* Replace default-ignorables with a zero-advance space glyph. */
for (/*continue*/; i < count; i++)
@ -518,40 +523,11 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
}
static inline void
hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
{
unsigned int count = c->buffer->len;
hb_glyph_info_t *info = c->buffer->info;
for (unsigned int i = 0; i < count; i++)
{
hb_ot_layout_glyph_class_mask_t klass;
/* Never mark default-ignorables as marks.
* They won't get in the way of lookups anyway,
* but having them as mark will cause them to be skipped
* over if the lookup-flag says so, but at least for the
* Mongolian variation selectors, looks like Uniscribe
* marks them as non-mark. Some Mongolian fonts without
* GDEF rely on this. Another notable character that
* this applies to is COMBINING GRAPHEME JOINER. */
klass = (_hb_glyph_info_get_general_category (&info[i]) !=
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
_hb_glyph_info_is_default_ignorable (&info[i])) ?
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
HB_OT_LAYOUT_GLYPH_PROPS_MARK;
_hb_glyph_info_set_glyph_props (&info[i], klass);
}
}
static inline void
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);
@ -576,16 +552,10 @@ 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))
hb_synthesize_glyph_classes (c);
c->plan->substitute (c->font, buffer);
hb_ot_layout_substitute_finish (c->font, buffer);
return;
}
@ -593,6 +563,9 @@ 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);
}
@ -612,20 +585,6 @@ zero_mark_width (hb_glyph_position_t *pos)
pos->y_advance = 0;
}
static inline void
zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets)
{
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
{
if (adjust_offsets)
adjust_mark_offsets (&buffer->pos[i]);
zero_mark_width (&buffer->pos[i]);
}
}
static inline void
zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
{
@ -647,26 +606,41 @@ 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);
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
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);
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
hb_ot_position_complex (hb_ot_shape_context_t *c)
{
hb_ot_layout_position_start (c->font, c->buffer);
bool ret = false;
unsigned int count = c->buffer->len;
bool has_positioning = hb_ot_layout_has_positioning (c->face);
bool has_positioning = (bool) hb_ot_layout_has_positioning (c->face);
/* If the font has no GPOS, AND, no fallback positioning will
* happen, AND, direction is forward, then when zeroing mark
* widths, we shift the mark with it, such that the mark
@ -685,15 +659,8 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
break;
/* Not currently used for any shaper:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
break;
*/
default:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
break;
}
@ -703,60 +670,56 @@ 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, apply GPOS, change it back. */
/* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
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);
}
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
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);
c->plan->position (c->font, c->buffer);
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);
}
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
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);
ret = true;
}
switch (c->plan->shaper->zero_width_marks)
{
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE:
zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
break;
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
break;
default:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
//case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
break;
}
/* Finishing off GPOS has to follow a certain order. */
hb_ot_layout_position_finish_advances (c->font, c->buffer);
hb_ot_zero_width_default_ignorables (c);
hb_ot_layout_position_finish_offsets (c->font, c->buffer);
return ret;
}
static inline void
hb_ot_position (hb_ot_shape_context_t *c)
{
hb_ot_layout_position_start (c->font, c->buffer);
c->buffer->clear_positions ();
hb_ot_position_default (c);
hb_bool_t fallback = !hb_ot_position_complex (c);
hb_ot_zero_width_default_ignorables (c);
hb_ot_layout_position_finish (c->font, c->buffer);
if (fallback && c->plan->shaper->fallback_position)
_hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
@ -778,6 +741,12 @@ 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;
@ -792,15 +761,22 @@ 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 ();
}
@ -820,6 +796,8 @@ _hb_ot_shape (hb_shape_plan_t *shape_plan,
/**
* hb_ot_shape_plan_collect_lookups:
*
* Since: 0.9.7
**/
void
@ -841,18 +819,20 @@ add_char (hb_font_t *font,
hb_set_t *glyphs)
{
hb_codepoint_t glyph;
if (font->get_glyph (u, 0, &glyph))
if (font->get_nominal_glyph (u, &glyph))
glyphs->add (glyph);
if (mirror)
{
hb_codepoint_t m = unicode->mirroring (u);
if (m != u && font->get_glyph (m, 0, &glyph))
if (m != u && font->get_nominal_glyph (m, &glyph))
glyphs->add (glyph);
}
}
/**
* hb_ot_shape_glyphs_closure:
*
* Since: 0.9.2
**/
void

View File

@ -36,14 +36,14 @@
HB_BEGIN_DECLS
/* TODO port to shape-plan / set. */
void
HB_EXTERN void
hb_ot_shape_glyphs_closure (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features,
hb_set_t *glyphs);
void
HB_EXTERN void
hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
hb_tag_t table_tag,
hb_set_t *lookup_indexes /* OUT */);

View File

@ -186,14 +186,18 @@ static const LangTag ot_languages[] = {
{"aa", HB_TAG('A','F','R',' ')}, /* Afar */
{"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */
{"abq", HB_TAG('A','B','A',' ')}, /* Abaza */
{"acf", HB_TAG('F','A','N',' ')}, /* French Antillean */
{"ach", HB_TAG('A','C','H',' ')}, /* Acoli */
{"acr", HB_TAG('A','C','R',' ')}, /* Achi */
{"ada", HB_TAG('D','N','G',' ')}, /* Dangme */
{"ady", HB_TAG('A','D','Y',' ')}, /* Adyghe */
{"af", HB_TAG('A','F','K',' ')}, /* Afrikaans */
{"ahg", HB_TAG('A','G','W',' ')}, /* Agaw */
{"aii", HB_TAG('S','W','A',' ')}, /* Swadaya Aramaic */
{"aio", HB_TAG('A','I','O',' ')}, /* Aiton */
{"aiw", HB_TAG('A','R','I',' ')}, /* Aari */
{"ak", HB_TAG('T','W','I',' ')}, /* Akan [macrolanguage] */
{"aka", HB_TAG('A','K','A',' ')}, /* Akan */
{"alt", HB_TAG('A','L','T',' ')}, /* [Southern] Altai */
{"am", HB_TAG('A','M','H',' ')}, /* Amharic */
{"amf", HB_TAG('H','B','N',' ')}, /* Hammer-Banna */
@ -206,6 +210,7 @@ static const LangTag ot_languages[] = {
{"as", HB_TAG('A','S','M',' ')}, /* Assamese */
{"ast", HB_TAG('A','S','T',' ')}, /* Asturian/Asturleonese/Bable/Leonese */
{"ath", HB_TAG('A','T','H',' ')}, /* Athapaskan [family] */
{"atj", HB_TAG('R','C','R',' ')}, /* R-Cree */
{"atv", HB_TAG('A','L','T',' ')}, /* [Northern] Altai */
{"av", HB_TAG('A','V','R',' ')}, /* Avaric */
{"awa", HB_TAG('A','W','A',' ')}, /* Awadhi */
@ -214,6 +219,7 @@ static const LangTag ot_languages[] = {
{"azb", HB_TAG('A','Z','B',' ')}, /* South Azerbaijani */
{"azj", HB_TAG('A','Z','E',' ')}, /* North Azerbaijani */
{"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */
{"bad", HB_TAG('B','A','D','0')}, /* Banda */
{"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [family] */
{"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolangauge] */
{"ban", HB_TAG('B','A','N',' ')}, /* Balinese */
@ -222,11 +228,13 @@ static const LangTag ot_languages[] = {
{"bci", HB_TAG('B','A','U',' ')}, /* Baoulé */
{"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol */
{"bcq", HB_TAG('B','C','H',' ')}, /* Bench */
{"bdy", HB_TAG('B','D','Y',' ')}, /* Bandjalang */
{"be", HB_TAG('B','E','L',' ')}, /* Belarusian */
{"bem", HB_TAG('B','E','M',' ')}, /* Bemba (Zambia) */
{"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */
{"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */
{"bft", HB_TAG('B','L','T',' ')}, /* Balti */
{"bfu", HB_TAG('L','A','H',' ')}, /* Lahuli */
{"bfy", HB_TAG('B','A','G',' ')}, /* Baghelkhandi */
{"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */
{"bgc", HB_TAG('B','G','C',' ')}, /* Haryanvi */
@ -260,11 +268,13 @@ static const LangTag ot_languages[] = {
{"bxr", HB_TAG('R','B','U',' ')}, /* Russian Buriat */
{"byn", HB_TAG('B','I','L',' ')}, /* Bilen */
{"ca", HB_TAG('C','A','T',' ')}, /* Catalan */
{"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */
{"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */
{"ce", HB_TAG('C','H','E',' ')}, /* Chechen */
{"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */
{"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */
{"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */
{"chk", HB_TAG('C','H','K','0')}, /* Chuukese */
{"cho", HB_TAG('C','H','O',' ')}, /* Choctaw */
{"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */
{"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */
@ -272,9 +282,12 @@ static const LangTag ot_languages[] = {
{"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */
{"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */
{"cop", HB_TAG('C','O','P',' ')}, /* Coptic */
{"cpp", HB_TAG('C','P','P',' ')}, /* Creoles */
{"cr", HB_TAG('C','R','E',' ')}, /* Cree */
{"cre", HB_TAG('Y','C','R',' ')}, /* Y-Cree */
{"crh", HB_TAG('C','R','T',' ')}, /* Crimean Tatar */
{"crj", HB_TAG('E','C','R',' ')}, /* [Southern] East Cree */
{"crk", HB_TAG('W','C','R',' ')}, /* West-Cree */
{"crl", HB_TAG('E','C','R',' ')}, /* [Northern] East Cree */
{"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */
{"crx", HB_TAG('C','R','R',' ')}, /* Carrier */
@ -283,21 +296,27 @@ static const LangTag ot_languages[] = {
{"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */
{"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */
{"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */
{"cuk", HB_TAG('C','U','K',' ')}, /* San Blas Kuna */
{"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */
{"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */
{"cy", HB_TAG('W','E','L',' ')}, /* Welsh */
{"da", HB_TAG('D','A','N',' ')}, /* Danish */
{"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) */
{"dar", HB_TAG('D','A','R',' ')}, /* Dargwa */
{"dax", HB_TAG('D','A','X',' ')}, /* Dayi */
{"de", HB_TAG('D','E','U',' ')}, /* German */
{"dgo", HB_TAG('D','G','O',' ')}, /* Dogri */
{"dhd", HB_TAG('M','A','W',' ')}, /* Dhundari */
{"dhg", HB_TAG('D','H','G',' ')}, /* Dhangu */
{"din", HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */
{"diq", HB_TAG('D','I','Q',' ')}, /* Dimli */
{"dje", HB_TAG('D','J','R',' ')}, /* Zarma */
{"djr", HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */
{"dng", HB_TAG('D','U','N',' ')}, /* Dungan */
{"dnj", HB_TAG('D','N','J',' ')}, /* Dan */
{"doi", HB_TAG('D','G','R',' ')}, /* Dogri [macrolanguage] */
{"dsb", HB_TAG('L','S','B',' ')}, /* Lower Sorbian */
{"duj", HB_TAG('D','U','J',' ')}, /* Dhuwal */
{"dv", HB_TAG('D','I','V',' ')}, /* Dhivehi/Divehi/Maldivian */
{"dyu", HB_TAG('J','U','L',' ')}, /* Jula */
{"dz", HB_TAG('D','Z','N',' ')}, /* Dzongkha */
@ -307,23 +326,30 @@ static const LangTag ot_languages[] = {
{"el", HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) */
{"emk", HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan */
{"en", HB_TAG('E','N','G',' ')}, /* English */
{"enf", HB_TAG('F','N','E',' ')}, /* Forest Nenets */
{"enh", HB_TAG('T','N','E',' ')}, /* Tundra Nenets */
{"eo", HB_TAG('N','T','O',' ')}, /* Esperanto */
{"eot", HB_TAG('B','T','I',' ')}, /* Beti (Côte d'Ivoire) */
{"es", HB_TAG('E','S','P',' ')}, /* Spanish */
{"esu", HB_TAG('E','S','U',' ')}, /* Central Yupik */
{"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
{"eu", HB_TAG('E','U','Q',' ')}, /* Basque */
{"eve", HB_TAG('E','V','N',' ')}, /* Even */
{"evn", HB_TAG('E','V','K',' ')}, /* Evenki */
{"fa", HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */
{"fan", HB_TAG('F','A','N','0')}, /* Fang */
{"fat", HB_TAG('F','A','T',' ')}, /* Fanti */
{"ff", HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */
{"fi", HB_TAG('F','I','N',' ')}, /* Finnish */
{"fil", HB_TAG('P','I','L',' ')}, /* Filipino */
{"fj", HB_TAG('F','J','I',' ')}, /* Fijian */
{"flm", HB_TAG('H','A','L',' ')}, /* Halam */
{"fo", HB_TAG('F','O','S',' ')}, /* Faroese */
{"fon", HB_TAG('F','O','N',' ')}, /* Fon */
{"fr", HB_TAG('F','R','A',' ')}, /* French */
{"frc", HB_TAG('F','R','C',' ')}, /* Cajun French */
{"frp", HB_TAG('F','R','P',' ')}, /* Arpitan/Francoprovençal */
{"fuf", HB_TAG('F','T','A',' ')}, /* Futa */
{"fur", HB_TAG('F','R','L',' ')}, /* Friulian */
{"fuv", HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */
{"fy", HB_TAG('F','R','I',' ')}, /* Western Frisian */
@ -334,17 +360,24 @@ static const LangTag ot_languages[] = {
{"gd", HB_TAG('G','A','E',' ')}, /* Scottish Gaelic */
{"gez", HB_TAG('G','E','Z',' ')}, /* Ge'ez */
{"ggo", HB_TAG('G','O','N',' ')}, /* Southern Gondi */
{"gih", HB_TAG('G','I','H',' ')}, /* Githabul */
{"gil", HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */
{"gkp", HB_TAG('G','K','P',' ')}, /* Kpelle (Guinea) */
{"gl", HB_TAG('G','A','L',' ')}, /* Galician */
{"gld", HB_TAG('N','A','N',' ')}, /* Nanai */
{"gle", HB_TAG('I','R','T',' ')}, /* Irish Traditional */
{"glk", HB_TAG('G','L','K',' ')}, /* Gilaki */
{"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */
{"gnn", HB_TAG('G','N','N',' ')}, /* Gumatj */
{"gno", HB_TAG('G','O','N',' ')}, /* Northern Gondi */
{"gog", HB_TAG('G','O','G',' ')}, /* Gogo */
{"gon", HB_TAG('G','O','N',' ')}, /* Gondi [macrolanguage] */
{"grt", HB_TAG('G','R','O',' ')}, /* Garo */
{"gru", HB_TAG('S','O','G',' ')}, /* Sodo Gurage */
{"gsw", HB_TAG('A','L','S',' ')}, /* Alsatian */
{"gu", HB_TAG('G','U','J',' ')}, /* Gujarati */
{"guc", HB_TAG('G','U','C',' ')}, /* Wayuu */
{"guf", HB_TAG('G','U','F',' ')}, /* Gupapuyngu */
{"guk", HB_TAG('G','M','Z',' ')}, /* Gumuz */
/*{"guk", HB_TAG('G','U','K',' ')},*/ /* Gumuz (in SIL fonts) */
{"guz", HB_TAG('G','U','Z',' ')}, /* Ekegusii/Gusii */
@ -355,9 +388,9 @@ static const LangTag ot_languages[] = {
{"hay", HB_TAG('H','A','Y',' ')}, /* Haya */
{"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */
{"he", HB_TAG('I','W','R',' ')}, /* Hebrew */
{"hz", HB_TAG('H','E','R',' ')}, /* Herero */
{"hi", HB_TAG('H','I','N',' ')}, /* Hindi */
{"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */
{"hmn", HB_TAG('H','M','N',' ')}, /* Hmong */
{"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */
{"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */
{"hno", HB_TAG('H','N','D',' ')}, /* [Northern] Hindko */
@ -371,11 +404,13 @@ static const LangTag ot_languages[] = {
{"hy", HB_TAG('H','Y','E',' ')}, /* Armenian */
{"hz", HB_TAG('H','E','R',' ')}, /* Herero */
{"ia", HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */
{"iba", HB_TAG('I','B','A',' ')}, /* Iban */
{"ibb", HB_TAG('I','B','B',' ')}, /* Ibibio */
{"id", HB_TAG('I','N','D',' ')}, /* Indonesian */
{"ie", HB_TAG('I','L','E',' ')}, /* Interlingue/Occidental */
{"ig", HB_TAG('I','B','O',' ')}, /* Igbo */
{"igb", HB_TAG('E','B','I',' ')}, /* Ebira */
{"ii", HB_TAG('Y','I','M',' ')}, /* Yi Modern */
{"ijc", HB_TAG('I','J','O',' ')}, /* Izon */
{"ijo", HB_TAG('I','J','O',' ')}, /* Ijo [family] */
{"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] */
@ -391,15 +426,20 @@ static const LangTag ot_languages[] = {
{"jv", HB_TAG('J','A','V',' ')}, /* Javanese */
{"ka", HB_TAG('K','A','T',' ')}, /* Georgian */
{"kaa", HB_TAG('K','R','K',' ')}, /* Karakalpak */
{"kab", HB_TAG('K','A','B',' ')}, /* Kabyle */
{"kab", HB_TAG('K','A','B','0')}, /* Kabyle */
{"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
{"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */
{"kat", HB_TAG('K','G','E',' ')}, /* Khutsuri Georgian */
{"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */
{"kde", HB_TAG('K','D','E',' ')}, /* Makonde */
{"kdr", HB_TAG('K','R','M',' ')}, /* Karaim */
{"kdt", HB_TAG('K','U','Y',' ')}, /* Kuy */
{"kea", HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */
{"kek", HB_TAG('K','E','K',' ')}, /* Kekchi */
{"kex", HB_TAG('K','K','N',' ')}, /* Kokni */
{"kfa", HB_TAG('K','O','D',' ')}, /* Kodagu */
{"kfr", HB_TAG('K','A','C',' ')}, /* Kachchi */
{"kfx", HB_TAG('K','U','L',' ')}, /* Kulvi */
{"kfy", HB_TAG('K','M','N',' ')}, /* Kumaoni */
{"kg", HB_TAG('K','O','N',' ')}, /* Kongo [macrolanguage] */
{"kha", HB_TAG('K','S','I',' ')}, /* Khasi */
@ -408,7 +448,9 @@ static const LangTag ot_languages[] = {
/*{"kht", HB_TAG('K','H','T',' ')},*/ /* Khamti (OpenType spec and SIL fonts) */
{"khw", HB_TAG('K','H','W',' ')}, /* Khowar */
{"ki", HB_TAG('K','I','K',' ')}, /* Gikuyu/Kikuyu */
{"kiu", HB_TAG('K','I','U',' ')}, /* Kirmanjki */
{"kj", HB_TAG('K','U','A',' ')}, /* Kuanyama/Kwanyama */
{"kjd", HB_TAG('K','J','D',' ')}, /* Southern Kiwai */
{"kjh", HB_TAG('K','H','A',' ')}, /* Khakass */
{"kjp", HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen */
{"kk", HB_TAG('K','A','Z',' ')}, /* Kazakh */
@ -422,6 +464,8 @@ static const LangTag ot_languages[] = {
{"ko", HB_TAG('K','O','R',' ')}, /* Korean */
{"koi", HB_TAG('K','O','P',' ')}, /* Komi-Permyak */
{"kok", HB_TAG('K','O','K',' ')}, /* Konkani [macrolanguage] */
{"kon", HB_TAG('K','O','N','0')}, /* Kongo */
{"kos", HB_TAG('K','O','S',' ')}, /* Kosraean */
{"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */
{"kpv", HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */
{"kpy", HB_TAG('K','Y','K',' ')}, /* Koryak */
@ -431,9 +475,11 @@ static const LangTag ot_languages[] = {
{"krl", HB_TAG('K','R','L',' ')}, /* Karelian */
{"kru", HB_TAG('K','U','U',' ')}, /* Kurukh */
{"ks", HB_TAG('K','S','H',' ')}, /* Kashmiri */
{"ksh", HB_TAG('K','S','H',' ')}, /* Kölsch */
{"ksh", HB_TAG('K','S','H','0')}, /* Ripuarian, Kölsch */
/*{"ksw", HB_TAG('K','R','N',' ')},*/ /* S'gaw Karen (Microsoft fonts?) */
{"ksw", HB_TAG('K','S','W',' ')}, /* S'gaw Karen (OpenType spec and SIL fonts) */
{"ktb", HB_TAG('K','E','B',' ')}, /* Kebena */
{"ktu", HB_TAG('K','O','N',' ')}, /* Kikongo */
{"ku", HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */
{"kum", HB_TAG('K','U','M',' ')}, /* Kumyk */
{"kv", HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */
@ -461,6 +507,7 @@ static const LangTag ot_languages[] = {
{"lmo", HB_TAG('L','M','O',' ')}, /* Lombard */
{"ln", HB_TAG('L','I','N',' ')}, /* Lingala */
{"lo", HB_TAG('L','A','O',' ')}, /* Lao */
{"lom", HB_TAG('L','O','M',' ')}, /* Loma */
{"lrc", HB_TAG('L','R','C',' ')}, /* Northern Luri */
{"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */
{"lu", HB_TAG('L','U','B',' ')}, /* Luba-Katanga */
@ -475,6 +522,8 @@ static const LangTag ot_languages[] = {
{"mag", HB_TAG('M','A','G',' ')}, /* Magahi */
{"mai", HB_TAG('M','T','H',' ')}, /* Maithili */
{"mak", HB_TAG('M','K','R',' ')}, /* Makasar */
{"mal", HB_TAG('M','A','L',' ')}, /* Malayalam */
{"mam", HB_TAG('M','A','M',' ')}, /* Mam */
{"man", HB_TAG('M','N','K',' ')}, /* Manding/Mandingo [macrolanguage] */
{"mdc", HB_TAG('M','L','E',' ')}, /* Male (Papua New Guinea) */
{"mdf", HB_TAG('M','O','K',' ')}, /* Moksha */
@ -517,6 +566,7 @@ static const LangTag ot_languages[] = {
{"mww", HB_TAG('M','W','W',' ')}, /* Hmong Daw */
{"my", HB_TAG('B','R','M',' ')}, /* Burmese */
{"mym", HB_TAG('M','E','N',' ')}, /* Me'en */
{"myn", HB_TAG('M','Y','N',' ')}, /* Mayan */
{"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) */
{"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */
{"mzn", HB_TAG('M','Z','N',' ')}, /* Mazanderani */
@ -534,6 +584,7 @@ static const LangTag ot_languages[] = {
{"ng", HB_TAG('N','D','G',' ')}, /* Ndonga */
{"nga", HB_TAG('N','G','A',' ')}, /* Ngabaka */
{"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */
{"ngo", HB_TAG('S','X','T',' ')}, /* Sutu */
{"niu", HB_TAG('N','I','U',' ')}, /* Niuean */
{"niv", HB_TAG('G','I','L',' ')}, /* Gilyak */
{"nl", HB_TAG('N','L','D',' ')}, /* Dutch */
@ -554,13 +605,15 @@ static const LangTag ot_languages[] = {
{"oc", HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */
{"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] */
{"ojs", HB_TAG('O','C','R',' ')}, /* Oji-Cree */
{"okm", HB_TAG('K','O','H',' ')}, /* Korean Old Hangul */
{"om", HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */
{"or", HB_TAG('O','R','I',' ')}, /* Oriya */
{"os", HB_TAG('O','S','S',' ')}, /* Ossetian */
{"pa", HB_TAG('P','A','N',' ')}, /* Panjabi */
{"pag", HB_TAG('P','A','G',' ')}, /* Pangasinan */
{"pam", HB_TAG('P','A','M',' ')}, /* Kapampangan/Pampanga */
{"pap", HB_TAG('P','A','P',' ')}, /* Papiamento */
{"pap", HB_TAG('P','A','P','0')}, /* Papiamento */
{"pau", HB_TAG('P','A','U',' ')}, /* Palauan */
{"pcc", HB_TAG('P','C','C',' ')}, /* Bouyei */
{"pcd", HB_TAG('P','C','D',' ')}, /* Picard */
{"pce", HB_TAG('P','L','G',' ')}, /* [Ruching] Palaung */
@ -574,24 +627,34 @@ static const LangTag ot_languages[] = {
{"plp", HB_TAG('P','A','P',' ')}, /* Palpa */
{"pms", HB_TAG('P','M','S',' ')}, /* Piemontese */
{"pnb", HB_TAG('P','N','B',' ')}, /* Western Panjabi */
{"poh", HB_TAG('P','O','H',' ')}, /* Pocomchi */
{"pon", HB_TAG('P','O','N',' ')}, /* Pohnpeian */
{"prs", HB_TAG('D','R','I',' ')}, /* Afghan Persian/Dari */
{"ps", HB_TAG('P','A','S',' ')}, /* Pashto/Pushto [macrolanguage] */
{"pt", HB_TAG('P','T','G',' ')}, /* Portuguese */
{"pwo", HB_TAG('P','W','O',' ')}, /* Pwo Western Karen */
{"qu", HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */
{"quc", HB_TAG('Q','U','C',' ')}, /* K'iche'/Quiché */
{"quh", HB_TAG('Q','U','H',' ')}, /* Quechua (Bolivia) */
{"quz", HB_TAG('Q','U','Z',' ')}, /* Cusco Quechua */
{"qvi", HB_TAG('Q','V','I',' ')}, /* Quechua (Ecuador) */
{"qwh", HB_TAG('Q','W','H',' ')}, /* Quechua (Peru) */
{"raj", HB_TAG('R','A','J',' ')}, /* Rajasthani [macrolanguage] */
{"rar", HB_TAG('R','A','R',' ')}, /* Rarotongan */
{"rbb", HB_TAG('P','L','G',' ')}, /* Rumai Palaung */
{"rej", HB_TAG('R','E','J',' ')}, /* Rejang */
{"ria", HB_TAG('R','I','A',' ')}, /* Riang (India) */
{"rif", HB_TAG('R','I','F',' ')}, /* Tarifit */
{"ril", HB_TAG('R','I','A',' ')}, /* Riang (Myanmar) */
{"rit", HB_TAG('R','I','T',' ')}, /* Ritarungo */
{"rki", HB_TAG('A','R','K',' ')}, /* Rakhine */
{"rkw", HB_TAG('R','K','W',' ')}, /* Arakwal */
{"rm", HB_TAG('R','M','S',' ')}, /* Romansh */
{"rmy", HB_TAG('R','M','Y',' ')}, /* Vlax Romani */
{"rn", HB_TAG('R','U','N',' ')}, /* Rundi */
{"ro", HB_TAG('R','O','M',' ')}, /* Romanian */
{"rom", HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */
{"rtm", HB_TAG('R','T','M',' ')}, /* Rotuman */
{"ru", HB_TAG('R','U','S',' ')}, /* Russian */
{"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */
{"rup", HB_TAG('R','U','P',' ')}, /* Aromanian/Arumanian/Macedo-Romanian */
@ -599,10 +662,11 @@ static const LangTag ot_languages[] = {
{"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */
{"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */
{"sah", HB_TAG('Y','A','K',' ')}, /* Yakut */
{"sam", HB_TAG('P','A','A',' ')}, /* Palestinian Aramaic */
{"sas", HB_TAG('S','A','S',' ')}, /* Sasak */
{"sat", HB_TAG('S','A','T',' ')}, /* Santali */
{"sck", HB_TAG('S','A','D',' ')}, /* Sadri */
{"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */
{"sck", HB_TAG('S','A','D',' ')}, /* Sadri */
{"scn", HB_TAG('S','C','N',' ')}, /* Sicilian */
{"sco", HB_TAG('S','C','O',' ')}, /* Scots */
{"scs", HB_TAG('S','L','A',' ')}, /* [North] Slavey */
@ -615,6 +679,7 @@ static const LangTag ot_languages[] = {
{"sgs", HB_TAG('S','G','S',' ')}, /* Samogitian */
{"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage */
/*{"sgw", HB_TAG('S','G','W',' ')},*/ /* Sebat Bet Gurage (in SIL fonts) */
{"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */
{"shn", HB_TAG('S','H','N',' ')}, /* Shan */
{"si", HB_TAG('S','N','H',' ')}, /* Sinhala */
{"sid", HB_TAG('S','I','D',' ')}, /* Sidamo */
@ -627,7 +692,7 @@ static const LangTag ot_languages[] = {
{"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */
{"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */
{"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */
{"sn", HB_TAG('S','N','A',' ')}, /* Shona */
{"sn", HB_TAG('S','N','A','0')}, /* Shona */
{"snk", HB_TAG('S','N','K',' ')}, /* Soninke */
{"so", HB_TAG('S','M','L',' ')}, /* Somali */
{"sop", HB_TAG('S','O','P',' ')}, /* Songe */
@ -665,20 +730,24 @@ static const LangTag ot_languages[] = {
{"tiv", HB_TAG('T','I','V',' ')}, /* Tiv */
{"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */
{"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */
{"tmh", HB_TAG('t','m','h',' ')}, /* Tamashek [macrolanguage] */
{"tmh", HB_TAG('T','M','H',' ')}, /* Tamashek */
{"tn", HB_TAG('T','N','A',' ')}, /* Tswana */
{"to", HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) */
{"tod", HB_TAG('T','O','D','0')}, /* Toma */
{"toi", HB_TAG('T','N','G',' ')}, /* Tonga */
{"tpi", HB_TAG('T','P','I',' ')}, /* Tok Pisin */
{"tr", HB_TAG('T','R','K',' ')}, /* Turkish */
{"tru", HB_TAG('T','U','A',' ')}, /* Turoyo Aramaic */
{"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */
{"tt", HB_TAG('T','A','T',' ')}, /* Tatar */
{"tum", HB_TAG('T','U','M',' ')}, /* Tumbuka */
{"tvl", HB_TAG('T','V','L',' ')}, /* Tuvalu */
{"tw", HB_TAG('T','W','I',' ')}, /* Twi */
{"ty", HB_TAG('T','H','T',' ')}, /* Tahitian */
{"tyv", HB_TAG('T','U','V',' ')}, /* Tuvin */
{"tyz", HB_TAG('T','Y','Z',' ')}, /* Tày */
{"tzm", HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight */
{"tzo", HB_TAG('T','Z','O',' ')}, /* Tzotzil */
{"udm", HB_TAG('U','D','M',' ')}, /* Udmurt */
{"ug", HB_TAG('U','Y','G',' ')}, /* Uighur */
{"uk", HB_TAG('U','K','R',' ')}, /* Ukrainian */
@ -690,8 +759,8 @@ static const LangTag ot_languages[] = {
{"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek */
{"ve", HB_TAG('V','E','N',' ')}, /* Venda */
{"vec", HB_TAG('V','E','C',' ')}, /* Venetian */
{"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */
{"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */
{"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */
{"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */
{"vo", HB_TAG('V','O','L',' ')}, /* Volapük */
{"vro", HB_TAG('V','R','O',' ')}, /* Võro */
@ -700,72 +769,60 @@ static const LangTag ot_languages[] = {
{"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */
{"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */
{"wle", HB_TAG('S','I','G',' ')}, /* Wolane */
{"wo", HB_TAG('W','L','F',' ')}, /* Wolof */
{"wry", HB_TAG('M','A','W',' ')}, /* Merwari */
{"wtm", HB_TAG('W','T','M',' ')}, /* Mewati */
{"wo", HB_TAG('W','L','F',' ')}, /* Wolof */
{"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */
{"xan", HB_TAG('S','E','K',' ')}, /* Sekota */
{"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */
{"xjb", HB_TAG('X','J','B',' ')}, /* Minjangbal */
{"xog", HB_TAG('X','O','G',' ')}, /* Soga */
{"xom", HB_TAG('K','M','O',' ')}, /* Komo (Sudan) */
{"xpe", HB_TAG('X','P','E',' ')}, /* Kpelle (Liberia) */
{"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */
{"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) */
{"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat (Todo) */
{"yao", HB_TAG('Y','A','O',' ')}, /* Yao */
{"yap", HB_TAG('Y','A','P',' ')}, /* Yapese */
{"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
{"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */
{"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */
{"za", HB_TAG('Z','H','A',' ')}, /* Chuang/Zhuang [macrolanguage] */
{"zea", HB_TAG('Z','E','A',' ')}, /* Zeeuws */
{"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Morrocan Tamazigh */
{"zne", HB_TAG('Z','N','D',' ')}, /* Zande */
{"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */
{"zum", HB_TAG('L','R','C',' ')} /* Kumzari */
{"zum", HB_TAG('L','R','C',' ')}, /* Kumzari */
{"zza", HB_TAG('Z','Z','A',' ')}, /* Zazaki */
/* The corresponding languages IDs for the following IDs are unclear,
* overlap, or are architecturally weird. Needs more research. */
/*{"ahg/awn/xan?", HB_TAG('A','G','W',' ')},*/ /* Agaw */
/*{"gsw?/gsw-FR?", HB_TAG('A','L','S',' ')},*/ /* Alsatian */
/*{"chp", HB_TAG('S','A','Y',' ')},*/ /* Sayisi */
/*{"cwd", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */
/*{"emk", HB_TAG('E','M','K',' ')},*/ /* Eastern Maninkakan */
/*{"krc", HB_TAG('B','A','L',' ')},*/ /* Balkar */
/*{"??", HB_TAG('B','C','R',' ')},*/ /* Bible Cree */
/*{"zh?", HB_TAG('C','H','N',' ')},*/ /* Chinese (seen in Microsoft fonts) */
/*{"acf/gcf?", HB_TAG('F','A','N',' ')},*/ /* French Antillean */
/*{"enf?/yrk?", HB_TAG('F','N','E',' ')},*/ /* Forest Nenets */
/*{"fuf?", HB_TAG('F','T','A',' ')},*/ /* Futa */
/*{"ar-Syrc?", HB_TAG('G','A','R',' ')},*/ /* Garshuni */
/*{"cfm/rnl?", HB_TAG('H','A','L',' ')},*/ /* Halam */
/*{"ga-Latg?/Latg?", HB_TAG('I','R','T',' ')},*/ /* Irish Traditional */
/*{"hy?", HB_TAG('H','Y','E','0')},*/ /* Armenian East (ISO 639-3 hye according to Microsoft, but thats equivalent to ISO 639-1 hy) */
/*{"ga-Latg?/" HB_TAG('I','R','T',' ')},*/ /* Irish Traditional */
/*{"krc", HB_TAG('K','A','R',' ')},*/ /* Karachay */
/*{"alw?/ktb?", HB_TAG('K','E','B',' ')},*/ /* Kebena */
/*{"Geok", HB_TAG('K','G','E',' ')},*/ /* Khutsuri Georgian */
/*{"ka-Geok?", HB_TAG('K','G','E',' ')},*/ /* Khutsuri Georgian */
/*{"kca", HB_TAG('K','H','K',' ')},*/ /* Khanty-Kazim */
/*{"kca", HB_TAG('K','H','S',' ')},*/ /* Khanty-Shurishkar */
/*{"kca", HB_TAG('K','H','V',' ')},*/ /* Khanty-Vakhi */
/*{"guz?/kqs?/kss?", HB_TAG('K','I','S',' ')},*/ /* Kisii */
/*{"kfa/kfi?/kpb?/xua?/xuj?", HB_TAG('K','O','D',' ')},*/ /* Kodagu */
/*{"okm?/oko?", HB_TAG('K','O','H',' ')},*/ /* Korean Old Hangul */
/*{"kon?/ktu?/...", HB_TAG('K','O','N',' ')},*/ /* Kikongo */
/*{"kfx?", HB_TAG('K','U','L',' ')},*/ /* Kulvi */
/*{"??", HB_TAG('L','A','H',' ')},*/ /* Lahuli */
/*{"??", HB_TAG('L','C','R',' ')},*/ /* L-Cree */
/*{"kqs, kss", HB_TAG('K','I','S',' ')},*/ /* Kisii */
/*{"lua", HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */
/*{"mlq", HB_TAG('M','L','N',' ')},*/ /* Malinke */
/*{"nso", HB_TAG('N','S','O',' ')},*/ /* Sotho, Northern */
/*{"??", HB_TAG('M','A','L',' ')},*/ /* Malayalam Traditional */
/*{"mnk?/mlq?/...", HB_TAG('M','L','N',' ')},*/ /* Malinke */
/*{"??", HB_TAG('N','C','R',' ')},*/ /* N-Cree */
/*{"??", HB_TAG('N','H','C',' ')},*/ /* Norway House Cree */
/*{"jpa?/sam?", HB_TAG('P','A','A',' ')},*/ /* Palestinian Aramaic */
/*{"polyton", HB_TAG('P','G','R',' ')},*/ /* Polytonic Greek */
/*{"??", HB_TAG('Q','I','N',' ')},*/ /* Asho Chin */
/*{"??", HB_TAG('R','C','R',' ')},*/ /* R-Cree */
/*{"chp?", HB_TAG('S','A','Y',' ')},*/ /* Sayisi */
/*{"xan?", HB_TAG('S','E','K',' ')},*/ /* Sekota */
/*{"ngo?", HB_TAG('S','X','T',' ')},*/ /* Sutu */
/*{"??", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */
/*{"tnz?/tog?/toi?", HB_TAG('T','N','G',' ')},*/ /* Tonga */
/*{"enh?/yrk?", HB_TAG('T','N','E',' ')},*/ /* Tundra Nenets */
/*{"??", HB_TAG('W','C','R',' ')},*/ /* West-Cree */
/*{"cre?", HB_TAG('Y','C','R',' ')},*/ /* Y-Cree */
/*{"csw", HB_TAG('N','C','R',' ')},*/ /* N-Cree */
/*{"csw", HB_TAG('N','H','C',' ')},*/ /* Norway House Cree */
/*{"el-polyton", HB_TAG('P','G','R',' ')},*/ /* Polytonic Greek */
/*{"bgr, cnh, cnw, czt, sez, tcp, csy, ctd, flm, pck, tcz, zom, cmr, dao, hlt, cka, cnk, mrh, mwg, cbl, cnb, csh", HB_TAG('Q','I','N',' ')},*/ /* Chin */
/*{"??", HB_TAG('Y','I','C',' ')},*/ /* Yi Classic */
/*{"ii?/Yiii?", HB_TAG('Y','I','M',' ')},*/ /* Yi Modern */
/*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */
/*{"zh-Latn-pinyin", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */
};
typedef struct {
@ -928,4 +985,27 @@ hb_ot_tag_to_language (hb_tag_t tag)
}
}
#ifdef MAIN
static inline void
test_langs_sorted (void)
{
for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
{
int c = lang_compare_first_component (ot_languages[i-1].language, ot_languages[i].language);
if (c >= 0)
{
fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n",
i, ot_languages[i-1].language, c, ot_languages[i].language);
abort();
}
}
}
int
main (void)
{
test_langs_sorted ();
return 0;
}
#endif

View File

@ -39,18 +39,18 @@ HB_BEGIN_DECLS
#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T')
#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't')
void
HB_EXTERN void
hb_ot_tags_from_script (hb_script_t script,
hb_tag_t *script_tag_1,
hb_tag_t *script_tag_2);
hb_script_t
HB_EXTERN hb_script_t
hb_ot_tag_to_script (hb_tag_t tag);
hb_tag_t
HB_EXTERN hb_tag_t
hb_ot_tag_from_language (hb_language_t language);
hb_language_t
HB_EXTERN hb_language_t
hb_ot_tag_to_language (hb_tag_t tag);

View File

@ -83,7 +83,7 @@ extern "C" void hb_free_impl(void *ptr);
#define unlikely(expr) (expr)
#endif
#ifndef __GNUC__
#if !defined(__GNUC__) && !defined(__clang__)
#undef __attribute__
#define __attribute__(x)
#endif
@ -119,6 +119,36 @@ 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,
@ -139,6 +169,7 @@ extern "C" void hb_free_impl(void *ptr);
# if defined(_WIN32_WCE)
/* Some things not defined on Windows CE. */
# define strdup _strdup
# define vsnprintf _vsnprintf
# define getenv(Name) NULL
# if _WIN32_WCE < 0x800
# define setlocale(Category, Locale) "C"
@ -149,6 +180,9 @@ static int errno = 0; /* Use something better? */
# endif
# if defined(_MSC_VER) && _MSC_VER < 1900
# define snprintf _snprintf
# elif defined(_MSC_VER) && _MSC_VER >= 1900
# /* Covers VC++ Error for strdup being a deprecated POSIX name and to instead use _strdup instead */
# define strdup _strdup
# endif
#endif
@ -210,9 +244,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))
/* 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]))
template <unsigned int cond> class hb_assert_constant_t {};
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
#define _PASTE1(a,b) a##b
#define PASTE(a,b) _PASTE1(a,b)
@ -578,6 +612,15 @@ static inline unsigned char TOLOWER (unsigned char c)
/* Debug */
/* HB_NDEBUG disables some sanity checks that are very safe to disable and
* should be disabled in production systems. If NDEBUG is defined, enable
* HB_NDEBUG; but if it's desirable that normal assert()s (which are very
* light-weight) to be enabled, then HB_DEBUG can be defined to disable
* the costlier checks. */
#ifdef NDEBUG
#define HB_NDEBUG
#endif
#ifndef HB_DEBUG
#define HB_DEBUG 0
#endif
@ -861,6 +904,29 @@ 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... :(.
*
* For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
*/
#ifdef _MSC_VER
# pragma warning(disable:4200)
# pragma warning(disable:4800)
#endif
#define HB_MARK_AS_FLAG_T(T) \
extern "C++" { \
static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
}
/* 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)))
@ -949,5 +1015,7 @@ hb_options (void)
return _hb_options.opts;
}
/* Size signifying variable-sized array */
#define VAR 1
#endif /* HB_PRIVATE_HH */

View File

@ -44,109 +44,109 @@ HB_BEGIN_DECLS
typedef struct hb_set_t hb_set_t;
hb_set_t *
HB_EXTERN hb_set_t *
hb_set_create (void);
hb_set_t *
HB_EXTERN hb_set_t *
hb_set_get_empty (void);
hb_set_t *
HB_EXTERN hb_set_t *
hb_set_reference (hb_set_t *set);
void
HB_EXTERN void
hb_set_destroy (hb_set_t *set);
hb_bool_t
HB_EXTERN hb_bool_t
hb_set_set_user_data (hb_set_t *set,
hb_user_data_key_t *key,
void * data,
hb_destroy_func_t destroy,
hb_bool_t replace);
void *
HB_EXTERN void *
hb_set_get_user_data (hb_set_t *set,
hb_user_data_key_t *key);
/* Returns false if allocation has failed before */
hb_bool_t
HB_EXTERN hb_bool_t
hb_set_allocation_successful (const hb_set_t *set);
void
HB_EXTERN void
hb_set_clear (hb_set_t *set);
hb_bool_t
HB_EXTERN hb_bool_t
hb_set_is_empty (const hb_set_t *set);
hb_bool_t
HB_EXTERN hb_bool_t
hb_set_has (const hb_set_t *set,
hb_codepoint_t codepoint);
/* Right now limited to 16-bit integers. Eventually will do full codepoint range, sans -1
* which we will use as a sentinel. */
void
HB_EXTERN void
hb_set_add (hb_set_t *set,
hb_codepoint_t codepoint);
void
HB_EXTERN void
hb_set_add_range (hb_set_t *set,
hb_codepoint_t first,
hb_codepoint_t last);
void
HB_EXTERN void
hb_set_del (hb_set_t *set,
hb_codepoint_t codepoint);
void
HB_EXTERN void
hb_set_del_range (hb_set_t *set,
hb_codepoint_t first,
hb_codepoint_t last);
hb_bool_t
HB_EXTERN hb_bool_t
hb_set_is_equal (const hb_set_t *set,
const hb_set_t *other);
void
HB_EXTERN void
hb_set_set (hb_set_t *set,
const hb_set_t *other);
void
HB_EXTERN void
hb_set_union (hb_set_t *set,
const hb_set_t *other);
void
HB_EXTERN void
hb_set_intersect (hb_set_t *set,
const hb_set_t *other);
void
HB_EXTERN void
hb_set_subtract (hb_set_t *set,
const hb_set_t *other);
void
HB_EXTERN void
hb_set_symmetric_difference (hb_set_t *set,
const hb_set_t *other);
void
HB_EXTERN void
hb_set_invert (hb_set_t *set);
unsigned int
HB_EXTERN unsigned int
hb_set_get_population (const hb_set_t *set);
/* Returns -1 if set empty. */
hb_codepoint_t
HB_EXTERN hb_codepoint_t
hb_set_get_min (const hb_set_t *set);
/* Returns -1 if set empty. */
hb_codepoint_t
HB_EXTERN hb_codepoint_t
hb_set_get_max (const hb_set_t *set);
/* Pass -1 in to get started. */
hb_bool_t
HB_EXTERN hb_bool_t
hb_set_next (const hb_set_t *set,
hb_codepoint_t *codepoint);
/* Pass -1 for first and last to get started. */
hb_bool_t
HB_EXTERN hb_bool_t
hb_set_next_range (const hb_set_t *set,
hb_codepoint_t *first,
hb_codepoint_t *last);

View File

@ -38,49 +38,49 @@ HB_BEGIN_DECLS
typedef struct hb_shape_plan_t hb_shape_plan_t;
hb_shape_plan_t *
HB_EXTERN hb_shape_plan_t *
hb_shape_plan_create (hb_face_t *face,
const hb_segment_properties_t *props,
const hb_feature_t *user_features,
unsigned int num_user_features,
const char * const *shaper_list);
hb_shape_plan_t *
HB_EXTERN hb_shape_plan_t *
hb_shape_plan_create_cached (hb_face_t *face,
const hb_segment_properties_t *props,
const hb_feature_t *user_features,
unsigned int num_user_features,
const char * const *shaper_list);
hb_shape_plan_t *
HB_EXTERN hb_shape_plan_t *
hb_shape_plan_get_empty (void);
hb_shape_plan_t *
HB_EXTERN hb_shape_plan_t *
hb_shape_plan_reference (hb_shape_plan_t *shape_plan);
void
HB_EXTERN void
hb_shape_plan_destroy (hb_shape_plan_t *shape_plan);
hb_bool_t
HB_EXTERN hb_bool_t
hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
hb_user_data_key_t *key,
void * data,
hb_destroy_func_t destroy,
hb_bool_t replace);
void *
HB_EXTERN void *
hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
hb_user_data_key_t *key);
hb_bool_t
HB_EXTERN hb_bool_t
hb_shape_plan_execute (hb_shape_plan_t *shape_plan,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features);
const char *
HB_EXTERN const char *
hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan);

View File

@ -210,13 +210,15 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
/**
* hb_feature_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
* @len: length of @str, or -1 if string is nul-terminated
* @len: length of @str, or -1 if string is %NULL terminated
* @feature: (out): the #hb_feature_t to initialize with the parsed values
*
* Parses a string into a #hb_feature_t. If @len is -1 then @str is
* %NULL-terminated.
* Parses a string into a #hb_feature_t.
*
* Return value: %TRUE if @str is successfully parsed, %FALSE otherwise
* TODO: document the syntax here.
*
* Return value:
* %true if @str is successfully parsed, %false otherwise.
*
* Since: 0.9.5
**/
@ -392,8 +394,6 @@ hb_shape_full (hb_font_t *font,
* positioned glyphs. If @features is not %NULL, it will be used to control the
* features applied during shaping.
*
* Return value: %FALSE if all shapers failed, %TRUE otherwise
*
* Since: 0.9.2
**/
void

View File

@ -47,29 +47,29 @@ typedef struct hb_feature_t {
unsigned int end;
} hb_feature_t;
hb_bool_t
HB_EXTERN hb_bool_t
hb_feature_from_string (const char *str, int len,
hb_feature_t *feature);
void
HB_EXTERN void
hb_feature_to_string (hb_feature_t *feature,
char *buf, unsigned int size);
void
HB_EXTERN void
hb_shape (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features);
hb_bool_t
HB_EXTERN hb_bool_t
hb_shape_full (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features,
const char * const *shaper_list);
const char **
HB_EXTERN const char **
hb_shape_list_shapers (void);

View File

@ -46,6 +46,9 @@ HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
#ifdef HAVE_UNISCRIBE
HB_SHAPER_IMPLEMENT (uniscribe)
#endif
#ifdef HAVE_DIRECTWRITE
HB_SHAPER_IMPLEMENT (directwrite)
#endif
#ifdef HAVE_CORETEXT
HB_SHAPER_IMPLEMENT (coretext)
#endif

View File

@ -154,6 +154,12 @@ static const hb_script_t ucdn_script_translate[] =
HB_SCRIPT_MULTANI,
HB_SCRIPT_OLD_HUNGARIAN,
HB_SCRIPT_SIGNWRITING,
HB_SCRIPT_ADLAM,
HB_SCRIPT_BHAIKSUKI,
HB_SCRIPT_MARCHEN,
HB_SCRIPT_NEWA,
HB_SCRIPT_OSAGE,
HB_SCRIPT_TANGUT,
};
static hb_unicode_combining_class_t

View File

@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ucdn.h"
typedef struct {
@ -24,14 +25,19 @@ typedef struct {
unsigned char bidi_class;
unsigned char mirrored;
unsigned char east_asian_width;
unsigned char normalization_check;
unsigned char script;
unsigned char linebreak_class;
} UCDRecord;
typedef struct {
unsigned short from, to;
} MirrorPair;
typedef struct {
unsigned short from, to;
unsigned char type;
} BracketPair;
typedef struct {
unsigned int start;
short count, index;
@ -108,6 +114,24 @@ static int compare_mp(const void *a, const void *b)
return mpa->from - mpb->from;
}
static int compare_bp(const void *a, const void *b)
{
BracketPair *bpa = (BracketPair *)a;
BracketPair *bpb = (BracketPair *)b;
return bpa->from - bpb->from;
}
static BracketPair *search_bp(uint32_t code)
{
BracketPair bp = {0,0,2};
BracketPair *res;
bp.from = code;
res = bsearch(&bp, bracket_pairs, BIDI_BRACKET_LEN, sizeof(BracketPair),
compare_bp);
return res;
}
static int hangul_pair_decompose(uint32_t code, uint32_t *a, uint32_t *b)
{
int si = code - SBASE;
@ -199,6 +223,42 @@ int ucdn_get_script(uint32_t code)
return get_ucd_record(code)->script;
}
int ucdn_get_linebreak_class(uint32_t code)
{
return get_ucd_record(code)->linebreak_class;
}
int ucdn_get_resolved_linebreak_class(uint32_t code)
{
const UCDRecord *record = get_ucd_record(code);
switch (record->linebreak_class)
{
case UCDN_LINEBREAK_CLASS_AI:
case UCDN_LINEBREAK_CLASS_SG:
case UCDN_LINEBREAK_CLASS_XX:
return UCDN_LINEBREAK_CLASS_AL;
case UCDN_LINEBREAK_CLASS_SA:
if (record->category == UCDN_GENERAL_CATEGORY_MC ||
record->category == UCDN_GENERAL_CATEGORY_MN)
return UCDN_LINEBREAK_CLASS_CM;
return UCDN_LINEBREAK_CLASS_AL;
case UCDN_LINEBREAK_CLASS_CJ:
return UCDN_LINEBREAK_CLASS_NS;
case UCDN_LINEBREAK_CLASS_CB:
return UCDN_LINEBREAK_CLASS_B2;
case UCDN_LINEBREAK_CLASS_NL:
return UCDN_LINEBREAK_CLASS_BK;
default:
return record->linebreak_class;
}
}
uint32_t ucdn_mirror(uint32_t code)
{
MirrorPair mp = {0};
@ -217,6 +277,24 @@ uint32_t ucdn_mirror(uint32_t code)
return res->to;
}
uint32_t ucdn_paired_bracket(uint32_t code)
{
BracketPair *res = search_bp(code);
if (res == NULL)
return code;
else
return res->to;
}
int ucdn_paired_bracket_type(uint32_t code)
{
BracketPair *res = search_bp(code);
if (res == NULL)
return UCDN_BIDI_PAIRED_BRACKET_TYPE_NONE;
else
return res->type;
}
int ucdn_decompose(uint32_t code, uint32_t *a, uint32_t *b)
{
const unsigned short *rec;

View File

@ -17,6 +17,8 @@
#ifndef UCDN_H
#define UCDN_H
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
# define HB_BEGIN_VISIBILITY _Pragma ("GCC visibility push(hidden)")
# define HB_END_VISIBILITY _Pragma ("GCC visibility pop")
@ -58,6 +60,7 @@ typedef unsigned __int64 uint64_t;
#endif
#define UCDN_EAST_ASIAN_F 0
#define UCDN_EAST_ASIAN_H 1
#define UCDN_EAST_ASIAN_W 2
@ -197,6 +200,53 @@ typedef unsigned __int64 uint64_t;
#define UCDN_SCRIPT_MULTANI 129
#define UCDN_SCRIPT_OLD_HUNGARIAN 130
#define UCDN_SCRIPT_SIGNWRITING 131
#define UCDN_SCRIPT_ADLAM 132
#define UCDN_SCRIPT_BHAIKSUKI 133
#define UCDN_SCRIPT_MARCHEN 134
#define UCDN_SCRIPT_NEWA 135
#define UCDN_SCRIPT_OSAGE 136
#define UCDN_SCRIPT_TANGUT 137
#define UCDN_LINEBREAK_CLASS_OP 0
#define UCDN_LINEBREAK_CLASS_CL 1
#define UCDN_LINEBREAK_CLASS_CP 2
#define UCDN_LINEBREAK_CLASS_QU 3
#define UCDN_LINEBREAK_CLASS_GL 4
#define UCDN_LINEBREAK_CLASS_NS 5
#define UCDN_LINEBREAK_CLASS_EX 6
#define UCDN_LINEBREAK_CLASS_SY 7
#define UCDN_LINEBREAK_CLASS_IS 8
#define UCDN_LINEBREAK_CLASS_PR 9
#define UCDN_LINEBREAK_CLASS_PO 10
#define UCDN_LINEBREAK_CLASS_NU 11
#define UCDN_LINEBREAK_CLASS_AL 12
#define UCDN_LINEBREAK_CLASS_HL 13
#define UCDN_LINEBREAK_CLASS_ID 14
#define UCDN_LINEBREAK_CLASS_IN 15
#define UCDN_LINEBREAK_CLASS_HY 16
#define UCDN_LINEBREAK_CLASS_BA 17
#define UCDN_LINEBREAK_CLASS_BB 18
#define UCDN_LINEBREAK_CLASS_B2 19
#define UCDN_LINEBREAK_CLASS_ZW 20
#define UCDN_LINEBREAK_CLASS_CM 21
#define UCDN_LINEBREAK_CLASS_WJ 22
#define UCDN_LINEBREAK_CLASS_H2 23
#define UCDN_LINEBREAK_CLASS_H3 24
#define UCDN_LINEBREAK_CLASS_JL 25
#define UCDN_LINEBREAK_CLASS_JV 26
#define UCDN_LINEBREAK_CLASS_JT 27
#define UCDN_LINEBREAK_CLASS_RI 28
#define UCDN_LINEBREAK_CLASS_AI 29
#define UCDN_LINEBREAK_CLASS_BK 30
#define UCDN_LINEBREAK_CLASS_CB 31
#define UCDN_LINEBREAK_CLASS_CJ 32
#define UCDN_LINEBREAK_CLASS_CR 33
#define UCDN_LINEBREAK_CLASS_LF 34
#define UCDN_LINEBREAK_CLASS_NL 35
#define UCDN_LINEBREAK_CLASS_SA 36
#define UCDN_LINEBREAK_CLASS_SG 37
#define UCDN_LINEBREAK_CLASS_SP 38
#define UCDN_LINEBREAK_CLASS_XX 39
#define UCDN_GENERAL_CATEGORY_CC 0
#define UCDN_GENERAL_CATEGORY_CF 1
@ -253,6 +303,10 @@ typedef unsigned __int64 uint64_t;
#define UCDN_BIDI_CLASS_FSI 21
#define UCDN_BIDI_CLASS_PDI 22
#define UCDN_BIDI_PAIRED_BRACKET_TYPE_OPEN 0
#define UCDN_BIDI_PAIRED_BRACKET_TYPE_CLOSE 1
#define UCDN_BIDI_PAIRED_BRACKET_TYPE_NONE 2
/**
* Return version of the Unicode database.
*
@ -301,6 +355,27 @@ int ucdn_get_bidi_class(uint32_t code);
*/
int ucdn_get_script(uint32_t code);
/**
* Get unresolved linebreak class of a codepoint. This does not take
* rule LB1 of UAX#14 into account. See ucdn_get_resolved_linebreak_class()
* for resolved linebreak classes.
*
* @param code Unicode codepoint
* @return value according to UCDN_LINEBREAK_* and as defined in UAX#14.
*/
int ucdn_get_linebreak_class(uint32_t code);
/**
* Get resolved linebreak class of a codepoint. This resolves characters
* in the AI, SG, XX, SA and CJ classes according to rule LB1 of UAX#14.
* In addition the CB class is resolved as the equivalent B2 class and
* the NL class is resolved as the equivalent BK class.
*
* @param code Unicode codepoint
* @return value according to UCDN_LINEBREAK_* and as defined in UAX#14.
*/
int ucdn_get_resolved_linebreak_class(uint32_t code);
/**
* Check if codepoint can be mirrored.
*
@ -318,6 +393,25 @@ int ucdn_get_mirrored(uint32_t code);
*/
uint32_t ucdn_mirror(uint32_t code);
/**
* Get paired bracket for a codepoint.
*
* @param code Unicode codepoint
* @return paired bracket codepoint or the original codepoint if no
* paired bracket character exists
*/
uint32_t ucdn_paired_bracket(uint32_t code);
/**
* Get paired bracket type for a codepoint.
*
* @param code Unicode codepoint
* @return value according to UCDN_BIDI_PAIRED_BRACKET_TYPE_* and as defined
* in UAX#9.
*
*/
int ucdn_paired_bracket_type(uint32_t code);
/**
* Pairwise canonical decomposition of a codepoint. This includes
* Hangul Jamo decomposition (see chapter 3.12 of the Unicode core
@ -359,6 +453,8 @@ int ucdn_compat_decompose(uint32_t code, uint32_t *decomposed);
*/
int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b);
HB_END_HEADER
#ifdef __cplusplus
}
#endif
#endif

View File

@ -115,6 +115,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
/* XXX This hack belongs to the Tibetan shaper:
* Reorder PADMA to ensure it comes after any vowel marks. */
if (unlikely (unicode == 0x0FC6u)) return 254;
/* Reorder TSA -PHRU to reorder before U+0F74 */
if (unlikely (unicode == 0x0F39u)) return 127;
return _hb_modified_combining_class[combining_class (unicode)];
}
@ -180,8 +182,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
case 0x17: return hb_in_range (ch, 0x17B4u, 0x17B5u);
case 0x18: return hb_in_range (ch, 0x180Bu, 0x180Eu);
case 0x20: return hb_in_ranges (ch, 0x200Bu, 0x200Fu,
0x202Au, 0x202Eu,
0x2060u, 0x206Fu);
0x202Au, 0x202Eu,
0x2060u, 0x206Fu);
case 0xFE: return hb_in_range (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
case 0xFF: return hb_in_range (ch, 0xFFF0u, 0xFFF8u);
default: return false;
@ -199,6 +201,50 @@ 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; /* U+1680 OGHAM SPACE MARK */
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;
@ -299,10 +345,12 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
/* Tibetan */
/* Tibetan
* Modify U+0F74 (ccc=132) to reorder before ccc=130 marks.
*/
#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
#define HB_MODIFIED_COMBINING_CLASS_CCC130 130 /* sign i */
#define HB_MODIFIED_COMBINING_CLASS_CCC132 132 /* sign u */
#define HB_MODIFIED_COMBINING_CLASS_CCC132 128 /* sign u */
/* Misc */
@ -313,5 +361,10 @@ 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_OR_MODIFIER_SYMBOL(gen_cat) \
(FLAG_SAFE (gen_cat) & \
(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL)))
#endif /* HB_UNICODE_PRIVATE_HH */

View File

@ -174,23 +174,23 @@ typedef struct hb_unicode_funcs_t hb_unicode_funcs_t;
/*
* just give me the best implementation you've got there.
*/
hb_unicode_funcs_t *
HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_get_default (void);
hb_unicode_funcs_t *
HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_create (hb_unicode_funcs_t *parent);
hb_unicode_funcs_t *
HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_get_empty (void);
hb_unicode_funcs_t *
HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs);
void
HB_EXTERN void
hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs);
hb_bool_t
HB_EXTERN hb_bool_t
hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
hb_user_data_key_t *key,
void * data,
@ -198,18 +198,18 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
hb_bool_t replace);
void *
HB_EXTERN void *
hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
hb_user_data_key_t *key);
void
HB_EXTERN void
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);
hb_bool_t
HB_EXTERN hb_bool_t
hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs);
hb_unicode_funcs_t *
HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs);
@ -285,7 +285,7 @@ typedef unsigned int (*hb_unicode_decompose_compatibility_fun
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_combining_class_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -301,7 +301,7 @@ hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_eastasian_width_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -317,7 +317,7 @@ hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_general_category_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -333,7 +333,7 @@ hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_mirroring_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -349,7 +349,7 @@ hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_script_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -365,7 +365,7 @@ hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_compose_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -381,7 +381,7 @@ hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_decompose_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -397,7 +397,7 @@ hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
*
* Since: 0.9.2
**/
void
HB_EXTERN void
hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_decompose_compatibility_func_t func,
void *user_data, hb_destroy_func_t destroy);
@ -405,62 +405,63 @@ hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
/* accessors */
/**
* hb_unicode_combining_class:
*
* Since: 0.9.2
**/
hb_unicode_combining_class_t
HB_EXTERN hb_unicode_combining_class_t
hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* hb_unicode_eastasian_width:
*
* Since: 0.9.2
**/
unsigned int
HB_EXTERN unsigned int
hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* hb_unicode_general_category:
*
* Since: 0.9.2
**/
hb_unicode_general_category_t
HB_EXTERN hb_unicode_general_category_t
hb_unicode_general_category (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* hb_unicode_mirroring:
*
* Since: 0.9.2
**/
hb_codepoint_t
HB_EXTERN hb_codepoint_t
hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* hb_unicode_script:
*
* Since: 0.9.2
**/
hb_script_t
HB_EXTERN hb_script_t
hb_unicode_script (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
/**
* Since: 0.9.2
**/
hb_bool_t
HB_EXTERN hb_bool_t
hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t a,
hb_codepoint_t b,
hb_codepoint_t *ab);
/**
* Since: 0.9.2
**/
hb_bool_t
HB_EXTERN hb_bool_t
hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t ab,
hb_codepoint_t *a,
hb_codepoint_t *b);
/**
* Since: 0.9.2
**/
unsigned int
HB_EXTERN unsigned int
hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t u,
hb_codepoint_t *decomposed);

View File

@ -146,11 +146,11 @@ struct hb_utf16_t
return text;
}
if (likely (hb_in_range (c, 0xD800u, 0xDBFFu)))
if (likely (c <= 0xDBFFu && text < end))
{
/* High-surrogate in c */
hb_codepoint_t l;
if (text < end && ((l = *text), likely (hb_in_range (l, 0xDC00u, 0xDFFFu))))
hb_codepoint_t l = *text;
if (likely (hb_in_range (l, 0xDC00u, 0xDFFFu)))
{
/* Low-surrogate in l */
*unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
@ -170,8 +170,7 @@ struct hb_utf16_t
hb_codepoint_t *unicode,
hb_codepoint_t replacement)
{
const uint16_t *end = text--;
hb_codepoint_t c = *text;
hb_codepoint_t c = *--text;
if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu)))
{
@ -179,14 +178,22 @@ struct hb_utf16_t
return text;
}
if (likely (start < text && hb_in_range (c, 0xDC00u, 0xDFFFu)))
text--;
if (likely (next (text, end, unicode, replacement) == end))
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;
}
}
/* Lonely / out-of-order surrogate. */
*unicode = replacement;
return end - 1;
return text;
}
@ -211,14 +218,9 @@ struct hb_utf32_t
hb_codepoint_t *unicode,
hb_codepoint_t 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;
hb_codepoint_t c = *unicode = *text++;
if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
*unicode = replacement;
return text;
}
@ -228,8 +230,10 @@ struct hb_utf32_t
hb_codepoint_t *unicode,
hb_codepoint_t replacement)
{
next (text - 1, text, unicode, replacement);
return text - 1;
hb_codepoint_t c = *unicode = *--text;
if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
*unicode = replacement;
return text;
}
static inline unsigned int

View File

@ -37,25 +37,25 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 0
#define HB_VERSION_MICRO 5
#define HB_VERSION_MINOR 3
#define HB_VERSION_MICRO 0
#define HB_VERSION_STRING "1.0.5"
#define HB_VERSION_STRING "1.3.0"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \
HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
void
HB_EXTERN void
hb_version (unsigned int *major,
unsigned int *minor,
unsigned int *micro);
const char *
HB_EXTERN const char *
hb_version_string (void);
hb_bool_t
HB_EXTERN hb_bool_t
hb_version_atleast (unsigned int major,
unsigned int minor,
unsigned int micro);

View File

@ -28,6 +28,10 @@
#define HB_H
#define HB_H_IN
#ifndef HB_EXTERN
#define HB_EXTERN extern
#endif
#include "hb-blob.h"
#include "hb-buffer.h"
#include "hb-common.h"