bug 841313 - update harfbuzz to upstream commit a0cb9f3... (v0.9.12+) to pick up Myanmar/SEAsian shapers and Indic fixes. r=jdaggett

This commit is contained in:
Jonathan Kew 2013-02-15 10:37:41 +00:00
Родитель fda9efaa98
Коммит 068fb3003a
37 изменённых файлов: 3275 добавлений и 425 удалений

Просмотреть файл

@ -63,6 +63,8 @@ HBHEADERS = \
hb-shape.h \
hb-shape-plan.h \
hb-unicode.h \
$(NULL)
HBNODISTHEADERS = \
hb-version.h \
$(NULL)
@ -85,7 +87,11 @@ HBSOURCES += \
hb-ot-shape-complex-indic.cc \
hb-ot-shape-complex-indic-machine.hh \
hb-ot-shape-complex-indic-private.hh \
hb-ot-shape-complex-indic-table.hh \
hb-ot-shape-complex-indic-table.cc \
hb-ot-shape-complex-myanmar.cc \
hb-ot-shape-complex-myanmar-machine.hh \
hb-ot-shape-complex-sea.cc \
hb-ot-shape-complex-sea-machine.hh \
hb-ot-shape-complex-thai.cc \
hb-ot-shape-complex-private.hh \
hb-ot-shape-normalize-private.hh \
@ -198,22 +204,26 @@ else
if HAVE_ICU
libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
else
# Use a C linker, not C++; Don't link to libstdc++
# Use a C linker for GCC, not C++; Don't link to libstdc++
if HAVE_GCC
libharfbuzz_la_LINK = $(LINK) $(libharfbuzz_la_LDFLAGS)
else
libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
endif
endif
endif
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) $(HBNODISTHEADERS)
nodist_libharfbuzz_la_SOURCES = $(nodist_HBSOURCES)
libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
libharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) $(export_symbols) -no-undefined
libharfbuzz_la_LIBADD = $(HBLIBS)
EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
pkginclude_HEADERS = $(HBHEADERS)
nodist_pkginclude_HEADERS = hb-version.h
nodist_pkginclude_HEADERS = $(HBNODISTHEADERS)
CLEANFILES += harfbuzz.def
harfbuzz.def: $(HBHEADERS)
harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
$(AM_V_GEN) (echo EXPORTS; \
(cat $^ || echo 'hb_ERROR ()' ) | \
$(EGREP) '^hb_.* \(' | \
@ -234,9 +244,9 @@ EXTRA_DIST += $(GENERATORS)
unicode-tables: arabic-table indic-table
indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.hh.tmp && \
mv hb-ot-shape-complex-indic-table.hh.tmp $(srcdir)/hb-ot-shape-complex-indic-table.hh || \
($(RM) hb-ot-shape-complex-indic-table.hh.tmp; false)
$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-indic-table.cc.tmp && \
mv hb-ot-shape-complex-indic-table.cc.tmp $(srcdir)/hb-ot-shape-complex-indic-table.cc || \
($(RM) hb-ot-shape-complex-indic-table.cc.tmp; false)
arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt
$(AM_V_GEN) $(builddir)/$^ > hb-ot-shape-complex-arabic-table.hh.tmp && \
@ -246,8 +256,17 @@ arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt
.PHONY: unicode-tables arabic-table indic-table
EXTRA_DIST += hb-ot-shape-complex-indic-machine.rl
$(srcdir)/hb-ot-shape-complex-indic-machine.hh: hb-ot-shape-complex-indic-machine.rl
BUILT_SOURCES += \
hb-ot-shape-complex-indic-machine.hh \
hb-ot-shape-complex-myanmar-machine.hh \
hb-ot-shape-complex-sea-machine.hh \
$(NULL)
EXTRA_DIST += \
hb-ot-shape-complex-indic-machine.rl \
hb-ot-shape-complex-myanmar-machine.rl \
hb-ot-shape-complex-sea-machine.rl \
$(NULL)
%.hh: %.rl
$(AM_V_GEN)$(top_srcdir)/missing --run ragel -e -F1 -o "$@.tmp" "$<" && \
mv "$@.tmp" "$@" || ( $(RM) "$@.tmp" && false )
@ -273,9 +292,8 @@ test_size_params_LDADD = libharfbuzz.la $(HBLIBS)
dist_check_SCRIPTS = \
check-c-linkage-decls.sh \
check-header-guards.sh \
check-exported-symbols.sh \
check-includes.sh \
check-internal-symbols.sh \
check-symbols.sh \
$(NULL)
if HAVE_ICU
@ -293,7 +311,7 @@ TESTS_ENVIRONMENT = \
srcdir="$(srcdir)" \
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
HBSOURCES="$(HBSOURCES)" \
HBHEADERS="$(HBHEADERS)" \
HBHEADERS="$(HBHEADERS) $(HBNODISTHEADERS)" \
$(NULL)
#-include $(INTROSPECTION_MAKEFILE)
@ -307,7 +325,7 @@ TESTS_ENVIRONMENT = \
#hb_1_0_gir_INCLUDES = GObject-2.0
#hb_1_0_gir_CFLAGS = $(INCLUDES) $(HBCFLAGS) -DHB_H -DHB_H_IN -DHB_OT_H -DHB_OT_H_IN
#hb_1_0_gir_LIBS = libharfbuzz.la
#hb_1_0_gir_FILES = $(HBHEADERS)
#hb_1_0_gir_FILES = $(HBHEADERS) $(HBNODISTHEADERS)
#
#girdir = $(datadir)/gir-1.0
#gir_DATA = $(INTROSPECTION_GIRS)

Просмотреть файл

@ -49,6 +49,9 @@ CPPSRCS = \
hb-ot-shape-complex-arabic.cc \
hb-ot-shape-complex-default.cc \
hb-ot-shape-complex-indic.cc \
hb-ot-shape-complex-indic-table.cc \
hb-ot-shape-complex-myanmar.cc \
hb-ot-shape-complex-sea.cc \
hb-ot-shape-complex-thai.cc \
hb-ot-shape-fallback.cc \
hb-ot-shape-normalize.cc \

Просмотреть файл

@ -75,8 +75,7 @@ for h in headers:
print " * %s" % (l.strip())
print " */"
print
print "#ifndef HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH"
print "#define HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH"
print '#include "hb-ot-shape-complex-indic-private.hh"'
print
# Shorten values
@ -182,8 +181,8 @@ print
occupancy = used * 100. / total
print "}; /* Table occupancy: %d%% */" % occupancy
print
print "static INDIC_TABLE_ELEMENT_TYPE"
print "get_indic_categories (hb_codepoint_t u)"
print "INDIC_TABLE_ELEMENT_TYPE"
print "hb_indic_get_categories (hb_codepoint_t u)"
print "{"
for (start,end) in zip (starts, ends):
offset = "indic_offset_0x%04x" % start
@ -202,8 +201,6 @@ for i in range (2):
print "#undef %s_%s" % \
(what_short[i], short[i][v])
print
print "#endif /* HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH */"
print
print "/* == End of generated table == */"
# Maintain at least 30% occupancy in the table */

Просмотреть файл

@ -42,7 +42,7 @@
#if 0
#elif !defined(HB_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -99,6 +99,18 @@ typedef int hb_atomic_int_t;
#define hb_atomic_ptr_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
#include <atomic.h>
#include <mbarrier.h>
typedef unsigned int hb_atomic_int_t;
#define hb_atomic_int_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
#define hb_atomic_ptr_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P))
#define hb_atomic_ptr_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
#elif !defined(HB_NO_MT)
#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */

Просмотреть файл

@ -24,6 +24,9 @@
* Red Hat Author(s): Behdad Esfahbod
*/
/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
#define _POSIX_C_SOURCE 199309L
#include "hb-private.hh"
#include "hb-blob.h"

Просмотреть файл

@ -790,7 +790,7 @@ hb_buffer_reset (hb_buffer_t *buffer)
}
void
hb_buffer_clear (hb_buffer_t *buffer)
hb_buffer_clear_contents (hb_buffer_t *buffer)
{
buffer->clear ();
}

Просмотреть файл

@ -193,7 +193,7 @@ hb_buffer_reset (hb_buffer_t *buffer);
/* Like reset, but does NOT clear unicode_funcs. */
void
hb_buffer_clear (hb_buffer_t *buffer);
hb_buffer_clear_contents (hb_buffer_t *buffer);
/* Returns false if allocation failed */
hb_bool_t

Просмотреть файл

@ -36,6 +36,24 @@
#include <locale.h>
/* hb_options_t */
hb_options_union_t _hb_options;
void
_hb_options_init (void)
{
hb_options_union_t u;
u.i = 0;
u.opts.initialized = 1;
char *c = getenv ("HB_OPTIONS");
u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
/* This is idempotent and threadsafe. */
_hb_options = u;
}
/* hb_tag_t */
@ -177,7 +195,7 @@ struct hb_language_item_t {
static hb_language_item_t *langs;
static
static inline
void free_langs (void)
{
while (langs) {
@ -414,5 +432,3 @@ hb_version_check (unsigned int major,
{
return HB_VERSION_CHECK (major, minor, micro);
}

Просмотреть файл

@ -403,7 +403,7 @@ hb_ft_font_create (FT_Face ft_face,
static FT_Library ft_library;
static
static inline
void free_ft_library (void)
{
FT_Done_FreeType (ft_library);

Просмотреть файл

@ -42,7 +42,7 @@
#if 0
#elif !defined(HB_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

Просмотреть файл

@ -616,10 +616,20 @@ struct Index : USHORT {
DEFINE_NULL_DATA (Index, "\xff\xff");
/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
typedef USHORT Offset;
struct Offset : USHORT
{
inline bool is_null (void) const { return 0 == *this; }
public:
DEFINE_SIZE_STATIC (2);
};
/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
typedef ULONG LongOffset;
struct LongOffset : ULONG
{
inline bool is_null (void) const { return 0 == *this; }
public:
DEFINE_SIZE_STATIC (4);
};
/* CheckSum */

Просмотреть файл

@ -336,8 +336,10 @@ struct Anchor
struct AnchorMatrix
{
inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols) const {
inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
*found = false;
if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
*found = !matrix[row * cols + col].is_null ();
return this+matrix[row * cols + col];
}
@ -392,7 +394,11 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
unsigned int mark_class = record.klass;
const Anchor& mark_anchor = this + record.markAnchor;
const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count);
bool found;
const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
/* If this subtable doesn't have an anchor for this base and this class,
* return false such that the subsequent subtables have a chance at it. */
if (unlikely (!found)) return TRACE_RETURN (false);
hb_position_t mark_x, mark_y, base_x, base_y;
@ -652,7 +658,7 @@ struct PairPosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@ -724,7 +730,7 @@ struct PairPosFormat2
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY (this);
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@ -874,7 +880,7 @@ struct CursivePosFormat1
/* We don't handle mark glyphs here. */
if (c->property & HB_OT_LAYOUT_GLYPH_PROPS_MARK) return TRACE_RETURN (false);
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (c->buffer->cur().codepoint)];
@ -1023,7 +1029,7 @@ struct MarkBasePosFormat1
/* now we search backwards for a non-mark glyph */
unsigned int property;
hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
do {
if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RETURN (false);
/* We only want to attach to the first of a MultipleSubst sequence. Reject others. */
@ -1127,7 +1133,7 @@ struct MarkLigPosFormat1
/* now we search backwards for a non-mark glyph */
unsigned int property;
hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RETURN (false);
/* The following assertion is too strong, so we've disabled it. */
@ -1243,8 +1249,8 @@ struct MarkMarkPosFormat1
/* now we search backwards for a suitable mark glyph until a non-mark glyph */
unsigned int property;
hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
if (!skippy_iter.prev (&property)) return TRACE_RETURN (false);
hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
if (!skippy_iter.prev (&property, c->lookup_props & ~LookupFlag::IgnoreFlags)) return TRACE_RETURN (false);
if (!(property & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) return TRACE_RETURN (false);
@ -1522,7 +1528,7 @@ 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, hb_bool_t zero_width_attahced_marks);
static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer);
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
@ -1555,17 +1561,13 @@ fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction
}
static void
fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, hb_bool_t zero_width_attached_marks)
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();
if (zero_width_attached_marks) {
pos[i].x_advance = 0;
pos[i].y_advance = 0;
}
pos[i].x_offset += pos[j].x_offset;
pos[i].y_offset += pos[j].y_offset;
@ -1592,7 +1594,7 @@ GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
}
void
GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer, hb_bool_t zero_width_attached_marks)
GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
{
unsigned int len;
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
@ -1604,7 +1606,7 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer, hb_bool_t
/* Handle attachments */
for (unsigned int i = 0; i < len; i++)
fix_mark_attachment (pos, i, direction, zero_width_attached_marks);
fix_mark_attachment (pos, i, direction);
HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);

Просмотреть файл

@ -62,7 +62,7 @@ struct hb_closure_context_t
template <typename T>
inline return_t process (const T &obj) { obj.closure (this); return HB_VOID; }
static return_t default_return_value (void) { return HB_VOID; }
bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; }
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
return_t recurse (unsigned int lookup_index)
{
if (unlikely (nesting_level_left == 0 || !recurse_func))
@ -111,7 +111,7 @@ struct hb_would_apply_context_t
template <typename T>
inline return_t process (const T &obj) { return obj.would_apply (this); }
static return_t default_return_value (void) { return false; }
bool stop_sublookup_iteration (const return_t r) const { return r; }
bool stop_sublookup_iteration (return_t r) const { return r; }
hb_face_t *face;
const hb_codepoint_t *glyphs;
@ -150,7 +150,7 @@ struct hb_collect_glyphs_context_t
template <typename T>
inline return_t process (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
static return_t default_return_value (void) { return HB_VOID; }
bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; }
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
return_t recurse (unsigned int lookup_index)
{
if (unlikely (nesting_level_left == 0 || !recurse_func))
@ -243,7 +243,7 @@ struct hb_apply_context_t
template <typename T>
inline return_t process (const T &obj) { return obj.apply (this); }
static return_t default_return_value (void) { return false; }
bool stop_sublookup_iteration (const return_t r) const { return r; }
bool stop_sublookup_iteration (return_t r) const { return r; }
return_t recurse (unsigned int lookup_index)
{
if (unlikely (nesting_level_left == 0 || !recurse_func))
@ -286,12 +286,12 @@ struct hb_apply_context_t
void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
struct mark_skipping_forward_iterator_t
struct skipping_forward_iterator_t
{
inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
unsigned int start_index_,
unsigned int num_items_,
bool context_match = false)
inline skipping_forward_iterator_t (hb_apply_context_t *c_,
unsigned int start_index_,
unsigned int num_items_,
bool context_match = false)
{
c = c_;
idx = start_index_;
@ -317,7 +317,7 @@ struct hb_apply_context_t
if (has_no_chance ())
return false;
idx++;
} while (c->should_skip_mark (&c->buffer->info[idx], lookup_props, property_out));
} while (c->should_skip (&c->buffer->info[idx], lookup_props, property_out));
num_items--;
return (c->buffer->info[idx].mask & mask) && (!syllable || syllable == c->buffer->info[idx].syllable ());
}
@ -335,13 +335,13 @@ struct hb_apply_context_t
unsigned int end;
};
struct mark_skipping_backward_iterator_t
struct skipping_backward_iterator_t
{
inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
unsigned int start_index_,
unsigned int num_items_,
hb_mask_t mask_ = 0,
bool match_syllable_ = true)
inline skipping_backward_iterator_t (hb_apply_context_t *c_,
unsigned int start_index_,
unsigned int num_items_,
hb_mask_t mask_ = 0,
bool match_syllable_ = true)
{
c = c_;
idx = start_index_;
@ -366,7 +366,7 @@ struct hb_apply_context_t
if (has_no_chance ())
return false;
idx--;
} while (c->should_skip_mark (&c->buffer->out_info[idx], lookup_props, property_out));
} while (c->should_skip (&c->buffer->out_info[idx], lookup_props, property_out));
num_items--;
return (c->buffer->out_info[idx].mask & mask) && (!syllable || syllable == c->buffer->out_info[idx].syllable ());
}
@ -435,9 +435,9 @@ struct hb_apply_context_t
}
inline bool
should_skip_mark (hb_glyph_info_t *info,
unsigned int lookup_props,
unsigned int *property_out) const
should_skip (hb_glyph_info_t *info,
unsigned int lookup_props,
unsigned int *property_out) const
{
unsigned int property;
@ -445,18 +445,13 @@ struct hb_apply_context_t
if (property_out)
*property_out = property;
/* If it's a mark, skip it if we don't accept it. */
if (unlikely (property & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
return !match_properties (info->codepoint, property, lookup_props);
/* If not a mark, don't skip. */
return false;
return !match_properties (info->codepoint, property, lookup_props);
}
inline bool should_mark_skip_current_glyph (void) const
inline bool should_skip_current_glyph (void) const
{
return should_skip_mark (&buffer->cur(), lookup_props, NULL);
return should_skip (&buffer->cur(), lookup_props, NULL);
}
inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) const
@ -602,7 +597,7 @@ static inline bool match_input (hb_apply_context_t *c,
{
TRACE_APPLY (NULL);
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
/*
@ -720,7 +715,7 @@ static inline void ligate_input (hb_apply_context_t *c,
for (unsigned int i = 1; i < count; i++)
{
while (c->should_mark_skip_current_glyph ())
while (c->should_skip_current_glyph ())
{
if (!is_mark_ligature) {
unsigned int new_lig_comp = components_so_far - last_num_components +
@ -759,7 +754,7 @@ static inline bool match_backtrack (hb_apply_context_t *c,
{
TRACE_APPLY (NULL);
hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
if (skippy_iter.has_no_chance ())
return TRACE_RETURN (false);
@ -784,7 +779,7 @@ static inline bool match_lookahead (hb_apply_context_t *c,
{
TRACE_APPLY (NULL);
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
if (skippy_iter.has_no_chance ())
return TRACE_RETURN (false);
@ -849,7 +844,7 @@ static inline bool apply_lookup (hb_apply_context_t *c,
{
if (unlikely (c->buffer->idx == end))
return TRACE_RETURN (true);
while (c->should_mark_skip_current_glyph ())
while (c->should_skip_current_glyph ())
{
/* No lookup applied for this index */
c->buffer->next_glyph ();

Просмотреть файл

@ -176,8 +176,7 @@ hb_ot_layout_position_lookup (hb_font_t *font,
/* Should be called after all the position_lookup's are done */
HB_INTERNAL void
hb_ot_layout_position_finish (hb_font_t *font,
hb_buffer_t *buffer,
hb_bool_t zero_width_attached_marks);
hb_buffer_t *buffer);

Просмотреть файл

@ -185,6 +185,8 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face,
return g.get_script_tags (start_offset, script_count, script_tags);
}
#define HB_OT_TAG_LATIN_SCRIPT HB_TAG ('l', 'a', 't', 'n')
hb_bool_t
hb_ot_layout_table_find_script (hb_face_t *face,
hb_tag_t table_tag,
@ -206,6 +208,11 @@ hb_ot_layout_table_find_script (hb_face_t *face,
if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
return false;
/* try with 'latn'; some old fonts put their features there even though
they're really trying to support Thai, for example :( */
if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index))
return false;
if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
return false;
}
@ -246,7 +253,6 @@ hb_ot_layout_table_choose_script (hb_face_t *face,
/* try with 'latn'; some old fonts put their features there even though
they're really trying to support Thai, for example :( */
#define HB_OT_TAG_LATIN_SCRIPT HB_TAG ('l', 'a', 't', 'n')
if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
if (chosen_script)
*chosen_script = HB_OT_TAG_LATIN_SCRIPT;
@ -721,9 +727,9 @@ hb_ot_layout_position_lookup (hb_font_t *font,
}
void
hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_bool_t zero_width_attached_marks)
hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
{
OT::GPOS::position_finish (font, buffer, zero_width_attached_marks);
OT::GPOS::position_finish (font, buffer);
}
hb_bool_t

Просмотреть файл

@ -354,6 +354,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
NULL, /* decompose */
NULL, /* compose */
setup_masks_arabic,
true, /* zero_width_attached_marks */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE,
true, /* fallback_position */
};

Просмотреть файл

@ -221,6 +221,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
NULL, /* decompose */
compose_default,
NULL, /* setup_masks */
true, /* zero_width_attached_marks */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE,
true, /* fallback_position */
};

Просмотреть файл

@ -34,11 +34,6 @@
#include "hb-ot-shape-private.hh" /* XXX Remove */
/* buffer var allocations */
#define indic_category() complex_var_u8_0() /* indic_category_t */
#define indic_position() complex_var_u8_1() /* indic_matra_category_t */
#define INDIC_TABLE_ELEMENT_TYPE uint16_t
/* Cateories used in the OpenType spec:
@ -102,7 +97,7 @@ enum indic_syllabic_category_t {
INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_C,
INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM,
INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM,
INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP,
@ -150,239 +145,7 @@ enum indic_matra_category_t {
ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
((M << 8) | S))
#include "hb-ot-shape-complex-indic-table.hh"
#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7F) == (Base))
#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900))
#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980))
#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00))
#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80))
#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00))
#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80))
#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00))
#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80))
#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00))
#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80))
#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780))
#define MATRA_POS_LEFT(u) POS_PRE_M
#define MATRA_POS_RIGHT(u) ( \
IS_DEVA(u) ? POS_AFTER_SUB : \
IS_BENG(u) ? POS_AFTER_POST : \
IS_GURU(u) ? POS_AFTER_POST : \
IS_GUJR(u) ? POS_AFTER_POST : \
IS_ORYA(u) ? POS_AFTER_POST : \
IS_TAML(u) ? POS_AFTER_POST : \
IS_TELU(u) ? (u <= 0x0C42 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
IS_KNDA(u) ? (u < 0x0CC3 || u > 0xCD6 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
IS_MLYM(u) ? POS_AFTER_POST : \
IS_SINH(u) ? POS_AFTER_SUB : \
IS_KHMR(u) ? POS_AFTER_POST : \
/*default*/ POS_AFTER_SUB \
)
#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \
IS_DEVA(u) ? POS_AFTER_SUB : \
IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
IS_GUJR(u) ? POS_AFTER_SUB : \
IS_ORYA(u) ? POS_AFTER_MAIN : \
IS_TAML(u) ? POS_AFTER_SUB : \
IS_TELU(u) ? POS_BEFORE_SUB : \
IS_KNDA(u) ? POS_BEFORE_SUB : \
IS_SINH(u) ? POS_AFTER_SUB : \
IS_KHMR(u) ? POS_AFTER_POST : \
/*default*/ POS_AFTER_SUB \
)
#define MATRA_POS_BOTTOM(u) ( \
IS_DEVA(u) ? POS_AFTER_SUB : \
IS_BENG(u) ? POS_AFTER_SUB : \
IS_GURU(u) ? POS_AFTER_POST : \
IS_GUJR(u) ? POS_AFTER_POST : \
IS_ORYA(u) ? POS_AFTER_SUB : \
IS_TAML(u) ? POS_AFTER_POST : \
IS_TELU(u) ? POS_BEFORE_SUB : \
IS_KNDA(u) ? POS_BEFORE_SUB : \
IS_MLYM(u) ? POS_AFTER_POST : \
IS_SINH(u) ? POS_AFTER_SUB : \
IS_KHMR(u) ? POS_AFTER_POST : \
/*default*/ POS_AFTER_SUB \
)
static inline indic_position_t
matra_position (hb_codepoint_t u, indic_position_t side)
{
switch ((int) side)
{
case POS_PRE_C: return MATRA_POS_LEFT (u);
case POS_POST_C: return MATRA_POS_RIGHT (u);
case POS_ABOVE_C: return MATRA_POS_TOP (u);
case POS_BELOW_C: return MATRA_POS_BOTTOM (u);
};
return side;
}
/* XXX
* This is a hack for now. We should move this data into the main Indic table.
* Or completely remove it and just check in the tables.
*/
static const hb_codepoint_t ra_chars[] = {
0x0930, /* Devanagari */
0x09B0, /* Bengali */
0x09F0, /* Bengali */
0x0A30, /* Gurmukhi */ /* No Reph */
0x0AB0, /* Gujarati */
0x0B30, /* Oriya */
0x0BB0, /* Tamil */ /* No Reph */
0x0C30, /* Telugu */ /* Reph formed only with ZWJ */
0x0CB0, /* Kannada */
0x0D30, /* Malayalam */ /* No Reph, Logical Repha */
0x0DBB, /* Sinhala */ /* Reph formed only with ZWJ */
0x179A, /* Khmer */ /* No Reph, Visual Repha */
};
static inline indic_position_t
consonant_position (hb_codepoint_t u)
{
if ((u & ~0x007F) == 0x1780)
return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not be reordered. */
return POS_BASE_C; /* Will recategorize later based on font lookups. */
}
static inline bool
is_ra (hb_codepoint_t u)
{
for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
if (u == ra_chars[i])
return true;
return false;
}
static inline bool
is_one_of (const hb_glyph_info_t &info, unsigned int flags)
{
/* If it ligated, all bets are off. */
if (is_a_ligature (info)) return false;
return !!(FLAG (info.indic_category()) & flags);
}
#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
static inline bool
is_joiner (const hb_glyph_info_t &info)
{
return is_one_of (info, JOINER_FLAGS);
}
/* Note:
*
* We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
* cannot happen in a consonant syllable. The plus side however is, we can call the
* consonant syllable logic from the vowel syllable function and get it all right! */
#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE))
static inline bool
is_consonant (const hb_glyph_info_t &info)
{
return is_one_of (info, CONSONANT_FLAGS);
}
#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng))
static inline bool
is_halant_or_coeng (const hb_glyph_info_t &info)
{
return is_one_of (info, HALANT_OR_COENG_FLAGS);
}
static inline void
set_indic_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = get_indic_categories (u);
indic_category_t cat = (indic_category_t) (type & 0x7F);
indic_position_t pos = (indic_position_t) (type >> 8);
/*
* Re-assign category
*/
/* The spec says U+0952 is OT_A. However, testing shows that Uniscribe
* treats U+0951..U+0952 all as OT_VD.
* TESTS:
* U+092E,U+0947,U+0952
* U+092E,U+0952,U+0947
* U+092E,U+0947,U+0951
* U+092E,U+0951,U+0947
* */
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0951, 0x0954)))
cat = OT_VD;
if (unlikely (u == 0x17D1))
cat = OT_X;
if (cat == OT_X &&
unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CB, 0x17D3))) /* Khmer Various signs */
{
/* These are like Top Matras. */
cat = OT_M;
pos = POS_ABOVE_C;
}
if (u == 0x17C6) /* Khmer Bindu doesn't like to be repositioned. */
cat = OT_N;
if (unlikely (u == 0x17D2)) cat = OT_Coeng; /* Khmer coeng */
else if (unlikely (u == 0x200C)) cat = OT_ZWNJ;
else if (unlikely (u == 0x200D)) cat = OT_ZWJ;
else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE;
else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. More like consonant medial. like 0A75. */
if (cat == OT_Repha) {
/* There are two kinds of characters marked as Repha:
* - The ones that are GenCat=Mn are already positioned visually, ie. after base. (eg. Khmer)
* - The ones that are GenCat=Lo is encoded logically, ie. beginning of syllable. (eg. Malayalam)
*
* We recategorize the first kind to look like a Nukta and attached to the base directly.
*/
if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
cat = OT_N;
}
/*
* Re-assign position.
*/
if ((FLAG (cat) & CONSONANT_FLAGS))
{
pos = consonant_position (u);
if (is_ra (u))
cat = OT_Ra;
}
else if (cat == OT_M)
{
pos = matra_position (u, pos);
}
else if (cat == OT_SM || cat == OT_VD)
{
pos = POS_SMVD;
}
if (unlikely (u == 0x0B01)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
info.indic_category() = cat;
info.indic_position() = pos;
}
HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
hb_indic_get_categories (hb_codepoint_t u);
#endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */

Просмотреть файл

@ -0,0 +1,869 @@
/* == Start of generated table == */
/*
* The following table is generated by running:
*
* ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt
*
* on files with these headers:
*
* # IndicSyllabicCategory-6.2.0.txt
* # Date: 2012-05-15, 21:12:00 GMT [KW]
* # IndicMatraCategory-6.2.0.txt
* # Date: 2012-05-15, 21:10:00 GMT [KW]
* # Blocks-6.2.0.txt
* # Date: 2012-05-14, 22:42:00 GMT [KW, LI]
*/
#include "hb-ot-shape-complex-indic-private.hh"
#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 11 chars; Avagraha */
#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 34 chars; Bindu */
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 123 chars; Consonant */
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 2 chars; Consonant_Dead */
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 17 chars; Consonant_Final */
#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 1 chars; Consonant_Head_Letter */
#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 12 chars; Consonant_Medial */
#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 4 chars; Consonant_Placeholder */
#define ISC_CR INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA /* 5 chars; Consonant_Repha */
#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 10 chars; Consonant_Subjoined */
#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 12 chars; Nukta */
#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 1 chars; Register_Shifter */
#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 3 chars; Tone_Letter */
#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 16 chars; Tone_Mark */
#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 34 chars; Virama */
#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 25 chars; Visarga */
#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 5 chars; Vowel */
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 165 chars; Vowel_Dependent */
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 59 chars; Vowel_Independent */
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 65 chars; Bottom */
#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */
#define IMC_I INDIC_MATRA_CATEGORY_INVISIBLE /* 6 chars; Invisible */
#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 30 chars; Left */
#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 8 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 /* 75 chars; Right */
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 83 chars; Top */
#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 6 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 /* 4 chars; Top_And_Left */
#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 2 chars; Top_And_Left_And_Right */
#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 8 chars; Top_And_Right */
#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 5 chars; Visual_Order_Left */
#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
#define indic_offset_0x0900 0
/* Devanagari (0900..097F) */
/* 0900 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(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),
/* 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), _(x,x), _(x,x), _(x,x), _(x,x), _(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), _(x,x), _(x,x),
/* 0968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0970 */ _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 0978 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* Bengali (0980..09FF) */
/* 0980 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(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),
/* 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),
/* 09D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
/* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 09E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Gurmukhi (0A00..0A7F) */
/* 0A00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(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),
/* 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), _(x,x), _(x,x),
/* 0A68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0A70 */ _(Bi,x), _(x,x), _(CP,x), _(CP,x), _(x,x), _(CM,x), _(x,x), _(x,x),
/* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Gujarati (0A80..0AFF) */
/* 0A80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(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),
/* 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),
/* 0AD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0AE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,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),
/* Oriya (0B00..0B7F) */
/* 0B00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(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),
/* 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),
/* 0B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
/* 0B60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0B70 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Tamil (0B80..0BFF) */
/* 0B80 */ _(x,x), _(x,x), _(Bi,x), _(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),
/* 0BA0 */ _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
/* 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),
/* 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),
/* 0BE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0BE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0BF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Telugu (0C00..0C7F) */
/* 0C00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(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),
/* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
/* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(A,x), _(M,T), _(M,T),
/* 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),
/* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0C68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0C78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Kannada (0C80..0CFF) */
/* 0C80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(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),
/* 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), _(x,x), _(x,x),
/* 0CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0CF0 */ _(x,x), _(x,x), _(x,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..0D7F) */
/* 0D00 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(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),
/* 0D20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0D28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 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), _(CR,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),
/* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0D68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0D78 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x),
/* Sinhala (0D80..0DFF) */
/* 0D80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(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),
/* 0DA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0DA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0DB0 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0DB8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x),
/* 0DC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
/* 0DC8 */ _(x,x), _(x,x), _(V,T), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
/* 0DD0 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(x,x), _(M,B), _(x,x),
/* 0DD8 */ _(M,R), _(M,L), _(M,TL), _(M,L), _(M,LR), _(M,LR), _(M,LR), _(M,R),
/* 0DE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0DE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0DF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Thai (0E00..0E7F) */
/* 0E00 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0E08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0E10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0E18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0E20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0E28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
/* 0E30 */ _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), _(M,T),
/* 0E38 */ _(M,B), _(M,B), _(V,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0E40 */_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL), _(M,R), _(x,x), _(M,T),
/* 0E48 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(Bi,x), _(V,T), _(x,x),
/* 0E50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0E58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0E60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0E68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0E70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0E78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Lao (0E80..0EFF) */
/* 0E80 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(C,x),
/* 0E88 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(C,x), _(x,x), _(x,x),
/* 0E90 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0E98 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0EA0 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x),
/* 0EA8 */ _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x),
/* 0EB0 */ _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), _(M,T),
/* 0EB8 */ _(M,B), _(M,B), _(x,x), _(M,T), _(CM,x), _(CM,x), _(x,x), _(x,x),
/* 0EC0 */_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL), _(x,x), _(x,x), _(x,x),
/* 0EC8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(Bi,x), _(x,x), _(x,x),
/* 0ED0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0ED8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x),
/* 0EE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0EE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0EF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0EF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Tibetan (0F00..0FFF) */
/* 0F00 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0F08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0F10 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0F18 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0F20 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0F28 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0F30 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0F38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0F40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0F48 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0F50 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0F58 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0F60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 0F68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
/* 0F70 */ _(x,x), _(M,B), _(M,T), _(M,TB), _(M,B), _(M,B), _(M,TB), _(M,TB),
/* 0F78 */ _(M,TB), _(M,TB), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(Vs,x),
/* 0F80 */ _(M,T), _(M,TB), _(Bi,x), _(Bi,x), _(V,B), _(A,x), _(x,x), _(x,x),
/* 0F88 */_(CHL,x),_(CHL,x),_(CHL,x),_(CHL,x),_(CHL,x), _(CS,x), _(CS,x), _(CS,x),
/* 0F90 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
/* 0F98 */ _(x,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
/* 0FA0 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
/* 0FA8 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
/* 0FB0 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
/* 0FB8 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x),
/* 0FC0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0FC8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0FD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0FD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0FE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0FE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0FF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 0FF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Myanmar (1000..109F) */
/* 1000 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1008 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1010 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 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), _(V,I), _(V,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(C,x),
/* 1040 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1048 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,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),
/* 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),
/* 1090 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1098 */ _(x,x), _(x,x), _(TM,x), _(TM,x), _(M,R), _(M,T), _(x,x), _(x,x),
#define indic_offset_0x1700 1952
/* Tagalog (1700..171F) */
/* 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), _(V,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..173F) */
/* 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), _(V,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..175F) */
/* 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..177F) */
/* 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..17FF) */
/* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1788 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1790 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1798 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 17A0 */ _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
/* 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,x), _(RS,x), _(x,x), _(CR,x), _(x,x), _(x,x), _(x,x),
/* 17D0 */ _(x,x), _(V,T), _(V,I), _(x,x), _(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),
/* 17E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 17E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 17F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 17F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x1900 2208
/* Limbu (1900..194F) */
/* 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), _(x,x), _(x,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), _(x,x), _(x,x),
/* 1948 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Tai Le (1950..197F) */
/* 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..19DF) */
/* 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 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 19D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* FILLER (19E0..19FF) */
/* 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..1A1F) */
/* 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,L), _(x,x), _(x,x), _(x,x), _(x,x),
/* Tai Tham (1A20..1AAF) */
/* 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,x), _(CM,x), _(CF,x),
/* 1A58 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x),
/* 1A60 */ _(V,I), _(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 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1A88 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1A90 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1A98 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1AA0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1AA8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x1b00 2640
/* Balinese (1B00..1B7F) */
/* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(CR,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 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1B58 */ _(x,x), _(x,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..1BBF) */
/* 1B80 */ _(Bi,x), _(CR,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), _(V,R), _(V,x), _(CS,x), _(CS,x), _(C,x), _(C,x),
/* 1BB0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1BB8 */ _(x,x), _(x,x), _(A,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x),
/* Batak (1BC0..1BFF) */
/* 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,x),
/* 1BE8 */ _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x),
/* 1BF0 */ _(CF,x), _(CF,x), _(V,R), _(V,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..1C4F) */
/* 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,x), _(Bi,x), _(x,x), _(N,x),
/* 1C38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1C40 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1C48 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x),
#define indic_offset_0x1cd0 2976
/* Vedic Extensions (1CD0..1CFF) */
/* 1CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1CE0 */ _(x,x), _(x,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), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0xa800 3024
/* Syloti Nagri (A800..A82F) */
/* A800 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(V,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),
/* FILLER (A830..A83F) */
/* 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),
/* Phags-pa (A840..A87F) */
/* 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..A8DF) */
/* 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 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A8D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* FILLER (A8E0..A8FF) */
/* A8E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A8E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A8F0 */ _(x,x), _(x,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),
/* Kayah Li (A900..A92F) */
/* A900 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A908 */ _(x,x), _(x,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..A95F) */
/* 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), _(V,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),
/* FILLER (A960..A97F) */
/* 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..A9DF) */
/* A980 */ _(Bi,x), _(Bi,x), _(CR,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 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A9D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* FILLER (A9E0..A9FF) */
/* A9E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A9E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A9F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* A9F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Cham (AA00..AA5F) */
/* 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,x), _(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 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AA58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* Myanmar Extended-A (AA60..AA7F) */
/* 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), _(x,x), _(x,x), _(x,x), _(x,x),
/* Tai Viet (AA80..AADF) */
/* 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..AAFF) */
/* 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), _(V,I), _(x,x),
/* AAF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0xabc0 3792
/* Meetei Mayek (ABC0..ABFF) */
/* 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), _(V,B), _(x,x), _(x,x),
/* ABF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* ABF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x10a00 3856
/* Kharoshthi (10A00..10A5F) */
/* 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), _(V,I),
/* 10A40 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 10A48 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 10A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 10A58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x11000 3952
/* Brahmi (11000..1107F) */
/* 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), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11058 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11060 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 11068 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,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), _(x,x),
/* Kaithi (11080..110CF) */
/* 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),
/* 110C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 110C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x11100 4160
/* Chakma (11100..1114F) */
/* 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), _(V,I), _(V,T), _(x,x), _(x,x), _(x,x),
/* 11138 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,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),
#define indic_offset_0x11180 4240
/* Sharada (11180..111DF) */
/* 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 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 111D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_0x11680 4336
/* Takri (11680..116CF) */
/* 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 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 116C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
#define indic_offset_total 4416
}; /* Table occupancy: 60% */
INDIC_TABLE_ELEMENT_TYPE
hb_indic_get_categories (hb_codepoint_t u)
{
if (0x0900 <= u && u <= 0x10A0) return indic_table[u - 0x0900 + indic_offset_0x0900];
if (0x1700 <= u && u <= 0x1800) return indic_table[u - 0x1700 + indic_offset_0x1700];
if (0x1900 <= u && u <= 0x1AB0) return indic_table[u - 0x1900 + indic_offset_0x1900];
if (0x1B00 <= u && u <= 0x1C50) return indic_table[u - 0x1B00 + indic_offset_0x1b00];
if (0x1CD0 <= u && u <= 0x1D00) return indic_table[u - 0x1CD0 + indic_offset_0x1cd0];
if (0xA800 <= u && u <= 0xAB00) return indic_table[u - 0xA800 + indic_offset_0xa800];
if (0xABC0 <= u && u <= 0xAC00) return indic_table[u - 0xABC0 + indic_offset_0xabc0];
if (0x10A00 <= u && u <= 0x10A60) return indic_table[u - 0x10A00 + indic_offset_0x10a00];
if (0x11000 <= u && u <= 0x110D0) return indic_table[u - 0x11000 + indic_offset_0x11000];
if (0x11100 <= u && u <= 0x11150) return indic_table[u - 0x11100 + indic_offset_0x11100];
if (0x11180 <= u && u <= 0x111E0) return indic_table[u - 0x11180 + indic_offset_0x11180];
if (0x11680 <= u && u <= 0x116D0) return indic_table[u - 0x11680 + indic_offset_0x11680];
if (unlikely (u == 0x00A0)) return _(CP,x);
if (unlikely (u == 0x25CC)) return _(CP,x);
return _(x,x);
}
#undef _
#undef ISC_A
#undef ISC_Bi
#undef ISC_C
#undef ISC_CD
#undef ISC_CF
#undef ISC_CHL
#undef ISC_CM
#undef ISC_CP
#undef ISC_CR
#undef ISC_CS
#undef ISC_ML
#undef ISC_N
#undef ISC_x
#undef ISC_RS
#undef ISC_TL
#undef ISC_TM
#undef ISC_V
#undef ISC_Vs
#undef ISC_Vo
#undef ISC_M
#undef ISC_VI
#undef IMC_B
#undef IMC_BR
#undef IMC_I
#undef IMC_L
#undef IMC_LR
#undef IMC_x
#undef IMC_O
#undef IMC_R
#undef IMC_T
#undef IMC_TB
#undef IMC_TBR
#undef IMC_TL
#undef IMC_TLR
#undef IMC_TR
#undef IMC_VOL
/* == End of generated table == */

Просмотреть файл

@ -27,49 +27,245 @@
#include "hb-ot-shape-complex-indic-private.hh"
#include "hb-ot-layout-private.hh"
/* buffer var allocations */
#define indic_category() complex_var_u8_0() /* indic_category_t */
#define indic_position() complex_var_u8_1() /* indic_position_t */
/*
* Global Indic shaper options.
* Indic shaper.
*/
struct indic_options_t
#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7F) == (Base))
#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900))
#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980))
#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00))
#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80))
#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00))
#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80))
#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00))
#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80))
#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00))
#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80))
#define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780))
#define MATRA_POS_LEFT(u) POS_PRE_M
#define MATRA_POS_RIGHT(u) ( \
IS_DEVA(u) ? POS_AFTER_SUB : \
IS_BENG(u) ? POS_AFTER_POST : \
IS_GURU(u) ? POS_AFTER_POST : \
IS_GUJR(u) ? POS_AFTER_POST : \
IS_ORYA(u) ? POS_AFTER_POST : \
IS_TAML(u) ? POS_AFTER_POST : \
IS_TELU(u) ? (u <= 0x0C42 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
IS_KNDA(u) ? (u < 0x0CC3 || u > 0xCD6 ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
IS_MLYM(u) ? POS_AFTER_POST : \
IS_SINH(u) ? POS_AFTER_SUB : \
IS_KHMR(u) ? POS_AFTER_POST : \
/*default*/ POS_AFTER_SUB \
)
#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \
IS_DEVA(u) ? POS_AFTER_SUB : \
IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
IS_GUJR(u) ? POS_AFTER_SUB : \
IS_ORYA(u) ? POS_AFTER_MAIN : \
IS_TAML(u) ? POS_AFTER_SUB : \
IS_TELU(u) ? POS_BEFORE_SUB : \
IS_KNDA(u) ? POS_BEFORE_SUB : \
IS_SINH(u) ? POS_AFTER_SUB : \
IS_KHMR(u) ? POS_AFTER_POST : \
/*default*/ POS_AFTER_SUB \
)
#define MATRA_POS_BOTTOM(u) ( \
IS_DEVA(u) ? POS_AFTER_SUB : \
IS_BENG(u) ? POS_AFTER_SUB : \
IS_GURU(u) ? POS_AFTER_POST : \
IS_GUJR(u) ? POS_AFTER_POST : \
IS_ORYA(u) ? POS_AFTER_SUB : \
IS_TAML(u) ? POS_AFTER_POST : \
IS_TELU(u) ? POS_BEFORE_SUB : \
IS_KNDA(u) ? POS_BEFORE_SUB : \
IS_MLYM(u) ? POS_AFTER_POST : \
IS_SINH(u) ? POS_AFTER_SUB : \
IS_KHMR(u) ? POS_AFTER_POST : \
/*default*/ POS_AFTER_SUB \
)
static inline indic_position_t
matra_position (hb_codepoint_t u, indic_position_t side)
{
int initialized : 1;
int uniscribe_bug_compatible : 1;
};
union indic_options_union_t {
int i;
indic_options_t opts;
};
ASSERT_STATIC (sizeof (int) == sizeof (indic_options_union_t));
static indic_options_union_t
indic_options_init (void)
{
indic_options_union_t u;
u.i = 0;
u.opts.initialized = 1;
char *c = getenv ("HB_OT_INDIC_OPTIONS");
u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
return u;
switch ((int) side)
{
case POS_PRE_C: return MATRA_POS_LEFT (u);
case POS_POST_C: return MATRA_POS_RIGHT (u);
case POS_ABOVE_C: return MATRA_POS_TOP (u);
case POS_BELOW_C: return MATRA_POS_BOTTOM (u);
};
return side;
}
static inline indic_options_t
indic_options (void)
{
static indic_options_union_t options;
/* XXX
* This is a hack for now. We should move this data into the main Indic table.
* Or completely remove it and just check in the tables.
*/
static const hb_codepoint_t ra_chars[] = {
0x0930, /* Devanagari */
0x09B0, /* Bengali */
0x09F0, /* Bengali */
0x0A30, /* Gurmukhi */ /* No Reph */
0x0AB0, /* Gujarati */
0x0B30, /* Oriya */
0x0BB0, /* Tamil */ /* No Reph */
0x0C30, /* Telugu */ /* Reph formed only with ZWJ */
0x0CB0, /* Kannada */
0x0D30, /* Malayalam */ /* No Reph, Logical Repha */
if (unlikely (!options.i)) {
/* This is idempotent and threadsafe. */
options = indic_options_init ();
0x0DBB, /* Sinhala */ /* Reph formed only with ZWJ */
0x179A, /* Khmer */ /* No Reph, Visual Repha */
};
static inline indic_position_t
consonant_position (hb_codepoint_t u)
{
if ((u & ~0x007F) == 0x1780)
return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not be reordered. */
return POS_BASE_C; /* Will recategorize later based on font lookups. */
}
static inline bool
is_ra (hb_codepoint_t u)
{
for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
if (u == ra_chars[i])
return true;
return false;
}
static inline bool
is_one_of (const hb_glyph_info_t &info, unsigned int flags)
{
/* If it ligated, all bets are off. */
if (is_a_ligature (info)) return false;
return !!(FLAG (info.indic_category()) & flags);
}
#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
static inline bool
is_joiner (const hb_glyph_info_t &info)
{
return is_one_of (info, JOINER_FLAGS);
}
/* Note:
*
* We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
* cannot happen in a consonant syllable. The plus side however is, we can call the
* consonant syllable logic from the vowel syllable function and get it all right! */
#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE))
static inline bool
is_consonant (const hb_glyph_info_t &info)
{
return is_one_of (info, CONSONANT_FLAGS);
}
#define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng))
static inline bool
is_halant_or_coeng (const hb_glyph_info_t &info)
{
return is_one_of (info, HALANT_OR_COENG_FLAGS);
}
static inline void
set_indic_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
indic_category_t cat = (indic_category_t) (type & 0x7F);
indic_position_t pos = (indic_position_t) (type >> 8);
/*
* Re-assign category
*/
/* The spec says U+0952 is OT_A. However, testing shows that Uniscribe
* treats U+0951..U+0952 all as OT_VD.
* TESTS:
* U+092E,U+0947,U+0952
* U+092E,U+0952,U+0947
* U+092E,U+0947,U+0951
* U+092E,U+0951,U+0947
* */
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0951, 0x0954)))
cat = OT_VD;
if (unlikely (u == 0x17D1))
cat = OT_X;
if (cat == OT_X &&
unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CB, 0x17D3))) /* Khmer Various signs */
{
/* These are like Top Matras. */
cat = OT_M;
pos = POS_ABOVE_C;
}
if (u == 0x17C6) /* Khmer Bindu doesn't like to be repositioned. */
cat = OT_N;
if (unlikely (u == 0x17D2)) cat = OT_Coeng; /* Khmer coeng */
else if (unlikely (u == 0x200C)) cat = OT_ZWNJ;
else if (unlikely (u == 0x200D)) cat = OT_ZWJ;
else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE;
else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. More like consonant medial. like 0A75. */
if (cat == OT_Repha) {
/* There are two kinds of characters marked as Repha:
* - The ones that are GenCat=Mn are already positioned visually, ie. after base. (eg. Khmer)
* - The ones that are GenCat=Lo is encoded logically, ie. beginning of syllable. (eg. Malayalam)
*
* We recategorize the first kind to look like a Nukta and attached to the base directly.
*/
if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
cat = OT_N;
}
return options.opts;
/*
* Re-assign position.
*/
if ((FLAG (cat) & CONSONANT_FLAGS))
{
pos = consonant_position (u);
if (is_ra (u))
cat = OT_Ra;
}
else if (cat == OT_M)
{
pos = matra_position (u, pos);
}
else if (cat == OT_SM || cat == OT_VD)
{
pos = POS_SMVD;
}
if (unlikely (u == 0x0B01)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
info.indic_category() = cat;
info.indic_position() = pos;
}
/*
* Things above this line should ideally be moved to the Indic table itself.
*/
/*
* Indic configurations. Note that we do not want to keep every single script-specific
@ -123,8 +319,6 @@ static const indic_config_t indic_configs[] =
{HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA},
{HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_FIRST,REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT},
{HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DEFAULT, REPH_MODE_VIS_REPHA},
/* Myanmar does not have the "old_indic" behavior, even though it has a "new" tag. */
{HB_SCRIPT_MYANMAR, false,0x1039,BASE_POS_LAST, REPH_POS_DEFAULT, REPH_MODE_EXPLICIT},
};
@ -150,13 +344,13 @@ indic_features[] =
{HB_TAG('r','p','h','f'), false},
{HB_TAG('r','k','r','f'), true},
{HB_TAG('p','r','e','f'), false},
{HB_TAG('h','a','l','f'), false},
{HB_TAG('b','l','w','f'), false},
{HB_TAG('h','a','l','f'), false},
{HB_TAG('a','b','v','f'), false},
{HB_TAG('p','s','t','f'), false},
{HB_TAG('c','f','a','r'), false},
{HB_TAG('c','j','c','t'), true},
{HB_TAG('v','a','t','u'), true},
{HB_TAG('c','j','c','t'), true},
/*
* Other features.
* These features are applied all at once, after final_reordering.
@ -182,13 +376,13 @@ enum {
RPHF,
_RKRF,
PREF,
HALF,
BLWF,
HALF,
ABVF,
PSTF,
CFAR,
_CJCT,
_VATU,
_CJCT,
INIT,
_PRES,
@ -247,7 +441,7 @@ static void
override_features_indic (hb_ot_shape_planner_t *plan)
{
/* Uniscribe does not apply 'kern'. */
if (indic_options ().uniscribe_bug_compatible)
if (hb_options ().uniscribe_bug_compatible)
plan->map.add_feature (HB_TAG('k','e','r','n'), 0, true);
plan->map.add_feature (HB_TAG('l','i','g','a'), 0, true);
@ -577,15 +771,12 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* base consonants.
*
* Only do this for unforced Reph. (ie. not for Ra,H,ZWJ. */
if (has_reph && base == start && start - limit <= 2) {
if (has_reph && base == start && limit - base <= 2) {
/* Have no other consonant, so Reph is not formed and Ra becomes base. */
has_reph = false;
}
}
if (base < end)
info[base].indic_position() = POS_BASE_C;
/* 2. Decompose and reorder Matras:
*
@ -644,15 +835,16 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
info[start].indic_position() = POS_RA_TO_BECOME_REPH;
/* For old-style Indic script tags, move the first post-base Halant after
* last consonant. */
* last consonant. Only do this if there is *not* a Halant after last
* consonant. Otherwise it becomes messy. */
if (indic_plan->is_old_spec) {
for (unsigned int i = base + 1; i < end; i++)
if (info[i].indic_category() == OT_H) {
unsigned int j;
for (j = end - 1; j > i; j--)
if (is_consonant (info[j]))
if (is_consonant (info[j]) || info[j].indic_category() == OT_H)
break;
if (j > i) {
if (info[j].indic_category() != OT_H && j > i) {
/* Move Halant to after last consonant. */
hb_glyph_info_t t = info[i];
memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
@ -745,6 +937,38 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
info[i].mask |= mask;
}
if (indic_plan->is_old_spec &&
buffer->props.script == HB_SCRIPT_DEVANAGARI)
{
/* Old-spec eye-lash Ra needs special handling. From the
* spec:
*
* "The feature 'below-base form' is applied to consonants
* having below-base forms and following the base consonant.
* The exception is vattu, which may appear below half forms
* as well as below the base glyph. The feature 'below-base
* form' will be applied to all such occurrences of Ra as well."
*
* Test case: U+0924,U+094D,U+0930,U+094d,U+0915
* with Sanskrit 2003 font.
*
* However, note that Ra,Halant,ZWJ is the correct way to
* request eyelash form of Ra, so we wouldbn't inhibit it
* in that sequence.
*
* Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915
*/
for (unsigned int i = start; i + 1 < base; i++)
if (info[i ].indic_category() == OT_Ra &&
info[i+1].indic_category() == OT_H &&
(i + 2 == base ||
info[i+2].indic_category() != OT_ZWJ))
{
info[i ].mask |= indic_plan->mask_array[BLWF];
info[i+1].mask |= indic_plan->mask_array[BLWF];
}
}
if (indic_plan->mask_array[PREF] && base + 2 < end)
{
/* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */
@ -809,7 +1033,7 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
/* We treat NBSP/dotted-circle as if they are consonants, so we should just chain.
* Only if not in compatibility mode that is... */
if (indic_options ().uniscribe_bug_compatible)
if (hb_options ().uniscribe_bug_compatible)
{
/* For dotted-circle, this is what Uniscribe does:
* If dotted-circle is the last glyph, it just does nothing.
@ -962,6 +1186,13 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
base--;
break;
}
if (base == end && start < base &&
info[base - 1].indic_category() != OT_ZWJ)
base--;
while (start < base &&
(info[base].indic_category() == OT_H ||
info[base].indic_category() == OT_N))
base--;
/* o Reorder matras:
@ -1013,6 +1244,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_glyph_info_t tmp = info[old_pos];
memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
info[new_pos] = tmp;
if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
base--;
new_pos--;
}
buffer->merge_clusters (new_pos, MIN (end, base + 1));
@ -1145,7 +1378,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* Uniscribe doesn't do this.
* TEST: U+0930,U+094D,U+0915,U+094B,U+094D
*/
if (!indic_options ().uniscribe_bug_compatible &&
if (!hb_options ().uniscribe_bug_compatible &&
unlikely (is_halant_or_coeng (info[new_reph_pos]))) {
for (unsigned int i = base + 1; i < new_reph_pos; i++)
if (info[i].indic_category() == OT_M) {
@ -1165,6 +1398,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_glyph_info_t reph = info[start];
memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0]));
info[new_reph_pos] = reph;
if (start < base && base <= new_reph_pos)
base--;
}
}
@ -1230,6 +1465,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_glyph_info_t tmp = info[old_pos];
memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
info[new_pos] = tmp;
if (new_pos <= base && base < old_pos)
base++;
}
}
@ -1249,7 +1486,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
/*
* Finish off the clusters and go home!
*/
if (indic_options ().uniscribe_bug_compatible)
if (hb_options ().uniscribe_bug_compatible)
{
/* Uniscribe merges the entire cluster.
* This means, half forms are submerged into the main consonants cluster.
@ -1365,7 +1602,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t glyph;
if (indic_options ().uniscribe_bug_compatible ||
if (hb_options ().uniscribe_bug_compatible ||
(c->font->get_glyph (ab, 0, &glyph) &&
indic_plan->pstf.would_substitute (&glyph, 1, true, c->font->face)))
{
@ -1408,6 +1645,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
decompose_indic,
compose_indic,
setup_masks_indic,
false, /* zero_width_attached_marks */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};

Просмотреть файл

@ -0,0 +1,391 @@
#line 1 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
/*
* 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_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
#include "hb-private.hh"
#line 36 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
1u, 30u, 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,
3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 5u, 8u,
5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u,
3u, 30u, 3u, 29u, 1u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u,
3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 0
};
static const char _myanmar_syllable_machine_key_spans[] = {
30, 28, 25, 4, 25, 23, 21, 21,
27, 27, 27, 27, 16, 27, 27, 27,
27, 27, 27, 27, 27, 27, 25, 4,
25, 23, 21, 21, 27, 27, 27, 27,
28, 27, 30, 27, 27, 27, 27, 27,
27, 27, 27, 27
};
static const short _myanmar_syllable_machine_index_offsets[] = {
0, 31, 60, 86, 91, 117, 141, 163,
185, 213, 241, 269, 297, 314, 342, 370,
398, 426, 454, 482, 510, 538, 566, 592,
597, 623, 647, 669, 691, 719, 747, 775,
803, 832, 860, 891, 919, 947, 975, 1003,
1031, 1059, 1087, 1115
};
static const char _myanmar_syllable_machine_indicies[] = {
1, 1, 2, 3, 4, 4, 0, 5,
0, 6, 0, 1, 0, 0, 0, 7,
0, 8, 1, 0, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 0, 20,
21, 22, 22, 19, 23, 19, 24, 19,
19, 19, 19, 19, 19, 19, 25, 19,
19, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 19, 22, 22, 19, 23,
19, 19, 19, 19, 19, 19, 19, 19,
19, 36, 19, 19, 19, 19, 19, 19,
30, 19, 19, 19, 34, 19, 22, 22,
19, 23, 19, 22, 22, 19, 23, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 30,
19, 19, 19, 34, 19, 37, 19, 22,
22, 19, 23, 19, 30, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 30, 19, 22, 22, 19,
23, 19, 19, 19, 19, 19, 19, 19,
19, 19, 38, 19, 19, 19, 19, 19,
19, 30, 19, 22, 22, 19, 23, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 30,
19, 20, 19, 22, 22, 19, 23, 19,
24, 19, 19, 19, 19, 19, 19, 19,
39, 19, 19, 39, 19, 19, 19, 30,
40, 19, 19, 34, 19, 20, 19, 22,
22, 19, 23, 19, 24, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 30, 19, 19, 19, 34,
19, 20, 19, 22, 22, 19, 23, 19,
24, 19, 19, 19, 19, 19, 19, 19,
39, 19, 19, 19, 19, 19, 19, 30,
40, 19, 19, 34, 19, 20, 19, 22,
22, 19, 23, 19, 24, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 30, 40, 19, 19, 34,
19, 1, 1, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
1, 19, 20, 19, 22, 22, 19, 23,
19, 24, 19, 19, 19, 19, 19, 19,
19, 25, 19, 19, 26, 27, 28, 29,
30, 31, 32, 33, 34, 19, 20, 19,
22, 22, 19, 23, 19, 24, 19, 19,
19, 19, 19, 19, 19, 33, 19, 19,
19, 19, 19, 19, 30, 31, 32, 33,
34, 19, 20, 19, 22, 22, 19, 23,
19, 24, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
30, 31, 32, 33, 34, 19, 20, 19,
22, 22, 19, 23, 19, 24, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 30, 31, 32, 19,
34, 19, 20, 19, 22, 22, 19, 23,
19, 24, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
30, 19, 32, 19, 34, 19, 20, 19,
22, 22, 19, 23, 19, 24, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
26, 19, 28, 19, 30, 31, 32, 33,
34, 19, 20, 19, 22, 22, 19, 23,
19, 24, 19, 19, 19, 19, 19, 19,
19, 33, 19, 19, 26, 19, 19, 19,
30, 31, 32, 33, 34, 19, 20, 19,
22, 22, 19, 23, 19, 24, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
26, 27, 28, 19, 30, 31, 32, 33,
34, 19, 20, 21, 22, 22, 19, 23,
19, 24, 19, 19, 19, 19, 19, 19,
19, 25, 19, 19, 26, 27, 28, 29,
30, 31, 32, 33, 34, 19, 3, 3,
41, 5, 41, 41, 41, 41, 41, 41,
41, 41, 41, 42, 41, 41, 41, 41,
41, 41, 13, 41, 41, 41, 17, 41,
3, 3, 41, 5, 41, 3, 3, 41,
5, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 13, 41, 41, 41, 17, 41, 43,
41, 3, 3, 41, 5, 41, 13, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 13, 41, 3,
3, 41, 5, 41, 41, 41, 41, 41,
41, 41, 41, 41, 44, 41, 41, 41,
41, 41, 41, 13, 41, 3, 3, 41,
5, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 13, 41, 2, 41, 3, 3, 41,
5, 41, 6, 41, 41, 41, 41, 41,
41, 41, 45, 41, 41, 45, 41, 41,
41, 13, 46, 41, 41, 17, 41, 2,
41, 3, 3, 41, 5, 41, 6, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 13, 41, 41,
41, 17, 41, 2, 41, 3, 3, 41,
5, 41, 6, 41, 41, 41, 41, 41,
41, 41, 45, 41, 41, 41, 41, 41,
41, 13, 46, 41, 41, 17, 41, 2,
41, 3, 3, 41, 5, 41, 6, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 13, 46, 41,
41, 17, 41, 20, 21, 22, 22, 19,
23, 19, 24, 19, 19, 19, 19, 19,
19, 19, 47, 19, 19, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 19,
20, 48, 22, 22, 19, 23, 19, 24,
19, 19, 19, 19, 19, 19, 19, 25,
19, 19, 26, 27, 28, 29, 30, 31,
32, 33, 34, 19, 1, 1, 2, 3,
3, 3, 41, 5, 41, 6, 41, 1,
41, 41, 41, 1, 41, 8, 1, 41,
9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 41, 2, 41, 3, 3, 41,
5, 41, 6, 41, 41, 41, 41, 41,
41, 41, 8, 41, 41, 9, 10, 11,
12, 13, 14, 15, 16, 17, 41, 2,
41, 3, 3, 41, 5, 41, 6, 41,
41, 41, 41, 41, 41, 41, 16, 41,
41, 41, 41, 41, 41, 13, 14, 15,
16, 17, 41, 2, 41, 3, 3, 41,
5, 41, 6, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 13, 14, 15, 16, 17, 41, 2,
41, 3, 3, 41, 5, 41, 6, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 13, 14, 15,
41, 17, 41, 2, 41, 3, 3, 41,
5, 41, 6, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 13, 41, 15, 41, 17, 41, 2,
41, 3, 3, 41, 5, 41, 6, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 9, 41, 11, 41, 13, 14, 15,
16, 17, 41, 2, 41, 3, 3, 41,
5, 41, 6, 41, 41, 41, 41, 41,
41, 41, 16, 41, 41, 9, 41, 41,
41, 13, 14, 15, 16, 17, 41, 2,
41, 3, 3, 41, 5, 41, 6, 41,
41, 41, 41, 41, 41, 41, 41, 41,
41, 9, 10, 11, 41, 13, 14, 15,
16, 17, 41, 2, 3, 3, 3, 41,
5, 41, 6, 41, 41, 41, 41, 41,
41, 41, 8, 41, 41, 9, 10, 11,
12, 13, 14, 15, 16, 17, 41, 0
};
static const char _myanmar_syllable_machine_trans_targs[] = {
0, 1, 22, 0, 0, 23, 29, 32,
35, 36, 40, 41, 42, 25, 38, 39,
37, 28, 43, 0, 2, 12, 0, 3,
9, 13, 14, 18, 19, 20, 5, 16,
17, 15, 8, 21, 4, 6, 7, 10,
11, 0, 24, 26, 27, 30, 31, 33,
34
};
static const char _myanmar_syllable_machine_trans_actions[] = {
3, 0, 0, 4, 5, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 6, 0, 0, 7, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 8, 0, 0, 0, 0, 0, 0,
0
};
static const char _myanmar_syllable_machine_to_state_actions[] = {
1, 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, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
static const char _myanmar_syllable_machine_from_state_actions[] = {
2, 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, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
static const short _myanmar_syllable_machine_eof_trans[] = {
0, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42,
20, 20, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42
};
static const int myanmar_syllable_machine_start = 0;
static const int myanmar_syllable_machine_first_final = 0;
static const int myanmar_syllable_machine_error = -1;
static const int myanmar_syllable_machine_en_main = 0;
#line 36 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
#line 90 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
for (unsigned int i = last; i < p+1; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
last = p+1; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te, act;
int cs;
hb_glyph_info_t *info = buffer->info;
#line 288 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
{
cs = myanmar_syllable_machine_start;
ts = 0;
te = 0;
act = 0;
}
#line 111 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
unsigned int syllable_serial = 1;
#line 305 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
{
int _slen;
int _trans;
const unsigned char *_keys;
const char *_inds;
if ( p == pe )
goto _test_eof;
_resume:
switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
case 2:
#line 1 "NONE"
{ts = p;}
break;
#line 319 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
}
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
_inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
_slen = _myanmar_syllable_machine_key_spans[cs];
_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
( info[p].myanmar_category()) <= _keys[1] ?
( info[p].myanmar_category()) - _keys[0] : _slen ];
_eof_trans:
cs = _myanmar_syllable_machine_trans_targs[_trans];
if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
goto _again;
switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
case 7:
#line 83 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (consonant_syllable); }}
break;
case 5:
#line 84 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (non_myanmar_cluster); }}
break;
case 4:
#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (broken_cluster); }}
break;
case 3:
#line 86 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (non_myanmar_cluster); }}
break;
case 6:
#line 83 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }}
break;
case 8:
#line 85 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }}
break;
#line 361 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
}
_again:
switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
case 1:
#line 1 "NONE"
{ts = 0;}
break;
#line 370 "hb-ot-shape-complex-myanmar-machine.hh.tmp"
}
if ( ++p != pe )
goto _resume;
_test_eof: {}
if ( p == eof )
{
if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
_trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
goto _eof_trans;
}
}
}
#line 120 "../../src/hb-ot-shape-complex-myanmar-machine.rl"
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */

Просмотреть файл

@ -0,0 +1,125 @@
/*
* 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_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
#include "hb-private.hh"
%%{
machine myanmar_syllable_machine;
alphtype unsigned char;
write data;
}%%
%%{
# Same order as enum myanmar_category_t. Not sure how to avoid duplication.
A = 10;
As = 18;
C = 1;
D = 19;
D0 = 20;
DB = 3;
GB = 12;
H = 4;
IV = 2;
MH = 21;
MR = 22;
MW = 23;
MY = 24;
PT = 25;
V = 8;
VAbv = 26;
VBlw = 27;
VPre = 28;
VPst = 29;
VS = 30;
ZWJ = 6;
ZWNJ = 5;
Ra = 16;
j = ZWJ|ZWNJ; # Joiners
k = (Ra As H); # Kinzi
c = C|Ra; # is_consonant
medial_group = MY? MR? ((MW MH? | MH) As?)?;
main_vowel_group = VPre* VAbv* VBlw* A* (DB As?)?;
post_vowel_group = VPst MH? As* VAbv* A* (DB As?)?;
pwo_tone_group = PT A* (DB As?)?;
complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_tone_group* V* j?;
syllable_tail = (H | complex_syllable_tail);
consonant_syllable = k? (c|IV|D|GB).VS? (H (c|IV).VS?)* syllable_tail;
broken_cluster = k? VS? syllable_tail;
other = any;
main := |*
consonant_syllable => { found_syllable (consonant_syllable); };
j => { found_syllable (non_myanmar_cluster); };
broken_cluster => { found_syllable (broken_cluster); };
other => { found_syllable (non_myanmar_cluster); };
*|;
}%%
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
for (unsigned int i = last; i < p+1; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
last = p+1; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te, act;
int cs;
hb_glyph_info_t *info = buffer->info;
%%{
write init;
getkey info[p].myanmar_category();
}%%
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
unsigned int syllable_serial = 1;
%%{
write exec;
}%%
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */

Просмотреть файл

@ -0,0 +1,561 @@
/*
* Copyright © 2011,2012,2013 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
*/
#include "hb-ot-shape-complex-indic-private.hh"
/* buffer var allocations */
#define myanmar_category() complex_var_u8_0() /* myanmar_category_t */
#define myanmar_position() complex_var_u8_1() /* myanmar_position_t */
/*
* Myanmar shaper.
*/
static const hb_tag_t
myanmar_features[] =
{
/*
* Basic features.
* These features are applied in order, one at a time, after initial_reordering.
*/
HB_TAG('r','p','h','f'),
HB_TAG('p','r','e','f'),
HB_TAG('b','l','w','f'),
HB_TAG('p','s','t','f'),
/*
* Other features.
* These features are applied all at once, after final_reordering.
*/
HB_TAG('p','r','e','s'),
HB_TAG('a','b','v','s'),
HB_TAG('b','l','w','s'),
HB_TAG('p','s','t','s'),
/* Positioning features, though we don't care about the types. */
HB_TAG('d','i','s','t'),
};
/*
* Must be in the same order as the myanmar_features array.
*/
enum {
_RPHF,
_PREF,
_BLWF,
_PSTF,
_PRES,
_ABVS,
_BLWS,
_PSTS,
_DIST,
MYANMAR_NUM_FEATURES,
MYANMAR_BASIC_FEATURES = _PRES /* Don't forget to update this! */
};
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
collect_features_myanmar (hb_ot_shape_planner_t *plan)
{
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
map->add_bool_feature (HB_TAG('l','o','c','l'));
/* The Indic specs do not require ccmp, but we apply it here since if
* there is a use of it, it's typically at the beginning. */
map->add_bool_feature (HB_TAG('c','c','m','p'));
unsigned int i = 0;
map->add_gsub_pause (initial_reordering);
for (; i < MYANMAR_BASIC_FEATURES; i++) {
map->add_bool_feature (myanmar_features[i]);
map->add_gsub_pause (NULL);
}
map->add_gsub_pause (final_reordering);
for (; i < MYANMAR_NUM_FEATURES; i++) {
map->add_bool_feature (myanmar_features[i]);
}
}
static void
override_features_myanmar (hb_ot_shape_planner_t *plan)
{
plan->map.add_feature (HB_TAG('l','i','g','a'), 0, true);
/*
* Note:
*
* Spec says 'mark' is used, and the mmrtext.ttf font from
* Windows 8 has lookups for it. But testing suggests that
* Windows 8 Uniscribe is NOT applying it. It *is* applying
* 'mkmk' however.
*/
if (hb_options ().uniscribe_bug_compatible)
plan->map.add_feature (HB_TAG('m','a','r','k'), 0, true);
}
enum syllable_type_t {
consonant_syllable,
broken_cluster,
non_myanmar_cluster,
};
#include "hb-ot-shape-complex-myanmar-machine.hh"
/* Note: This enum is duplicated in the -machine.rl source file.
* Not sure how to avoid duplication. */
enum myanmar_category_t {
OT_As = 18, /* Asat */
OT_D = 19, /* Digits except zero */
OT_D0 = 20, /* Digit zero */
OT_DB = OT_N, /* Dot below */
OT_GB = OT_DOTTEDCIRCLE,
OT_MH = 21, /* Various consonant medial types */
OT_MR = 22, /* Various consonant medial types */
OT_MW = 23, /* Various consonant medial types */
OT_MY = 24, /* Various consonant medial types */
OT_PT = 25, /* Pwo and other tones */
OT_VAbv = 26,
OT_VBlw = 27,
OT_VPre = 28,
OT_VPst = 29,
OT_VS = 30 /* Variation selectors */
};
static inline bool
is_one_of (const hb_glyph_info_t &info, unsigned int flags)
{
/* If it ligated, all bets are off. */
if (is_a_ligature (info)) return false;
return !!(FLAG (info.myanmar_category()) & flags);
}
/* Note:
*
* We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
* cannot happen in a consonant syllable. The plus side however is, we can call the
* consonant syllable logic from the vowel syllable function and get it all right! */
#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_GB))
static inline bool
is_consonant (const hb_glyph_info_t &info)
{
return is_one_of (info, CONSONANT_FLAGS);
}
static inline void
set_myanmar_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
indic_category_t cat = (indic_category_t) (type & 0x7F);
indic_position_t pos = (indic_position_t) (type >> 8);
/* Myanmar
* http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze
*/
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00, 0xFE0F)))
cat = (indic_category_t) OT_VS;
else if (unlikely (u == 0x200C)) cat = (indic_category_t) OT_ZWNJ;
else if (unlikely (u == 0x200D)) cat = (indic_category_t) OT_ZWJ;
switch (u)
{
case 0x002D: case 0x00A0: case 0x00D7: case 0x2012:
case 0x2013: case 0x2014: case 0x2015: case 0x2022:
case 0x25CC: case 0x25FB: case 0x25FC: case 0x25FD:
case 0x25FE:
cat = (indic_category_t) OT_GB;
break;
case 0x1004: case 0x101B: case 0x105A:
cat = (indic_category_t) OT_Ra;
break;
case 0x1032: case 0x1036:
cat = (indic_category_t) OT_A;
break;
case 0x103A:
cat = (indic_category_t) OT_As;
break;
case 0x1041: case 0x1042: case 0x1043: case 0x1044:
case 0x1045: case 0x1046: case 0x1047: case 0x1048:
case 0x1049: case 0x1090: case 0x1091: case 0x1092:
case 0x1093: case 0x1094: case 0x1095: case 0x1096:
case 0x1097: case 0x1098: case 0x1099:
cat = (indic_category_t) OT_D;
break;
case 0x1040:
cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
break;
case 0x103E: case 0x1060:
cat = (indic_category_t) OT_MH;
break;
case 0x103C:
cat = (indic_category_t) OT_MR;
break;
case 0x103D: case 0x1082:
cat = (indic_category_t) OT_MW;
break;
case 0x103B: case 0x105E: case 0x105F:
cat = (indic_category_t) OT_MY;
break;
case 0x1063: case 0x1064: case 0x1069: case 0x106A:
case 0x106B: case 0x106C: case 0x106D: case 0xAA7B:
cat = (indic_category_t) OT_PT;
break;
case 0x1038: case 0x1087: case 0x1088: case 0x1089:
case 0x108A: case 0x108B: case 0x108C: case 0x108D:
case 0x108F: case 0x109A: case 0x109B: case 0x109C:
cat = (indic_category_t) OT_SM;
break;
}
if (cat == OT_M)
{
switch ((int) pos)
{
case POS_PRE_C: cat = (indic_category_t) OT_VPre;
pos = POS_PRE_M; break;
case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break;
case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break;
case POS_POST_C: cat = (indic_category_t) OT_VPst; break;
}
}
info.myanmar_category() = (myanmar_category_t) cat;
info.myanmar_position() = pos;
}
static void
setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
{
HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category);
HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position);
/* We cannot setup masks here. We save information about characters
* and setup masks later on in a pause-callback. */
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
set_myanmar_properties (buffer->info[i]);
}
static void
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
find_syllables (buffer);
}
static int
compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
{
int a = pa->myanmar_position();
int b = pb->myanmar_position();
return a < b ? -1 : a == b ? 0 : +1;
}
/* Rules from:
* http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm */
static void
initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
hb_glyph_info_t *info = buffer->info;
unsigned int base = end;
bool has_reph = false;
{
unsigned int limit = start;
if (start + 3 <= end &&
info[start ].myanmar_category() == OT_Ra &&
info[start+1].myanmar_category() == OT_As &&
info[start+2].myanmar_category() == OT_H)
{
limit += 3;
base = start;
has_reph = true;
}
{
if (!has_reph)
base = limit;
for (unsigned int i = limit; i < end; i++)
if (is_consonant (info[i]))
{
base = i;
break;
}
}
}
/* Reorder! */
{
unsigned int i = start;
for (; i < start + (has_reph ? 3 : 0); i++)
info[i].myanmar_position() = POS_AFTER_MAIN;
for (; i < base; i++)
info[i].myanmar_position() = POS_PRE_C;
if (i < end)
{
info[i].myanmar_position() = POS_BASE_C;
i++;
}
indic_position_t pos = POS_AFTER_MAIN;
/* The following loop may be ugly, but it implements all of
* Myanmar reordering! */
for (; i < end; i++)
{
if (info[i].myanmar_category() == OT_MR) /* Pre-base reordering */
{
info[i].myanmar_position() = POS_PRE_C;
continue;
}
if (info[i].myanmar_position() < POS_BASE_C) /* Left matra */
{
continue;
}
if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == OT_VBlw)
{
pos = POS_BELOW_C;
info[i].myanmar_position() = pos;
continue;
}
if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_A)
{
info[i].myanmar_position() = POS_BEFORE_SUB;
continue;
}
if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_VBlw)
{
info[i].myanmar_position() = pos;
continue;
}
if (pos == POS_BELOW_C && info[i].myanmar_category() != OT_A)
{
pos = POS_AFTER_SUB;
info[i].myanmar_position() = pos;
continue;
}
info[i].myanmar_position() = pos;
}
}
buffer->merge_clusters (start, end);
/* Sit tight, rock 'n roll! */
hb_bubble_sort (info + start, end - start, compare_myanmar_order);
}
static void
initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
/* We already inserted dotted-circles, so just call the consonant_syllable. */
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
}
static void
initial_reordering_non_myanmar_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer HB_UNUSED,
unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
}
static void
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type) {
case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return;
case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return;
case non_myanmar_cluster: initial_reordering_non_myanmar_cluster (plan, face, buffer, start, end); return;
}
}
static inline void
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
/* Note: This loop is extra overhead, but should not be measurable. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) {
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CC;
set_myanmar_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
{
last_syllable = syllable;
hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
info.syllable() = buffer->cur().syllable();
buffer->output_info (info);
}
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
if (unlikely (!count)) return;
unsigned int last = 0;
unsigned int last_syllable = info[0].syllable();
for (unsigned int i = 1; i < count; i++)
if (last_syllable != info[i].syllable()) {
initial_reordering_syllable (plan, font->face, buffer, last, i);
last = i;
last_syllable = info[last].syllable();
}
initial_reordering_syllable (plan, font->face, buffer, last, count);
}
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
/* Zero syllables now... */
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
}
static hb_ot_shape_normalization_mode_t
normalization_preference_myanmar (const hb_segment_properties_t *props HB_UNUSED)
{
return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT;
}
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
{
"myanmar",
collect_features_myanmar,
override_features_myanmar,
NULL, /* data_create */
NULL, /* data_destroy */
NULL, /* preprocess_text */
normalization_preference_myanmar,
NULL, /* decompose */
NULL, /* compose */
setup_masks_myanmar,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF,
false, /* fallback_position */
};

Просмотреть файл

@ -39,12 +39,20 @@
#define complex_var_u8_1() var2.u8[3]
enum hb_ot_shape_zero_width_marks_type_t {
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF
};
/* Master OT shaper list */
#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
HB_COMPLEX_SHAPER_IMPLEMENT (sea) \
HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
/* ^--- Add new shapers here */
@ -130,7 +138,8 @@ struct hb_ot_complex_shaper_t
hb_buffer_t *buffer,
hb_font_t *font);
bool zero_width_attached_marks;
hb_ot_shape_zero_width_marks_type_t zero_width_marks;
bool fallback_position;
};
@ -254,13 +263,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-4.1 additions */
case HB_SCRIPT_BUGINESE:
case HB_SCRIPT_NEW_TAI_LUE:
/* Unicode-5.0 additions */
case HB_SCRIPT_BALINESE:
/* Unicode-5.1 additions */
case HB_SCRIPT_CHAM:
case HB_SCRIPT_LEPCHA:
case HB_SCRIPT_REJANG:
case HB_SCRIPT_SUNDANESE:
@ -269,19 +276,22 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_JAVANESE:
case HB_SCRIPT_KAITHI:
case HB_SCRIPT_MEETEI_MAYEK:
case HB_SCRIPT_TAI_THAM:
/* Unicode-6.0 additions */
/* Unicode-6.1 additions */
case HB_SCRIPT_CHAKMA:
case HB_SCRIPT_SHARADA:
case HB_SCRIPT_TAKRI:
/* Only use Indic shaper if the font has Indic tables. */
if (planner->map.found_script[0])
return &_hb_ot_complex_shaper_indic;
else
/* If the designer designed the font for the 'DFLT' script,
* use the default shaper. Otherwise, use the Indic shaper.
* Note that for some simple scripts, there may not be *any*
* GSUB/GPOS needed, so there may be no scripts found! */
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T'))
return &_hb_ot_complex_shaper_default;
else
return &_hb_ot_complex_shaper_indic;
case HB_SCRIPT_KHMER:
/* A number of Khmer fonts in the wild don't have a 'pref' feature,
@ -300,12 +310,30 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
return &_hb_ot_complex_shaper_default;
case HB_SCRIPT_MYANMAR:
/* For Myanmar, we only want to use the Indic shaper if the "new" script
/* For Myanmar, we only want to use the Myanmar shaper if the "new" script
* tag is found. For "old" script tag we want to use the default shaper. */
if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
return &_hb_ot_complex_shaper_indic;
return &_hb_ot_complex_shaper_myanmar;
else
return &_hb_ot_complex_shaper_default;
/* Unicode-4.1 additions */
case HB_SCRIPT_NEW_TAI_LUE:
/* Unicode-5.1 additions */
case HB_SCRIPT_CHAM:
/* Unicode-5.2 additions */
case HB_SCRIPT_TAI_THAM:
/* If the designer designed the font for the 'DFLT' script,
* use the default shaper. Otherwise, use the Indic shaper.
* Note that for some simple scripts, there may not be *any*
* GSUB/GPOS needed, so there may be no scripts found! */
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T'))
return &_hb_ot_complex_shaper_default;
else
return &_hb_ot_complex_shaper_sea;
}
}

Просмотреть файл

@ -0,0 +1,224 @@
#line 1 "../../src/hb-ot-shape-complex-sea-machine.rl"
/*
* Copyright © 2011,2012,2013 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_SHAPE_COMPLEX_SEA_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH
#include "hb-private.hh"
#line 36 "hb-ot-shape-complex-sea-machine.hh.tmp"
static const unsigned char _sea_syllable_machine_trans_keys[] = {
1u, 1u, 1u, 1u, 1u, 29u, 3u, 29u, 3u, 29u, 1u, 1u, 0
};
static const char _sea_syllable_machine_key_spans[] = {
1, 1, 29, 27, 27, 1
};
static const char _sea_syllable_machine_index_offsets[] = {
0, 2, 4, 34, 62, 90
};
static const char _sea_syllable_machine_indicies[] = {
1, 0, 3, 2, 1, 1, 3, 5,
4, 4, 4, 4, 4, 3, 4, 1,
4, 4, 4, 4, 3, 4, 4, 4,
4, 3, 4, 4, 4, 3, 3, 3,
3, 4, 1, 7, 6, 6, 6, 6,
6, 1, 6, 6, 6, 6, 6, 6,
1, 6, 6, 6, 6, 1, 6, 6,
6, 1, 1, 1, 1, 6, 3, 9,
8, 8, 8, 8, 8, 3, 8, 8,
8, 8, 8, 8, 3, 8, 8, 8,
8, 3, 8, 8, 8, 3, 3, 3,
3, 8, 3, 10, 0
};
static const char _sea_syllable_machine_trans_targs[] = {
2, 3, 2, 4, 2, 5, 2, 0,
2, 1, 2
};
static const char _sea_syllable_machine_trans_actions[] = {
1, 2, 3, 2, 6, 0, 7, 0,
8, 0, 9
};
static const char _sea_syllable_machine_to_state_actions[] = {
0, 0, 4, 0, 0, 0
};
static const char _sea_syllable_machine_from_state_actions[] = {
0, 0, 5, 0, 0, 0
};
static const char _sea_syllable_machine_eof_trans[] = {
1, 3, 0, 7, 9, 11
};
static const int sea_syllable_machine_start = 2;
static const int sea_syllable_machine_first_final = 2;
static const int sea_syllable_machine_error = -1;
static const int sea_syllable_machine_en_main = 2;
#line 36 "../../src/hb-ot-shape-complex-sea-machine.rl"
#line 67 "../../src/hb-ot-shape-complex-sea-machine.rl"
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
for (unsigned int i = last; i < p+1; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
last = p+1; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te, act;
int cs;
hb_glyph_info_t *info = buffer->info;
#line 117 "hb-ot-shape-complex-sea-machine.hh.tmp"
{
cs = sea_syllable_machine_start;
ts = 0;
te = 0;
act = 0;
}
#line 88 "../../src/hb-ot-shape-complex-sea-machine.rl"
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
unsigned int syllable_serial = 1;
#line 134 "hb-ot-shape-complex-sea-machine.hh.tmp"
{
int _slen;
int _trans;
const unsigned char *_keys;
const char *_inds;
if ( p == pe )
goto _test_eof;
_resume:
switch ( _sea_syllable_machine_from_state_actions[cs] ) {
case 5:
#line 1 "NONE"
{ts = p;}
break;
#line 148 "hb-ot-shape-complex-sea-machine.hh.tmp"
}
_keys = _sea_syllable_machine_trans_keys + (cs<<1);
_inds = _sea_syllable_machine_indicies + _sea_syllable_machine_index_offsets[cs];
_slen = _sea_syllable_machine_key_spans[cs];
_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].sea_category()) &&
( info[p].sea_category()) <= _keys[1] ?
( info[p].sea_category()) - _keys[0] : _slen ];
_eof_trans:
cs = _sea_syllable_machine_trans_targs[_trans];
if ( _sea_syllable_machine_trans_actions[_trans] == 0 )
goto _again;
switch ( _sea_syllable_machine_trans_actions[_trans] ) {
case 2:
#line 1 "NONE"
{te = p+1;}
break;
case 6:
#line 63 "../../src/hb-ot-shape-complex-sea-machine.rl"
{te = p+1;{ found_syllable (non_sea_cluster); }}
break;
case 7:
#line 61 "../../src/hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }}
break;
case 8:
#line 62 "../../src/hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }}
break;
case 9:
#line 63 "../../src/hb-ot-shape-complex-sea-machine.rl"
{te = p;p--;{ found_syllable (non_sea_cluster); }}
break;
case 1:
#line 61 "../../src/hb-ot-shape-complex-sea-machine.rl"
{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
break;
case 3:
#line 62 "../../src/hb-ot-shape-complex-sea-machine.rl"
{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
break;
#line 194 "hb-ot-shape-complex-sea-machine.hh.tmp"
}
_again:
switch ( _sea_syllable_machine_to_state_actions[cs] ) {
case 4:
#line 1 "NONE"
{ts = 0;}
break;
#line 203 "hb-ot-shape-complex-sea-machine.hh.tmp"
}
if ( ++p != pe )
goto _resume;
_test_eof: {}
if ( p == eof )
{
if ( _sea_syllable_machine_eof_trans[cs] > 0 ) {
_trans = _sea_syllable_machine_eof_trans[cs] - 1;
goto _eof_trans;
}
}
}
#line 97 "../../src/hb-ot-shape-complex-sea-machine.rl"
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH */

Просмотреть файл

@ -0,0 +1,102 @@
/*
* Copyright © 2011,2012,2013 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_SHAPE_COMPLEX_SEA_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH
#include "hb-private.hh"
%%{
machine sea_syllable_machine;
alphtype unsigned char;
write data;
}%%
%%{
# Same order as enum sea_category_t. Not sure how to avoid duplication.
C = 1;
GB = 12; # Generic Base
H = 4; # Halant
IV = 2; # Independent Vowel
MR = 22; # Medial Ra
CM = 17; # Consonant Medial
VAbv = 26;
VBlw = 27;
VPre = 28;
VPst = 29;
T = 3; # Tone Marks
A = 10; # Anusvara
syllable_tail = (VPre|VAbv|VBlw|VPst|H.C|CM|MR|T|A)*;
consonant_syllable = (C|IV|GB) syllable_tail;
broken_cluster = syllable_tail;
other = any;
main := |*
consonant_syllable => { found_syllable (consonant_syllable); };
broken_cluster => { found_syllable (broken_cluster); };
other => { found_syllable (non_sea_cluster); };
*|;
}%%
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
for (unsigned int i = last; i < p+1; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
last = p+1; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts HB_UNUSED, te, act;
int cs;
hb_glyph_info_t *info = buffer->info;
%%{
write init;
getkey info[p].sea_category();
}%%
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
unsigned int syllable_serial = 1;
%%{
write exec;
}%%
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_SEA_MACHINE_HH */

Просмотреть файл

@ -0,0 +1,400 @@
/*
* Copyright © 2011,2012,2013 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
*/
#include "hb-ot-shape-complex-indic-private.hh"
/* buffer var allocations */
#define sea_category() complex_var_u8_0() /* indic_category_t */
#define sea_position() complex_var_u8_1() /* indic_position_t */
/*
* South-East Asian shaper.
* Loosely based on the Myanmar spec / shaper.
* There is no OpenType spec for this.
*/
static const hb_tag_t
sea_features[] =
{
/*
* Basic features.
* These features are applied in order, one at a time, after initial_reordering.
*/
HB_TAG('p','r','e','f'),
HB_TAG('a','b','v','f'),
HB_TAG('b','l','w','f'),
HB_TAG('p','s','t','f'),
/*
* Other features.
* These features are applied all at once, after final_reordering.
*/
HB_TAG('p','r','e','s'),
HB_TAG('a','b','v','s'),
HB_TAG('b','l','w','s'),
HB_TAG('p','s','t','s'),
/* Positioning features, though we don't care about the types. */
HB_TAG('d','i','s','t'),
};
/*
* Must be in the same order as the sea_features array.
*/
enum {
_PREF,
_ABVF,
_BLWF,
_PSTF,
_PRES,
_ABVS,
_BLWS,
_PSTS,
_DIST,
SEA_NUM_FEATURES,
SEA_BASIC_FEATURES = _PRES /* Don't forget to update this! */
};
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
collect_features_sea (hb_ot_shape_planner_t *plan)
{
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
map->add_bool_feature (HB_TAG('l','o','c','l'));
/* The Indic specs do not require ccmp, but we apply it here since if
* there is a use of it, it's typically at the beginning. */
map->add_bool_feature (HB_TAG('c','c','m','p'));
unsigned int i = 0;
map->add_gsub_pause (initial_reordering);
for (; i < SEA_BASIC_FEATURES; i++) {
map->add_bool_feature (sea_features[i]);
map->add_gsub_pause (NULL);
}
map->add_gsub_pause (final_reordering);
for (; i < SEA_NUM_FEATURES; i++) {
map->add_bool_feature (sea_features[i]);
}
}
static void
override_features_sea (hb_ot_shape_planner_t *plan)
{
plan->map.add_feature (HB_TAG('l','i','g','a'), 0, true);
}
enum syllable_type_t {
consonant_syllable,
broken_cluster,
non_sea_cluster,
};
#include "hb-ot-shape-complex-sea-machine.hh"
/* Note: This enum is duplicated in the -machine.rl source file.
* Not sure how to avoid duplication. */
enum sea_category_t {
// OT_C = 1,
OT_GB = 12, /* Generic Base XXX DOTTED CIRCLE only for now */
// OT_H = 4, /* Halant */
OT_IV = 2, /* Independent Vowel */
OT_MR = 22, /* Medial Ra */
// OT_CM = 17, /* Consonant Medial */
OT_VAbv = 26,
OT_VBlw = 27,
OT_VPre = 28,
OT_VPst = 29,
OT_T = 3, /* Tone Marks */
// OT_A = 10, /* Anusvara */
};
static inline void
set_sea_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u);
indic_category_t cat = (indic_category_t) (type & 0x7F);
indic_position_t pos = (indic_position_t) (type >> 8);
/* Medial Ra */
if (u == 0x1A55 || u == 0xAA34)
cat = (indic_category_t) OT_MR;
if (cat == OT_M)
{
switch ((int) pos)
{
case POS_PRE_C: cat = (indic_category_t) OT_VPre; break;
case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break;
case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break;
case POS_POST_C: cat = (indic_category_t) OT_VPst; break;
}
}
info.sea_category() = (sea_category_t) cat;
info.sea_position() = pos;
}
static void
setup_masks_sea (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
{
HB_BUFFER_ALLOCATE_VAR (buffer, sea_category);
HB_BUFFER_ALLOCATE_VAR (buffer, sea_position);
/* We cannot setup masks here. We save information about characters
* and setup masks later on in a pause-callback. */
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
set_sea_properties (buffer->info[i]);
}
static void
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
find_syllables (buffer);
}
static int
compare_sea_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
{
int a = pa->sea_position();
int b = pb->sea_position();
return a < b ? -1 : a == b ? 0 : +1;
}
static void
initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
hb_glyph_info_t *info = buffer->info;
unsigned int base = start;
/* Reorder! */
unsigned int i = start;
for (; i < base; i++)
info[i].sea_position() = POS_PRE_C;
if (i < end)
{
info[i].sea_position() = POS_BASE_C;
i++;
}
for (; i < end; i++)
{
if (info[i].sea_category() == OT_MR) /* Pre-base reordering */
{
info[i].sea_position() = POS_PRE_C;
continue;
}
if (info[i].sea_position() < POS_BASE_C) /* Left matra */
{
continue;
}
info[i].sea_position() = POS_AFTER_MAIN;
}
buffer->merge_clusters (start, end);
/* Sit tight, rock 'n roll! */
hb_bubble_sort (info + start, end - start, compare_sea_order);
}
static void
initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
/* We already inserted dotted-circles, so just call the consonant_syllable. */
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
}
static void
initial_reordering_non_sea_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer HB_UNUSED,
unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
}
static void
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type) {
case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return;
case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return;
case non_sea_cluster: initial_reordering_non_sea_cluster (plan, face, buffer, start, end); return;
}
}
static inline void
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
/* Note: This loop is extra overhead, but should not be measurable. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
if ((buffer->info[i].syllable() & 0x0F) == broken_cluster) {
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CC;
set_sea_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
{
last_syllable = syllable;
hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask;
info.syllable() = buffer->cur().syllable();
buffer->output_info (info);
}
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
if (unlikely (!count)) return;
unsigned int last = 0;
unsigned int last_syllable = info[0].syllable();
for (unsigned int i = 1; i < count; i++)
if (last_syllable != info[i].syllable()) {
initial_reordering_syllable (plan, font->face, buffer, last, i);
last = i;
last_syllable = info[last].syllable();
}
initial_reordering_syllable (plan, font->face, buffer, last, count);
}
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
/* Zero syllables now... */
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
HB_BUFFER_DEALLOCATE_VAR (buffer, sea_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, sea_position);
}
static hb_ot_shape_normalization_mode_t
normalization_preference_sea (const hb_segment_properties_t *props HB_UNUSED)
{
return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT;
}
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea =
{
"sea",
collect_features_sea,
override_features_sea,
NULL, /* data_create */
NULL, /* data_destroy */
NULL, /* preprocess_text */
normalization_preference_sea,
NULL, /* decompose */
NULL, /* compose */
setup_masks_sea,
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};

Просмотреть файл

@ -373,6 +373,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
NULL, /* decompose */
NULL, /* compose */
NULL, /* setup_masks */
true, /* zero_width_attached_marks */
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE,
false,/* fallback_position */
};

Просмотреть файл

@ -192,30 +192,23 @@ decompose_compatibility (const hb_ot_shape_normalize_context_t *c, hb_codepoint_
}
/* Returns true if recomposition may be benefitial. */
static inline bool
static inline void
decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest)
{
hb_buffer_t * const buffer = c->buffer;
hb_codepoint_t glyph;
unsigned int len = 1;
/* Kind of a cute waterfall here... */
if (shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph))
next_char (buffer, glyph);
else if ((len = decompose (c, shortest, buffer->cur().codepoint)))
else if (decompose (c, shortest, buffer->cur().codepoint))
skip_char (buffer);
else if (!shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph))
next_char (buffer, glyph);
else if ((len = decompose_compatibility (c, buffer->cur().codepoint)))
else if (decompose_compatibility (c, buffer->cur().codepoint))
skip_char (buffer);
else
next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
/*
* A recomposition would only be useful if we decomposed into at least three
* characters...
*/
return len > 2;
}
static inline void
@ -239,7 +232,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns
}
/* Returns true if recomposition may be benefitial. */
static inline bool
static inline void
decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end)
{
hb_buffer_t * const buffer = c->buffer;
@ -247,23 +240,20 @@ decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned
for (unsigned int i = buffer->idx; i < end; i++)
if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) {
handle_variation_selector_cluster (c, end);
return false;
return;
}
while (buffer->idx < end)
decompose_current_character (c, false);
/* We can be smarter here and only return true if there are at least two ccc!=0 marks.
* But does not matter. */
return true;
}
static inline bool
static inline void
decompose_cluster (const hb_ot_shape_normalize_context_t *c, bool short_circuit, unsigned int end)
{
if (likely (c->buffer->idx + 1 == end))
return decompose_current_character (c, short_circuit);
decompose_current_character (c, short_circuit);
else
return decompose_multi_char_cluster (c, end);
decompose_multi_char_cluster (c, end);
}
@ -296,7 +286,6 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
bool short_circuit = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED &&
mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT;
bool can_use_recompose = false;
unsigned int count;
/* We do a fairly straightforward yet custom normalization process in three
@ -317,15 +306,11 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
if (buffer->cur().cluster != buffer->info[end].cluster)
break;
can_use_recompose = decompose_cluster (&c, short_circuit, end) || can_use_recompose;
decompose_cluster (&c, short_circuit, end);
}
buffer->swap_buffers ();
if (mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL && !can_use_recompose)
return; /* Done! */
/* Second round, reorder (inplace) */
count = buffer->len;
@ -369,9 +354,11 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
{
hb_codepoint_t composed, glyph;
if (/* If mode is NOT COMPOSED_FULL (ie. it's COMPOSED_DIACRITICS), we don't try to
* compose a CCC=0 character with it's preceding starter. */
* compose a non-mark character with it's preceding starter. This is just an
* optimization to avoid trying to compose every two neighboring glyphs in most
* scripts. */
(mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL ||
_hb_glyph_info_get_modified_combining_class (&buffer->cur()) != 0) &&
HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) &&
/* If there's anything between the starter and this char, they should have CCC
* smaller than this character's. */
(starter == buffer->out_len - 1 ||

Просмотреть файл

@ -405,7 +405,8 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
hb_ot_layout_position_start (c->font, c->buffer);
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++) {
for (unsigned int i = 0; i < count; i++)
{
c->font->get_glyph_advance_for_direction (c->buffer->info[i].codepoint,
c->buffer->props.direction,
&c->buffer->pos[i].x_advance,
@ -414,6 +415,26 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
c->buffer->props.direction,
&c->buffer->pos[i].x_offset,
&c->buffer->pos[i].y_offset);
}
/* Zero'ing mark widths by GDEF (as used in Myanmar spec) happens
* *before* GPOS. */
switch (c->plan->shaper->zero_width_marks)
{
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF:
for (unsigned int i = 0; i < count; i++)
if ((c->buffer->info[i].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
{
c->buffer->pos[i].x_advance = 0;
c->buffer->pos[i].y_advance = 0;
}
break;
default:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE:
break;
}
}
@ -421,12 +442,12 @@ static inline bool
hb_ot_position_complex (hb_ot_shape_context_t *c)
{
bool ret = false;
unsigned int count = c->buffer->len;
if (hb_ot_layout_has_positioning (c->face))
{
/* Change glyph origin to what GPOS expects, apply GPOS, change it back. */
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++) {
c->font->add_glyph_origin_for_direction (c->buffer->info[i].codepoint,
HB_DIRECTION_LTR,
@ -446,7 +467,26 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
ret = true;
}
hb_ot_layout_position_finish (c->font, c->buffer, c->plan->shaper->zero_width_attached_marks);
/* Zero'ing mark widths by Unicode happens
* *after* GPOS. */
switch (c->plan->shaper->zero_width_marks)
{
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE:
for (unsigned int i = 0; i < count; i++)
if (_hb_glyph_info_get_general_category (&c->buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
{
c->buffer->pos[i].x_advance = 0;
c->buffer->pos[i].y_advance = 0;
}
break;
default:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF:
break;
}
hb_ot_layout_position_finish (c->font, c->buffer);
return ret;
}

Просмотреть файл

@ -854,4 +854,33 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
}
/* Global runtime options. */
struct hb_options_t
{
int initialized : 1;
int uniscribe_bug_compatible : 1;
};
union hb_options_union_t {
int i;
hb_options_t opts;
};
ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
HB_INTERNAL void
_hb_options_init (void);
extern HB_INTERNAL hb_options_union_t _hb_options;
static inline hb_options_t
hb_options (void)
{
if (unlikely (!_hb_options.i))
_hb_options_init ();
return _hb_options.opts;
}
#endif /* HB_PRIVATE_HH */

Просмотреть файл

@ -202,7 +202,7 @@ hb_feature_to_string (hb_feature_t *feature,
static const char **static_shaper_list;
static
static inline
void free_static_shaper_list (void)
{
free (static_shaper_list);

Просмотреть файл

@ -95,7 +95,10 @@ hb_##shaper##_shaper_##object##_data_ensure (hb_##object##_t *object) \
if (unlikely (!data)) \
data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), NULL, data)) { \
HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
if (data && \
data != HB_SHAPER_DATA_INVALID && \
data != HB_SHAPER_DATA_SUCCEEDED) \
HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
goto retry; \
} \
} \

Просмотреть файл

@ -40,7 +40,7 @@ static const hb_shaper_pair_t all_shapers[] = {
static const hb_shaper_pair_t *static_shapers;
static
static inline
void free_static_shapers (void)
{
if (unlikely (static_shapers != all_shapers))

Просмотреть файл

@ -107,6 +107,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
unsigned int
modified_combining_class (hb_codepoint_t unicode)
{
/* XXX This hack belongs to the Myanmar shaper. */
if (unicode == 0x1037) unicode = 0x103A;
return _hb_modified_combining_class[combining_class (unicode)];
}

Просмотреть файл

@ -38,9 +38,9 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 0
#define HB_VERSION_MINOR 9
#define HB_VERSION_MICRO 10
#define HB_VERSION_MICRO 12
#define HB_VERSION_STRING "0.9.10"
#define HB_VERSION_STRING "0.9.12"
#define HB_VERSION_CHECK(major,minor,micro) \
((major)*10000+(minor)*100+(micro) >= \

Просмотреть файл

@ -29,11 +29,38 @@
#if defined(HB_ATOMIC_INT_NIL)
#pragma message("Could not find any system to define atomic_int macros, library may NOT be thread-safe.")
#ifdef _MSC_VER
#pragma message("Could not find any system to define atomic_int macros, library may NOT be thread-safe")
#else
#warning "Could not find any system to define atomic_int macros, library may NOT be thread-safe"
#endif
#endif
#if defined(HB_MUTEX_IMPL_NIL)
#pragma message("Could not find any system to define mutex macros, library may NOT be thread-safe.")
#ifdef _MSC_VER
#pragma message("Could not find any system to define mutex macros, library may NOT be thread-safe")
#else
#warning "Could not find any system to define mutex macros, library may NOT be thread-safe"
#endif
#endif
#if defined(HB_ATOMIC_INT_NIL) || defined(HB_MUTEX_IMPL_NIL)
#pragma message("To suppress these warnings, define HB_NO_MT.")
#ifdef _MSC_VER
#pragma message("To suppress these warnings, define HB_NO_MT")
#else
#warning "To suppress these warnings, define HB_NO_MT"
#endif
#endif
#include "hb-unicode-private.hh"
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
#ifdef _MSC_VER
#pragma message("Could not find any Unicode functions implementation, you have to provide your own")
#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS")
#else
#warning "Could not find any Unicode functions implementation, you have to provide your own"
#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS"
#endif
#endif