[HarfBuzz] harfbuzz-ng: Branch 'master' - 33 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Tue Oct 12 09:35:17 PDT 2010
TODO | 2
autogen.sh | 3
configure.ac | 1
src/Makefile.am | 12
src/check-c-linkage-decls.sh | 2
src/check-header-guards.sh | 2
src/gen-arabic-joining-table.py | 39 ++
src/hb-buffer-private.hh | 14
src/hb-buffer.cc | 1
src/hb-font.cc | 76 ++++
src/hb-font.h | 60 +++
src/hb-open-type-private.hh | 13
src/hb-ot-layout-private.hh | 12
src/hb-ot-map-private.hh | 156 ++++++++
src/hb-ot-map.cc | 165 +++++++++
src/hb-ot-shape-arabic.cc | 706 ++++++++++++++++++++++++++++++++++++++++
src/hb-ot-shape-private.hh | 60 +++
src/hb-ot-shape.cc | 532 ++++++------------------------
src/hb-ot-tag.c | 17
src/hb-private.h | 4
src/hb-unicode.c | 38 ++
src/hb-unicode.h | 33 +
22 files changed, 1502 insertions(+), 446 deletions(-)
New commits:
commit f4792d99eee0e8cd72b7cb01c96a09f16e2a72ce
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Oct 12 12:32:18 2010 -0400
Fix infinite loop!
Untested code is indeed buggy code.
Mozilla bug #603352.
diff --git a/src/hb-ot-tag.c b/src/hb-ot-tag.c
index 32d455d..c325802 100644
--- a/src/hb-ot-tag.c
+++ b/src/hb-ot-tag.c
@@ -630,13 +630,11 @@ hb_ot_tag_from_language (hb_language_t language)
char tag[4];
int i;
lang_str += 6;
- i = 0;
#define IS_LETTER(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
#define TO_UPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) + 'A' - 'a' : (c))
- while (i < 4 && IS_LETTER (lang_str[i])) {
+ for (i = 0; i < 4 && IS_LETTER (lang_str[i]); i++)
tag[i] = TO_UPPER (lang_str[i]);
- }
- while (i < 4)
+ for (; i < 4; i++)
tag[i] = ' ';
return HB_TAG_STR (tag);
}
commit 993d1e786a32612b796dae8309ce402a4121bec7
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Oct 12 11:17:30 2010 -0400
Fix missing negation in unreachable code!
Mozilla bug #603346
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index ea1d371..38ba3a3 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -587,7 +587,7 @@ struct GenericArrayOf
* other structs. */
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
- if (array[i].sanitize (c))
+ if (unlikely (!array[i].sanitize (c)))
return false;
return true;
}
@@ -697,9 +697,8 @@ struct HeadlessArrayOf
* to do have a simple sanitize(), ie. they do not reference
* other structs. */
unsigned int count = len ? len - 1 : 0;
- Type *a = array;
for (unsigned int i = 0; i < count; i++)
- if (unlikely (!a[i].sanitize (c)))
+ if (unlikely (!array[i].sanitize (c)))
return false;
return true;
}
commit 52601275d5e4000dada4f925fb78723eeeee7bd4
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 20:38:46 2010 -0400
More separation
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index e11f1c6..8fc9c4f 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -79,15 +79,8 @@ hb_ot_shape_collect_features (hb_ot_shape_context_t *c)
static void
-hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c)
+hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
{
- hb_ot_shape_collect_features (c);
-
- /* Compile features */
- c->map->compile (c);
-
- /* Set masks in buffer */
-
hb_mask_t global_mask = c->map->get_global_mask ();
if (global_mask)
c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
@@ -278,7 +271,7 @@ hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
- hb_ot_shape_setup_lookups (c);
+ hb_ot_shape_setup_masks (c);
hb_form_clusters (c);
@@ -335,6 +328,9 @@ hb_ot_shape (hb_font_t *font,
c.original_direction = buffer->props.direction;
c.map = ↦
+ hb_ot_shape_collect_features (&c);
+ c.map->compile (&c);
+
hb_ot_shape_internal (&c);
}
commit 6b7e6758626268ba1c7c266128e618ec73ae2c0f
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 20:30:04 2010 -0400
Minor
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 103a497..e11f1c6 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -147,25 +147,25 @@ is_variation_selector (hb_codepoint_t unicode)
}
static void
-hb_form_clusters (hb_buffer_t *buffer)
+hb_form_clusters (hb_ot_shape_context_t *c)
{
- unsigned int count = buffer->len;
+ unsigned int count = c->buffer->len;
for (unsigned int i = 1; i < count; i++)
- if (buffer->unicode->v.get_general_category (buffer->info[i].codepoint) == HB_CATEGORY_NON_SPACING_MARK)
- buffer->info[i].cluster = buffer->info[i - 1].cluster;
+ if (c->buffer->unicode->v.get_general_category (c->buffer->info[i].codepoint) == HB_CATEGORY_NON_SPACING_MARK)
+ c->buffer->info[i].cluster = c->buffer->info[i - 1].cluster;
}
static void
-hb_ensure_native_direction (hb_buffer_t *buffer)
+hb_ensure_native_direction (hb_ot_shape_context_t *c)
{
- hb_direction_t direction = buffer->props.direction;
+ hb_direction_t direction = c->buffer->props.direction;
/* TODO vertical */
if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
- direction != _hb_script_get_horizontal_direction (buffer->props.script))
+ direction != _hb_script_get_horizontal_direction (c->buffer->props.script))
{
- hb_buffer_reverse_clusters (buffer);
- buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
+ hb_buffer_reverse_clusters (c->buffer);
+ c->buffer->props.direction = HB_DIRECTION_REVERSE (c->buffer->props.direction);
}
}
@@ -280,7 +280,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
hb_ot_shape_setup_lookups (c);
- hb_form_clusters (c->buffer);
+ hb_form_clusters (c);
/* SUBSTITUTE */
{
@@ -289,7 +289,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
/* Mirroring needs to see the original direction */
hb_mirror_chars (c);
- hb_ensure_native_direction (c->buffer);
+ hb_ensure_native_direction (c);
hb_substitute_default (c);
commit aa9c450bb2d7c3c9e36ea32e3558250391a0582d
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 20:27:38 2010 -0400
Enable 'rtlm' mirroring
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 29b9c32..816ce4f 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -105,9 +105,7 @@ struct hb_ot_map_t {
hb_ot_map_t (void) : feature_count (0) {}
- void add_feature (hb_tag_t tag,
- unsigned int value,
- bool global)
+ void add_feature (hb_tag_t tag, unsigned int value, bool global)
{
feature_info_t *info = &feature_infos[feature_count++];
info->tag = tag;
@@ -116,11 +114,14 @@ struct hb_ot_map_t {
info->global = global;
}
+ inline void add_bool_feature (hb_tag_t tag, bool global = true)
+ { add_feature (tag, 1, global); }
+
HB_INTERNAL void compile (hb_ot_shape_context_t *c);
hb_mask_t get_global_mask (void) const { return global_mask; }
- hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift) const {
+ hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const {
const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
if (shift) *shift = map ? map->shift : 0;
return map ? map->mask : 0;
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index b43f697..103a497 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -53,12 +53,12 @@ hb_ot_shape_collect_features (hb_ot_shape_context_t *c)
{
switch (c->original_direction) {
case HB_DIRECTION_LTR:
- c->map->add_feature (HB_TAG ('l','t','r','a'), 1, true);
- c->map->add_feature (HB_TAG ('l','t','r','m'), 1, true);
+ c->map->add_bool_feature (HB_TAG ('l','t','r','a'));
+ c->map->add_bool_feature (HB_TAG ('l','t','r','m'));
break;
case HB_DIRECTION_RTL:
- c->map->add_feature (HB_TAG ('r','t','l','a'), 1, true);
- c->map->add_feature (HB_TAG ('r','t','l','m'), 1, false);
+ c->map->add_bool_feature (HB_TAG ('r','t','l','a'));
+ c->map->add_bool_feature (HB_TAG ('r','t','l','m'), false);
break;
case HB_DIRECTION_TTB:
case HB_DIRECTION_BTT:
@@ -67,7 +67,7 @@ hb_ot_shape_collect_features (hb_ot_shape_context_t *c)
}
for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
- c->map->add_feature (default_features[i], 1, true);
+ c->map->add_bool_feature (default_features[i]);
/* complex */
@@ -173,22 +173,22 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
/* Substitute */
static void
-hb_mirror_chars (hb_buffer_t *buffer)
+hb_mirror_chars (hb_ot_shape_context_t *c)
{
- hb_unicode_get_mirroring_func_t get_mirroring = buffer->unicode->v.get_mirroring;
+ hb_unicode_get_mirroring_func_t get_mirroring = c->buffer->unicode->v.get_mirroring;
- if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
+ if (HB_DIRECTION_IS_FORWARD (c->buffer->props.direction))
return;
-// map = c->map.find_feature (HB_TAG ('r','t','l','m'));
+ hb_mask_t rtlm_mask = c->map->get_mask (HB_TAG ('r','t','l','m'));
- unsigned int count = buffer->len;
+ unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++) {
- hb_codepoint_t codepoint = get_mirroring (buffer->info[i].codepoint);
- if (likely (codepoint == buffer->info[i].codepoint))
-;// buffer->info[i].mask |= map->mask;
+ hb_codepoint_t codepoint = get_mirroring (c->buffer->info[i].codepoint);
+ if (likely (codepoint == c->buffer->info[i].codepoint))
+ c->buffer->info[i].mask |= rtlm_mask;
else
- buffer->info[i].codepoint = codepoint;
+ c->buffer->info[i].codepoint = codepoint;
}
}
@@ -287,7 +287,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
c->buffer->clear_masks ();
/* Mirroring needs to see the original direction */
- hb_mirror_chars (c->buffer);
+ hb_mirror_chars (c);
hb_ensure_native_direction (c->buffer);
commit 36925f695d349a53d52ecc3a58f18240a6977463
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 20:20:32 2010 -0400
Rename hb_mask_allocator_t to hb_ot_map_t
hb_ot_plan_t may be a better name, donno.
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 9bd4bf1..29b9c32 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -41,7 +41,7 @@ HB_BEGIN_DECLS
static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
-struct hb_mask_allocator_t {
+struct hb_ot_map_t {
private:
@@ -103,7 +103,7 @@ struct hb_mask_allocator_t {
public:
- hb_mask_allocator_t (void) : feature_count (0) {}
+ hb_ot_map_t (void) : feature_count (0) {}
void add_feature (hb_tag_t tag,
unsigned int value,
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 2092a77..8cf21b4 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -34,7 +34,7 @@ HB_BEGIN_DECLS
void
-hb_mask_allocator_t::compile (hb_ot_shape_context_t *c)
+hb_ot_map_t::compile (hb_ot_shape_context_t *c)
{
global_mask = 0;
lookup_count[0] = lookup_count[1] = 0;
diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh
index c8a0295..b00be33 100644
--- a/src/hb-ot-shape-private.hh
+++ b/src/hb-ot-shape-private.hh
@@ -35,7 +35,7 @@
HB_BEGIN_DECLS
-struct hb_mask_allocator_t;
+struct hb_ot_map_t;
struct hb_ot_shape_context_t
{
@@ -51,7 +51,7 @@ struct hb_ot_shape_context_t
hb_bool_t applied_substitute_complex;
hb_bool_t applied_position_complex;
- struct hb_mask_allocator_t *allocator;
+ struct hb_ot_map_t *map;
};
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index aff1476..b43f697 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -49,17 +49,16 @@ hb_tag_t default_features[] = {
};
static void
-hb_ot_shape_collect_features (hb_ot_shape_context_t *c,
- hb_mask_allocator_t *allocator)
+hb_ot_shape_collect_features (hb_ot_shape_context_t *c)
{
switch (c->original_direction) {
case HB_DIRECTION_LTR:
- allocator->add_feature (HB_TAG ('l','t','r','a'), 1, true);
- allocator->add_feature (HB_TAG ('l','t','r','m'), 1, true);
+ c->map->add_feature (HB_TAG ('l','t','r','a'), 1, true);
+ c->map->add_feature (HB_TAG ('l','t','r','m'), 1, true);
break;
case HB_DIRECTION_RTL:
- allocator->add_feature (HB_TAG ('r','t','l','a'), 1, true);
- allocator->add_feature (HB_TAG ('r','t','l','m'), 1, false);
+ c->map->add_feature (HB_TAG ('r','t','l','a'), 1, true);
+ c->map->add_feature (HB_TAG ('r','t','l','m'), 1, false);
break;
case HB_DIRECTION_TTB:
case HB_DIRECTION_BTT:
@@ -68,29 +67,28 @@ hb_ot_shape_collect_features (hb_ot_shape_context_t *c,
}
for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
- allocator->add_feature (default_features[i], 1, true);
+ c->map->add_feature (default_features[i], 1, true);
/* complex */
for (unsigned int i = 0; i < c->num_features; i++) {
const hb_feature_t *feature = &c->features[i];
- allocator->add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
+ c->map->add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
}
}
static void
-hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
- hb_mask_allocator_t *allocator)
+hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c)
{
- hb_ot_shape_collect_features (c, allocator);
+ hb_ot_shape_collect_features (c);
/* Compile features */
- allocator->compile (c);
+ c->map->compile (c);
/* Set masks in buffer */
- hb_mask_t global_mask = allocator->get_global_mask ();
+ hb_mask_t global_mask = c->map->get_global_mask ();
if (global_mask)
c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
@@ -99,7 +97,7 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
hb_feature_t *feature = &c->features[i];
if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
unsigned int shift;
- hb_mask_t mask = allocator->get_mask (feature->tag, &shift);
+ hb_mask_t mask = c->map->get_mask (feature->tag, &shift);
c->buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
}
}
@@ -109,27 +107,25 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
static void
-hb_ot_substitute_complex (hb_ot_shape_context_t *c,
- const hb_mask_allocator_t *allocator)
+hb_ot_substitute_complex (hb_ot_shape_context_t *c)
{
if (!hb_ot_layout_has_substitution (c->face))
return;
- allocator->substitute (c);
+ c->map->substitute (c);
c->applied_substitute_complex = TRUE;
return;
}
static void
-hb_ot_position_complex (hb_ot_shape_context_t *c,
- const hb_mask_allocator_t *allocator)
+hb_ot_position_complex (hb_ot_shape_context_t *c)
{
if (!hb_ot_layout_has_positioning (c->face))
return;
- allocator->position (c);
+ c->map->position (c);
hb_ot_layout_position_finish (c->font, c->face, c->buffer);
@@ -184,7 +180,7 @@ hb_mirror_chars (hb_buffer_t *buffer)
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
return;
-// map = allocator.find_feature (HB_TAG ('r','t','l','m'));
+// map = c->map.find_feature (HB_TAG ('r','t','l','m'));
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++) {
@@ -282,10 +278,7 @@ hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
- hb_mask_allocator_t allocator;
-
- hb_ot_shape_setup_lookups (c, &allocator);
-
+ hb_ot_shape_setup_lookups (c);
hb_form_clusters (c->buffer);
@@ -300,7 +293,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
hb_substitute_default (c);
- hb_ot_substitute_complex (c, &allocator);
+ hb_ot_substitute_complex (c);
if (!c->applied_substitute_complex)
hb_substitute_complex_fallback (c);
@@ -312,7 +305,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
hb_position_default (c);
- hb_ot_position_complex (c, &allocator);
+ hb_ot_position_complex (c);
hb_bool_t position_fallback = !c->applied_position_complex;
if (position_fallback)
@@ -336,9 +329,11 @@ hb_ot_shape (hb_font_t *font,
unsigned int num_features)
{
hb_ot_shape_context_t c = {font, face, buffer, features, num_features};
+ hb_ot_map_t map;
/* Setup transient context members */
c.original_direction = buffer->props.direction;
+ c.map = ↦
hb_ot_shape_internal (&c);
}
commit f5dd3be46b5c77a2c5b97b82a0b67ac9e851b898
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 20:16:23 2010 -0400
Improve checks
diff --git a/src/check-c-linkage-decls.sh b/src/check-c-linkage-decls.sh
index c262516..711d089 100755
--- a/src/check-c-linkage-decls.sh
+++ b/src/check-c-linkage-decls.sh
@@ -8,7 +8,7 @@ stat=0
cd "$srcdir"
-for x in *.c *.cc *.h *.hh ; do
+for x in hb-*.c hb-*.cc hb-*.h hb-*.hh ; do
if ! grep -q HB_BEGIN_DECLS "$x" || ! grep -q HB_END_DECLS "$x"; then
echo "Ouch, file $x does not HB_BEGIN_DECLS / HB_END_DECLS"
stat=1
diff --git a/src/check-header-guards.sh b/src/check-header-guards.sh
index 59c399a..c966cd2 100755
--- a/src/check-header-guards.sh
+++ b/src/check-header-guards.sh
@@ -8,7 +8,7 @@ stat=0
cd "$srcdir"
-for x in *.h *.hh ; do
+for x in hb-*.h hb-*.hh ; do
tag=`echo "$x" | tr 'a-z.-' 'A-Z_'`
lines=`grep "\<$tag\>" "$x" | wc -l`
if test "x$lines" != x3; then
commit 5a2b0b3878cd9c62121bb4fd6344e102a9ee1825
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 20:14:57 2010 -0400
Add hb-ot-map.cc
diff --git a/src/Makefile.am b/src/Makefile.am
index c47a1a5..4908876 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,7 @@ HBSOURCES += \
hb-ot-layout-gsubgpos-private.hh \
hb-ot-layout-gsub-private.hh \
hb-ot-layout-private.hh \
+ hb-ot-map.cc \
hb-ot-map-private.hh \
hb-ot-shape.cc \
hb-ot-shape-private.hh \
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 4d1deef..9bd4bf1 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -116,134 +116,9 @@ struct hb_mask_allocator_t {
info->global = global;
}
- void compile (hb_ot_shape_context_t *c)
- {
- global_mask = 0;
- lookup_count[0] = lookup_count[1] = 0;
-
- if (!feature_count)
- return;
-
-
- /* Fetch script/language indices for GSUB/GPOS. We need these later to skip
- * features not available in either table and not waste precious bits for them. */
-
- const hb_tag_t *script_tags;
- hb_tag_t language_tag;
-
- script_tags = hb_ot_tags_from_script (c->buffer->props.script);
- language_tag = hb_ot_tag_from_language (c->buffer->props.language);
-
- unsigned int script_index[2], language_index[2];
- for (unsigned int table_index = 0; table_index < 2; table_index++) {
- hb_tag_t table_tag = table_tags[table_index];
- hb_ot_layout_table_choose_script (c->face, table_tag, script_tags, &script_index[table_index]);
- hb_ot_layout_script_find_language (c->face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
- }
-
-
- /* Sort features and merge duplicates */
- qsort (feature_infos, feature_count, sizeof (feature_infos[0]), (hb_compare_func_t) feature_info_t::cmp);
- unsigned int j = 0;
- for (unsigned int i = 1; i < feature_count; i++)
- if (feature_infos[i].tag != feature_infos[j].tag)
- feature_infos[++j] = feature_infos[i];
- else {
- if (feature_infos[i].global)
- feature_infos[j] = feature_infos[i];
- else {
- feature_infos[j].global = false;
- feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
- }
- }
- feature_count = j + 1;
-
-
- /* Allocate bits now */
- unsigned int next_bit = 1;
- j = 0;
- for (unsigned int i = 0; i < feature_count; i++) {
- const feature_info_t *info = &feature_infos[i];
-
- unsigned int bits_needed;
-
- if (info->global && info->value == 1)
- /* Uses the global bit */
- bits_needed = 0;
- else
- bits_needed = _hb_bit_storage (info->value);
-
- if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
- continue; /* Feature disabled, or not enough bits. */
-
-
- bool found = false;
- unsigned int feature_index[2];
- for (unsigned int table_index = 0; table_index < 2; table_index++)
- found |= hb_ot_layout_language_find_feature (c->face,
- table_tags[table_index],
- script_index[table_index],
- language_index[table_index],
- info->tag,
- &feature_index[table_index]);
- if (!found)
- continue;
-
-
- feature_map_t *map = &feature_maps[j++];
-
- map->tag = info->tag;
- map->index[0] = feature_index[0];
- map->index[1] = feature_index[1];
- if (info->global && info->value == 1) {
- /* Uses the global bit */
- map->shift = 0;
- map->mask = 1;
- } else {
- map->shift = next_bit;
- map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
- next_bit += bits_needed;
- if (info->global)
- global_mask |= map->mask;
- }
-
- }
- feature_count = j;
-
-
- for (unsigned int table_index = 0; table_index < 2; table_index++) {
- hb_tag_t table_tag = table_tags[table_index];
-
- /* Collect lookup indices for features */
-
- unsigned int required_feature_index;
- if (hb_ot_layout_language_get_required_feature_index (c->face,
- table_tag,
- script_index[table_index],
- language_index[table_index],
- &required_feature_index))
- add_lookups (c, table_index, required_feature_index, 1);
-
- for (unsigned i = 0; i < feature_count; i++)
- add_lookups (c, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
-
- /* Sort lookups and merge duplicates */
- qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), (hb_compare_func_t) lookup_map_t::cmp);
- if (lookup_count[table_index])
- {
- unsigned int j = 0;
- for (unsigned int i = 1; i < lookup_count[table_index]; i++)
- if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
- lookup_maps[table_index][++j] = lookup_maps[table_index][i];
- else
- lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
- j++;
- lookup_count[table_index] = j;
- }
- }
- }
+ HB_INTERNAL void compile (hb_ot_shape_context_t *c);
- hb_mask_t get_global_mask (void) { return global_mask; }
+ hb_mask_t get_global_mask (void) const { return global_mask; }
hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift) const {
const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
new file mode 100644
index 0000000..2092a77
--- /dev/null
+++ b/src/hb-ot-map.cc
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2009,2010 Red Hat, Inc.
+ * Copyright (C) 2010 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-ot-map-private.hh"
+
+#include "hb-ot-shape-private.hh"
+
+HB_BEGIN_DECLS
+
+
+void
+hb_mask_allocator_t::compile (hb_ot_shape_context_t *c)
+{
+ global_mask = 0;
+ lookup_count[0] = lookup_count[1] = 0;
+
+ if (!feature_count)
+ return;
+
+
+ /* Fetch script/language indices for GSUB/GPOS. We need these later to skip
+ * features not available in either table and not waste precious bits for them. */
+
+ const hb_tag_t *script_tags;
+ hb_tag_t language_tag;
+
+ script_tags = hb_ot_tags_from_script (c->buffer->props.script);
+ language_tag = hb_ot_tag_from_language (c->buffer->props.language);
+
+ unsigned int script_index[2], language_index[2];
+ for (unsigned int table_index = 0; table_index < 2; table_index++) {
+ hb_tag_t table_tag = table_tags[table_index];
+ hb_ot_layout_table_choose_script (c->face, table_tag, script_tags, &script_index[table_index]);
+ hb_ot_layout_script_find_language (c->face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
+ }
+
+
+ /* Sort features and merge duplicates */
+ qsort (feature_infos, feature_count, sizeof (feature_infos[0]), (hb_compare_func_t) feature_info_t::cmp);
+ unsigned int j = 0;
+ for (unsigned int i = 1; i < feature_count; i++)
+ if (feature_infos[i].tag != feature_infos[j].tag)
+ feature_infos[++j] = feature_infos[i];
+ else {
+ if (feature_infos[i].global)
+ feature_infos[j] = feature_infos[i];
+ else {
+ feature_infos[j].global = false;
+ feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
+ }
+ }
+ feature_count = j + 1;
+
+
+ /* Allocate bits now */
+ unsigned int next_bit = 1;
+ j = 0;
+ for (unsigned int i = 0; i < feature_count; i++) {
+ const feature_info_t *info = &feature_infos[i];
+
+ unsigned int bits_needed;
+
+ if (info->global && info->value == 1)
+ /* Uses the global bit */
+ bits_needed = 0;
+ else
+ bits_needed = _hb_bit_storage (info->value);
+
+ if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
+ continue; /* Feature disabled, or not enough bits. */
+
+
+ bool found = false;
+ unsigned int feature_index[2];
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ found |= hb_ot_layout_language_find_feature (c->face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ info->tag,
+ &feature_index[table_index]);
+ if (!found)
+ continue;
+
+
+ feature_map_t *map = &feature_maps[j++];
+
+ map->tag = info->tag;
+ map->index[0] = feature_index[0];
+ map->index[1] = feature_index[1];
+ if (info->global && info->value == 1) {
+ /* Uses the global bit */
+ map->shift = 0;
+ map->mask = 1;
+ } else {
+ map->shift = next_bit;
+ map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
+ next_bit += bits_needed;
+ if (info->global)
+ global_mask |= map->mask;
+ }
+
+ }
+ feature_count = j;
+
+
+ for (unsigned int table_index = 0; table_index < 2; table_index++) {
+ hb_tag_t table_tag = table_tags[table_index];
+
+ /* Collect lookup indices for features */
+
+ unsigned int required_feature_index;
+ if (hb_ot_layout_language_get_required_feature_index (c->face,
+ table_tag,
+ script_index[table_index],
+ language_index[table_index],
+ &required_feature_index))
+ add_lookups (c, table_index, required_feature_index, 1);
+
+ for (unsigned i = 0; i < feature_count; i++)
+ add_lookups (c, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
+
+ /* Sort lookups and merge duplicates */
+ qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), (hb_compare_func_t) lookup_map_t::cmp);
+ if (lookup_count[table_index])
+ {
+ unsigned int j = 0;
+ for (unsigned int i = 1; i < lookup_count[table_index]; i++)
+ if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
+ lookup_maps[table_index][++j] = lookup_maps[table_index][i];
+ else
+ lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
+ j++;
+ lookup_count[table_index] = j;
+ }
+ }
+}
+
+
+HB_END_DECLS
commit ecc4550ed7bc900a61081edfbcd0ad09cbf29b36
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 20:05:29 2010 -0400
Fix feature overriding
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 2d790b0..4d1deef 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -152,7 +152,7 @@ struct hb_mask_allocator_t {
if (feature_infos[i].global)
feature_infos[j] = feature_infos[i];
else {
- feature_infos[j].global = feature_infos[j].global && (feature_infos[j].value == feature_infos[i].value);
+ feature_infos[j].global = false;
feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
}
}
commit 8f08c3275040870a645ef034a38d30c05c619f21
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 19:43:48 2010 -0400
Minor cleanup
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index b83a2e3..ea1d371 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -718,13 +718,9 @@ struct SortedArrayOf : ArrayOf<Type> {
template <typename SearchType>
inline int search (const SearchType &x) const {
class Cmp {
- public: static int cmp (const void *p1, const void *p2) {
- const SearchType *a = reinterpret_cast<const SearchType *>(p1);
- const Type *b = reinterpret_cast<const Type *>(p2);
- return b->cmp (*a);
- }
+ public: static int cmp (const SearchType *a, const Type *b) { return b->cmp (*a); }
};
- const Type *p = (const Type *) bsearch (&x, this->array, this->len, sizeof (this->array[0]), Cmp::cmp);
+ const Type *p = (const Type *) bsearch (&x, this->array, this->len, sizeof (this->array[0]), (hb_compare_func_t) Cmp::cmp);
return p ? p - this->array : -1;
}
};
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 786a0d0..2d790b0 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -43,23 +43,16 @@ static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
struct hb_mask_allocator_t {
+ private:
+
struct feature_info_t {
hb_tag_t tag;
unsigned int value;
unsigned int seq;
bool global;
- static int
- cmp (const void *p1, const void *p2)
- {
- const feature_info_t *a = reinterpret_cast<const feature_info_t *>(p1);
- const feature_info_t *b = reinterpret_cast<const feature_info_t *>(p2);
-
- if (a->tag != b->tag)
- return a->tag < b->tag ? -1 : 1;
-
- return a->seq < b->seq ? -1 : 1;
- }
+ static int cmp (const feature_info_t *a, const feature_info_t *b)
+ { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); }
};
struct feature_map_t {
@@ -68,28 +61,16 @@ struct hb_mask_allocator_t {
unsigned int shift;
hb_mask_t mask;
- static int
- cmp (const void *p1, const void *p2)
- {
- const feature_map_t *a = reinterpret_cast<const feature_map_t *>(p1);
- const feature_map_t *b = reinterpret_cast<const feature_map_t *>(p2);
-
- return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0;
- }
+ static int cmp (const feature_map_t *a, const feature_map_t *b)
+ { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; }
};
struct lookup_map_t {
unsigned int index;
hb_mask_t mask;
- static int
- cmp (const void *p1, const void *p2)
- {
- const lookup_map_t *a = reinterpret_cast<const lookup_map_t *>(p1);
- const lookup_map_t *b = reinterpret_cast<const lookup_map_t *>(p2);
-
- return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
- }
+ static int cmp (const lookup_map_t *a, const lookup_map_t *b)
+ { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; }
};
@@ -120,6 +101,7 @@ struct hb_mask_allocator_t {
+ public:
hb_mask_allocator_t (void) : feature_count (0) {}
@@ -160,10 +142,8 @@ struct hb_mask_allocator_t {
}
- /* Sort the features so we can bsearch later */
- qsort (feature_infos, feature_count, sizeof (feature_infos[0]), feature_info_t::cmp);
-
- /* Remove dups, let later-occurring features override earlier ones. */
+ /* Sort features and merge duplicates */
+ qsort (feature_infos, feature_count, sizeof (feature_infos[0]), (hb_compare_func_t) feature_info_t::cmp);
unsigned int j = 0;
for (unsigned int i = 1; i < feature_count; i++)
if (feature_infos[i].tag != feature_infos[j].tag)
@@ -248,9 +228,7 @@ struct hb_mask_allocator_t {
add_lookups (c, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
/* Sort lookups and merge duplicates */
-
- qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), lookup_map_t::cmp);
-
+ qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), (hb_compare_func_t) lookup_map_t::cmp);
if (lookup_count[table_index])
{
unsigned int j = 0;
@@ -268,22 +246,17 @@ struct hb_mask_allocator_t {
hb_mask_t get_global_mask (void) { return global_mask; }
hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift) const {
- const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), feature_map_t::cmp);
- if (likely (map)) {
- if (shift) *shift = map->shift;
- return map->mask;
- } else {
- if (shift) *shift = 0;
- return 0;
- }
+ const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
+ if (shift) *shift = map ? map->shift : 0;
+ return map ? map->mask : 0;
}
- void substitute (hb_ot_shape_context_t *c) const {
+ inline void substitute (hb_ot_shape_context_t *c) const {
for (unsigned int i = 0; i < lookup_count[0]; i++)
hb_ot_layout_substitute_lookup (c->face, c->buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
}
- void position (hb_ot_shape_context_t *c) const {
+ inline void position (hb_ot_shape_context_t *c) const {
for (unsigned int i = 0; i < lookup_count[1]; i++)
hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask);
}
diff --git a/src/hb-ot-tag.c b/src/hb-ot-tag.c
index 448f795..32d455d 100644
--- a/src/hb-ot-tag.c
+++ b/src/hb-ot-tag.c
@@ -591,10 +591,9 @@ static const LangTag ot_languages[] = {
};
static int
-lang_compare_first_component (const void *pa,
- const void *pb)
+lang_compare_first_component (const char *a,
+ const char *b)
{
- const char *a = pa, *b = pb;
unsigned int da, db;
const char *p;
@@ -645,7 +644,7 @@ hb_ot_tag_from_language (hb_language_t language)
/* find a language matching in the first component */
lang_tag = bsearch (lang_str, ot_languages,
ARRAY_LENGTH (ot_languages), sizeof (LangTag),
- lang_compare_first_component);
+ (hb_compare_func_t) lang_compare_first_component);
/* we now need to find the best language matching */
if (lang_tag)
@@ -654,12 +653,12 @@ hb_ot_tag_from_language (hb_language_t language)
/* go to the final one matching in the first component */
while (lang_tag + 1 < ot_languages + ARRAY_LENGTH (ot_languages) &&
- lang_compare_first_component (lang_str, lang_tag + 1) == 0)
+ lang_compare_first_component (lang_str, (lang_tag + 1)->language) == 0)
lang_tag++;
/* go back, find which one matches completely */
while (lang_tag >= ot_languages &&
- lang_compare_first_component (lang_str, lang_tag) == 0)
+ lang_compare_first_component (lang_str, lang_tag->language) == 0)
{
if (lang_matches (lang_str, lang_tag->language)) {
found = TRUE;
diff --git a/src/hb-private.h b/src/hb-private.h
index ad7c362..1d4cfc9 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -186,6 +186,10 @@ _hb_ctz (unsigned int number)
#endif
}
+/* Type of bsearch() / qsort() compare function */
+typedef int (*hb_compare_func_t) (const void *, const void *);
+
+
/* We need external help for these */
#ifdef HAVE_GLIB
commit a806762a314e83154793d96ee665e6668d6b56de
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 19:18:40 2010 -0400
Add hb-ot-shape-private.hh
diff --git a/src/Makefile.am b/src/Makefile.am
index dba3bb3..c47a1a5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -49,6 +49,7 @@ HBSOURCES += \
hb-ot-layout-private.hh \
hb-ot-map-private.hh \
hb-ot-shape.cc \
+ hb-ot-shape-private.hh \
hb-ot-shape-arabic.cc \
hb-ot-tag.c \
$(NULL)
diff --git a/src/hb-ot-shape-arabic.cc b/src/hb-ot-shape-arabic.cc
index 1eb3081..7729be1 100644
--- a/src/hb-ot-shape-arabic.cc
+++ b/src/hb-ot-shape-arabic.cc
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "hb-ot-shape-private.h"
+#include "hb-ot-shape-private.hh"
HB_BEGIN_DECLS
diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh
new file mode 100644
index 0000000..c8a0295
--- /dev/null
+++ b/src/hb-ot-shape-private.hh
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 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_PRIVATE_HH
+#define HB_OT_SHAPE_PRIVATE_HH
+
+#include "hb-private.h"
+
+#include "hb-ot-shape.h"
+
+#include "hb-buffer-private.hh"
+
+HB_BEGIN_DECLS
+
+struct hb_mask_allocator_t;
+
+struct hb_ot_shape_context_t
+{
+ /* Input to hb_ot_shape() */
+ hb_font_t *font;
+ hb_face_t *face;
+ hb_buffer_t *buffer;
+ hb_feature_t *features;
+ unsigned int num_features;
+
+ /* Transient stuff */
+ hb_direction_t original_direction;
+ hb_bool_t applied_substitute_complex;
+ hb_bool_t applied_position_complex;
+
+ struct hb_mask_allocator_t *allocator;
+};
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_SHAPE_PRIVATE_HH */
commit 4924affe0f0adf75f2a0e2137a71206b0576d63f
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 19:18:16 2010 -0400
Add hb-ot-map-private.hh
diff --git a/src/Makefile.am b/src/Makefile.am
index 8e7ac47..dba3bb3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,7 @@ HBSOURCES += \
hb-ot-layout-gsubgpos-private.hh \
hb-ot-layout-gsub-private.hh \
hb-ot-layout-private.hh \
+ hb-ot-map-private.hh \
hb-ot-shape.cc \
hb-ot-shape-arabic.cc \
hb-ot-tag.c \
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
new file mode 100644
index 0000000..786a0d0
--- /dev/null
+++ b/src/hb-ot-map-private.hh
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2009,2010 Red Hat, Inc.
+ * Copyright (C) 2010 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_MAP_PRIVATE_HH
+#define HB_OT_MAP_PRIVATE_HH
+
+#include "hb-ot-shape-private.hh"
+
+#include "hb-ot-layout.h"
+
+HB_BEGIN_DECLS
+
+
+#define MAX_FEATURES 100 /* FIXME */
+#define MAX_LOOKUPS 1000 /* FIXME */
+
+static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
+
+struct hb_mask_allocator_t {
+
+ struct feature_info_t {
+ hb_tag_t tag;
+ unsigned int value;
+ unsigned int seq;
+ bool global;
+
+ static int
+ cmp (const void *p1, const void *p2)
+ {
+ const feature_info_t *a = reinterpret_cast<const feature_info_t *>(p1);
+ const feature_info_t *b = reinterpret_cast<const feature_info_t *>(p2);
+
+ if (a->tag != b->tag)
+ return a->tag < b->tag ? -1 : 1;
+
+ return a->seq < b->seq ? -1 : 1;
+ }
+ };
+
+ struct feature_map_t {
+ hb_tag_t tag; /* should be first for our bsearch to work */
+ unsigned int index[2]; /* GSUB, GPOS */
+ unsigned int shift;
+ hb_mask_t mask;
+
+ static int
+ cmp (const void *p1, const void *p2)
+ {
+ const feature_map_t *a = reinterpret_cast<const feature_map_t *>(p1);
+ const feature_map_t *b = reinterpret_cast<const feature_map_t *>(p2);
+
+ return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0;
+ }
+ };
+
+ struct lookup_map_t {
+ unsigned int index;
+ hb_mask_t mask;
+
+ static int
+ cmp (const void *p1, const void *p2)
+ {
+ const lookup_map_t *a = reinterpret_cast<const lookup_map_t *>(p1);
+ const lookup_map_t *b = reinterpret_cast<const lookup_map_t *>(p2);
+
+ return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
+ }
+ };
+
+
+ void
+ add_lookups (hb_ot_shape_context_t *c,
+ unsigned int table_index,
+ unsigned int feature_index,
+ hb_mask_t mask)
+ {
+ unsigned int i = MAX_LOOKUPS - lookup_count[table_index];
+ lookup_map_t *lookups = lookup_maps[table_index] + lookup_count[table_index];
+
+ unsigned int *lookup_indices = (unsigned int *) lookups;
+
+ hb_ot_layout_feature_get_lookup_indexes (c->face,
+ table_tags[table_index],
+ feature_index,
+ 0, &i,
+ lookup_indices);
+
+ lookup_count[table_index] += i;
+
+ while (i--) {
+ lookups[i].mask = mask;
+ lookups[i].index = lookup_indices[i];
+ }
+ }
+
+
+
+
+ hb_mask_allocator_t (void) : feature_count (0) {}
+
+ void add_feature (hb_tag_t tag,
+ unsigned int value,
+ bool global)
+ {
+ feature_info_t *info = &feature_infos[feature_count++];
+ info->tag = tag;
+ info->value = value;
+ info->seq = feature_count;
+ info->global = global;
+ }
+
+ void compile (hb_ot_shape_context_t *c)
+ {
+ global_mask = 0;
+ lookup_count[0] = lookup_count[1] = 0;
+
+ if (!feature_count)
+ return;
+
+
+ /* Fetch script/language indices for GSUB/GPOS. We need these later to skip
+ * features not available in either table and not waste precious bits for them. */
+
+ const hb_tag_t *script_tags;
+ hb_tag_t language_tag;
+
+ script_tags = hb_ot_tags_from_script (c->buffer->props.script);
+ language_tag = hb_ot_tag_from_language (c->buffer->props.language);
+
+ unsigned int script_index[2], language_index[2];
+ for (unsigned int table_index = 0; table_index < 2; table_index++) {
+ hb_tag_t table_tag = table_tags[table_index];
+ hb_ot_layout_table_choose_script (c->face, table_tag, script_tags, &script_index[table_index]);
+ hb_ot_layout_script_find_language (c->face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
+ }
+
+
+ /* Sort the features so we can bsearch later */
+ qsort (feature_infos, feature_count, sizeof (feature_infos[0]), feature_info_t::cmp);
+
+ /* Remove dups, let later-occurring features override earlier ones. */
+ unsigned int j = 0;
+ for (unsigned int i = 1; i < feature_count; i++)
+ if (feature_infos[i].tag != feature_infos[j].tag)
+ feature_infos[++j] = feature_infos[i];
+ else {
+ if (feature_infos[i].global)
+ feature_infos[j] = feature_infos[i];
+ else {
+ feature_infos[j].global = feature_infos[j].global && (feature_infos[j].value == feature_infos[i].value);
+ feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
+ }
+ }
+ feature_count = j + 1;
+
+
+ /* Allocate bits now */
+ unsigned int next_bit = 1;
+ j = 0;
+ for (unsigned int i = 0; i < feature_count; i++) {
+ const feature_info_t *info = &feature_infos[i];
+
+ unsigned int bits_needed;
+
+ if (info->global && info->value == 1)
+ /* Uses the global bit */
+ bits_needed = 0;
+ else
+ bits_needed = _hb_bit_storage (info->value);
+
+ if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
+ continue; /* Feature disabled, or not enough bits. */
+
+
+ bool found = false;
+ unsigned int feature_index[2];
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ found |= hb_ot_layout_language_find_feature (c->face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ info->tag,
+ &feature_index[table_index]);
+ if (!found)
+ continue;
+
+
+ feature_map_t *map = &feature_maps[j++];
+
+ map->tag = info->tag;
+ map->index[0] = feature_index[0];
+ map->index[1] = feature_index[1];
+ if (info->global && info->value == 1) {
+ /* Uses the global bit */
+ map->shift = 0;
+ map->mask = 1;
+ } else {
+ map->shift = next_bit;
+ map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
+ next_bit += bits_needed;
+ if (info->global)
+ global_mask |= map->mask;
+ }
+
+ }
+ feature_count = j;
+
+
+ for (unsigned int table_index = 0; table_index < 2; table_index++) {
+ hb_tag_t table_tag = table_tags[table_index];
+
+ /* Collect lookup indices for features */
+
+ unsigned int required_feature_index;
+ if (hb_ot_layout_language_get_required_feature_index (c->face,
+ table_tag,
+ script_index[table_index],
+ language_index[table_index],
+ &required_feature_index))
+ add_lookups (c, table_index, required_feature_index, 1);
+
+ for (unsigned i = 0; i < feature_count; i++)
+ add_lookups (c, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
+
+ /* Sort lookups and merge duplicates */
+
+ qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), lookup_map_t::cmp);
+
+ if (lookup_count[table_index])
+ {
+ unsigned int j = 0;
+ for (unsigned int i = 1; i < lookup_count[table_index]; i++)
+ if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
+ lookup_maps[table_index][++j] = lookup_maps[table_index][i];
+ else
+ lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
+ j++;
+ lookup_count[table_index] = j;
+ }
+ }
+ }
+
+ hb_mask_t get_global_mask (void) { return global_mask; }
+
+ hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift) const {
+ const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), feature_map_t::cmp);
+ if (likely (map)) {
+ if (shift) *shift = map->shift;
+ return map->mask;
+ } else {
+ if (shift) *shift = 0;
+ return 0;
+ }
+ }
+
+ void substitute (hb_ot_shape_context_t *c) const {
+ for (unsigned int i = 0; i < lookup_count[0]; i++)
+ hb_ot_layout_substitute_lookup (c->face, c->buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
+ }
+
+ void position (hb_ot_shape_context_t *c) const {
+ for (unsigned int i = 0; i < lookup_count[1]; i++)
+ hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask);
+ }
+
+ private:
+
+ hb_mask_t global_mask;
+
+ unsigned int feature_count;
+ feature_info_t feature_infos[MAX_FEATURES]; /* used before compile() only */
+ feature_map_t feature_maps[MAX_FEATURES];
+
+ lookup_map_t lookup_maps[2][MAX_LOOKUPS]; /* GSUB/GPOS */
+ unsigned int lookup_count[2];
+};
+
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_MAP_PRIVATE_HH */
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 11dcaa1..aff1476 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -26,11 +26,9 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "hb-ot-shape-private.h"
+#include "hb-ot-shape-private.hh"
-#include "hb-open-type-private.hh"
-
-#include "hb-ot-layout.h"
+#include "hb-ot-map-private.hh"
HB_BEGIN_DECLS
@@ -50,266 +48,6 @@ hb_tag_t default_features[] = {
HB_TAG('r','l','i','g')
};
-#define MAX_FEATURES 100 /* FIXME */
-#define MAX_LOOKUPS 1000 /* FIXME */
-
-static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
-
-
-struct hb_mask_allocator_t {
-
- struct feature_info_t {
- hb_tag_t tag;
- unsigned int value;
- unsigned int seq;
- bool global;
-
- static int
- cmp (const void *p1, const void *p2)
- {
- const feature_info_t *a = reinterpret_cast<const feature_info_t *>(p1);
- const feature_info_t *b = reinterpret_cast<const feature_info_t *>(p2);
-
- if (a->tag != b->tag)
- return a->tag < b->tag ? -1 : 1;
-
- return a->seq < b->seq ? -1 : 1;
- }
- };
-
- struct feature_map_t {
- hb_tag_t tag; /* should be first for our bsearch to work */
- unsigned int index[2]; /* GSUB, GPOS */
- unsigned int shift;
- hb_mask_t mask;
-
- static int
- cmp (const void *p1, const void *p2)
- {
- const feature_map_t *a = reinterpret_cast<const feature_map_t *>(p1);
- const feature_map_t *b = reinterpret_cast<const feature_map_t *>(p2);
-
- return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0;
- }
- };
-
- struct lookup_map_t {
- unsigned int index;
- hb_mask_t mask;
-
- static int
- cmp (const void *p1, const void *p2)
- {
- const lookup_map_t *a = reinterpret_cast<const lookup_map_t *>(p1);
- const lookup_map_t *b = reinterpret_cast<const lookup_map_t *>(p2);
-
- return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
- }
- };
-
-
- void
- add_lookups (hb_ot_shape_context_t *c,
- unsigned int table_index,
- unsigned int feature_index,
- hb_mask_t mask)
- {
- unsigned int i = MAX_LOOKUPS - lookup_count[table_index];
- lookup_map_t *lookups = lookup_maps[table_index] + lookup_count[table_index];
-
- unsigned int *lookup_indices = (unsigned int *) lookups;
-
- hb_ot_layout_feature_get_lookup_indexes (c->face,
- table_tags[table_index],
- feature_index,
- 0, &i,
- lookup_indices);
-
- lookup_count[table_index] += i;
-
- while (i--) {
- lookups[i].mask = mask;
- lookups[i].index = lookup_indices[i];
- }
- }
-
-
-
-
- hb_mask_allocator_t (void) : feature_count (0) {}
-
- void add_feature (hb_tag_t tag,
- unsigned int value,
- bool global)
- {
- feature_info_t *info = &feature_infos[feature_count++];
- info->tag = tag;
- info->value = value;
- info->seq = feature_count;
- info->global = global;
- }
-
- void compile (hb_ot_shape_context_t *c)
- {
- global_mask = 0;
- lookup_count[0] = lookup_count[1] = 0;
-
- if (!feature_count)
- return;
-
-
- /* Fetch script/language indices for GSUB/GPOS. We need these later to skip
- * features not available in either table and not waste precious bits for them. */
-
- const hb_tag_t *script_tags;
- hb_tag_t language_tag;
-
- script_tags = hb_ot_tags_from_script (c->buffer->props.script);
- language_tag = hb_ot_tag_from_language (c->buffer->props.language);
-
- unsigned int script_index[2], language_index[2];
- for (unsigned int table_index = 0; table_index < 2; table_index++) {
- hb_tag_t table_tag = table_tags[table_index];
- hb_ot_layout_table_choose_script (c->face, table_tag, script_tags, &script_index[table_index]);
- hb_ot_layout_script_find_language (c->face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
- }
-
-
- /* Sort the features so we can bsearch later */
- qsort (feature_infos, feature_count, sizeof (feature_infos[0]), feature_info_t::cmp);
-
- /* Remove dups, let later-occurring features override earlier ones. */
- unsigned int j = 0;
- for (unsigned int i = 1; i < feature_count; i++)
- if (feature_infos[i].tag != feature_infos[j].tag)
- feature_infos[++j] = feature_infos[i];
- else {
- if (feature_infos[i].global)
- feature_infos[j] = feature_infos[i];
- else {
- feature_infos[j].global = feature_infos[j].global && (feature_infos[j].value == feature_infos[i].value);
- feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
- }
- }
- feature_count = j + 1;
-
-
- /* Allocate bits now */
- unsigned int next_bit = 1;
- j = 0;
- for (unsigned int i = 0; i < feature_count; i++) {
- const feature_info_t *info = &feature_infos[i];
-
- unsigned int bits_needed;
-
- if (info->global && info->value == 1)
- /* Uses the global bit */
- bits_needed = 0;
- else
- bits_needed = _hb_bit_storage (info->value);
-
- if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
- continue; /* Feature disabled, or not enough bits. */
-
-
- bool found = false;
- unsigned int feature_index[2];
- for (unsigned int table_index = 0; table_index < 2; table_index++)
- found |= hb_ot_layout_language_find_feature (c->face,
- table_tags[table_index],
- script_index[table_index],
- language_index[table_index],
- info->tag,
- &feature_index[table_index]);
- if (!found)
- continue;
-
-
- feature_map_t *map = &feature_maps[j++];
-
- map->tag = info->tag;
- map->index[0] = feature_index[0];
- map->index[1] = feature_index[1];
- if (info->global && info->value == 1) {
- /* Uses the global bit */
- map->shift = 0;
- map->mask = 1;
- } else {
- map->shift = next_bit;
- map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
- next_bit += bits_needed;
- if (info->global)
- global_mask |= map->mask;
- }
-
- }
- feature_count = j;
-
-
- for (unsigned int table_index = 0; table_index < 2; table_index++) {
- hb_tag_t table_tag = table_tags[table_index];
-
- /* Collect lookup indices for features */
-
- unsigned int required_feature_index;
- if (hb_ot_layout_language_get_required_feature_index (c->face,
- table_tag,
- script_index[table_index],
- language_index[table_index],
- &required_feature_index))
- add_lookups (c, table_index, required_feature_index, 1);
-
- for (unsigned i = 0; i < feature_count; i++)
- add_lookups (c, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
-
- /* Sort lookups and merge duplicates */
-
- qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), lookup_map_t::cmp);
-
- if (lookup_count[table_index])
- {
- unsigned int j = 0;
- for (unsigned int i = 1; i < lookup_count[table_index]; i++)
- if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
- lookup_maps[table_index][++j] = lookup_maps[table_index][i];
- else
- lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
- j++;
- lookup_count[table_index] = j;
- }
- }
- }
-
- hb_mask_t get_global_mask (void) { return global_mask; }
-
- const feature_map_t *find_feature (hb_tag_t tag) const {
- static const feature_map_t off_map = { HB_TAG_NONE, {Index::NOT_FOUND_INDEX,Index::NOT_FOUND_INDEX}, 0, 0 };
- const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), feature_map_t::cmp);
- return map ? map : &off_map;
- }
-
- void substitute (hb_ot_shape_context_t *c) const {
- for (unsigned int i = 0; i < lookup_count[0]; i++)
- hb_ot_layout_substitute_lookup (c->face, c->buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
- }
-
- void position (hb_ot_shape_context_t *c) const {
- for (unsigned int i = 0; i < lookup_count[1]; i++)
- hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask);
- }
-
- private:
-
- hb_mask_t global_mask;
-
- unsigned int feature_count;
- feature_info_t feature_infos[MAX_FEATURES]; /* used before compile() only */
- feature_map_t feature_maps[MAX_FEATURES];
-
- lookup_map_t lookup_maps[2][MAX_LOOKUPS]; /* GSUB/GPOS */
- unsigned int lookup_count[2];
-};
-
static void
hb_ot_shape_collect_features (hb_ot_shape_context_t *c,
hb_mask_allocator_t *allocator)
@@ -359,9 +97,11 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
for (unsigned int i = 0; i < c->num_features; i++)
{
hb_feature_t *feature = &c->features[i];
- const hb_mask_allocator_t::feature_map_t *map = allocator->find_feature (feature->tag);
- if (!(feature->start == 0 && feature->end == (unsigned int)-1))
- c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
+ if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
+ unsigned int shift;
+ hb_mask_t mask = allocator->get_mask (feature->tag, &shift);
+ c->buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
+ }
}
/* complex */
commit a7c5046d6b676a32298b97403a49235f7f255161
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 18:47:47 2010 -0400
Add private hb_segment_properties_t
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index ce7a3b5..d9f3d4d 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -62,6 +62,12 @@ ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_internal_glyph_info_t));
ASSERT_STATIC (sizeof (hb_glyph_position_t) == sizeof (hb_internal_glyph_position_t));
ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
+typedef struct _hb_segment_properties_t {
+ hb_direction_t direction;
+ hb_script_t script;
+ hb_language_t language;
+} hb_segment_properties_t;
+
HB_INTERNAL void
_hb_buffer_swap (hb_buffer_t *buffer);
@@ -110,13 +116,9 @@ struct _hb_buffer_t {
hb_reference_count_t ref_count;
/* Information about how the text in the buffer should be treated */
- hb_unicode_funcs_t *unicode;
- struct properties_t {
- hb_direction_t direction;
- hb_script_t script;
- hb_language_t language;
- } props;
+ hb_unicode_funcs_t *unicode; /* Unicode functions */
+ hb_segment_properties_t props; /* Script, language, direction */
/* Buffer contents */
commit b897c607d91d569f4eaa681d1f5b3d9f3d2bb093
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 18:41:57 2010 -0400
Flip the OT bit-allocation vs gsub/gpos inside-out
We now build our entire attack plan before jumping in.
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index febac35..11dcaa1 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -50,49 +50,11 @@ hb_tag_t default_features[] = {
HB_TAG('r','l','i','g')
};
-struct lookup_map {
- unsigned int index;
- hb_mask_t mask;
-};
-
-
-static void
-add_lookups (hb_face_t *face,
- hb_tag_t table_tag,
- unsigned int feature_index,
- hb_mask_t mask,
- lookup_map *lookups,
- unsigned int *num_lookups,
- unsigned int room_lookups)
-{
- unsigned int i = room_lookups - *num_lookups;
- lookups += *num_lookups;
-
- unsigned int *lookup_indices = (unsigned int *) lookups;
-
- hb_ot_layout_feature_get_lookup_indexes (face, table_tag, feature_index, 0,
- &i,
- lookup_indices);
-
- *num_lookups += i;
-
- while (i--) {
- lookups[i].mask = mask;
- lookups[i].index = lookup_indices[i];
- }
-}
-
-static int
-cmp_lookups (const void *p1, const void *p2)
-{
- const lookup_map *a = (const lookup_map *) p1;
- const lookup_map *b = (const lookup_map *) p2;
-
- return a->index - b->index;
-}
+#define MAX_FEATURES 100 /* FIXME */
+#define MAX_LOOKUPS 1000 /* FIXME */
+static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
-#define MAX_FEATURES 100 /* FIXME */
struct hb_mask_allocator_t {
@@ -116,8 +78,8 @@ struct hb_mask_allocator_t {
};
struct feature_map_t {
- hb_tag_t tag; /* should be first */
- unsigned int index;
+ hb_tag_t tag; /* should be first for our bsearch to work */
+ unsigned int index[2]; /* GSUB, GPOS */
unsigned int shift;
hb_mask_t mask;
@@ -131,50 +93,112 @@ struct hb_mask_allocator_t {
}
};
- hb_mask_allocator_t (void) : count (0) {}
+ struct lookup_map_t {
+ unsigned int index;
+ hb_mask_t mask;
+
+ static int
+ cmp (const void *p1, const void *p2)
+ {
+ const lookup_map_t *a = reinterpret_cast<const lookup_map_t *>(p1);
+ const lookup_map_t *b = reinterpret_cast<const lookup_map_t *>(p2);
+
+ return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
+ }
+ };
+
+
+ void
+ add_lookups (hb_ot_shape_context_t *c,
+ unsigned int table_index,
+ unsigned int feature_index,
+ hb_mask_t mask)
+ {
+ unsigned int i = MAX_LOOKUPS - lookup_count[table_index];
+ lookup_map_t *lookups = lookup_maps[table_index] + lookup_count[table_index];
+
+ unsigned int *lookup_indices = (unsigned int *) lookups;
+
+ hb_ot_layout_feature_get_lookup_indexes (c->face,
+ table_tags[table_index],
+ feature_index,
+ 0, &i,
+ lookup_indices);
+
+ lookup_count[table_index] += i;
+
+ while (i--) {
+ lookups[i].mask = mask;
+ lookups[i].index = lookup_indices[i];
+ }
+ }
+
+
+
+
+ hb_mask_allocator_t (void) : feature_count (0) {}
void add_feature (hb_tag_t tag,
unsigned int value,
bool global)
{
- feature_info_t *info = &infos[count++];
+ feature_info_t *info = &feature_infos[feature_count++];
info->tag = tag;
info->value = value;
- info->seq = count;
+ info->seq = feature_count;
info->global = global;
}
- void compile (hb_face_t *face,
- hb_tag_t table_tag,
- unsigned int script_index,
- unsigned int language_index)
+ void compile (hb_ot_shape_context_t *c)
{
- global_mask = 0;
- unsigned int next_bit = 1;
+ global_mask = 0;
+ lookup_count[0] = lookup_count[1] = 0;
- if (!count)
+ if (!feature_count)
return;
- qsort (infos, count, sizeof (infos[0]), feature_info_t::cmp);
+ /* Fetch script/language indices for GSUB/GPOS. We need these later to skip
+ * features not available in either table and not waste precious bits for them. */
+
+ const hb_tag_t *script_tags;
+ hb_tag_t language_tag;
+
+ script_tags = hb_ot_tags_from_script (c->buffer->props.script);
+ language_tag = hb_ot_tag_from_language (c->buffer->props.language);
+
+ unsigned int script_index[2], language_index[2];
+ for (unsigned int table_index = 0; table_index < 2; table_index++) {
+ hb_tag_t table_tag = table_tags[table_index];
+ hb_ot_layout_table_choose_script (c->face, table_tag, script_tags, &script_index[table_index]);
+ hb_ot_layout_script_find_language (c->face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
+ }
+
+
+ /* Sort the features so we can bsearch later */
+ qsort (feature_infos, feature_count, sizeof (feature_infos[0]), feature_info_t::cmp);
+
+ /* Remove dups, let later-occurring features override earlier ones. */
unsigned int j = 0;
- for (unsigned int i = 1; i < count; i++)
- if (infos[i].tag != infos[j].tag)
- infos[++j] = infos[i];
+ for (unsigned int i = 1; i < feature_count; i++)
+ if (feature_infos[i].tag != feature_infos[j].tag)
+ feature_infos[++j] = feature_infos[i];
else {
- if (infos[i].global)
- infos[j] = infos[i];
+ if (feature_infos[i].global)
+ feature_infos[j] = feature_infos[i];
else {
- infos[j].global = infos[j].global && (infos[j].value == infos[i].value);
- infos[j].value = MAX (infos[j].value, infos[i].value);
+ feature_infos[j].global = feature_infos[j].global && (feature_infos[j].value == feature_infos[i].value);
+ feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
}
}
- count = j + 1;
+ feature_count = j + 1;
+
/* Allocate bits now */
+ unsigned int next_bit = 1;
j = 0;
- for (unsigned int i = 0; i < count; i++) {
- const feature_info_t *info = &infos[i];
+ for (unsigned int i = 0; i < feature_count; i++) {
+ const feature_info_t *info = &feature_infos[i];
unsigned int bits_needed;
@@ -187,53 +211,103 @@ struct hb_mask_allocator_t {
if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
continue; /* Feature disabled, or not enough bits. */
- unsigned int feature_index;
- if (!hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
- info->tag, &feature_index))
+
+ bool found = false;
+ unsigned int feature_index[2];
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ found |= hb_ot_layout_language_find_feature (c->face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ info->tag,
+ &feature_index[table_index]);
+ if (!found)
continue;
- feature_map_t *map = &maps[j++];
+
+ feature_map_t *map = &feature_maps[j++];
map->tag = info->tag;
- map->index = feature_index;
+ map->index[0] = feature_index[0];
+ map->index[1] = feature_index[1];
if (info->global && info->value == 1) {
- /* Use the global bit */
+ /* Uses the global bit */
map->shift = 0;
map->mask = 1;
} else {
map->shift = next_bit;
map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
next_bit += bits_needed;
+ if (info->global)
+ global_mask |= map->mask;
}
- if (info->global && map->mask != 1)
- global_mask |= map->mask;
}
- count = j;
- }
+ feature_count = j;
- hb_mask_t get_global_mask (void) { return global_mask; }
- const feature_map_t *get_features (unsigned int *num_features) const {
- *num_features = count;
- return maps;
+ for (unsigned int table_index = 0; table_index < 2; table_index++) {
+ hb_tag_t table_tag = table_tags[table_index];
+
+ /* Collect lookup indices for features */
+
+ unsigned int required_feature_index;
+ if (hb_ot_layout_language_get_required_feature_index (c->face,
+ table_tag,
+ script_index[table_index],
+ language_index[table_index],
+ &required_feature_index))
+ add_lookups (c, table_index, required_feature_index, 1);
+
+ for (unsigned i = 0; i < feature_count; i++)
+ add_lookups (c, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
+
+ /* Sort lookups and merge duplicates */
+
+ qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), lookup_map_t::cmp);
+
+ if (lookup_count[table_index])
+ {
+ unsigned int j = 0;
+ for (unsigned int i = 1; i < lookup_count[table_index]; i++)
+ if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
+ lookup_maps[table_index][++j] = lookup_maps[table_index][i];
+ else
+ lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
+ j++;
+ lookup_count[table_index] = j;
+ }
+ }
}
+ hb_mask_t get_global_mask (void) { return global_mask; }
const feature_map_t *find_feature (hb_tag_t tag) const {
- static const feature_map_t off_map = { HB_TAG_NONE, Index::NOT_FOUND_INDEX, 0, 0 };
- const feature_map_t *map = (const feature_map_t *) bsearch (&tag, maps, count, sizeof (maps[0]), feature_map_t::cmp);
+ static const feature_map_t off_map = { HB_TAG_NONE, {Index::NOT_FOUND_INDEX,Index::NOT_FOUND_INDEX}, 0, 0 };
+ const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), feature_map_t::cmp);
return map ? map : &off_map;
}
+ void substitute (hb_ot_shape_context_t *c) const {
+ for (unsigned int i = 0; i < lookup_count[0]; i++)
+ hb_ot_layout_substitute_lookup (c->face, c->buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
+ }
- private:
+ void position (hb_ot_shape_context_t *c) const {
+ for (unsigned int i = 0; i < lookup_count[1]; i++)
+ hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask);
+ }
- unsigned int count;
- feature_info_t infos[MAX_FEATURES];
+ private:
- feature_map_t maps[MAX_FEATURES];
hb_mask_t global_mask;
+
+ unsigned int feature_count;
+ feature_info_t feature_infos[MAX_FEATURES]; /* used before compile() only */
+ feature_map_t feature_maps[MAX_FEATURES];
+
+ lookup_map_t lookup_maps[2][MAX_LOOKUPS]; /* GSUB/GPOS */
+ unsigned int lookup_count[2];
};
static void
@@ -269,70 +343,23 @@ hb_ot_shape_collect_features (hb_ot_shape_context_t *c,
static void
hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
- lookup_map *lookups,
- unsigned int *num_lookups)
+ hb_mask_allocator_t *allocator)
{
- hb_mask_allocator_t allocator;
-
- hb_ot_shape_collect_features (c, &allocator);
+ hb_ot_shape_collect_features (c, allocator);
/* Compile features */
- unsigned int script_index, language_index, feature_index;
- unsigned int room_lookups;
-
- hb_ot_layout_table_choose_script (c->face, c->table_tag,
- hb_ot_tags_from_script (c->buffer->props.script),
- &script_index);
- hb_ot_layout_script_find_language (c->face, c->table_tag, script_index,
- hb_ot_tag_from_language (c->buffer->props.language),
- &language_index);
-
- allocator.compile (c->face, c->table_tag, script_index, language_index);
-
-
- /* Gather lookup indices for features */
-
- room_lookups = *num_lookups;
- *num_lookups = 0;
-
- if (hb_ot_layout_language_get_required_feature_index (c->face, c->table_tag, script_index, language_index,
- &feature_index))
- add_lookups (c->face, c->table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
-
- const hb_mask_allocator_t::feature_map_t *map;
- unsigned int num_features;
-
- map = allocator.get_features (&num_features);
- for (unsigned i = 0; i < num_features; i++)
- add_lookups (c->face, c->table_tag, map[i].index, map[i].mask, lookups, num_lookups, room_lookups);
-
- /* Sort lookups and merge duplicates */
-
- qsort (lookups, *num_lookups, sizeof (lookups[0]), cmp_lookups);
-
- if (*num_lookups)
- {
- unsigned int j = 0;
- for (unsigned int i = 1; i < *num_lookups; i++)
- if (lookups[i].index != lookups[j].index)
- lookups[++j] = lookups[i];
- else
- lookups[j].mask |= lookups[i].mask;
- j++;
- *num_lookups = j;
- }
-
+ allocator->compile (c);
/* Set masks in buffer */
- hb_mask_t global_mask = allocator.get_global_mask ();
+ hb_mask_t global_mask = allocator->get_global_mask ();
if (global_mask)
c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
for (unsigned int i = 0; i < c->num_features; i++)
{
hb_feature_t *feature = &c->features[i];
- map = allocator.find_feature (feature->tag);
+ const hb_mask_allocator_t::feature_map_t *map = allocator->find_feature (feature->tag);
if (!(feature->start == 0 && feature->end == (unsigned int)-1))
c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
}
@@ -342,40 +369,27 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
static void
-hb_ot_substitute_complex (hb_ot_shape_context_t *c)
+hb_ot_substitute_complex (hb_ot_shape_context_t *c,
+ const hb_mask_allocator_t *allocator)
{
- lookup_map lookups[1000]; /* FIXME */
- unsigned int num_lookups = ARRAY_LENGTH (lookups);
-
if (!hb_ot_layout_has_substitution (c->face))
return;
- c->table_tag = HB_OT_TAG_GSUB;
-
- hb_ot_shape_setup_lookups (c, lookups, &num_lookups);
-
- for (unsigned int i = 0; i < num_lookups; i++)
- hb_ot_layout_substitute_lookup (c->face, c->buffer, lookups[i].index, lookups[i].mask);
+ allocator->substitute (c);
c->applied_substitute_complex = TRUE;
return;
}
static void
-hb_ot_position_complex (hb_ot_shape_context_t *c)
+hb_ot_position_complex (hb_ot_shape_context_t *c,
+ const hb_mask_allocator_t *allocator)
{
- lookup_map lookups[1000]; /* FIXME */
- unsigned int num_lookups = ARRAY_LENGTH (lookups);
if (!hb_ot_layout_has_positioning (c->face))
return;
- c->table_tag = HB_OT_TAG_GPOS;
-
- hb_ot_shape_setup_lookups (c, lookups, &num_lookups);
-
- for (unsigned int i = 0; i < num_lookups; i++)
- hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookups[i].index, lookups[i].mask);
+ allocator->position (c);
hb_ot_layout_position_finish (c->font, c->face, c->buffer);
@@ -528,6 +542,11 @@ hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
+ hb_mask_allocator_t allocator;
+
+ hb_ot_shape_setup_lookups (c, &allocator);
+
+
hb_form_clusters (c->buffer);
/* SUBSTITUTE */
@@ -541,7 +560,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
hb_substitute_default (c);
- hb_ot_substitute_complex (c);
+ hb_ot_substitute_complex (c, &allocator);
if (!c->applied_substitute_complex)
hb_substitute_complex_fallback (c);
@@ -553,7 +572,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
hb_position_default (c);
- hb_ot_position_complex (c);
+ hb_ot_position_complex (c, &allocator);
hb_bool_t position_fallback = !c->applied_position_complex;
if (position_fallback)
commit e89b7d2a61b7f58e6c7cec00d5ce2246dee1e8a1
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 12:29:59 2010 -0400
Logically separate feature collection
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 8b8b76f..febac35 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -237,20 +237,17 @@ struct hb_mask_allocator_t {
};
static void
-hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
- lookup_map *lookups,
- unsigned int *num_lookups)
+hb_ot_shape_collect_features (hb_ot_shape_context_t *c,
+ hb_mask_allocator_t *allocator)
{
- hb_mask_allocator_t allocator;
-
switch (c->original_direction) {
case HB_DIRECTION_LTR:
- allocator.add_feature (HB_TAG ('l','t','r','a'), 1, true);
- allocator.add_feature (HB_TAG ('l','t','r','m'), 1, true);
+ allocator->add_feature (HB_TAG ('l','t','r','a'), 1, true);
+ allocator->add_feature (HB_TAG ('l','t','r','m'), 1, true);
break;
case HB_DIRECTION_RTL:
- allocator.add_feature (HB_TAG ('r','t','l','a'), 1, true);
- allocator.add_feature (HB_TAG ('r','t','l','m'), 1, false);
+ allocator->add_feature (HB_TAG ('r','t','l','a'), 1, true);
+ allocator->add_feature (HB_TAG ('r','t','l','m'), 1, false);
break;
case HB_DIRECTION_TTB:
case HB_DIRECTION_BTT:
@@ -259,15 +256,25 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
}
for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
- allocator.add_feature (default_features[i], 1, true);
+ allocator->add_feature (default_features[i], 1, true);
/* complex */
for (unsigned int i = 0; i < c->num_features; i++) {
const hb_feature_t *feature = &c->features[i];
- allocator.add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
+ allocator->add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
}
+}
+
+
+static void
+hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
+ lookup_map *lookups,
+ unsigned int *num_lookups)
+{
+ hb_mask_allocator_t allocator;
+ hb_ot_shape_collect_features (c, &allocator);
/* Compile features */
unsigned int script_index, language_index, feature_index;
commit 5b88908f12ad1d828dd6075fb8fc0036c2d6af3a
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri Oct 8 12:23:01 2010 -0400
Minor
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index a206ff9..8b8b76f 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -237,14 +237,6 @@ struct hb_mask_allocator_t {
};
static void
-hb_ot_shape_setup_lookups_complex (hb_ot_shape_context_t *c,
- lookup_map *lookups,
- unsigned int *num_lookups)
-{
- /* XXX */
-}
-
-static void
hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
lookup_map *lookups,
unsigned int *num_lookups)
@@ -269,7 +261,7 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
allocator.add_feature (default_features[i], 1, true);
- hb_ot_shape_setup_lookups_complex (c, lookups, num_lookups);
+ /* complex */
for (unsigned int i = 0; i < c->num_features; i++) {
const hb_feature_t *feature = &c->features[i];
@@ -326,6 +318,10 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
/* Set masks in buffer */
+ hb_mask_t global_mask = allocator.get_global_mask ();
+ if (global_mask)
+ c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
+
for (unsigned int i = 0; i < c->num_features; i++)
{
hb_feature_t *feature = &c->features[i];
@@ -334,9 +330,7 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
}
- hb_mask_t global_mask = allocator.get_global_mask ();
- if (global_mask)
- c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
+ /* complex */
}
commit 5360ce0c5c33f921b3f9ad3f42529a19df5ad0fe
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Oct 7 21:21:11 2010 -0400
Move some more code around
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index dd7a546..a206ff9 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -249,20 +249,6 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
lookup_map *lookups,
unsigned int *num_lookups)
{
- unsigned int script_index, language_index, feature_index;
- unsigned int room_lookups;
-
- room_lookups = *num_lookups;
- *num_lookups = 0;
-
- hb_ot_layout_table_choose_script (c->face, c->table_tag,
- hb_ot_tags_from_script (c->buffer->props.script),
- &script_index);
- hb_ot_layout_script_find_language (c->face, c->table_tag, script_index,
- hb_ot_tag_from_language (c->buffer->props.language),
- &language_index);
-
-
hb_mask_allocator_t allocator;
switch (c->original_direction) {
@@ -292,11 +278,24 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
/* Compile features */
+ unsigned int script_index, language_index, feature_index;
+ unsigned int room_lookups;
+
+ hb_ot_layout_table_choose_script (c->face, c->table_tag,
+ hb_ot_tags_from_script (c->buffer->props.script),
+ &script_index);
+ hb_ot_layout_script_find_language (c->face, c->table_tag, script_index,
+ hb_ot_tag_from_language (c->buffer->props.language),
+ &language_index);
+
allocator.compile (c->face, c->table_tag, script_index, language_index);
/* Gather lookup indices for features */
+ room_lookups = *num_lookups;
+ *num_lookups = 0;
+
if (hb_ot_layout_language_get_required_feature_index (c->face, c->table_tag, script_index, language_index,
&feature_index))
add_lookups (c->face, c->table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
commit d9c726078828d50db62e05407a3f38f2e7607533
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Oct 7 21:19:54 2010 -0400
Minor
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 58d1e7f..dd7a546 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -249,7 +249,8 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
lookup_map *lookups,
unsigned int *num_lookups)
{
- unsigned int i, j, script_index, language_index, feature_index, room_lookups;
+ unsigned int script_index, language_index, feature_index;
+ unsigned int room_lookups;
room_lookups = *num_lookups;
*num_lookups = 0;
@@ -279,7 +280,7 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
break;
}
- for (i = 0; i < ARRAY_LENGTH (default_features); i++)
+ for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
allocator.add_feature (default_features[i], 1, true);
hb_ot_shape_setup_lookups_complex (c, lookups, num_lookups);
@@ -304,7 +305,7 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
unsigned int num_features;
map = allocator.get_features (&num_features);
- for (i = 0; i < num_features; i++)
+ for (unsigned i = 0; i < num_features; i++)
add_lookups (c->face, c->table_tag, map[i].index, map[i].mask, lookups, num_lookups, room_lookups);
/* Sort lookups and merge duplicates */
@@ -313,7 +314,8 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
if (*num_lookups)
{
- for (i = 1, j = 0; i < *num_lookups; i++)
+ unsigned int j = 0;
+ for (unsigned int i = 1; i < *num_lookups; i++)
if (lookups[i].index != lookups[j].index)
lookups[++j] = lookups[i];
else
@@ -325,7 +327,7 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
/* Set masks in buffer */
- for (i = 0; i < c->num_features; i++)
+ for (unsigned int i = 0; i < c->num_features; i++)
{
hb_feature_t *feature = &c->features[i];
map = allocator.find_feature (feature->tag);
@@ -344,7 +346,6 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
{
lookup_map lookups[1000]; /* FIXME */
unsigned int num_lookups = ARRAY_LENGTH (lookups);
- unsigned int i;
if (!hb_ot_layout_has_substitution (c->face))
return;
@@ -353,7 +354,7 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
hb_ot_shape_setup_lookups (c, lookups, &num_lookups);
- for (i = 0; i < num_lookups; i++)
+ for (unsigned int i = 0; i < num_lookups; i++)
hb_ot_layout_substitute_lookup (c->face, c->buffer, lookups[i].index, lookups[i].mask);
c->applied_substitute_complex = TRUE;
@@ -365,7 +366,6 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
{
lookup_map lookups[1000]; /* FIXME */
unsigned int num_lookups = ARRAY_LENGTH (lookups);
- unsigned int i;
if (!hb_ot_layout_has_positioning (c->face))
return;
@@ -374,7 +374,7 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
hb_ot_shape_setup_lookups (c, lookups, &num_lookups);
- for (i = 0; i < num_lookups; i++)
+ for (unsigned int i = 0; i < num_lookups; i++)
hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookups[i].index, lookups[i].mask);
hb_ot_layout_position_finish (c->font, c->face, c->buffer);
commit efe0d682e860ffd23a1d17c68c8273f17d51c1c9
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Oct 7 21:12:46 2010 -0400
Simplify compiling lookups
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 79f3097..58d1e7f 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -213,6 +213,13 @@ struct hb_mask_allocator_t {
}
hb_mask_t get_global_mask (void) { return global_mask; }
+
+ const feature_map_t *get_features (unsigned int *num_features) const {
+ *num_features = count;
+ return maps;
+ }
+
+
const feature_map_t *find_feature (hb_tag_t tag) const {
static const feature_map_t off_map = { HB_TAG_NONE, Index::NOT_FOUND_INDEX, 0, 0 };
const feature_map_t *map = (const feature_map_t *) bsearch (&tag, maps, count, sizeof (maps[0]), feature_map_t::cmp);
@@ -287,52 +294,18 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
allocator.compile (c->face, c->table_tag, script_index, language_index);
- /* Gather lookup indices for features and set buffer masks at the same time */
+ /* Gather lookup indices for features */
if (hb_ot_layout_language_get_required_feature_index (c->face, c->table_tag, script_index, language_index,
&feature_index))
add_lookups (c->face, c->table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
const hb_mask_allocator_t::feature_map_t *map;
+ unsigned int num_features;
- hb_mask_t global_mask = allocator.get_global_mask ();
- if (global_mask)
- c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
-
- switch (c->original_direction) {
- case HB_DIRECTION_LTR:
- map = allocator.find_feature (HB_TAG ('l','t','r','a'));
- add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
- map = allocator.find_feature (HB_TAG ('l','t','r','m'));
- add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
- break;
- case HB_DIRECTION_RTL:
- map = allocator.find_feature (HB_TAG ('r','t','l','a'));
- add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
- map = allocator.find_feature (HB_TAG ('r','t','l','m'));
- add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
- break;
- case HB_DIRECTION_TTB:
- case HB_DIRECTION_BTT:
- default:
- break;
- }
-
- for (i = 0; i < ARRAY_LENGTH (default_features); i++)
- {
- map = allocator.find_feature (default_features[i]);
- add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
- }
-
- for (i = 0; i < c->num_features; i++)
- {
- hb_feature_t *feature = &c->features[i];
- map = allocator.find_feature (feature->tag);
- add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
- if (!(feature->start == 0 && feature->end == (unsigned int)-1))
- c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
- }
-
+ map = allocator.get_features (&num_features);
+ for (i = 0; i < num_features; i++)
+ add_lookups (c->face, c->table_tag, map[i].index, map[i].mask, lookups, num_lookups, room_lookups);
/* Sort lookups and merge duplicates */
@@ -348,6 +321,21 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
j++;
*num_lookups = j;
}
+
+
+ /* Set masks in buffer */
+
+ for (i = 0; i < c->num_features; i++)
+ {
+ hb_feature_t *feature = &c->features[i];
+ map = allocator.find_feature (feature->tag);
+ if (!(feature->start == 0 && feature->end == (unsigned int)-1))
+ c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
+ }
+
+ hb_mask_t global_mask = allocator.get_global_mask ();
+ if (global_mask)
+ c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
}
commit 476c94218b4f5b8e119e82b0e10b641e0c10bf56
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Oct 7 17:47:33 2010 -0400
Rename
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index a4eafe1..79f3097 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009,2010 Red Hat, Inc.
+ * Copyright (C) 2010 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -22,6 +23,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
#include "hb-ot-shape-private.h"
@@ -55,7 +57,7 @@ struct lookup_map {
static void
-add_feature (hb_face_t *face,
+add_lookups (hb_face_t *face,
hb_tag_t table_tag,
unsigned int feature_index,
hb_mask_t mask,
@@ -289,7 +291,7 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
if (hb_ot_layout_language_get_required_feature_index (c->face, c->table_tag, script_index, language_index,
&feature_index))
- add_feature (c->face, c->table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
+ add_lookups (c->face, c->table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
const hb_mask_allocator_t::feature_map_t *map;
@@ -300,15 +302,15 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
switch (c->original_direction) {
case HB_DIRECTION_LTR:
map = allocator.find_feature (HB_TAG ('l','t','r','a'));
- add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
map = allocator.find_feature (HB_TAG ('l','t','r','m'));
- add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
break;
case HB_DIRECTION_RTL:
map = allocator.find_feature (HB_TAG ('r','t','l','a'));
- add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
map = allocator.find_feature (HB_TAG ('r','t','l','m'));
- add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
break;
case HB_DIRECTION_TTB:
case HB_DIRECTION_BTT:
@@ -319,14 +321,14 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
for (i = 0; i < ARRAY_LENGTH (default_features); i++)
{
map = allocator.find_feature (default_features[i]);
- add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
}
for (i = 0; i < c->num_features; i++)
{
hb_feature_t *feature = &c->features[i];
map = allocator.find_feature (feature->tag);
- add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_lookups (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
if (!(feature->start == 0 && feature->end == (unsigned int)-1))
c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
}
commit 34db6f031d7ac009f554386ef990bad44886b9ee
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Oct 7 01:21:19 2010 -0400
Add XXX note
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index ccc075a..047dafd 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -483,6 +483,7 @@ _hb_buffer_set_masks (hb_buffer_t *buffer,
return;
}
+ /* XXX can't bsearch since .cluster may not be sorted. */
/* Binary search to find the start position and go from there. */
unsigned int min = 0, max = buffer->len;
while (min < max)
commit 98aa3f65446496dc250d9b01d98cacfdf1157e06
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Oct 6 00:23:36 2010 -0400
Call hb_ot_shape_setup_lookups_complex()
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 053a823..a4eafe1 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -228,6 +228,14 @@ struct hb_mask_allocator_t {
};
static void
+hb_ot_shape_setup_lookups_complex (hb_ot_shape_context_t *c,
+ lookup_map *lookups,
+ unsigned int *num_lookups)
+{
+ /* XXX */
+}
+
+static void
hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
lookup_map *lookups,
unsigned int *num_lookups)
@@ -265,7 +273,7 @@ hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
for (i = 0; i < ARRAY_LENGTH (default_features); i++)
allocator.add_feature (default_features[i], 1, true);
- /* XXX complex-shaper features go here */
+ hb_ot_shape_setup_lookups_complex (c, lookups, num_lookups);
for (unsigned int i = 0; i < c->num_features; i++) {
const hb_feature_t *feature = &c->features[i];
commit f1d07885dc358e79c237e824c94b3320c0a9c17d
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Oct 6 00:21:37 2010 -0400
Rename setup_lookups()
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index d79ccfb..053a823 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -228,9 +228,9 @@ struct hb_mask_allocator_t {
};
static void
-setup_lookups (hb_ot_shape_context_t *c,
- lookup_map *lookups,
- unsigned int *num_lookups)
+hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
+ lookup_map *lookups,
+ unsigned int *num_lookups)
{
unsigned int i, j, script_index, language_index, feature_index, room_lookups;
@@ -353,7 +353,7 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
c->table_tag = HB_OT_TAG_GSUB;
- setup_lookups (c, lookups, &num_lookups);
+ hb_ot_shape_setup_lookups (c, lookups, &num_lookups);
for (i = 0; i < num_lookups; i++)
hb_ot_layout_substitute_lookup (c->face, c->buffer, lookups[i].index, lookups[i].mask);
@@ -374,7 +374,7 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
c->table_tag = HB_OT_TAG_GPOS;
- setup_lookups (c, lookups, &num_lookups);
+ hb_ot_shape_setup_lookups (c, lookups, &num_lookups);
for (i = 0; i < num_lookups; i++)
hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookups[i].index, lookups[i].mask);
commit affc5abac7bdae51df85856a5478d34d96fda4fe
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Oct 6 00:18:16 2010 -0400
Move table_tag to hb_ot_shape_context_t
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 25048a1..d79ccfb 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -229,7 +229,6 @@ struct hb_mask_allocator_t {
static void
setup_lookups (hb_ot_shape_context_t *c,
- hb_tag_t table_tag,
lookup_map *lookups,
unsigned int *num_lookups)
{
@@ -238,10 +237,10 @@ setup_lookups (hb_ot_shape_context_t *c,
room_lookups = *num_lookups;
*num_lookups = 0;
- hb_ot_layout_table_choose_script (c->face, table_tag,
+ hb_ot_layout_table_choose_script (c->face, c->table_tag,
hb_ot_tags_from_script (c->buffer->props.script),
&script_index);
- hb_ot_layout_script_find_language (c->face, table_tag, script_index,
+ hb_ot_layout_script_find_language (c->face, c->table_tag, script_index,
hb_ot_tag_from_language (c->buffer->props.language),
&language_index);
@@ -275,14 +274,14 @@ setup_lookups (hb_ot_shape_context_t *c,
/* Compile features */
- allocator.compile (c->face, table_tag, script_index, language_index);
+ allocator.compile (c->face, c->table_tag, script_index, language_index);
/* Gather lookup indices for features and set buffer masks at the same time */
- if (hb_ot_layout_language_get_required_feature_index (c->face, table_tag, script_index, language_index,
+ if (hb_ot_layout_language_get_required_feature_index (c->face, c->table_tag, script_index, language_index,
&feature_index))
- add_feature (c->face, table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
+ add_feature (c->face, c->table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
const hb_mask_allocator_t::feature_map_t *map;
@@ -293,15 +292,15 @@ setup_lookups (hb_ot_shape_context_t *c,
switch (c->original_direction) {
case HB_DIRECTION_LTR:
map = allocator.find_feature (HB_TAG ('l','t','r','a'));
- add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
map = allocator.find_feature (HB_TAG ('l','t','r','m'));
- add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
break;
case HB_DIRECTION_RTL:
map = allocator.find_feature (HB_TAG ('r','t','l','a'));
- add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
map = allocator.find_feature (HB_TAG ('r','t','l','m'));
- add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
break;
case HB_DIRECTION_TTB:
case HB_DIRECTION_BTT:
@@ -312,14 +311,14 @@ setup_lookups (hb_ot_shape_context_t *c,
for (i = 0; i < ARRAY_LENGTH (default_features); i++)
{
map = allocator.find_feature (default_features[i]);
- add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
}
for (i = 0; i < c->num_features; i++)
{
hb_feature_t *feature = &c->features[i];
map = allocator.find_feature (feature->tag);
- add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, c->table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
if (!(feature->start == 0 && feature->end == (unsigned int)-1))
c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
}
@@ -352,7 +351,9 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
if (!hb_ot_layout_has_substitution (c->face))
return;
- setup_lookups (c, HB_OT_TAG_GSUB, lookups, &num_lookups);
+ c->table_tag = HB_OT_TAG_GSUB;
+
+ setup_lookups (c, lookups, &num_lookups);
for (i = 0; i < num_lookups; i++)
hb_ot_layout_substitute_lookup (c->face, c->buffer, lookups[i].index, lookups[i].mask);
@@ -371,7 +372,9 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
if (!hb_ot_layout_has_positioning (c->face))
return;
- setup_lookups (c, HB_OT_TAG_GPOS, lookups, &num_lookups);
+ c->table_tag = HB_OT_TAG_GPOS;
+
+ setup_lookups (c, lookups, &num_lookups);
for (i = 0; i < num_lookups; i++)
hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookups[i].index, lookups[i].mask);
commit 967240dd8b96802345ef273e75427066e91ea8fb
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Oct 5 23:00:05 2010 -0400
Add internal hb_ot_shape_context_t
diff --git a/src/hb-ot-shape-arabic.cc b/src/hb-ot-shape-arabic.cc
index 705a6f9..1eb3081 100644
--- a/src/hb-ot-shape-arabic.cc
+++ b/src/hb-ot-shape-arabic.cc
@@ -24,13 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "hb-ot-shape.h"
-
-#include "hb-buffer-private.hh"
-
-#include "hb-open-type-private.hh"
-
-#include "hb-ot-layout.h"
+#include "hb-ot-shape-private.h"
HB_BEGIN_DECLS
@@ -676,18 +670,14 @@ static const struct arabic_state_table_entry {
void
-_hb_ot_analyze_complex_arabic (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features HB_UNUSED,
- unsigned int num_features HB_UNUSED)
+_hb_ot_analyze_complex_arabic (hb_ot_shape_context_t *c)
{
- unsigned int count = buffer->len;
+ unsigned int count = c->buffer->len;
unsigned int prev = 0, state = 0;
for (unsigned int i = 0; i < count; i++) {
- unsigned int this_type = get_joining_type (buffer->info[i].codepoint, buffer->unicode->v.get_general_category (buffer->info[i].codepoint));
+ unsigned int this_type = get_joining_type (c->buffer->info[i].codepoint, c->buffer->unicode->v.get_general_category (c->buffer->info[i].codepoint));
if (unlikely (this_type == JOINING_TYPE_T))
continue;
@@ -695,21 +685,21 @@ _hb_ot_analyze_complex_arabic (hb_font_t *font,
const arabic_state_table_entry *entry = arabic_state_table[state];
if (entry->prev_action != NONE)
- buffer->info[prev].gproperty = entry->prev_action;
+ c->buffer->info[prev].gproperty = entry->prev_action;
- buffer->info[i].gproperty = entry->curr_action;
+ c->buffer->info[i].gproperty = entry->curr_action;
prev = i;
state = entry->next_state;
}
hb_mask_t mask_array[TOTAL_NUM_FEATURES] = {0};
- unsigned int num_masks = buffer->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
+ unsigned int num_masks = c->buffer->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
for (unsigned int i = 0; i < num_masks; i++)
mask_array[i] = 0 /* XXX find_mask */;
for (unsigned int i = 0; i < count; i++)
- buffer->info[i].mask |= mask_array[buffer->info[i].gproperty];
+ c->buffer->info[i].mask |= mask_array[c->buffer->info[i].gproperty];
}
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 4173942..25048a1 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -24,9 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#include "hb-ot-shape.h"
-
-#include "hb-buffer-private.hh"
+#include "hb-ot-shape-private.h"
#include "hb-open-type-private.hh"
@@ -230,31 +228,27 @@ struct hb_mask_allocator_t {
};
static void
-setup_lookups (hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features,
- hb_tag_t table_tag,
- lookup_map *lookups,
- unsigned int *num_lookups,
- hb_direction_t original_direction)
+setup_lookups (hb_ot_shape_context_t *c,
+ hb_tag_t table_tag,
+ lookup_map *lookups,
+ unsigned int *num_lookups)
{
unsigned int i, j, script_index, language_index, feature_index, room_lookups;
room_lookups = *num_lookups;
*num_lookups = 0;
- hb_ot_layout_table_choose_script (face, table_tag,
- hb_ot_tags_from_script (buffer->props.script),
+ hb_ot_layout_table_choose_script (c->face, table_tag,
+ hb_ot_tags_from_script (c->buffer->props.script),
&script_index);
- hb_ot_layout_script_find_language (face, table_tag, script_index,
- hb_ot_tag_from_language (buffer->props.language),
+ hb_ot_layout_script_find_language (c->face, table_tag, script_index,
+ hb_ot_tag_from_language (c->buffer->props.language),
&language_index);
hb_mask_allocator_t allocator;
- switch (original_direction) {
+ switch (c->original_direction) {
case HB_DIRECTION_LTR:
allocator.add_feature (HB_TAG ('l','t','r','a'), 1, true);
allocator.add_feature (HB_TAG ('l','t','r','m'), 1, true);
@@ -274,40 +268,40 @@ setup_lookups (hb_face_t *face,
/* XXX complex-shaper features go here */
- for (unsigned int i = 0; i < num_features; i++) {
- const hb_feature_t *feature = &features[i];
+ for (unsigned int i = 0; i < c->num_features; i++) {
+ const hb_feature_t *feature = &c->features[i];
allocator.add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
}
/* Compile features */
- allocator.compile (face, table_tag, script_index, language_index);
+ allocator.compile (c->face, table_tag, script_index, language_index);
/* Gather lookup indices for features and set buffer masks at the same time */
- if (hb_ot_layout_language_get_required_feature_index (face, table_tag, script_index, language_index,
+ if (hb_ot_layout_language_get_required_feature_index (c->face, table_tag, script_index, language_index,
&feature_index))
- add_feature (face, table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
+ add_feature (c->face, table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
const hb_mask_allocator_t::feature_map_t *map;
hb_mask_t global_mask = allocator.get_global_mask ();
if (global_mask)
- buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
+ c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);
- switch (original_direction) {
+ switch (c->original_direction) {
case HB_DIRECTION_LTR:
map = allocator.find_feature (HB_TAG ('l','t','r','a'));
- add_feature (face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
map = allocator.find_feature (HB_TAG ('l','t','r','m'));
- add_feature (face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
break;
case HB_DIRECTION_RTL:
map = allocator.find_feature (HB_TAG ('r','t','l','a'));
- add_feature (face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
map = allocator.find_feature (HB_TAG ('r','t','l','m'));
- add_feature (face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
break;
case HB_DIRECTION_TTB:
case HB_DIRECTION_BTT:
@@ -318,16 +312,16 @@ setup_lookups (hb_face_t *face,
for (i = 0; i < ARRAY_LENGTH (default_features); i++)
{
map = allocator.find_feature (default_features[i]);
- add_feature (face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
}
- for (i = 0; i < num_features; i++)
+ for (i = 0; i < c->num_features; i++)
{
- hb_feature_t *feature = &features[i];
+ hb_feature_t *feature = &c->features[i];
map = allocator.find_feature (feature->tag);
- add_feature (face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
+ add_feature (c->face, table_tag, map->index, map->mask, lookups, num_lookups, room_lookups);
if (!(feature->start == 0 && feature->end == (unsigned int)-1))
- buffer->set_masks (features[i].value << map->shift, map->mask, feature->start, feature->end);
+ c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
}
@@ -348,58 +342,44 @@ setup_lookups (hb_face_t *face,
}
-static hb_bool_t
-hb_ot_substitute_complex (hb_font_t *font HB_UNUSED,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features,
- hb_direction_t original_direction)
+static void
+hb_ot_substitute_complex (hb_ot_shape_context_t *c)
{
lookup_map lookups[1000]; /* FIXME */
unsigned int num_lookups = ARRAY_LENGTH (lookups);
unsigned int i;
- if (!hb_ot_layout_has_substitution (face))
- return FALSE;
+ if (!hb_ot_layout_has_substitution (c->face))
+ return;
- setup_lookups (face, buffer, features, num_features,
- HB_OT_TAG_GSUB,
- lookups, &num_lookups,
- original_direction);
+ setup_lookups (c, HB_OT_TAG_GSUB, lookups, &num_lookups);
for (i = 0; i < num_lookups; i++)
- hb_ot_layout_substitute_lookup (face, buffer, lookups[i].index, lookups[i].mask);
+ hb_ot_layout_substitute_lookup (c->face, c->buffer, lookups[i].index, lookups[i].mask);
- return TRUE;
+ c->applied_substitute_complex = TRUE;
+ return;
}
-static hb_bool_t
-hb_ot_position_complex (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features,
- hb_direction_t original_direction)
+static void
+hb_ot_position_complex (hb_ot_shape_context_t *c)
{
- lookup_map lookups[1000];
+ lookup_map lookups[1000]; /* FIXME */
unsigned int num_lookups = ARRAY_LENGTH (lookups);
unsigned int i;
- if (!hb_ot_layout_has_positioning (face))
- return FALSE;
+ if (!hb_ot_layout_has_positioning (c->face))
+ return;
- setup_lookups (face, buffer, features, num_features,
- HB_OT_TAG_GPOS,
- lookups, &num_lookups,
- original_direction);
+ setup_lookups (c, HB_OT_TAG_GPOS, lookups, &num_lookups);
for (i = 0; i < num_lookups; i++)
- hb_ot_layout_position_lookup (font, face, buffer, lookups[i].index, lookups[i].mask);
+ hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookups[i].index, lookups[i].mask);
- hb_ot_layout_position_finish (font, face, buffer);
+ hb_ot_layout_position_finish (c->font, c->face, c->buffer);
- return TRUE;
+ c->applied_position_complex = TRUE;
+ return;
}
@@ -424,20 +404,18 @@ hb_form_clusters (hb_buffer_t *buffer)
buffer->info[i].cluster = buffer->info[i - 1].cluster;
}
-static hb_direction_t
+static void
hb_ensure_native_direction (hb_buffer_t *buffer)
{
- hb_direction_t original_direction = buffer->props.direction;
+ hb_direction_t direction = buffer->props.direction;
/* TODO vertical */
- if (HB_DIRECTION_IS_HORIZONTAL (original_direction) &&
- original_direction != _hb_script_get_horizontal_direction (buffer->props.script))
+ if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
+ direction != _hb_script_get_horizontal_direction (buffer->props.script))
{
hb_buffer_reverse_clusters (buffer);
buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
}
-
- return original_direction;
}
@@ -487,21 +465,13 @@ hb_map_glyphs (hb_font_t *font,
}
static void
-hb_substitute_default (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features HB_UNUSED,
- unsigned int num_features HB_UNUSED)
+hb_substitute_default (hb_ot_shape_context_t *c)
{
- hb_map_glyphs (font, face, buffer);
+ hb_map_glyphs (c->font, c->face, c->buffer);
}
static void
-hb_substitute_complex_fallback (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- hb_buffer_t *buffer HB_UNUSED,
- hb_feature_t *features HB_UNUSED,
- unsigned int num_features HB_UNUSED)
+hb_substitute_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
{
/* TODO Arabic */
}
@@ -510,114 +480,107 @@ hb_substitute_complex_fallback (hb_font_t *font HB_UNUSED,
/* Position */
static void
-hb_position_default (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features HB_UNUSED,
- unsigned int num_features HB_UNUSED)
+hb_position_default (hb_ot_shape_context_t *c)
{
- hb_buffer_clear_positions (buffer);
+ hb_buffer_clear_positions (c->buffer);
- unsigned int count = buffer->len;
+ unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++) {
hb_glyph_metrics_t metrics;
- hb_font_get_glyph_metrics (font, face, buffer->info[i].codepoint, &metrics);
- buffer->pos[i].x_advance = metrics.x_advance;
- buffer->pos[i].y_advance = metrics.y_advance;
+ hb_font_get_glyph_metrics (c->font, c->face, c->buffer->info[i].codepoint, &metrics);
+ c->buffer->pos[i].x_advance = metrics.x_advance;
+ c->buffer->pos[i].y_advance = metrics.y_advance;
}
}
static void
-hb_position_complex_fallback (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- hb_buffer_t *buffer HB_UNUSED,
- hb_feature_t *features HB_UNUSED,
- unsigned int num_features HB_UNUSED)
+hb_position_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
{
/* TODO Mark pos */
}
static void
-hb_truetype_kern (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features HB_UNUSED,
- unsigned int num_features HB_UNUSED)
+hb_truetype_kern (hb_ot_shape_context_t *c)
{
/* TODO Check for kern=0 */
- unsigned int count = buffer->len;
+ unsigned int count = c->buffer->len;
for (unsigned int i = 1; i < count; i++) {
hb_position_t kern, kern1, kern2;
- kern = hb_font_get_kerning (font, face, buffer->info[i - 1].codepoint, buffer->info[i].codepoint);
+ kern = hb_font_get_kerning (c->font, c->face, c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint);
kern1 = kern >> 1;
kern2 = kern - kern1;
- buffer->pos[i - 1].x_advance += kern1;
- buffer->pos[i].x_advance += kern2;
- buffer->pos[i].x_offset += kern2;
+ c->buffer->pos[i - 1].x_advance += kern1;
+ c->buffer->pos[i].x_advance += kern2;
+ c->buffer->pos[i].x_offset += kern2;
}
}
static void
-hb_position_complex_fallback_visual (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features)
+hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
{
- hb_truetype_kern (font, face, buffer, features, num_features);
+ hb_truetype_kern (c);
}
/* Do it! */
-void
-hb_ot_shape (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features)
+static void
+hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
- hb_direction_t original_direction;
- hb_bool_t substitute_fallback, position_fallback;
-
- hb_form_clusters (buffer);
+ hb_form_clusters (c->buffer);
/* SUBSTITUTE */
{
- buffer->clear_masks ();
+ c->buffer->clear_masks ();
/* Mirroring needs to see the original direction */
- hb_mirror_chars (buffer);
+ hb_mirror_chars (c->buffer);
- original_direction = hb_ensure_native_direction (buffer);
+ hb_ensure_native_direction (c->buffer);
- hb_substitute_default (font, face, buffer, features, num_features);
+ hb_substitute_default (c);
- substitute_fallback = !hb_ot_substitute_complex (font, face, buffer, features, num_features, original_direction);
+ hb_ot_substitute_complex (c);
- if (substitute_fallback)
- hb_substitute_complex_fallback (font, face, buffer, features, num_features);
+ if (!c->applied_substitute_complex)
+ hb_substitute_complex_fallback (c);
}
/* POSITION */
{
- buffer->clear_masks ();
+ c->buffer->clear_masks ();
- hb_position_default (font, face, buffer, features, num_features);
+ hb_position_default (c);
- position_fallback = !hb_ot_position_complex (font, face, buffer, features, num_features, original_direction);
+ hb_ot_position_complex (c);
+ hb_bool_t position_fallback = !c->applied_position_complex;
if (position_fallback)
- hb_position_complex_fallback (font, face, buffer, features, num_features);
+ hb_position_complex_fallback (c);
- if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
- hb_buffer_reverse (buffer);
+ if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
+ hb_buffer_reverse (c->buffer);
if (position_fallback)
- hb_position_complex_fallback_visual (font, face, buffer, features, num_features);
+ hb_position_complex_fallback_visual (c);
}
- buffer->props.direction = original_direction;
+ c->buffer->props.direction = c->original_direction;
+}
+
+void
+hb_ot_shape (hb_font_t *font,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ hb_feature_t *features,
+ unsigned int num_features)
+{
+ hb_ot_shape_context_t c = {font, face, buffer, features, num_features};
+
+ /* Setup transient context members */
+ c.original_direction = buffer->props.direction;
+
+ hb_ot_shape_internal (&c);
}
commit 3eb936f1539475098f39be78654b9c39b86f0799
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Oct 5 18:36:58 2010 -0400
Add Arabic/Syriac/N'ko shaping logic
Not hooked up just yet.
diff --git a/src/Makefile.am b/src/Makefile.am
index ea6fb50..8e7ac47 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,7 @@
# Process this file with automake to produce Makefile.in
NULL =
+EXTRA_DIST =
# The following warning options are useful for debugging: -Wpadded -Wcast-align
#AM_CXXFLAGS =
@@ -47,6 +48,7 @@ HBSOURCES += \
hb-ot-layout-gsub-private.hh \
hb-ot-layout-private.hh \
hb-ot-shape.cc \
+ hb-ot-shape-arabic.cc \
hb-ot-tag.c \
$(NULL)
HBHEADERS += \
@@ -106,6 +108,13 @@ libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
libharfbuzz_la_LIBADD = $(HBLIBS)
pkginclude_HEADERS = $(HBHEADERS)
+
+GENERATORS = \
+ gen-arabic-joining-table.py \
+ $(NULL)
+
+EXTRA_DIST += $(GENERATORS)
+
noinst_PROGRAMS = main test
main_SOURCES = main.cc
diff --git a/src/gen-arabic-joining-table.py b/src/gen-arabic-joining-table.py
new file mode 100755
index 0000000..f12c207
--- /dev/null
+++ b/src/gen-arabic-joining-table.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+
+import sys
+
+header = sys.stdin.readline(), sys.stdin.readline()
+dic = dict()
+for line in sys.stdin:
+ if line[:1] != '0':
+ continue
+
+ fields = [x.strip() for x in line.split(';')]
+ u = int(fields[0], 16)
+
+ if u < 0x0600 or (u > 0x07FF and u != 0x200C and u != 0x200D):
+ raise Exception ("Ooops, unexpected unicode character: ", fields)
+ dic[u] = fields
+
+print " /*"
+print " * The following table is generated by running:"
+print " *"
+print " * ./gen-arabic-joining-table.py < ArabicShaping.txt"
+print " *"
+print " * on the ArabicShaping.txt file with the header:"
+print " *"
+for line in header:
+ print " * %s" % (line.strip())
+print " */"
+print " /* == Start of generated table == */"
+for i in range(0x0600, 0x0800):
+ if i not in dic:
+ print " JOINING_TYPE_X, /* %04X */" % i
+ else:
+ entry = dic[i]
+ if entry[3] in ["ALAPH", "DALATH RISH"]:
+ value = "JOINING_GROUP_" + entry[3].replace(' ', '_')
+ else:
+ value = "JOINING_TYPE_" + entry[2]
+ print " %s, /* %s */" % (value, '; '.join(entry))
+print " /* == End of generated table == */"
diff --git a/src/hb-ot-shape-arabic.cc b/src/hb-ot-shape-arabic.cc
new file mode 100644
index 0000000..705a6f9
--- /dev/null
+++ b/src/hb-ot-shape-arabic.cc
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2010 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.h"
+
+#include "hb-buffer-private.hh"
+
+#include "hb-open-type-private.hh"
+
+#include "hb-ot-layout.h"
+
+HB_BEGIN_DECLS
+
+/*
+ * Bits used in the joining tables
+ */
+enum {
+ JOINING_TYPE_U = 0,
+ JOINING_TYPE_R = 1,
+ JOINING_TYPE_D = 2,
+ JOINING_TYPE_C = JOINING_TYPE_D,
+ JOINING_GROUP_ALAPH = 3,
+ JOINING_GROUP_DALATH_RISH = 4,
+ NUM_STATE_MACHINE_COLS = 5,
+
+ /* We deliberately don't have a JOINING_TYPE_L since that's unused in Unicode. */
+
+ JOINING_TYPE_T = 6,
+ JOINING_TYPE_X = 7, /* means: use general-category to choose between U or T. */
+};
+
+/*
+ * Joining types:
+ */
+
+
+/*
+ * Main joining-type table, covering U+0600..U+07FF.
+ * Includes Arabic, Syriac, and N'ko.
+ */
+static const uint8_t arabic_syriac_nko_joining_types[0x0800 - 0x0600 + 1] =
+{
+ /*
+ * The following table is generated by running:
+ *
+ * ./gen-arabic-joining-table.py < ArabicShaping.txt
+ *
+ * on the ArabicShaping.txt file with the header:
+ *
+ * # ArabicShaping-5.2.0.txt
+ * # Date: 2009-08-17, 11:11:00 PDT [KW]
+ */
+ /* == Start of generated table == */
+ JOINING_TYPE_U, /* 0600; ARABIC NUMBER SIGN; U; No_Joining_Group */
+ JOINING_TYPE_U, /* 0601; ARABIC SIGN SANAH; U; No_Joining_Group */
+ JOINING_TYPE_U, /* 0602; ARABIC FOOTNOTE MARKER; U; No_Joining_Group */
+ JOINING_TYPE_U, /* 0603; ARABIC SIGN SAFHA; U; No_Joining_Group */
+ JOINING_TYPE_X, /* 0604 */
+ JOINING_TYPE_X, /* 0605 */
+ JOINING_TYPE_X, /* 0606 */
+ JOINING_TYPE_X, /* 0607 */
+ JOINING_TYPE_U, /* 0608; ARABIC RAY; U; No_Joining_Group */
+ JOINING_TYPE_X, /* 0609 */
+ JOINING_TYPE_X, /* 060A */
+ JOINING_TYPE_U, /* 060B; AFGHANI SIGN; U; No_Joining_Group */
+ JOINING_TYPE_X, /* 060C */
+ JOINING_TYPE_X, /* 060D */
+ JOINING_TYPE_X, /* 060E */
+ JOINING_TYPE_X, /* 060F */
+ JOINING_TYPE_X, /* 0610 */
+ JOINING_TYPE_X, /* 0611 */
+ JOINING_TYPE_X, /* 0612 */
+ JOINING_TYPE_X, /* 0613 */
+ JOINING_TYPE_X, /* 0614 */
+ JOINING_TYPE_X, /* 0615 */
+ JOINING_TYPE_X, /* 0616 */
+ JOINING_TYPE_X, /* 0617 */
+ JOINING_TYPE_X, /* 0618 */
+ JOINING_TYPE_X, /* 0619 */
+ JOINING_TYPE_X, /* 061A */
+ JOINING_TYPE_X, /* 061B */
+ JOINING_TYPE_X, /* 061C */
+ JOINING_TYPE_X, /* 061D */
+ JOINING_TYPE_X, /* 061E */
+ JOINING_TYPE_X, /* 061F */
+ JOINING_TYPE_X, /* 0620 */
+ JOINING_TYPE_U, /* 0621; HAMZA; U; No_Joining_Group */
+ JOINING_TYPE_R, /* 0622; MADDA ON ALEF; R; ALEF */
+ JOINING_TYPE_R, /* 0623; HAMZA ON ALEF; R; ALEF */
+ JOINING_TYPE_R, /* 0624; HAMZA ON WAW; R; WAW */
+ JOINING_TYPE_R, /* 0625; HAMZA UNDER ALEF; R; ALEF */
+ JOINING_TYPE_D, /* 0626; HAMZA ON YEH; D; YEH */
+ JOINING_TYPE_R, /* 0627; ALEF; R; ALEF */
+ JOINING_TYPE_D, /* 0628; BEH; D; BEH */
+ JOINING_TYPE_R, /* 0629; TEH MARBUTA; R; TEH MARBUTA */
+ JOINING_TYPE_D, /* 062A; TEH; D; BEH */
+ JOINING_TYPE_D, /* 062B; THEH; D; BEH */
+ JOINING_TYPE_D, /* 062C; JEEM; D; HAH */
+ JOINING_TYPE_D, /* 062D; HAH; D; HAH */
+ JOINING_TYPE_D, /* 062E; KHAH; D; HAH */
+ JOINING_TYPE_R, /* 062F; DAL; R; DAL */
+ JOINING_TYPE_R, /* 0630; THAL; R; DAL */
+ JOINING_TYPE_R, /* 0631; REH; R; REH */
+ JOINING_TYPE_R, /* 0632; ZAIN; R; REH */
+ JOINING_TYPE_D, /* 0633; SEEN; D; SEEN */
+ JOINING_TYPE_D, /* 0634; SHEEN; D; SEEN */
+ JOINING_TYPE_D, /* 0635; SAD; D; SAD */
+ JOINING_TYPE_D, /* 0636; DAD; D; SAD */
+ JOINING_TYPE_D, /* 0637; TAH; D; TAH */
+ JOINING_TYPE_D, /* 0638; ZAH; D; TAH */
+ JOINING_TYPE_D, /* 0639; AIN; D; AIN */
+ JOINING_TYPE_D, /* 063A; GHAIN; D; AIN */
+ JOINING_TYPE_D, /* 063B; KEHEH WITH 2 DOTS ABOVE; D; GAF */
+ JOINING_TYPE_D, /* 063C; KEHEH WITH 3 DOTS BELOW; D; GAF */
+ JOINING_TYPE_D, /* 063D; FARSI YEH WITH INVERTED V; D; FARSI YEH */
+ JOINING_TYPE_D, /* 063E; FARSI YEH WITH 2 DOTS ABOVE; D; FARSI YEH */
+ JOINING_TYPE_D, /* 063F; FARSI YEH WITH 3 DOTS ABOVE; D; FARSI YEH */
+ JOINING_TYPE_C, /* 0640; TATWEEL; C; No_Joining_Group */
+ JOINING_TYPE_D, /* 0641; FEH; D; FEH */
+ JOINING_TYPE_D, /* 0642; QAF; D; QAF */
+ JOINING_TYPE_D, /* 0643; KAF; D; KAF */
+ JOINING_TYPE_D, /* 0644; LAM; D; LAM */
+ JOINING_TYPE_D, /* 0645; MEEM; D; MEEM */
+ JOINING_TYPE_D, /* 0646; NOON; D; NOON */
+ JOINING_TYPE_D, /* 0647; HEH; D; HEH */
+ JOINING_TYPE_R, /* 0648; WAW; R; WAW */
+ JOINING_TYPE_D, /* 0649; ALEF MAKSURA; D; YEH */
+ JOINING_TYPE_D, /* 064A; YEH; D; YEH */
+ JOINING_TYPE_X, /* 064B */
+ JOINING_TYPE_X, /* 064C */
+ JOINING_TYPE_X, /* 064D */
+ JOINING_TYPE_X, /* 064E */
+ JOINING_TYPE_X, /* 064F */
+ JOINING_TYPE_X, /* 0650 */
+ JOINING_TYPE_X, /* 0651 */
+ JOINING_TYPE_X, /* 0652 */
+ JOINING_TYPE_X, /* 0653 */
+ JOINING_TYPE_X, /* 0654 */
+ JOINING_TYPE_X, /* 0655 */
+ JOINING_TYPE_X, /* 0656 */
+ JOINING_TYPE_X, /* 0657 */
+ JOINING_TYPE_X, /* 0658 */
+ JOINING_TYPE_X, /* 0659 */
+ JOINING_TYPE_X, /* 065A */
+ JOINING_TYPE_X, /* 065B */
+ JOINING_TYPE_X, /* 065C */
+ JOINING_TYPE_X, /* 065D */
+ JOINING_TYPE_X, /* 065E */
+ JOINING_TYPE_X, /* 065F */
+ JOINING_TYPE_X, /* 0660 */
+ JOINING_TYPE_X, /* 0661 */
+ JOINING_TYPE_X, /* 0662 */
+ JOINING_TYPE_X, /* 0663 */
+ JOINING_TYPE_X, /* 0664 */
+ JOINING_TYPE_X, /* 0665 */
+ JOINING_TYPE_X, /* 0666 */
+ JOINING_TYPE_X, /* 0667 */
+ JOINING_TYPE_X, /* 0668 */
+ JOINING_TYPE_X, /* 0669 */
+ JOINING_TYPE_X, /* 066A */
+ JOINING_TYPE_X, /* 066B */
+ JOINING_TYPE_X, /* 066C */
+ JOINING_TYPE_X, /* 066D */
+ JOINING_TYPE_D, /* 066E; DOTLESS BEH; D; BEH */
+ JOINING_TYPE_D, /* 066F; DOTLESS QAF; D; QAF */
+ JOINING_TYPE_X, /* 0670 */
+ JOINING_TYPE_R, /* 0671; HAMZAT WASL ON ALEF; R; ALEF */
+ JOINING_TYPE_R, /* 0672; WAVY HAMZA ON ALEF; R; ALEF */
+ JOINING_TYPE_R, /* 0673; WAVY HAMZA UNDER ALEF; R; ALEF */
+ JOINING_TYPE_U, /* 0674; HIGH HAMZA; U; No_Joining_Group */
+ JOINING_TYPE_R, /* 0675; HIGH HAMZA ALEF; R; ALEF */
+ JOINING_TYPE_R, /* 0676; HIGH HAMZA WAW; R; WAW */
+ JOINING_TYPE_R, /* 0677; HIGH HAMZA WAW WITH DAMMA; R; WAW */
+ JOINING_TYPE_D, /* 0678; HIGH HAMZA YEH; D; YEH */
+ JOINING_TYPE_D, /* 0679; TEH WITH SMALL TAH; D; BEH */
+ JOINING_TYPE_D, /* 067A; TEH WITH 2 DOTS VERTICAL ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 067B; BEH WITH 2 DOTS VERTICAL BELOW; D; BEH */
+ JOINING_TYPE_D, /* 067C; TEH WITH RING; D; BEH */
+ JOINING_TYPE_D, /* 067D; TEH WITH 3 DOTS ABOVE DOWNWARD; D; BEH */
+ JOINING_TYPE_D, /* 067E; TEH WITH 3 DOTS BELOW; D; BEH */
+ JOINING_TYPE_D, /* 067F; TEH WITH 4 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 0680; BEH WITH 4 DOTS BELOW; D; BEH */
+ JOINING_TYPE_D, /* 0681; HAMZA ON HAH; D; HAH */
+ JOINING_TYPE_D, /* 0682; HAH WITH 2 DOTS VERTICAL ABOVE; D; HAH */
+ JOINING_TYPE_D, /* 0683; HAH WITH MIDDLE 2 DOTS; D; HAH */
+ JOINING_TYPE_D, /* 0684; HAH WITH MIDDLE 2 DOTS VERTICAL; D; HAH */
+ JOINING_TYPE_D, /* 0685; HAH WITH 3 DOTS ABOVE; D; HAH */
+ JOINING_TYPE_D, /* 0686; HAH WITH MIDDLE 3 DOTS DOWNWARD; D; HAH */
+ JOINING_TYPE_D, /* 0687; HAH WITH MIDDLE 4 DOTS; D; HAH */
+ JOINING_TYPE_R, /* 0688; DAL WITH SMALL TAH; R; DAL */
+ JOINING_TYPE_R, /* 0689; DAL WITH RING; R; DAL */
+ JOINING_TYPE_R, /* 068A; DAL WITH DOT BELOW; R; DAL */
+ JOINING_TYPE_R, /* 068B; DAL WITH DOT BELOW AND SMALL TAH; R; DAL */
+ JOINING_TYPE_R, /* 068C; DAL WITH 2 DOTS ABOVE; R; DAL */
+ JOINING_TYPE_R, /* 068D; DAL WITH 2 DOTS BELOW; R; DAL */
+ JOINING_TYPE_R, /* 068E; DAL WITH 3 DOTS ABOVE; R; DAL */
+ JOINING_TYPE_R, /* 068F; DAL WITH 3 DOTS ABOVE DOWNWARD; R; DAL */
+ JOINING_TYPE_R, /* 0690; DAL WITH 4 DOTS ABOVE; R; DAL */
+ JOINING_TYPE_R, /* 0691; REH WITH SMALL TAH; R; REH */
+ JOINING_TYPE_R, /* 0692; REH WITH SMALL V; R; REH */
+ JOINING_TYPE_R, /* 0693; REH WITH RING; R; REH */
+ JOINING_TYPE_R, /* 0694; REH WITH DOT BELOW; R; REH */
+ JOINING_TYPE_R, /* 0695; REH WITH SMALL V BELOW; R; REH */
+ JOINING_TYPE_R, /* 0696; REH WITH DOT BELOW AND DOT ABOVE; R; REH */
+ JOINING_TYPE_R, /* 0697; REH WITH 2 DOTS ABOVE; R; REH */
+ JOINING_TYPE_R, /* 0698; REH WITH 3 DOTS ABOVE; R; REH */
+ JOINING_TYPE_R, /* 0699; REH WITH 4 DOTS ABOVE; R; REH */
+ JOINING_TYPE_D, /* 069A; SEEN WITH DOT BELOW AND DOT ABOVE; D; SEEN */
+ JOINING_TYPE_D, /* 069B; SEEN WITH 3 DOTS BELOW; D; SEEN */
+ JOINING_TYPE_D, /* 069C; SEEN WITH 3 DOTS BELOW AND 3 DOTS ABOVE; D; SEEN */
+ JOINING_TYPE_D, /* 069D; SAD WITH 2 DOTS BELOW; D; SAD */
+ JOINING_TYPE_D, /* 069E; SAD WITH 3 DOTS ABOVE; D; SAD */
+ JOINING_TYPE_D, /* 069F; TAH WITH 3 DOTS ABOVE; D; TAH */
+ JOINING_TYPE_D, /* 06A0; AIN WITH 3 DOTS ABOVE; D; AIN */
+ JOINING_TYPE_D, /* 06A1; DOTLESS FEH; D; FEH */
+ JOINING_TYPE_D, /* 06A2; FEH WITH DOT MOVED BELOW; D; FEH */
+ JOINING_TYPE_D, /* 06A3; FEH WITH DOT BELOW; D; FEH */
+ JOINING_TYPE_D, /* 06A4; FEH WITH 3 DOTS ABOVE; D; FEH */
+ JOINING_TYPE_D, /* 06A5; FEH WITH 3 DOTS BELOW; D; FEH */
+ JOINING_TYPE_D, /* 06A6; FEH WITH 4 DOTS ABOVE; D; FEH */
+ JOINING_TYPE_D, /* 06A7; QAF WITH DOT ABOVE; D; QAF */
+ JOINING_TYPE_D, /* 06A8; QAF WITH 3 DOTS ABOVE; D; QAF */
+ JOINING_TYPE_D, /* 06A9; KEHEH; D; GAF */
+ JOINING_TYPE_D, /* 06AA; SWASH KAF; D; SWASH KAF */
+ JOINING_TYPE_D, /* 06AB; KAF WITH RING; D; GAF */
+ JOINING_TYPE_D, /* 06AC; KAF WITH DOT ABOVE; D; KAF */
+ JOINING_TYPE_D, /* 06AD; KAF WITH 3 DOTS ABOVE; D; KAF */
+ JOINING_TYPE_D, /* 06AE; KAF WITH 3 DOTS BELOW; D; KAF */
+ JOINING_TYPE_D, /* 06AF; GAF; D; GAF */
+ JOINING_TYPE_D, /* 06B0; GAF WITH RING; D; GAF */
+ JOINING_TYPE_D, /* 06B1; GAF WITH 2 DOTS ABOVE; D; GAF */
+ JOINING_TYPE_D, /* 06B2; GAF WITH 2 DOTS BELOW; D; GAF */
+ JOINING_TYPE_D, /* 06B3; GAF WITH 2 DOTS VERTICAL BELOW; D; GAF */
+ JOINING_TYPE_D, /* 06B4; GAF WITH 3 DOTS ABOVE; D; GAF */
+ JOINING_TYPE_D, /* 06B5; LAM WITH SMALL V; D; LAM */
+ JOINING_TYPE_D, /* 06B6; LAM WITH DOT ABOVE; D; LAM */
+ JOINING_TYPE_D, /* 06B7; LAM WITH 3 DOTS ABOVE; D; LAM */
+ JOINING_TYPE_D, /* 06B8; LAM WITH 3 DOTS BELOW; D; LAM */
+ JOINING_TYPE_D, /* 06B9; NOON WITH DOT BELOW; D; NOON */
+ JOINING_TYPE_D, /* 06BA; DOTLESS NOON; D; NOON */
+ JOINING_TYPE_D, /* 06BB; DOTLESS NOON WITH SMALL TAH; D; NOON */
+ JOINING_TYPE_D, /* 06BC; NOON WITH RING; D; NOON */
+ JOINING_TYPE_D, /* 06BD; NYA; D; NYA */
+ JOINING_TYPE_D, /* 06BE; KNOTTED HEH; D; KNOTTED HEH */
+ JOINING_TYPE_D, /* 06BF; HAH WITH MIDDLE 3 DOTS DOWNWARD AND DOT ABOVE; D; HAH */
+ JOINING_TYPE_R, /* 06C0; HAMZA ON HEH; R; TEH MARBUTA */
+ JOINING_TYPE_D, /* 06C1; HEH GOAL; D; HEH GOAL */
+ JOINING_TYPE_D, /* 06C2; HAMZA ON HEH GOAL; D; HEH GOAL */
+ JOINING_TYPE_R, /* 06C3; TEH MARBUTA GOAL; R; HAMZA ON HEH GOAL */
+ JOINING_TYPE_R, /* 06C4; WAW WITH RING; R; WAW */
+ JOINING_TYPE_R, /* 06C5; WAW WITH BAR; R; WAW */
+ JOINING_TYPE_R, /* 06C6; WAW WITH SMALL V; R; WAW */
+ JOINING_TYPE_R, /* 06C7; WAW WITH DAMMA; R; WAW */
+ JOINING_TYPE_R, /* 06C8; WAW WITH ALEF ABOVE; R; WAW */
+ JOINING_TYPE_R, /* 06C9; WAW WITH INVERTED SMALL V; R; WAW */
+ JOINING_TYPE_R, /* 06CA; WAW WITH 2 DOTS ABOVE; R; WAW */
+ JOINING_TYPE_R, /* 06CB; WAW WITH 3 DOTS ABOVE; R; WAW */
+ JOINING_TYPE_D, /* 06CC; FARSI YEH; D; FARSI YEH */
+ JOINING_TYPE_R, /* 06CD; YEH WITH TAIL; R; YEH WITH TAIL */
+ JOINING_TYPE_D, /* 06CE; FARSI YEH WITH SMALL V; D; FARSI YEH */
+ JOINING_TYPE_R, /* 06CF; WAW WITH DOT ABOVE; R; WAW */
+ JOINING_TYPE_D, /* 06D0; YEH WITH 2 DOTS VERTICAL BELOW; D; YEH */
+ JOINING_TYPE_D, /* 06D1; YEH WITH 3 DOTS BELOW; D; YEH */
+ JOINING_TYPE_R, /* 06D2; YEH BARREE; R; YEH BARREE */
+ JOINING_TYPE_R, /* 06D3; HAMZA ON YEH BARREE; R; YEH BARREE */
+ JOINING_TYPE_X, /* 06D4 */
+ JOINING_TYPE_R, /* 06D5; AE; R; TEH MARBUTA */
+ JOINING_TYPE_X, /* 06D6 */
+ JOINING_TYPE_X, /* 06D7 */
+ JOINING_TYPE_X, /* 06D8 */
+ JOINING_TYPE_X, /* 06D9 */
+ JOINING_TYPE_X, /* 06DA */
+ JOINING_TYPE_X, /* 06DB */
+ JOINING_TYPE_X, /* 06DC */
+ JOINING_TYPE_U, /* 06DD; ARABIC END OF AYAH; U; No_Joining_Group */
+ JOINING_TYPE_X, /* 06DE */
+ JOINING_TYPE_X, /* 06DF */
+ JOINING_TYPE_X, /* 06E0 */
+ JOINING_TYPE_X, /* 06E1 */
+ JOINING_TYPE_X, /* 06E2 */
+ JOINING_TYPE_X, /* 06E3 */
+ JOINING_TYPE_X, /* 06E4 */
+ JOINING_TYPE_X, /* 06E5 */
+ JOINING_TYPE_X, /* 06E6 */
+ JOINING_TYPE_X, /* 06E7 */
+ JOINING_TYPE_X, /* 06E8 */
+ JOINING_TYPE_X, /* 06E9 */
+ JOINING_TYPE_X, /* 06EA */
+ JOINING_TYPE_X, /* 06EB */
+ JOINING_TYPE_X, /* 06EC */
+ JOINING_TYPE_X, /* 06ED */
+ JOINING_TYPE_R, /* 06EE; DAL WITH INVERTED V; R; DAL */
+ JOINING_TYPE_R, /* 06EF; REH WITH INVERTED V; R; REH */
+ JOINING_TYPE_X, /* 06F0 */
+ JOINING_TYPE_X, /* 06F1 */
+ JOINING_TYPE_X, /* 06F2 */
+ JOINING_TYPE_X, /* 06F3 */
+ JOINING_TYPE_X, /* 06F4 */
+ JOINING_TYPE_X, /* 06F5 */
+ JOINING_TYPE_X, /* 06F6 */
+ JOINING_TYPE_X, /* 06F7 */
+ JOINING_TYPE_X, /* 06F8 */
+ JOINING_TYPE_X, /* 06F9 */
+ JOINING_TYPE_D, /* 06FA; SEEN WITH DOT BELOW AND 3 DOTS ABOVE; D; SEEN */
+ JOINING_TYPE_D, /* 06FB; DAD WITH DOT BELOW; D; SAD */
+ JOINING_TYPE_D, /* 06FC; GHAIN WITH DOT BELOW; D; AIN */
+ JOINING_TYPE_X, /* 06FD */
+ JOINING_TYPE_X, /* 06FE */
+ JOINING_TYPE_D, /* 06FF; HEH WITH INVERTED V; D; KNOTTED HEH */
+ JOINING_TYPE_X, /* 0700 */
+ JOINING_TYPE_X, /* 0701 */
+ JOINING_TYPE_X, /* 0702 */
+ JOINING_TYPE_X, /* 0703 */
+ JOINING_TYPE_X, /* 0704 */
+ JOINING_TYPE_X, /* 0705 */
+ JOINING_TYPE_X, /* 0706 */
+ JOINING_TYPE_X, /* 0707 */
+ JOINING_TYPE_X, /* 0708 */
+ JOINING_TYPE_X, /* 0709 */
+ JOINING_TYPE_X, /* 070A */
+ JOINING_TYPE_X, /* 070B */
+ JOINING_TYPE_X, /* 070C */
+ JOINING_TYPE_X, /* 070D */
+ JOINING_TYPE_X, /* 070E */
+ JOINING_TYPE_X, /* 070F */
+ JOINING_GROUP_ALAPH, /* 0710; ALAPH; R; ALAPH */
+ JOINING_TYPE_X, /* 0711 */
+ JOINING_TYPE_D, /* 0712; BETH; D; BETH */
+ JOINING_TYPE_D, /* 0713; GAMAL; D; GAMAL */
+ JOINING_TYPE_D, /* 0714; GAMAL GARSHUNI; D; GAMAL */
+ JOINING_GROUP_DALATH_RISH, /* 0715; DALATH; R; DALATH RISH */
+ JOINING_GROUP_DALATH_RISH, /* 0716; DOTLESS DALATH RISH; R; DALATH RISH */
+ JOINING_TYPE_R, /* 0717; HE; R; HE */
+ JOINING_TYPE_R, /* 0718; WAW; R; SYRIAC WAW */
+ JOINING_TYPE_R, /* 0719; ZAIN; R; ZAIN */
+ JOINING_TYPE_D, /* 071A; HETH; D; HETH */
+ JOINING_TYPE_D, /* 071B; TETH; D; TETH */
+ JOINING_TYPE_D, /* 071C; TETH GARSHUNI; D; TETH */
+ JOINING_TYPE_D, /* 071D; YUDH; D; YUDH */
+ JOINING_TYPE_R, /* 071E; YUDH HE; R; YUDH HE */
+ JOINING_TYPE_D, /* 071F; KAPH; D; KAPH */
+ JOINING_TYPE_D, /* 0720; LAMADH; D; LAMADH */
+ JOINING_TYPE_D, /* 0721; MIM; D; MIM */
+ JOINING_TYPE_D, /* 0722; NUN; D; NUN */
+ JOINING_TYPE_D, /* 0723; SEMKATH; D; SEMKATH */
+ JOINING_TYPE_D, /* 0724; FINAL SEMKATH; D; FINAL SEMKATH */
+ JOINING_TYPE_D, /* 0725; E; D; E */
+ JOINING_TYPE_D, /* 0726; PE; D; PE */
+ JOINING_TYPE_D, /* 0727; REVERSED PE; D; REVERSED PE */
+ JOINING_TYPE_R, /* 0728; SADHE; R; SADHE */
+ JOINING_TYPE_D, /* 0729; QAPH; D; QAPH */
+ JOINING_GROUP_DALATH_RISH, /* 072A; RISH; R; DALATH RISH */
+ JOINING_TYPE_D, /* 072B; SHIN; D; SHIN */
+ JOINING_TYPE_R, /* 072C; TAW; R; TAW */
+ JOINING_TYPE_D, /* 072D; PERSIAN BHETH; D; BETH */
+ JOINING_TYPE_D, /* 072E; PERSIAN GHAMAL; D; GAMAL */
+ JOINING_GROUP_DALATH_RISH, /* 072F; PERSIAN DHALATH; R; DALATH RISH */
+ JOINING_TYPE_X, /* 0730 */
+ JOINING_TYPE_X, /* 0731 */
+ JOINING_TYPE_X, /* 0732 */
+ JOINING_TYPE_X, /* 0733 */
+ JOINING_TYPE_X, /* 0734 */
+ JOINING_TYPE_X, /* 0735 */
+ JOINING_TYPE_X, /* 0736 */
+ JOINING_TYPE_X, /* 0737 */
+ JOINING_TYPE_X, /* 0738 */
+ JOINING_TYPE_X, /* 0739 */
+ JOINING_TYPE_X, /* 073A */
+ JOINING_TYPE_X, /* 073B */
+ JOINING_TYPE_X, /* 073C */
+ JOINING_TYPE_X, /* 073D */
+ JOINING_TYPE_X, /* 073E */
+ JOINING_TYPE_X, /* 073F */
+ JOINING_TYPE_X, /* 0740 */
+ JOINING_TYPE_X, /* 0741 */
+ JOINING_TYPE_X, /* 0742 */
+ JOINING_TYPE_X, /* 0743 */
+ JOINING_TYPE_X, /* 0744 */
+ JOINING_TYPE_X, /* 0745 */
+ JOINING_TYPE_X, /* 0746 */
+ JOINING_TYPE_X, /* 0747 */
+ JOINING_TYPE_X, /* 0748 */
+ JOINING_TYPE_X, /* 0749 */
+ JOINING_TYPE_X, /* 074A */
+ JOINING_TYPE_X, /* 074B */
+ JOINING_TYPE_X, /* 074C */
+ JOINING_TYPE_R, /* 074D; SOGDIAN ZHAIN; R; ZHAIN */
+ JOINING_TYPE_D, /* 074E; SOGDIAN KHAPH; D; KHAPH */
+ JOINING_TYPE_D, /* 074F; SOGDIAN FE; D; FE */
+ JOINING_TYPE_D, /* 0750; BEH WITH 3 DOTS HORIZONTALLY BELOW; D; BEH */
+ JOINING_TYPE_D, /* 0751; BEH WITH DOT BELOW AND 3 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 0752; BEH WITH 3 DOTS POINTING UPWARDS BELOW; D; BEH */
+ JOINING_TYPE_D, /* 0753; BEH WITH 3 DOTS POINTING UPWARDS BELOW AND 2 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 0754; BEH WITH 2 DOTS BELOW AND DOT ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 0755; BEH WITH INVERTED SMALL V BELOW; D; BEH */
+ JOINING_TYPE_D, /* 0756; BEH WITH SMALL V; D; BEH */
+ JOINING_TYPE_D, /* 0757; HAH WITH 2 DOTS ABOVE; D; HAH */
+ JOINING_TYPE_D, /* 0758; HAH WITH 3 DOTS POINTING UPWARDS BELOW; D; HAH */
+ JOINING_TYPE_R, /* 0759; DAL WITH 2 DOTS VERTICALLY BELOW AND SMALL TAH; R; DAL */
+ JOINING_TYPE_R, /* 075A; DAL WITH INVERTED SMALL V BELOW; R; DAL */
+ JOINING_TYPE_R, /* 075B; REH WITH STROKE; R; REH */
+ JOINING_TYPE_D, /* 075C; SEEN WITH 4 DOTS ABOVE; D; SEEN */
+ JOINING_TYPE_D, /* 075D; AIN WITH 2 DOTS ABOVE; D; AIN */
+ JOINING_TYPE_D, /* 075E; AIN WITH 3 DOTS POINTING DOWNWARDS ABOVE; D; AIN */
+ JOINING_TYPE_D, /* 075F; AIN WITH 2 DOTS VERTICALLY ABOVE; D; AIN */
+ JOINING_TYPE_D, /* 0760; FEH WITH 2 DOTS BELOW; D; FEH */
+ JOINING_TYPE_D, /* 0761; FEH WITH 3 DOTS POINTING UPWARDS BELOW; D; FEH */
+ JOINING_TYPE_D, /* 0762; KEHEH WITH DOT ABOVE; D; GAF */
+ JOINING_TYPE_D, /* 0763; KEHEH WITH 3 DOTS ABOVE; D; GAF */
+ JOINING_TYPE_D, /* 0764; KEHEH WITH 3 DOTS POINTING UPWARDS BELOW; D; GAF */
+ JOINING_TYPE_D, /* 0765; MEEM WITH DOT ABOVE; D; MEEM */
+ JOINING_TYPE_D, /* 0766; MEEM WITH DOT BELOW; D; MEEM */
+ JOINING_TYPE_D, /* 0767; NOON WITH 2 DOTS BELOW; D; NOON */
+ JOINING_TYPE_D, /* 0768; NOON WITH SMALL TAH; D; NOON */
+ JOINING_TYPE_D, /* 0769; NOON WITH SMALL V; D; NOON */
+ JOINING_TYPE_D, /* 076A; LAM WITH BAR; D; LAM */
+ JOINING_TYPE_R, /* 076B; REH WITH 2 DOTS VERTICALLY ABOVE; R; REH */
+ JOINING_TYPE_R, /* 076C; REH WITH HAMZA ABOVE; R; REH */
+ JOINING_TYPE_D, /* 076D; SEEN WITH 2 DOTS VERTICALLY ABOVE; D; SEEN */
+ JOINING_TYPE_D, /* 076E; HAH WITH SMALL TAH BELOW; D; HAH */
+ JOINING_TYPE_D, /* 076F; HAH WITH SMALL TAH AND 2 DOTS; D; HAH */
+ JOINING_TYPE_D, /* 0770; SEEN WITH SMALL TAH AND 2 DOTS; D; SEEN */
+ JOINING_TYPE_R, /* 0771; REH WITH SMALL TAH AND 2 DOTS; R; REH */
+ JOINING_TYPE_D, /* 0772; HAH WITH SMALL TAH ABOVE; D; HAH */
+ JOINING_TYPE_R, /* 0773; ALEF WITH DIGIT TWO ABOVE; R; ALEF */
+ JOINING_TYPE_R, /* 0774; ALEF WITH DIGIT THREE ABOVE; R; ALEF */
+ JOINING_TYPE_D, /* 0775; FARSI YEH WITH DIGIT TWO ABOVE; D; FARSI YEH */
+ JOINING_TYPE_D, /* 0776; FARSI YEH WITH DIGIT THREE ABOVE; D; FARSI YEH */
+ JOINING_TYPE_D, /* 0777; YEH WITH DIGIT FOUR BELOW; D; YEH */
+ JOINING_TYPE_R, /* 0778; WAW WITH DIGIT TWO ABOVE; R; WAW */
+ JOINING_TYPE_R, /* 0779; WAW WITH DIGIT THREE ABOVE; R; WAW */
+ JOINING_TYPE_D, /* 077A; YEH BARREE WITH DIGIT TWO ABOVE; D; BURUSHASKI YEH BARREE */
+ JOINING_TYPE_D, /* 077B; YEH BARREE WITH DIGIT THREE ABOVE; D; BURUSHASKI YEH BARREE */
+ JOINING_TYPE_D, /* 077C; HAH WITH DIGIT FOUR BELOW; D; HAH */
+ JOINING_TYPE_D, /* 077D; SEEN WITH DIGIT FOUR ABOVE; D; SEEN */
+ JOINING_TYPE_D, /* 077E; SEEN WITH INVERTED V; D; SEEN */
+ JOINING_TYPE_D, /* 077F; KAF WITH 2 DOTS ABOVE; D; KAF */
+ JOINING_TYPE_X, /* 0780 */
+ JOINING_TYPE_X, /* 0781 */
+ JOINING_TYPE_X, /* 0782 */
+ JOINING_TYPE_X, /* 0783 */
+ JOINING_TYPE_X, /* 0784 */
+ JOINING_TYPE_X, /* 0785 */
+ JOINING_TYPE_X, /* 0786 */
+ JOINING_TYPE_X, /* 0787 */
+ JOINING_TYPE_X, /* 0788 */
+ JOINING_TYPE_X, /* 0789 */
+ JOINING_TYPE_X, /* 078A */
+ JOINING_TYPE_X, /* 078B */
+ JOINING_TYPE_X, /* 078C */
+ JOINING_TYPE_X, /* 078D */
+ JOINING_TYPE_X, /* 078E */
+ JOINING_TYPE_X, /* 078F */
+ JOINING_TYPE_X, /* 0790 */
+ JOINING_TYPE_X, /* 0791 */
+ JOINING_TYPE_X, /* 0792 */
+ JOINING_TYPE_X, /* 0793 */
+ JOINING_TYPE_X, /* 0794 */
+ JOINING_TYPE_X, /* 0795 */
+ JOINING_TYPE_X, /* 0796 */
+ JOINING_TYPE_X, /* 0797 */
+ JOINING_TYPE_X, /* 0798 */
+ JOINING_TYPE_X, /* 0799 */
+ JOINING_TYPE_X, /* 079A */
+ JOINING_TYPE_X, /* 079B */
+ JOINING_TYPE_X, /* 079C */
+ JOINING_TYPE_X, /* 079D */
+ JOINING_TYPE_X, /* 079E */
+ JOINING_TYPE_X, /* 079F */
+ JOINING_TYPE_X, /* 07A0 */
+ JOINING_TYPE_X, /* 07A1 */
+ JOINING_TYPE_X, /* 07A2 */
+ JOINING_TYPE_X, /* 07A3 */
+ JOINING_TYPE_X, /* 07A4 */
+ JOINING_TYPE_X, /* 07A5 */
+ JOINING_TYPE_X, /* 07A6 */
+ JOINING_TYPE_X, /* 07A7 */
+ JOINING_TYPE_X, /* 07A8 */
+ JOINING_TYPE_X, /* 07A9 */
+ JOINING_TYPE_X, /* 07AA */
+ JOINING_TYPE_X, /* 07AB */
+ JOINING_TYPE_X, /* 07AC */
+ JOINING_TYPE_X, /* 07AD */
+ JOINING_TYPE_X, /* 07AE */
+ JOINING_TYPE_X, /* 07AF */
+ JOINING_TYPE_X, /* 07B0 */
+ JOINING_TYPE_X, /* 07B1 */
+ JOINING_TYPE_X, /* 07B2 */
+ JOINING_TYPE_X, /* 07B3 */
+ JOINING_TYPE_X, /* 07B4 */
+ JOINING_TYPE_X, /* 07B5 */
+ JOINING_TYPE_X, /* 07B6 */
+ JOINING_TYPE_X, /* 07B7 */
+ JOINING_TYPE_X, /* 07B8 */
+ JOINING_TYPE_X, /* 07B9 */
+ JOINING_TYPE_X, /* 07BA */
+ JOINING_TYPE_X, /* 07BB */
+ JOINING_TYPE_X, /* 07BC */
+ JOINING_TYPE_X, /* 07BD */
+ JOINING_TYPE_X, /* 07BE */
+ JOINING_TYPE_X, /* 07BF */
+ JOINING_TYPE_X, /* 07C0 */
+ JOINING_TYPE_X, /* 07C1 */
+ JOINING_TYPE_X, /* 07C2 */
+ JOINING_TYPE_X, /* 07C3 */
+ JOINING_TYPE_X, /* 07C4 */
+ JOINING_TYPE_X, /* 07C5 */
+ JOINING_TYPE_X, /* 07C6 */
+ JOINING_TYPE_X, /* 07C7 */
+ JOINING_TYPE_X, /* 07C8 */
+ JOINING_TYPE_X, /* 07C9 */
+ JOINING_TYPE_D, /* 07CA; NKO A; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07CB; NKO EE; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07CC; NKO I; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07CD; NKO E; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07CE; NKO U; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07CF; NKO OO; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D0; NKO O; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D1; NKO DAGBASINNA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D2; NKO N; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D3; NKO BA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D4; NKO PA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D5; NKO TA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D6; NKO JA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D7; NKO CHA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D8; NKO DA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07D9; NKO RA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07DA; NKO RRA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07DB; NKO SA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07DC; NKO GBA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07DD; NKO FA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07DE; NKO KA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07DF; NKO LA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E0; NKO NA WOLOSO; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E1; NKO MA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E2; NKO NYA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E3; NKO NA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E4; NKO HA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E5; NKO WA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E6; NKO YA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E7; NKO NYA WOLOSO; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E8; NKO JONA JA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07E9; NKO JONA CHA; D; No_Joining_Group */
+ JOINING_TYPE_D, /* 07EA; NKO JONA RA; D; No_Joining_Group */
+ JOINING_TYPE_X, /* 07EB */
+ JOINING_TYPE_X, /* 07EC */
+ JOINING_TYPE_X, /* 07ED */
+ JOINING_TYPE_X, /* 07EE */
+ JOINING_TYPE_X, /* 07EF */
+ JOINING_TYPE_X, /* 07F0 */
+ JOINING_TYPE_X, /* 07F1 */
+ JOINING_TYPE_X, /* 07F2 */
+ JOINING_TYPE_X, /* 07F3 */
+ JOINING_TYPE_X, /* 07F4 */
+ JOINING_TYPE_X, /* 07F5 */
+ JOINING_TYPE_X, /* 07F6 */
+ JOINING_TYPE_X, /* 07F7 */
+ JOINING_TYPE_X, /* 07F8 */
+ JOINING_TYPE_X, /* 07F9 */
+ JOINING_TYPE_C, /* 07FA; NKO LAJANYALAN; C; No_Joining_Group */
+ JOINING_TYPE_X, /* 07FB */
+ JOINING_TYPE_X, /* 07FC */
+ JOINING_TYPE_X, /* 07FD */
+ JOINING_TYPE_X, /* 07FE */
+ JOINING_TYPE_X, /* 07FF */
+ /* == End of generated table == */
+ JOINING_TYPE_X
+};
+
+static unsigned int get_joining_type (hb_codepoint_t u, hb_category_t gen_cat)
+{
+ /* TODO Macroize the magic bit operations */
+
+ if (likely ((u & ~(0x0600^0x07FF)) == 0x0600)) {
+ unsigned int j_type = arabic_syriac_nko_joining_types[u - 0x0600];
+ if (likely (j_type != JOINING_TYPE_X))
+ return j_type;
+ }
+
+ if (unlikely ((u & ~(0x200C^0x200D)) == 0x200C)) {
+ return u == 0x200C ? JOINING_TYPE_U : JOINING_TYPE_C;
+ }
+
+ return ((1<<gen_cat) & ((1<<HB_CATEGORY_NON_SPACING_MARK)|(1<<HB_CATEGORY_ENCLOSING_MARK)|(1<<HB_CATEGORY_FORMAT))) ?
+ JOINING_TYPE_T : JOINING_TYPE_U;
+}
+
+
+
+static const hb_tag_t arabic_syriac_features[] =
+{
+ HB_TAG('i','n','i','t'),
+ HB_TAG('m','e','d','i'),
+ HB_TAG('f','i','n','a'),
+ HB_TAG('i','s','o','l'),
+ /* Syriac */
+ HB_TAG('m','e','d','2'),
+ HB_TAG('f','i','n','2'),
+ HB_TAG('f','i','n','3'),
+ HB_TAG_NONE
+};
+
+
+/* Same order as the feature array */
+enum {
+ INIT,
+ MEDI,
+ FINA,
+ ISOL,
+
+ /* Syriac */
+ MED2,
+ FIN2,
+ FIN3,
+
+ NONE,
+
+ COMMON_NUM_FEATURES = 4,
+ SYRIAC_NUM_FEATURES = 7,
+ TOTAL_NUM_FEATURES = NONE
+};
+
+static const struct arabic_state_table_entry {
+ uint8_t prev_action;
+ uint8_t curr_action;
+ uint8_t next_state;
+ uint8_t padding;
+} arabic_state_table[][NUM_STATE_MACHINE_COLS] =
+{
+ /* jt_U, jt_R, jt_D, jg_ALAPH, jg_DALATH_RISH */
+
+ /* State 0: prev was U, not willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,6}, },
+
+ /* State 1: prev was R or ISOL/ALAPH, not willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN2,5}, {NONE,ISOL,6}, },
+
+ /* State 2: prev was D/ISOL, willing to join. */
+ { {NONE,NONE,0}, {INIT,FINA,1}, {INIT,FINA,3}, {INIT,FINA,4}, {INIT,FINA,6}, },
+
+ /* State 3: prev was D/FINA, willing to join. */
+ { {NONE,NONE,0}, {MEDI,FINA,1}, {MEDI,FINA,3}, {MEDI,FINA,4}, {MEDI,FINA,6}, },
+
+ /* State 4: prev was FINA ALAPH, not willing to join. */
+ { {NONE,NONE,0}, {MED2,ISOL,1}, {MED2,ISOL,2}, {MED2,FIN2,5}, {MED2,ISOL,6}, },
+
+ /* State 5: prev was FIN2/FIN3 ALAPH, not willing to join. */
+ { {NONE,NONE,0}, {ISOL,ISOL,1}, {ISOL,ISOL,2}, {ISOL,FIN2,5}, {ISOL,ISOL,6}, },
+
+ /* State 6: prev was DALATH/RISH, not willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN3,5}, {NONE,ISOL,6}, }
+};
+
+
+void
+_hb_ot_analyze_complex_arabic (hb_font_t *font,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ hb_feature_t *features HB_UNUSED,
+ unsigned int num_features HB_UNUSED)
+{
+ unsigned int count = buffer->len;
+ unsigned int prev = 0, state = 0;
+
+ for (unsigned int i = 0; i < count; i++) {
+
+ unsigned int this_type = get_joining_type (buffer->info[i].codepoint, buffer->unicode->v.get_general_category (buffer->info[i].codepoint));
+
+ if (unlikely (this_type == JOINING_TYPE_T))
+ continue;
+
+ const arabic_state_table_entry *entry = arabic_state_table[state];
+
+ if (entry->prev_action != NONE)
+ buffer->info[prev].gproperty = entry->prev_action;
+
+ buffer->info[i].gproperty = entry->curr_action;
+
+ prev = i;
+ state = entry->next_state;
+ }
+
+ hb_mask_t mask_array[TOTAL_NUM_FEATURES] = {0};
+ unsigned int num_masks = buffer->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
+ for (unsigned int i = 0; i < num_masks; i++)
+ mask_array[i] = 0 /* XXX find_mask */;
+
+ for (unsigned int i = 0; i < count; i++)
+ buffer->info[i].mask |= mask_array[buffer->info[i].gproperty];
+}
+
+
+HB_END_DECLS
commit 0109816b50064a314389333ff64aaf22cb4b1e56
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Oct 5 18:36:45 2010 -0400
Update build system
diff --git a/autogen.sh b/autogen.sh
index e4317db..fb0148b 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -171,9 +171,6 @@ do_cmd $AUTOHEADER
touch ChangeLog
-# We don't call gtkdocize right now. When we do, we should then modify
-# the generated gtk-doc.make and move it to build/Makefile.am.gtk-doc.
-# See that file for details.
#do_cmd $GTKDOCIZE $GTKDOCIZE_FLAGS
do_cmd $AUTOMAKE $AUTOMAKE_FLAGS
diff --git a/configure.ac b/configure.ac
index 721c912..56c6323 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,6 +9,7 @@ AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL dnl ([1.4]) Don't remove!
AC_PROG_CC
+AM_PROG_CC_C_O
AC_PROG_CXX
AC_CHECK_FUNCS(mprotect sysconf getpagesize)
commit e81d7afe6e0e9dd26025f3243a11cf0b408a8046
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Mon Oct 4 18:18:48 2010 -0400
Add hb_face_get_upem()
diff --git a/src/hb-font.cc b/src/hb-font.cc
index fd5df93..223b2b4 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -397,6 +397,12 @@ hb_face_get_table (hb_face_t *face,
return blob;
}
+unsigned int
+hb_face_get_upem (hb_face_t *face)
+{
+ return (face->head_table ? face->head_table : &Null(head))->get_upem ();
+}
+
/*
* hb_font_t
diff --git a/src/hb-font.h b/src/hb-font.h
index 7815985..934f17c 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -78,6 +78,9 @@ hb_blob_t *
hb_face_get_table (hb_face_t *face,
hb_tag_t tag);
+unsigned int
+hb_face_get_upem (hb_face_t *face);
+
/*
* hb_font_funcs_t
commit d47f79db92fa45d51cd5f7845db8a206f5ec122b
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Mon Oct 4 18:13:30 2010 -0400
Add TODO item
diff --git a/TODO b/TODO
index 2537bb6..001f437 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,7 @@
- Rename get_table to reference_table
+- Avoid allocating blob objects internally for for_data() faces
+
- head table access cleanup (div by zero now!)
- cache various expensive scale computation
commit bd361945a89ea31e6c4525aa030e18744ea81fb3
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Mon Oct 4 17:22:57 2010 -0400
Add API comments
diff --git a/src/hb-font.h b/src/hb-font.h
index 266b74a..7815985 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -61,7 +61,19 @@ hb_face_get_reference_count (hb_face_t *face);
void
hb_face_destroy (hb_face_t *face);
-/* Returns NULL if not found */
+/* XXX
+ *
+ * I have two major concerns about this API as it is right now:
+ *
+ * - Jonathan Kew convinced me to make it return NULL if table not found (280af1bd),
+ * however, that is WRONG IMO. The API should not differentiate between a non-existing
+ * table vs a zero-length table vs a very short table. It only leads to implementations
+ * that check for non-NULL and assume that they've got a usable table going on... This
+ * actually happened with Firefox.
+ *
+ * - It has to be renamed to reference_table() since unlike any other _get_ API, a reference
+ * ownership transfer happens and the user is responsible to destroy the result.
+ */
hb_blob_t *
hb_face_get_table (hb_face_t *face,
hb_tag_t tag);
@@ -196,7 +208,8 @@ hb_font_set_funcs (hb_font_t *font,
*
* The client is responsible for:
*
- * - Take ownership of the reference on the returned klass
+ * - Take ownership of the reference on the returned klass,
+ *
* - Calling "destroy(user_data)" exactly once if returned destroy func
* is not NULL and the returned info is not needed anymore.
*/
commit 645f6f265b5f6fb85b3c0f59ea874d58c86e3917
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Mon Oct 4 17:01:01 2010 -0400
Add is_mutable() functions
Correspond to the make_mutable() ones.
diff --git a/src/hb-font.cc b/src/hb-font.cc
index e257cd8..fd5df93 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -141,6 +141,12 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
ffuncs->immutable = TRUE;
}
+hb_bool_t
+hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
+{
+ return ffuncs->immutable = TRUE;
+}
+
void
hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
diff --git a/src/hb-font.h b/src/hb-font.h
index a7b6d8f..266b74a 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -91,6 +91,8 @@ hb_font_funcs_copy (hb_font_funcs_t *ffuncs);
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs);
+hb_bool_t
+hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
/* funcs */
diff --git a/src/hb-unicode.c b/src/hb-unicode.c
index 19a891b..280c61f 100644
--- a/src/hb-unicode.c
+++ b/src/hb-unicode.c
@@ -108,6 +108,12 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
ufuncs->immutable = TRUE;
}
+hb_bool_t
+hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
+{
+ return ufuncs->immutable;
+}
+
void
hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
diff --git a/src/hb-unicode.h b/src/hb-unicode.h
index a84a948..4edab48 100644
--- a/src/hb-unicode.h
+++ b/src/hb-unicode.h
@@ -201,6 +201,8 @@ hb_unicode_funcs_copy (hb_unicode_funcs_t *ufuncs);
void
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);
+hb_bool_t
+hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs);
/*
* funcs
commit 19c0eab8cf96d00e168c4b11ec435019c1ed44f7
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Mon Oct 4 16:45:21 2010 -0400
Add getters for all setter APIs
One in particular is not a straight getter: hb_font_unset_funcs() is
special because of the specific needs of the lifecycle management of
the user_data object.
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 8a547a3..e257cd8 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -183,6 +183,32 @@ hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
}
+hb_font_get_glyph_func_t
+hb_font_funcs_get_glyph_func (hb_font_funcs_t *ffuncs)
+{
+ return ffuncs->v.get_glyph;
+}
+
+hb_font_get_contour_point_func_t
+hb_font_funcs_get_contour_point_func (hb_font_funcs_t *ffuncs)
+{
+ return ffuncs->v.get_contour_point;
+}
+
+hb_font_get_glyph_metrics_func_t
+hb_font_funcs_get_glyph_metrics_func (hb_font_funcs_t *ffuncs)
+{
+ return ffuncs->v.get_glyph_metrics;
+}
+
+hb_font_get_kerning_func_t
+hb_font_funcs_get_kerning_func (hb_font_funcs_t *ffuncs)
+{
+ return ffuncs->v.get_kerning;
+}
+
+
+
hb_codepoint_t
hb_font_get_glyph (hb_font_t *font, hb_face_t *face,
hb_codepoint_t unicode, hb_codepoint_t variation_selector)
@@ -444,6 +470,26 @@ hb_font_set_funcs (hb_font_t *font,
}
void
+hb_font_unset_funcs (hb_font_t *font,
+ hb_font_funcs_t **klass,
+ hb_destroy_func_t *destroy,
+ void **user_data)
+{
+ /* None of the input arguments can be NULL. */
+
+ *klass = font->klass;
+ *destroy = font->destroy;
+ *user_data = font->user_data;
+
+ if (HB_OBJECT_IS_INERT (font))
+ return;
+
+ font->klass = NULL;
+ font->destroy = NULL;
+ font->user_data = NULL;
+}
+
+void
hb_font_set_scale (hb_font_t *font,
unsigned int x_scale,
unsigned int y_scale)
@@ -456,6 +502,15 @@ hb_font_set_scale (hb_font_t *font,
}
void
+hb_font_get_scale (hb_font_t *font,
+ unsigned int *x_scale,
+ unsigned int *y_scale)
+{
+ if (x_scale) *x_scale = font->x_scale;
+ if (y_scale) *y_scale = font->y_scale;
+}
+
+void
hb_font_set_ppem (hb_font_t *font,
unsigned int x_ppem,
unsigned int y_ppem)
@@ -467,5 +522,14 @@ hb_font_set_ppem (hb_font_t *font,
font->y_ppem = y_ppem;
}
+void
+hb_font_get_ppem (hb_font_t *font,
+ unsigned int *x_ppem,
+ unsigned int *y_ppem)
+{
+ if (x_ppem) *x_ppem = font->x_ppem;
+ if (y_ppem) *y_ppem = font->y_ppem;
+}
+
HB_END_DECLS
diff --git a/src/hb-font.h b/src/hb-font.h
index 6f1f3ca..a7b6d8f 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -132,6 +132,21 @@ hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
hb_font_get_kerning_func_t kerning_func);
+/* These never return NULL. Return fallback defaults instead. */
+
+hb_font_get_glyph_func_t
+hb_font_funcs_get_glyph_func (hb_font_funcs_t *ffuncs);
+
+hb_font_get_contour_point_func_t
+hb_font_funcs_get_contour_point_func (hb_font_funcs_t *ffuncs);
+
+hb_font_get_glyph_metrics_func_t
+hb_font_funcs_get_glyph_metrics_func (hb_font_funcs_t *ffuncs);
+
+hb_font_get_kerning_func_t
+hb_font_funcs_get_kerning_func (hb_font_funcs_t *ffuncs);
+
+
hb_codepoint_t
hb_font_get_glyph (hb_font_t *font, hb_face_t *face,
hb_codepoint_t unicode, hb_codepoint_t variation_selector);
@@ -174,6 +189,21 @@ hb_font_set_funcs (hb_font_t *font,
hb_destroy_func_t destroy,
void *user_data);
+/* Returns what was set and unsets it, but doesn't destroy(user_data).
+ * This is useful for wrapping / chaining font_funcs_t's.
+ *
+ * The client is responsible for:
+ *
+ * - Take ownership of the reference on the returned klass
+ * - Calling "destroy(user_data)" exactly once if returned destroy func
+ * is not NULL and the returned info is not needed anymore.
+ */
+void
+hb_font_unset_funcs (hb_font_t *font,
+ hb_font_funcs_t **klass,
+ hb_destroy_func_t *destroy,
+ void **user_data);
+
/*
* We should add support for full matrices.
@@ -183,6 +213,11 @@ hb_font_set_scale (hb_font_t *font,
unsigned int x_scale,
unsigned int y_scale);
+void
+hb_font_get_scale (hb_font_t *font,
+ unsigned int *x_scale,
+ unsigned int *y_scale);
+
/*
* A zero value means "no hinting in that direction"
*/
@@ -191,6 +226,11 @@ hb_font_set_ppem (hb_font_t *font,
unsigned int x_ppem,
unsigned int y_ppem);
+void
+hb_font_get_ppem (hb_font_t *font,
+ unsigned int *x_ppem,
+ unsigned int *y_ppem);
+
HB_END_DECLS
diff --git a/src/hb-unicode.c b/src/hb-unicode.c
index 2de963e..19a891b 100644
--- a/src/hb-unicode.c
+++ b/src/hb-unicode.c
@@ -160,6 +160,38 @@ hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
}
+hb_unicode_get_mirroring_func_t
+hb_unicode_funcs_get_mirroring_func (hb_unicode_funcs_t *ufuncs)
+{
+ return ufuncs->v.get_mirroring;
+}
+
+hb_unicode_get_general_category_func_t
+hb_unicode_funcs_get_general_category_func (hb_unicode_funcs_t *ufuncs)
+{
+ return ufuncs->v.get_general_category;
+}
+
+hb_unicode_get_script_func_t
+hb_unicode_funcs_get_script_func (hb_unicode_funcs_t *ufuncs)
+{
+ return ufuncs->v.get_script;
+}
+
+hb_unicode_get_combining_class_func_t
+hb_unicode_funcs_get_combining_class_func (hb_unicode_funcs_t *ufuncs)
+{
+ return ufuncs->v.get_combining_class;
+}
+
+hb_unicode_get_eastasian_width_func_t
+hb_unicode_funcs_get_eastasian_width_func (hb_unicode_funcs_t *ufuncs)
+{
+ return ufuncs->v.get_eastasian_width;
+}
+
+
+
hb_codepoint_t
hb_unicode_get_mirroring (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode)
diff --git a/src/hb-unicode.h b/src/hb-unicode.h
index 8aeba33..a84a948 100644
--- a/src/hb-unicode.h
+++ b/src/hb-unicode.h
@@ -202,7 +202,12 @@ void
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);
-/* funcs */
+/*
+ * funcs
+ */
+
+
+/* typedefs */
typedef hb_codepoint_t (*hb_unicode_get_mirroring_func_t) (hb_codepoint_t unicode);
typedef hb_category_t (*hb_unicode_get_general_category_func_t) (hb_codepoint_t unicode);
@@ -211,6 +216,8 @@ typedef unsigned int (*hb_unicode_get_combining_class_func_t) (hb_codepoint_t un
typedef unsigned int (*hb_unicode_get_eastasian_width_func_t) (hb_codepoint_t unicode);
+/* setters */
+
void
hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_get_mirroring_func_t mirroring_func);
@@ -232,6 +239,28 @@ hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_get_eastasian_width_func_t eastasian_width_func);
+/* getters */
+
+/* These never return NULL. Return fallback defaults instead. */
+
+hb_unicode_get_mirroring_func_t
+hb_unicode_funcs_get_mirroring_func (hb_unicode_funcs_t *ufuncs);
+
+hb_unicode_get_general_category_func_t
+hb_unicode_funcs_get_general_category_func (hb_unicode_funcs_t *ufuncs);
+
+hb_unicode_get_script_func_t
+hb_unicode_funcs_get_script_func (hb_unicode_funcs_t *ufuncs);
+
+hb_unicode_get_combining_class_func_t
+hb_unicode_funcs_get_combining_class_func (hb_unicode_funcs_t *ufuncs);
+
+hb_unicode_get_eastasian_width_func_t
+hb_unicode_funcs_get_eastasian_width_func (hb_unicode_funcs_t *ufuncs);
+
+
+/* accessors */
+
hb_codepoint_t
hb_unicode_get_mirroring (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t unicode);
commit f0feb084b0fd1510474b25404d1dcc5686ee0538
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 3 19:09:39 2010 -0400
Minor
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index c1ae99f..fbaff13 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -70,16 +70,18 @@ struct hb_ot_layout_context_t
{
struct gpos_t
{
- unsigned int last; /* the last valid glyph--used with cursive positioning */
+ unsigned int last; /* the last matched glyph--used with cursive positioning */
hb_position_t anchor_x; /* the coordinates of the anchor point */
- hb_position_t anchor_y; /* of the last valid glyph */
+ hb_position_t anchor_y; /* of the last matched glyph */
} gpos;
} info;
/* Convert from font-space to user-space */
- /* XXX speed up */
- inline hb_position_t scale_x (int16_t v) { return (int64_t) this->font->x_scale * v / this->face->head_table->get_upem (); }
- inline hb_position_t scale_y (int16_t v) { return (int64_t) this->font->y_scale * v / this->face->head_table->get_upem (); }
+ inline hb_position_t scale_x (int16_t v) { return scale (v, this->font->x_scale); }
+ inline hb_position_t scale_y (int16_t v) { return scale (v, this->font->y_scale); }
+
+ private:
+ inline hb_position_t scale (int16_t v, unsigned int scale) { return v * (int64_t) scale / this->face->head_table->get_upem (); }
};
More information about the HarfBuzz
mailing list