summaryrefslogtreecommitdiffstats
path: root/third_party
diff options
context:
space:
mode:
authorbashi@chromium.org <bashi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-05 00:33:17 +0000
committerbashi@chromium.org <bashi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-05 00:33:17 +0000
commitf4e59db002be2b735b9b96b0b54ab3234851e6eb (patch)
tree94de05308f504462d5ff92671e7ae01be9efbbff /third_party
parent56510ba355dee2cd6592cdf0d27c4c41ef0cae8b (diff)
downloadchromium_src-f4e59db002be2b735b9b96b0b54ab3234851e6eb.zip
chromium_src-f4e59db002be2b735b9b96b0b54ab3234851e6eb.tar.gz
chromium_src-f4e59db002be2b735b9b96b0b54ab3234851e6eb.tar.bz2
Roll harfbuzz-ng 3b8fd9c48f4bde368bf2d465c148b9743a9216ee
The revision provides HB_NO_MT macro that disables multi-threading support. We don't need multi-threading support for harfbuzz-ng. BUG=none TEST=compiled ("make harfbuzz-ng") Review URL: https://chromiumcodereview.appspot.com/10510004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140446 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r--third_party/harfbuzz-ng/README.chromium4
-rw-r--r--third_party/harfbuzz-ng/harfbuzz.gyp9
-rw-r--r--third_party/harfbuzz-ng/src/hb-atomic-private.hh79
-rw-r--r--third_party/harfbuzz-ng/src/hb-blob.cc2
-rw-r--r--third_party/harfbuzz-ng/src/hb-blob.h4
-rw-r--r--third_party/harfbuzz-ng/src/hb-buffer-private.hh16
-rw-r--r--third_party/harfbuzz-ng/src/hb-buffer.cc26
-rw-r--r--third_party/harfbuzz-ng/src/hb-buffer.h4
-rw-r--r--third_party/harfbuzz-ng/src/hb-cache-private.hh72
-rw-r--r--third_party/harfbuzz-ng/src/hb-common.cc23
-rw-r--r--third_party/harfbuzz-ng/src/hb-common.h242
-rw-r--r--third_party/harfbuzz-ng/src/hb-fallback-shape-private.hh9
-rw-r--r--third_party/harfbuzz-ng/src/hb-fallback-shape.cc9
-rw-r--r--third_party/harfbuzz-ng/src/hb-font-private.hh2
-rw-r--r--third_party/harfbuzz-ng/src/hb-font.cc84
-rw-r--r--third_party/harfbuzz-ng/src/hb-font.h32
-rw-r--r--third_party/harfbuzz-ng/src/hb-ft.cc54
-rw-r--r--third_party/harfbuzz-ng/src/hb-ft.h2
-rw-r--r--third_party/harfbuzz-ng/src/hb-glib.cc11
-rw-r--r--third_party/harfbuzz-ng/src/hb-glib.h1
-rw-r--r--third_party/harfbuzz-ng/src/hb-gobject-enums.cc63
-rw-r--r--third_party/harfbuzz-ng/src/hb-gobject.h1
-rw-r--r--third_party/harfbuzz-ng/src/hb-graphite2-private.hh (renamed from third_party/harfbuzz-ng/src/hb-ot-shape.h)29
-rw-r--r--third_party/harfbuzz-ng/src/hb-graphite2.cc14
-rw-r--r--third_party/harfbuzz-ng/src/hb-graphite2.h10
-rw-r--r--third_party/harfbuzz-ng/src/hb-icu.h1
-rw-r--r--third_party/harfbuzz-ng/src/hb-mutex-private.hh41
-rw-r--r--third_party/harfbuzz-ng/src/hb-object-private.hh87
-rw-r--r--third_party/harfbuzz-ng/src/hb-open-file-private.hh23
-rw-r--r--third_party/harfbuzz-ng/src/hb-open-type-private.hh122
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-head-table.hh4
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh4
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh4
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh208
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh50
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh445
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh673
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh696
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-private.hh4
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout.cc14
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout.h14
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-map-private.hh4
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-map.cc15
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh7
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-name-table.hh17
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh252
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc92
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh343
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh270
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh182
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc920
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc150
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh172
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh46
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc149
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-private.hh86
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape.cc152
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-tag.h6
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot.h11
-rw-r--r--third_party/harfbuzz-ng/src/hb-private.hh202
-rw-r--r--third_party/harfbuzz-ng/src/hb-set-private.hh169
-rw-r--r--third_party/harfbuzz-ng/src/hb-set.cc191
-rw-r--r--third_party/harfbuzz-ng/src/hb-set.h132
-rw-r--r--third_party/harfbuzz-ng/src/hb-shape.cc26
-rw-r--r--third_party/harfbuzz-ng/src/hb-shape.h5
-rw-r--r--third_party/harfbuzz-ng/src/hb-tt-font.cc3
-rw-r--r--third_party/harfbuzz-ng/src/hb-unicode-private.hh51
-rw-r--r--third_party/harfbuzz-ng/src/hb-unicode.cc57
-rw-r--r--third_party/harfbuzz-ng/src/hb-unicode.h4
-rw-r--r--third_party/harfbuzz-ng/src/hb-uniscribe-private.hh42
-rw-r--r--third_party/harfbuzz-ng/src/hb-uniscribe.cc12
-rw-r--r--third_party/harfbuzz-ng/src/hb-uniscribe.h10
-rw-r--r--third_party/harfbuzz-ng/src/hb-version.h8
-rw-r--r--third_party/harfbuzz-ng/src/hb-warning.cc66
-rw-r--r--third_party/harfbuzz-ng/src/hb.h3
-rw-r--r--third_party/harfbuzz-ng/src/indic.cc46
-rw-r--r--third_party/harfbuzz-ng/src/main.cc9
77 files changed, 4971 insertions, 2131 deletions
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium
index 9930732..f66a274 100644
--- a/third_party/harfbuzz-ng/README.chromium
+++ b/third_party/harfbuzz-ng/README.chromium
@@ -2,8 +2,8 @@ Name: harfbuzz-ng
Short Name: harfbuzz-ng
URL: http://freedesktop.org/wiki/Software/HarfBuzz
Version: unknown
-Date: 20120127
-Revision: 1a5a91dc0d8bf4b72a2f22dc6300b06ad7000b79
+Date: 20120604
+Revision: 3b8fd9c48f4bde368bf2d465c148b9743a9216ee
Security Critical: yes
Description:
diff --git a/third_party/harfbuzz-ng/harfbuzz.gyp b/third_party/harfbuzz-ng/harfbuzz.gyp
index ea8e48d..6a69487 100644
--- a/third_party/harfbuzz-ng/harfbuzz.gyp
+++ b/third_party/harfbuzz-ng/harfbuzz.gyp
@@ -13,13 +13,16 @@
'defines': [
'HAVE_OT',
'HAVE_ICU',
+ 'HB_NO_MT',
],
'sources': [
+ 'src/hb-atomic-private.hh',
'src/hb-blob.cc',
'src/hb-blob.h',
'src/hb-buffer-private.hh',
'src/hb-buffer.cc',
'src/hb-buffer.h',
+ 'src/hb-cache-private.hh',
'src/hb-common.cc',
'src/hb-common.h',
'src/hb-fallback-shape-private.hh',
@@ -56,18 +59,21 @@
'src/hb-ot-shape-complex-arabic-table.hh',
'src/hb-ot-shape-complex-arabic.cc',
'src/hb-ot-shape-complex-indic-machine.hh',
+ 'src/hb-ot-shape-complex-indic-private.hh',
'src/hb-ot-shape-complex-indic-table.hh',
'src/hb-ot-shape-complex-indic.cc',
'src/hb-ot-shape-complex-misc.cc',
'src/hb-ot-shape-complex-private.hh',
'src/hb-ot-shape-normalize.cc',
+ 'src/hb-ot-shape-normalize-private.hh',
'src/hb-ot-shape-private.hh',
'src/hb-ot-shape.cc',
- 'src/hb-ot-shape.h',
'src/hb-ot-tag.cc',
'src/hb-ot-tag.h',
'src/hb-ot.h',
'src/hb-private.hh',
+ 'src/hb-set.cc',
+ 'src/hb-set-private.hh',
'src/hb-shape.cc',
'src/hb-shape.h',
'src/hb-tt-font.cc',
@@ -75,6 +81,7 @@
'src/hb-unicode.cc',
'src/hb-unicode.h',
'src/hb-version.h',
+ 'src/hb-warning.cc',
'src/hb.h',
],
'sources/': [
diff --git a/third_party/harfbuzz-ng/src/hb-atomic-private.hh b/third_party/harfbuzz-ng/src/hb-atomic-private.hh
new file mode 100644
index 0000000..d6bd1c9
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-atomic-private.hh
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2007 Chris Wilson
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Contributor(s):
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ATOMIC_PRIVATE_HH
+#define HB_ATOMIC_PRIVATE_HH
+
+#include "hb-private.hh"
+
+
+/* atomic_int */
+
+/* We need external help for these */
+
+#if 0
+
+
+#elif !defined(HB_NO_MT) && defined(_MSC_VER) && _MSC_VER >= 1600
+
+#include <intrin.h>
+typedef long hb_atomic_int_t;
+#define hb_atomic_int_add(AI, V) _InterlockedExchangeAdd (&(AI), (V))
+
+
+#elif !defined(HB_NO_MT) && defined(__APPLE__)
+
+#include <libkern/OSAtomic.h>
+typedef int32_t hb_atomic_int_t;
+#define hb_atomic_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_GLIB)
+
+#include <glib.h>
+typedef volatile int hb_atomic_int_t;
+#if GLIB_CHECK_VERSION(2,29,5)
+#define hb_atomic_int_add(AI, V) g_atomic_int_add (&(AI), (V))
+#else
+#define hb_atomic_int_add(AI, V) g_atomic_int_exchange_and_add (&(AI), (V))
+#endif
+
+
+#else
+
+#define HB_ATOMIC_INT_NIL 1
+typedef volatile int hb_atomic_int_t;
+#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V))
+
+#endif
+
+
+#endif /* HB_ATOMIC_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-blob.cc b/third_party/harfbuzz-ng/src/hb-blob.cc
index b2b1d9c..ee997ad 100644
--- a/third_party/harfbuzz-ng/src/hb-blob.cc
+++ b/third_party/harfbuzz-ng/src/hb-blob.cc
@@ -301,7 +301,7 @@ _try_writable (hb_blob_t *blob)
return TRUE;
- DEBUG_MSG_FUNC (BLOB, blob, "currect data is -> %p\n", blob->data);
+ DEBUG_MSG_FUNC (BLOB, blob, "current data is -> %p\n", blob->data);
char *new_data;
diff --git a/third_party/harfbuzz-ng/src/hb-blob.h b/third_party/harfbuzz-ng/src/hb-blob.h
index 50c9ae3..360310b 100644
--- a/third_party/harfbuzz-ng/src/hb-blob.h
+++ b/third_party/harfbuzz-ng/src/hb-blob.h
@@ -24,6 +24,10 @@
* Red Hat Author(s): Behdad Esfahbod
*/
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
#ifndef HB_BLOB_H
#define HB_BLOB_H
diff --git a/third_party/harfbuzz-ng/src/hb-buffer-private.hh b/third_party/harfbuzz-ng/src/hb-buffer-private.hh
index 4292222..e9e0f82 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-buffer-private.hh
@@ -70,6 +70,15 @@ struct _hb_buffer_t {
hb_glyph_info_t *out_info;
hb_glyph_position_t *pos;
+ inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
+ inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
+
+ inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
+ inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
+
+ inline hb_glyph_info_t &prev (void) { return out_info[out_len - 1]; }
+ inline hb_glyph_info_t prev (void) const { return info[out_len - 1]; }
+
unsigned int serial;
uint8_t allocated_var_bytes[8];
const char *allocated_var_owner[8];
@@ -104,7 +113,7 @@ struct _hb_buffer_t {
const uint16_t *glyph_data_be);
HB_INTERNAL void replace_glyphs (unsigned int num_in,
unsigned int num_out,
- const uint16_t *glyph_data);
+ const hb_codepoint_t *glyph_data);
HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
/* Makes a copy of the glyph at idx to output and replace glyph_index */
HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
@@ -131,6 +140,11 @@ struct _hb_buffer_t {
unsigned int cluster_start,
unsigned int cluster_end);
+ HB_INTERNAL void merge_clusters (unsigned int start,
+ unsigned int end);
+ HB_INTERNAL void merge_out_clusters (unsigned int start,
+ unsigned int end);
+
/* Internal methods */
HB_INTERNAL bool enlarge (unsigned int size);
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.cc b/third_party/harfbuzz-ng/src/hb-buffer.cc
index e8bdfb1..c566a4a 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer.cc
+++ b/third_party/harfbuzz-ng/src/hb-buffer.cc
@@ -223,6 +223,7 @@ hb_buffer_t::swap_buffers (void)
if (unlikely (in_error)) return;
assert (have_output);
+ have_output = FALSE;
if (out_info != info)
{
@@ -270,7 +271,7 @@ hb_buffer_t::replace_glyphs_be16 (unsigned int num_in,
void
hb_buffer_t::replace_glyphs (unsigned int num_in,
unsigned int num_out,
- const uint16_t *glyph_data)
+ const uint32_t *glyph_data)
{
if (!make_room_for (num_in, num_out)) return;
@@ -431,6 +432,29 @@ hb_buffer_t::reverse_clusters (void)
}
void
+hb_buffer_t::merge_clusters (unsigned int start,
+ unsigned int end)
+{
+ unsigned int cluster = this->info[start].cluster;
+
+ for (unsigned int i = start + 1; i < end; i++)
+ cluster = MIN (cluster, this->info[i].cluster);
+ for (unsigned int i = start; i < end; i++)
+ this->info[i].cluster = cluster;
+}
+void
+hb_buffer_t::merge_out_clusters (unsigned int start,
+ unsigned int end)
+{
+ unsigned int cluster = this->out_info[start].cluster;
+
+ for (unsigned int i = start + 1; i < end; i++)
+ cluster = MIN (cluster, this->out_info[i].cluster);
+ for (unsigned int i = start; i < end; i++)
+ this->out_info[i].cluster = cluster;
+}
+
+void
hb_buffer_t::guess_properties (void)
{
/* If script is set to INVALID, guess from buffer contents */
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.h b/third_party/harfbuzz-ng/src/hb-buffer.h
index 9582ebe..ca1bbf4 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer.h
+++ b/third_party/harfbuzz-ng/src/hb-buffer.h
@@ -27,6 +27,10 @@
* Google Author(s): Behdad Esfahbod
*/
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
#ifndef HB_BUFFER_H
#define HB_BUFFER_H
diff --git a/third_party/harfbuzz-ng/src/hb-cache-private.hh b/third_party/harfbuzz-ng/src/hb-cache-private.hh
new file mode 100644
index 0000000..a0928a0
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-cache-private.hh
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_CACHE_PRIVATE_HH
+#define HB_CACHE_PRIVATE_HH
+
+#include "hb-private.hh"
+
+
+/* Implements a lock-free cache for int->int functions. */
+
+template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
+struct hb_cache_t
+{
+ ASSERT_STATIC (key_bits >= cache_bits);
+ ASSERT_STATIC (key_bits + value_bits - cache_bits < 8 * sizeof (unsigned int));
+
+ inline void clear (void)
+ {
+ memset (values, 255, sizeof (values));
+ }
+
+ inline bool get (unsigned int key, unsigned int *value)
+ {
+ unsigned int k = key & ((1<<cache_bits)-1);
+ unsigned int v = values[k];
+ if ((v >> value_bits) != (key >> cache_bits))
+ return false;
+ }
+
+ inline bool set (unsigned int key, unsigned int value)
+ {
+ if (unlikely ((key >> key_bits) || (value >> value_bits)))
+ return false; /* Overflows */
+ unsigned int k = key & ((1<<cache_bits)-1);
+ unsigned int v = ((key>>cache_bits)<<value_bits) | value;
+ values[k] = v;
+ return true;
+ }
+
+ private:
+ unsigned int values[1<<cache_bits];
+};
+
+typedef hb_cache_t<21, 16, 8> hb_cmap_cache_t;
+typedef hb_cache_t<16, 24, 8> hb_advance_cache_t;
+
+
+#endif /* HB_CACHE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-common.cc b/third_party/harfbuzz-ng/src/hb-common.cc
index 6093289..bfbba65 100644
--- a/third_party/harfbuzz-ng/src/hb-common.cc
+++ b/third_party/harfbuzz-ng/src/hb-common.cc
@@ -1,6 +1,6 @@
/*
* Copyright © 2009,2010 Red Hat, Inc.
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -80,7 +80,7 @@ hb_direction_from_string (const char *str, int len)
char c = TOLOWER (str[0]);
for (unsigned int i = 0; i < ARRAY_LENGTH (direction_strings); i++)
if (c == direction_strings[i][0])
- return (hb_direction_t) i;
+ return (hb_direction_t) (HB_DIRECTION_LTR + i);
return HB_DIRECTION_INVALID;
}
@@ -88,8 +88,9 @@ hb_direction_from_string (const char *str, int len)
const char *
hb_direction_to_string (hb_direction_t direction)
{
- if (likely ((unsigned int) direction < ARRAY_LENGTH (direction_strings)))
- return direction_strings[direction];
+ if (likely ((unsigned int) (direction - HB_DIRECTION_LTR)
+ < ARRAY_LENGTH (direction_strings)))
+ return direction_strings[direction - HB_DIRECTION_LTR];
return "invalid";
}
@@ -264,20 +265,30 @@ hb_script_to_iso15924_tag (hb_script_t script)
hb_direction_t
hb_script_get_horizontal_direction (hb_script_t script)
{
+ /* http://goo.gl/x9ilM */
switch ((hb_tag_t) script)
{
+ /* Unicode-1.1 additions */
case HB_SCRIPT_ARABIC:
case HB_SCRIPT_HEBREW:
+
+ /* Unicode-3.0 additions */
case HB_SCRIPT_SYRIAC:
case HB_SCRIPT_THAANA:
/* Unicode-4.0 additions */
case HB_SCRIPT_CYPRIOT:
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_KHAROSHTHI:
+
/* Unicode-5.0 additions */
case HB_SCRIPT_PHOENICIAN:
case HB_SCRIPT_NKO:
+ /* Unicode-5.1 additions */
+ case HB_SCRIPT_LYDIAN:
+
/* Unicode-5.2 additions */
case HB_SCRIPT_AVESTAN:
case HB_SCRIPT_IMPERIAL_ARAMAIC:
@@ -290,6 +301,10 @@ hb_script_get_horizontal_direction (hb_script_t script)
/* Unicode-6.0 additions */
case HB_SCRIPT_MANDAIC:
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_MEROITIC_CURSIVE:
+ case HB_SCRIPT_MEROITIC_HIEROGLYPHS:
+
return HB_DIRECTION_RTL;
}
diff --git a/third_party/harfbuzz-ng/src/hb-common.h b/third_party/harfbuzz-ng/src/hb-common.h
index b7fef32..562b04c 100644
--- a/third_party/harfbuzz-ng/src/hb-common.h
+++ b/third_party/harfbuzz-ng/src/hb-common.h
@@ -1,6 +1,6 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -26,6 +26,10 @@
* Google Author(s): Behdad Esfahbod
*/
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
#ifndef HB_COMMON_H
#define HB_COMMON_H
@@ -89,39 +93,40 @@ typedef uint32_t hb_tag_t;
#define HB_TAG_NONE HB_TAG(0,0,0,0)
-/* len=-1 means s is NUL-terminated */
-hb_tag_t hb_tag_from_string (const char *s, int len);
+/* len=-1 means str is NUL-terminated */
+hb_tag_t hb_tag_from_string (const char *str, int len);
/* hb_direction_t */
typedef enum {
- HB_DIRECTION_INVALID = -1,
- HB_DIRECTION_LTR = 0,
+ HB_DIRECTION_INVALID = 0,
+ HB_DIRECTION_LTR = 4,
HB_DIRECTION_RTL,
HB_DIRECTION_TTB,
HB_DIRECTION_BTT
} hb_direction_t;
-/* len=-1 means s is NUL-terminated */
+/* len=-1 means str is NUL-terminated */
hb_direction_t
hb_direction_from_string (const char *str, int len);
const char *
hb_direction_to_string (hb_direction_t direction);
-#define HB_DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 0)
-#define HB_DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 2)
-#define HB_DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 0)
-#define HB_DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 1)
-#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1))
+#define HB_DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 4)
+#define HB_DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 6)
+#define HB_DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 4)
+#define HB_DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 5)
+#define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4)
+#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1)) /* Direction must be valid */
/* hb_language_t */
typedef struct _hb_language_t *hb_language_t;
-/* len=-1 means s is NUL-terminated */
+/* len=-1 means str is NUL-terminated */
hb_language_t
hb_language_from_string (const char *str, int len);
@@ -174,119 +179,138 @@ typedef enum
/* hb_script_t */
/* http://unicode.org/iso15924/ */
+/* http://goo.gl/x9ilM */
typedef enum
{
- HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'),
- HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'),
- HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'),
- HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'),
- HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'),
- HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'),
- HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'),
- HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'),
- HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'),
- HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'),
- HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'),
- HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'),
- HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'),
- HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'),
- HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'),
- HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'),
- HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'),
- HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'),
- HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'),
- HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'),
- HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'),
- HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'),
- HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'),
- HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'),
- HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'),
- HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'),
- HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'),
- HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'),
- HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'),
- HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'),
- HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'),
- HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'),
- HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'),
- HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'),
- HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'),
- HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'),
- HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'),
- HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'),
- HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'),
- HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'),
- HB_SCRIPT_CANADIAN_ABORIGINAL = HB_TAG ('C','a','n','s'),
- HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'),
- HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'),
- HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'),
- HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'),
- HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'),
+ /* Unicode-1.1 additions */
+ HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'),
+ HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'),
+ HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'),
+ HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'),
+ HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'),
+ HB_SCRIPT_CANADIAN_ABORIGINAL = HB_TAG ('C','a','n','s'),
+ HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'),
+ HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'),
+ HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'),
+ HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'),
+ HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'),
+ HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'),
+ HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'),
+ HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'),
+ HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'),
+ HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'),
+ HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'),
+ HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'),
+ HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'),
+ HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'),
+ HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'),
+ HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'),
+ HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'),
+ HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'),
+ HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'),
+ HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'),
+ HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'),
+ HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'),
+ HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'),
+ HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'),
+ HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'),
+ HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'),
+ HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'),
+
+ /* Unicode-2.0 additions */
+ HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'),
+
+ /* Unicode-3.0 additions */
+ HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'),
+ HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'),
+ HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'),
+ HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'),
+ HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'),
+
+ /* Unicode-3.1 additions */
+ HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'),
+ HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'),
+ HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'),
+
+ /* Unicode-3.2 additions */
+ HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'),
+ HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'),
+ HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'),
+ HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'),
/* Unicode-4.0 additions */
- HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'),
- HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'),
- HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'),
- HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'),
- HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'),
- HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'),
- HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'),
- HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'),
+ HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'),
+ HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'),
+ HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'),
+ HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'),
+ HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'),
+ HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'),
+ HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'),
+ HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'),
/* Unicode-4.1 additions */
- HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'),
- HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'),
- HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'),
- HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'),
- HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'),
- HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'),
- HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'),
+ HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'),
+ HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'),
+ HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'),
+ HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'),
+ HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'),
+ HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'),
+ HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'),
/* Unicode-5.0 additions */
- HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'),
- HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'),
- HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'),
- HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'),
- HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'),
- HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'),
+ HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'),
+ HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'),
+ HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'),
+ HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'),
+ HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'),
+ HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'),
/* Unicode-5.1 additions */
- HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'),
- HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'),
- HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'),
- HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'),
- HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'),
- HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'),
- HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'),
- HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'),
- HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'),
- HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'),
- HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'),
+ HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'),
+ HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'),
+ HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'),
+ HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'),
+ HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'),
+ HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'),
+ HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'),
+ HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'),
+ HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'),
+ HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'),
+ HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'),
/* Unicode-5.2 additions */
- HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'),
- HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'),
- HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'),
- HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'),
- HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'),
- HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'),
- HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'),
- HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'),
- HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'),
- HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'),
- HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'),
- HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'),
- HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'),
- HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'),
- HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'),
+ HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'),
+ HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'),
+ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'),
+ HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'),
+ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'),
+ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'),
+ HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'),
+ HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'),
+ HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'),
+ HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'),
+ HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'),
+ HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'),
+ HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'),
+ HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'),
+ HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'),
/* Unicode-6.0 additions */
- HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'),
- HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'),
- HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'),
+ HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'),
+ HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'),
+ HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'),
+
+ /* Unicode-6.1 additions */
+ HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'),
+ HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'),
+ HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'),
+ HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'),
+ HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'),
+ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'),
+ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'),
/* No script set */
- HB_SCRIPT_INVALID = HB_TAG_NONE
+ HB_SCRIPT_INVALID = HB_TAG_NONE
} hb_script_t;
diff --git a/third_party/harfbuzz-ng/src/hb-fallback-shape-private.hh b/third_party/harfbuzz-ng/src/hb-fallback-shape-private.hh
index d0beb16..159456d 100644
--- a/third_party/harfbuzz-ng/src/hb-fallback-shape-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-fallback-shape-private.hh
@@ -36,11 +36,10 @@ HB_BEGIN_DECLS
HB_INTERNAL hb_bool_t
-hb_fallback_shape (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options);
+_hb_fallback_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features);
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-fallback-shape.cc b/third_party/harfbuzz-ng/src/hb-fallback-shape.cc
index 2fd527f..20ea43e 100644
--- a/third_party/harfbuzz-ng/src/hb-fallback-shape.cc
+++ b/third_party/harfbuzz-ng/src/hb-fallback-shape.cc
@@ -29,11 +29,10 @@
#include "hb-buffer-private.hh"
hb_bool_t
-hb_fallback_shape (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options)
+_hb_fallback_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features HB_UNUSED,
+ unsigned int num_features HB_UNUSED)
{
buffer->guess_properties ();
diff --git a/third_party/harfbuzz-ng/src/hb-font-private.hh b/third_party/harfbuzz-ng/src/hb-font-private.hh
index d896e72..e10e105 100644
--- a/third_party/harfbuzz-ng/src/hb-font-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-font-private.hh
@@ -50,6 +50,8 @@
HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_name) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
/* ^--- Add new callbacks here */
struct _hb_font_funcs_t {
diff --git a/third_party/harfbuzz-ng/src/hb-font.cc b/third_party/harfbuzz-ng/src/hb-font.cc
index d549455..1862ac3 100644
--- a/third_party/harfbuzz-ng/src/hb-font.cc
+++ b/third_party/harfbuzz-ng/src/hb-font.cc
@@ -33,6 +33,8 @@
#include "hb-open-file-private.hh"
#include "hb-ot-head-table.hh"
+#include "hb-cache-private.hh"
+
#include <string.h>
@@ -42,7 +44,7 @@
*/
static hb_bool_t
-hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t unicode,
hb_codepoint_t variation_selector,
@@ -57,7 +59,7 @@ hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
}
static hb_position_t
-hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_h_advance_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
@@ -69,7 +71,7 @@ hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
}
static hb_position_t
-hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_v_advance_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
@@ -81,7 +83,7 @@ hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
}
static hb_bool_t
-hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_h_origin_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_position_t *x,
@@ -89,9 +91,7 @@ hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
if (font->parent) {
- hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent,
- glyph,
- x, y);
+ hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent, glyph, x, y);
if (ret)
font->parent_scale_position (x, y);
return ret;
@@ -102,7 +102,7 @@ hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
}
static hb_bool_t
-hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_v_origin_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_position_t *x,
@@ -110,9 +110,7 @@ hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
if (font->parent) {
- hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
- glyph,
- x, y);
+ hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent, glyph, x, y);
if (ret)
font->parent_scale_position (x, y);
return ret;
@@ -123,7 +121,7 @@ hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
}
static hb_position_t
-hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t left_glyph,
hb_codepoint_t right_glyph,
@@ -136,7 +134,7 @@ hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
}
static hb_position_t
-hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t top_glyph,
hb_codepoint_t bottom_glyph,
@@ -149,7 +147,7 @@ hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
}
static hb_bool_t
-hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_extents_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents,
@@ -171,7 +169,7 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
}
static hb_bool_t
-hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_contour_point_nil (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
unsigned int point_index,
@@ -180,9 +178,7 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
void *user_data HB_UNUSED)
{
if (font->parent) {
- hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent,
- glyph, point_index,
- x, y);
+ hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent, glyph, point_index, x, y);
if (ret)
font->parent_scale_position (x, y);
return ret;
@@ -192,6 +188,34 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
return FALSE;
}
+static hb_bool_t
+hb_font_get_glyph_name_nil (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ char *name, unsigned int size,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return hb_font_get_glyph_name (font->parent, glyph, name, size);
+
+ snprintf (name, size, "gid%u", glyph);
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_glyph_from_name_nil (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ const char *name, int len, /* -1 means nul-terminated */
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return hb_font_get_glyph_from_name (font->parent, name, len, glyph);
+
+ *glyph = 0;
+ return FALSE;
+}
+
static hb_font_funcs_t _hb_font_funcs_nil = {
HB_OBJECT_HEADER_STATIC,
@@ -403,6 +427,28 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
font->klass->user_data.glyph_contour_point);
}
+hb_bool_t
+hb_font_get_glyph_name (hb_font_t *font,
+ hb_codepoint_t glyph,
+ char *name, unsigned int size)
+{
+ return font->klass->get.glyph_name (font, font->user_data,
+ glyph,
+ name, size,
+ font->klass->user_data.glyph_name);
+}
+
+hb_bool_t
+hb_font_get_glyph_from_name (hb_font_t *font,
+ const char *name, int len, /* -1 means nul-terminated */
+ hb_codepoint_t *glyph)
+{
+ return font->klass->get.glyph_from_name (font, font->user_data,
+ name, len,
+ glyph,
+ font->klass->user_data.glyph_from_name);
+}
+
/* A bit higher-level, and with fallback */
@@ -729,7 +775,7 @@ hb_face_set_index (hb_face_t *face,
if (hb_object_is_inert (face))
return;
- face->index = 0;
+ face->index = index;
}
unsigned int
diff --git a/third_party/harfbuzz-ng/src/hb-font.h b/third_party/harfbuzz-ng/src/hb-font.h
index 8a9dda5..b98759b 100644
--- a/third_party/harfbuzz-ng/src/hb-font.h
+++ b/third_party/harfbuzz-ng/src/hb-font.h
@@ -24,6 +24,10 @@
* Red Hat Author(s): Behdad Esfahbod
*/
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
#ifndef HB_FONT_H
#define HB_FONT_H
@@ -188,6 +192,16 @@ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, vo
void *user_data);
+typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ char *name, unsigned int size,
+ void *user_data);
+typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data,
+ const char *name, int len, /* -1 means nul-terminated */
+ hb_codepoint_t *glyph,
+ void *user_data);
+
+
/* func setters */
void
@@ -231,6 +245,15 @@ hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_contour_point_func_t func,
void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_name_func_t glyph_func,
+ void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_from_name_func_t glyph_func,
+ void *user_data, hb_destroy_func_t destroy);
+
/* func dispatch */
@@ -272,6 +295,15 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
hb_codepoint_t glyph, unsigned int point_index,
hb_position_t *x, hb_position_t *y);
+hb_bool_t
+hb_font_get_glyph_name (hb_font_t *font,
+ hb_codepoint_t glyph,
+ char *name, unsigned int size);
+hb_bool_t
+hb_font_get_glyph_from_name (hb_font_t *font,
+ const char *name, int len, /* -1 means nul-terminated */
+ hb_codepoint_t *glyph);
+
/* high-level funcs, with fallback */
diff --git a/third_party/harfbuzz-ng/src/hb-ft.cc b/third_party/harfbuzz-ng/src/hb-ft.cc
index 23c2cc0..90adc0d 100644
--- a/third_party/harfbuzz-ng/src/hb-ft.cc
+++ b/third_party/harfbuzz-ng/src/hb-ft.cc
@@ -61,6 +61,8 @@
* provide any API to get to the transform/delta set on the face. :(
*
* - Always use FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH?
+ *
+ * - FT_Load_Glyph() is exteremely costly. Do something about it?
*/
@@ -229,21 +231,55 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
return TRUE;
}
+static hb_bool_t
+hb_ft_get_glyph_name (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ char *name, unsigned int size,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+
+ hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size);
+ if (!ret)
+ snprintf (name, size, "gid%u", glyph);
+
+ return ret;
+}
+
+static hb_bool_t
+hb_ft_get_glyph_from_name (hb_font_t *font,
+ void *font_data,
+ const char *name, int len, /* -1 means nul-terminated */
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+
+ if (len < 0)
+ *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name);
+ else {
+ /* Make a nul-terminated version. */
+ char buf[128];
+ len = MIN (len, (int) sizeof (buf) - 1);
+ strncpy (buf, name, len);
+ buf[len] = '\0';
+ *glyph = FT_Get_Name_Index (ft_face, buf);
+ }
+
+ return *glyph != 0;
+}
+
+
static hb_font_funcs_t ft_ffuncs = {
HB_OBJECT_HEADER_STATIC,
TRUE, /* immutable */
{
- hb_ft_get_glyph,
- hb_ft_get_glyph_h_advance,
- hb_ft_get_glyph_v_advance,
- hb_ft_get_glyph_h_origin,
- hb_ft_get_glyph_v_origin,
- hb_ft_get_glyph_h_kerning,
- hb_ft_get_glyph_v_kerning,
- hb_ft_get_glyph_extents,
- hb_ft_get_glyph_contour_point,
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name,
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
}
};
diff --git a/third_party/harfbuzz-ng/src/hb-ft.h b/third_party/harfbuzz-ng/src/hb-ft.h
index c1772ac..696251e 100644
--- a/third_party/harfbuzz-ng/src/hb-ft.h
+++ b/third_party/harfbuzz-ng/src/hb-ft.h
@@ -29,8 +29,6 @@
#include "hb.h"
-#include "hb-font.h"
-
#include <ft2build.h>
#include FT_FREETYPE_H
diff --git a/third_party/harfbuzz-ng/src/hb-glib.cc b/third_party/harfbuzz-ng/src/hb-glib.cc
index f990988..26d40a3 100644
--- a/third_party/harfbuzz-ng/src/hb-glib.cc
+++ b/third_party/harfbuzz-ng/src/hb-glib.cc
@@ -144,7 +144,16 @@ glib_script_to_script[] =
/* Unicode-6.0 additions */
HB_SCRIPT_BATAK,
HB_SCRIPT_BRAHMI,
- HB_SCRIPT_MANDAIC
+ HB_SCRIPT_MANDAIC,
+
+ /* Unicode-6.1 additions */
+ HB_SCRIPT_CHAKMA,
+ HB_SCRIPT_MEROITIC_CURSIVE,
+ HB_SCRIPT_MEROITIC_HIEROGLYPHS,
+ HB_SCRIPT_MIAO,
+ HB_SCRIPT_SHARADA,
+ HB_SCRIPT_SORA_SOMPENG,
+ HB_SCRIPT_TAKRI
};
#endif
diff --git a/third_party/harfbuzz-ng/src/hb-glib.h b/third_party/harfbuzz-ng/src/hb-glib.h
index 3bc3ebf..63a9d33 100644
--- a/third_party/harfbuzz-ng/src/hb-glib.h
+++ b/third_party/harfbuzz-ng/src/hb-glib.h
@@ -30,6 +30,7 @@
#define HB_GLIB_H
#include "hb.h"
+
#include <glib.h>
HB_BEGIN_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-gobject-enums.cc b/third_party/harfbuzz-ng/src/hb-gobject-enums.cc
index 9d16c85..64adbc9 100644
--- a/third_party/harfbuzz-ng/src/hb-gobject-enums.cc
+++ b/third_party/harfbuzz-ng/src/hb-gobject-enums.cc
@@ -148,83 +148,83 @@ hb_script_t_hb_script_t_get_type (void)
{
static const GEnumValue values[] = {
{ HB_SCRIPT_COMMON, "HB_SCRIPT_COMMON", "common" },
- { HB_SCRIPT_INHERITED, "HB_SCRIPT_INHERITED", "inherited" },
{ HB_SCRIPT_ARABIC, "HB_SCRIPT_ARABIC", "arabic" },
{ HB_SCRIPT_ARMENIAN, "HB_SCRIPT_ARMENIAN", "armenian" },
{ HB_SCRIPT_BENGALI, "HB_SCRIPT_BENGALI", "bengali" },
{ HB_SCRIPT_BOPOMOFO, "HB_SCRIPT_BOPOMOFO", "bopomofo" },
+ { HB_SCRIPT_CANADIAN_ABORIGINAL, "HB_SCRIPT_CANADIAN_ABORIGINAL", "canadian-aboriginal" },
{ HB_SCRIPT_CHEROKEE, "HB_SCRIPT_CHEROKEE", "cherokee" },
{ HB_SCRIPT_COPTIC, "HB_SCRIPT_COPTIC", "coptic" },
{ HB_SCRIPT_CYRILLIC, "HB_SCRIPT_CYRILLIC", "cyrillic" },
- { HB_SCRIPT_DESERET, "HB_SCRIPT_DESERET", "deseret" },
{ HB_SCRIPT_DEVANAGARI, "HB_SCRIPT_DEVANAGARI", "devanagari" },
- { HB_SCRIPT_ETHIOPIC, "HB_SCRIPT_ETHIOPIC", "ethiopic" },
{ HB_SCRIPT_GEORGIAN, "HB_SCRIPT_GEORGIAN", "georgian" },
- { HB_SCRIPT_GOTHIC, "HB_SCRIPT_GOTHIC", "gothic" },
{ HB_SCRIPT_GREEK, "HB_SCRIPT_GREEK", "greek" },
{ HB_SCRIPT_GUJARATI, "HB_SCRIPT_GUJARATI", "gujarati" },
{ HB_SCRIPT_GURMUKHI, "HB_SCRIPT_GURMUKHI", "gurmukhi" },
- { HB_SCRIPT_HAN, "HB_SCRIPT_HAN", "han" },
{ HB_SCRIPT_HANGUL, "HB_SCRIPT_HANGUL", "hangul" },
+ { HB_SCRIPT_HAN, "HB_SCRIPT_HAN", "han" },
{ HB_SCRIPT_HEBREW, "HB_SCRIPT_HEBREW", "hebrew" },
{ HB_SCRIPT_HIRAGANA, "HB_SCRIPT_HIRAGANA", "hiragana" },
+ { HB_SCRIPT_INHERITED, "HB_SCRIPT_INHERITED", "inherited" },
{ HB_SCRIPT_KANNADA, "HB_SCRIPT_KANNADA", "kannada" },
{ HB_SCRIPT_KATAKANA, "HB_SCRIPT_KATAKANA", "katakana" },
- { HB_SCRIPT_KHMER, "HB_SCRIPT_KHMER", "khmer" },
{ HB_SCRIPT_LAO, "HB_SCRIPT_LAO", "lao" },
{ HB_SCRIPT_LATIN, "HB_SCRIPT_LATIN", "latin" },
{ HB_SCRIPT_MALAYALAM, "HB_SCRIPT_MALAYALAM", "malayalam" },
{ HB_SCRIPT_MONGOLIAN, "HB_SCRIPT_MONGOLIAN", "mongolian" },
- { HB_SCRIPT_MYANMAR, "HB_SCRIPT_MYANMAR", "myanmar" },
{ HB_SCRIPT_OGHAM, "HB_SCRIPT_OGHAM", "ogham" },
- { HB_SCRIPT_OLD_ITALIC, "HB_SCRIPT_OLD_ITALIC", "old-italic" },
{ HB_SCRIPT_ORIYA, "HB_SCRIPT_ORIYA", "oriya" },
{ HB_SCRIPT_RUNIC, "HB_SCRIPT_RUNIC", "runic" },
- { HB_SCRIPT_SINHALA, "HB_SCRIPT_SINHALA", "sinhala" },
{ HB_SCRIPT_SYRIAC, "HB_SCRIPT_SYRIAC", "syriac" },
{ HB_SCRIPT_TAMIL, "HB_SCRIPT_TAMIL", "tamil" },
{ HB_SCRIPT_TELUGU, "HB_SCRIPT_TELUGU", "telugu" },
- { HB_SCRIPT_THAANA, "HB_SCRIPT_THAANA", "thaana" },
{ HB_SCRIPT_THAI, "HB_SCRIPT_THAI", "thai" },
- { HB_SCRIPT_TIBETAN, "HB_SCRIPT_TIBETAN", "tibetan" },
- { HB_SCRIPT_CANADIAN_ABORIGINAL, "HB_SCRIPT_CANADIAN_ABORIGINAL", "canadian-aboriginal" },
{ HB_SCRIPT_YI, "HB_SCRIPT_YI", "yi" },
- { HB_SCRIPT_TAGALOG, "HB_SCRIPT_TAGALOG", "tagalog" },
- { HB_SCRIPT_HANUNOO, "HB_SCRIPT_HANUNOO", "hanunoo" },
+ { HB_SCRIPT_TIBETAN, "HB_SCRIPT_TIBETAN", "tibetan" },
+ { HB_SCRIPT_ETHIOPIC, "HB_SCRIPT_ETHIOPIC", "ethiopic" },
+ { HB_SCRIPT_KHMER, "HB_SCRIPT_KHMER", "khmer" },
+ { HB_SCRIPT_MYANMAR, "HB_SCRIPT_MYANMAR", "myanmar" },
+ { HB_SCRIPT_SINHALA, "HB_SCRIPT_SINHALA", "sinhala" },
+ { HB_SCRIPT_THAANA, "HB_SCRIPT_THAANA", "thaana" },
+ { HB_SCRIPT_DESERET, "HB_SCRIPT_DESERET", "deseret" },
+ { HB_SCRIPT_GOTHIC, "HB_SCRIPT_GOTHIC", "gothic" },
+ { HB_SCRIPT_OLD_ITALIC, "HB_SCRIPT_OLD_ITALIC", "old-italic" },
{ HB_SCRIPT_BUHID, "HB_SCRIPT_BUHID", "buhid" },
+ { HB_SCRIPT_HANUNOO, "HB_SCRIPT_HANUNOO", "hanunoo" },
+ { HB_SCRIPT_TAGALOG, "HB_SCRIPT_TAGALOG", "tagalog" },
{ HB_SCRIPT_TAGBANWA, "HB_SCRIPT_TAGBANWA", "tagbanwa" },
{ HB_SCRIPT_BRAILLE, "HB_SCRIPT_BRAILLE", "braille" },
{ HB_SCRIPT_CYPRIOT, "HB_SCRIPT_CYPRIOT", "cypriot" },
{ HB_SCRIPT_LIMBU, "HB_SCRIPT_LIMBU", "limbu" },
+ { HB_SCRIPT_LINEAR_B, "HB_SCRIPT_LINEAR_B", "linear-b" },
{ HB_SCRIPT_OSMANYA, "HB_SCRIPT_OSMANYA", "osmanya" },
{ HB_SCRIPT_SHAVIAN, "HB_SCRIPT_SHAVIAN", "shavian" },
- { HB_SCRIPT_LINEAR_B, "HB_SCRIPT_LINEAR_B", "linear-b" },
{ HB_SCRIPT_TAI_LE, "HB_SCRIPT_TAI_LE", "tai-le" },
{ HB_SCRIPT_UGARITIC, "HB_SCRIPT_UGARITIC", "ugaritic" },
- { HB_SCRIPT_NEW_TAI_LUE, "HB_SCRIPT_NEW_TAI_LUE", "new-tai-lue" },
{ HB_SCRIPT_BUGINESE, "HB_SCRIPT_BUGINESE", "buginese" },
{ HB_SCRIPT_GLAGOLITIC, "HB_SCRIPT_GLAGOLITIC", "glagolitic" },
- { HB_SCRIPT_TIFINAGH, "HB_SCRIPT_TIFINAGH", "tifinagh" },
- { HB_SCRIPT_SYLOTI_NAGRI, "HB_SCRIPT_SYLOTI_NAGRI", "syloti-nagri" },
- { HB_SCRIPT_OLD_PERSIAN, "HB_SCRIPT_OLD_PERSIAN", "old-persian" },
{ HB_SCRIPT_KHAROSHTHI, "HB_SCRIPT_KHAROSHTHI", "kharoshthi" },
- { HB_SCRIPT_UNKNOWN, "HB_SCRIPT_UNKNOWN", "unknown" },
+ { HB_SCRIPT_NEW_TAI_LUE, "HB_SCRIPT_NEW_TAI_LUE", "new-tai-lue" },
+ { HB_SCRIPT_OLD_PERSIAN, "HB_SCRIPT_OLD_PERSIAN", "old-persian" },
+ { HB_SCRIPT_SYLOTI_NAGRI, "HB_SCRIPT_SYLOTI_NAGRI", "syloti-nagri" },
+ { HB_SCRIPT_TIFINAGH, "HB_SCRIPT_TIFINAGH", "tifinagh" },
{ HB_SCRIPT_BALINESE, "HB_SCRIPT_BALINESE", "balinese" },
{ HB_SCRIPT_CUNEIFORM, "HB_SCRIPT_CUNEIFORM", "cuneiform" },
- { HB_SCRIPT_PHOENICIAN, "HB_SCRIPT_PHOENICIAN", "phoenician" },
- { HB_SCRIPT_PHAGS_PA, "HB_SCRIPT_PHAGS_PA", "phags-pa" },
{ HB_SCRIPT_NKO, "HB_SCRIPT_NKO", "nko" },
+ { HB_SCRIPT_PHAGS_PA, "HB_SCRIPT_PHAGS_PA", "phags-pa" },
+ { HB_SCRIPT_PHOENICIAN, "HB_SCRIPT_PHOENICIAN", "phoenician" },
+ { HB_SCRIPT_UNKNOWN, "HB_SCRIPT_UNKNOWN", "unknown" },
+ { HB_SCRIPT_CARIAN, "HB_SCRIPT_CARIAN", "carian" },
+ { HB_SCRIPT_CHAM, "HB_SCRIPT_CHAM", "cham" },
{ HB_SCRIPT_KAYAH_LI, "HB_SCRIPT_KAYAH_LI", "kayah-li" },
{ HB_SCRIPT_LEPCHA, "HB_SCRIPT_LEPCHA", "lepcha" },
+ { HB_SCRIPT_LYCIAN, "HB_SCRIPT_LYCIAN", "lycian" },
+ { HB_SCRIPT_LYDIAN, "HB_SCRIPT_LYDIAN", "lydian" },
+ { HB_SCRIPT_OL_CHIKI, "HB_SCRIPT_OL_CHIKI", "ol-chiki" },
{ HB_SCRIPT_REJANG, "HB_SCRIPT_REJANG", "rejang" },
- { HB_SCRIPT_SUNDANESE, "HB_SCRIPT_SUNDANESE", "sundanese" },
{ HB_SCRIPT_SAURASHTRA, "HB_SCRIPT_SAURASHTRA", "saurashtra" },
- { HB_SCRIPT_CHAM, "HB_SCRIPT_CHAM", "cham" },
- { HB_SCRIPT_OL_CHIKI, "HB_SCRIPT_OL_CHIKI", "ol-chiki" },
+ { HB_SCRIPT_SUNDANESE, "HB_SCRIPT_SUNDANESE", "sundanese" },
{ HB_SCRIPT_VAI, "HB_SCRIPT_VAI", "vai" },
- { HB_SCRIPT_CARIAN, "HB_SCRIPT_CARIAN", "carian" },
- { HB_SCRIPT_LYCIAN, "HB_SCRIPT_LYCIAN", "lycian" },
- { HB_SCRIPT_LYDIAN, "HB_SCRIPT_LYDIAN", "lydian" },
{ HB_SCRIPT_AVESTAN, "HB_SCRIPT_AVESTAN", "avestan" },
{ HB_SCRIPT_BAMUM, "HB_SCRIPT_BAMUM", "bamum" },
{ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, "HB_SCRIPT_EGYPTIAN_HIEROGLYPHS", "egyptian-hieroglyphs" },
@@ -243,6 +243,13 @@ hb_script_t_hb_script_t_get_type (void)
{ HB_SCRIPT_BATAK, "HB_SCRIPT_BATAK", "batak" },
{ HB_SCRIPT_BRAHMI, "HB_SCRIPT_BRAHMI", "brahmi" },
{ HB_SCRIPT_MANDAIC, "HB_SCRIPT_MANDAIC", "mandaic" },
+ { HB_SCRIPT_CHAKMA, "HB_SCRIPT_CHAKMA", "chakma" },
+ { HB_SCRIPT_MEROITIC_CURSIVE, "HB_SCRIPT_MEROITIC_CURSIVE", "meroitic-cursive" },
+ { HB_SCRIPT_MEROITIC_HIEROGLYPHS, "HB_SCRIPT_MEROITIC_HIEROGLYPHS", "meroitic-hieroglyphs" },
+ { HB_SCRIPT_MIAO, "HB_SCRIPT_MIAO", "miao" },
+ { HB_SCRIPT_SHARADA, "HB_SCRIPT_SHARADA", "sharada" },
+ { HB_SCRIPT_SORA_SOMPENG, "HB_SCRIPT_SORA_SOMPENG", "sora-sompeng" },
+ { HB_SCRIPT_TAKRI, "HB_SCRIPT_TAKRI", "takri" },
{ HB_SCRIPT_INVALID, "HB_SCRIPT_INVALID", "invalid" },
{ 0, NULL, NULL }
};
diff --git a/third_party/harfbuzz-ng/src/hb-gobject.h b/third_party/harfbuzz-ng/src/hb-gobject.h
index 25fc941..4f23fdd 100644
--- a/third_party/harfbuzz-ng/src/hb-gobject.h
+++ b/third_party/harfbuzz-ng/src/hb-gobject.h
@@ -28,6 +28,7 @@
#define HB_GOBJECT_H
#include "hb.h"
+
#include <glib-object.h>
HB_BEGIN_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.h b/third_party/harfbuzz-ng/src/hb-graphite2-private.hh
index 1897e84..644ea75 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape.h
+++ b/third_party/harfbuzz-ng/src/hb-graphite2-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2010 Red Hat, Inc.
+ * Copyright © 2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -21,27 +21,22 @@
* 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_SHAPE_H
-#define HB_OT_SHAPE_H
+#ifndef HB_GRAPHITE2_PRIVATE_HH
+#define HB_GRAPHITE2_PRIVATE_HH
-#include "hb-common.h"
-#include "hb-shape.h"
+#include "hb-private.hh"
+#include "hb-graphite2.h"
-HB_BEGIN_DECLS
+HB_INTERNAL hb_bool_t
+_hb_graphite2_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features);
-hb_bool_t
-hb_ot_shape (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options);
-
-HB_END_DECLS
-
-#endif /* HB_OT_SHAPE_H */
+#endif /* HB_GRAPHITE2_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-graphite2.cc b/third_party/harfbuzz-ng/src/hb-graphite2.cc
index 0675759..eab2eae 100644
--- a/third_party/harfbuzz-ng/src/hb-graphite2.cc
+++ b/third_party/harfbuzz-ng/src/hb-graphite2.cc
@@ -130,6 +130,7 @@ static void _hb_gr_font_data_destroy (void *data)
hb_gr_font_data_t *f = (hb_gr_font_data_t *) data;
gr_font_destroy (f->grfont);
+ free (f);
}
static hb_user_data_key_t hb_gr_data_key;
@@ -212,15 +213,17 @@ _hb_gr_font_get_data (hb_font_t *font)
hb_bool_t
-hb_graphite_shape (hb_font_t *font,
+_hb_graphite_shape (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options)
+ unsigned int num_features)
{
buffer->guess_properties ();
+ /* XXX We do a hell of a lot of stuff just to figure out this font
+ * is not graphite! Shouldn't do. */
+
hb_gr_font_data_t *data = _hb_gr_font_get_data (font);
if (!data->grface) return FALSE;
@@ -244,11 +247,10 @@ hb_graphite_shape (hb_font_t *font,
features++;
}
- unsigned short *gids = NULL;
+ hb_codepoint_t *gids = NULL, *pg;
hb_gr_cluster_t *clusters = NULL;
gr_segment *seg = NULL;
uint32_t *text = NULL;
- unsigned short *pg;
const gr_slot *is;
unsigned int ci = 0, ic = 0;
float curradvx = 0., curradvy = 0.;
@@ -277,7 +279,7 @@ hb_graphite_shape (hb_font_t *font,
clusters = (hb_gr_cluster_t *) calloc (charlen, sizeof (hb_gr_cluster_t));
if (!glyphlen || !clusters) goto dieout;
- gids = (uint16_t *) malloc (glyphlen * sizeof (uint16_t));
+ gids = (hb_codepoint_t *) malloc (glyphlen * sizeof (hb_codepoint_t));
if (!gids) goto dieout;
pg = gids;
diff --git a/third_party/harfbuzz-ng/src/hb-graphite2.h b/third_party/harfbuzz-ng/src/hb-graphite2.h
index 68bd019..2d16cc8 100644
--- a/third_party/harfbuzz-ng/src/hb-graphite2.h
+++ b/third_party/harfbuzz-ng/src/hb-graphite2.h
@@ -26,20 +26,14 @@
#ifndef HB_GRAPHITE2_H
#define HB_GRAPHITE2_H
-#include "hb-common.h"
-#include "hb-shape.h"
+#include "hb.h"
HB_BEGIN_DECLS
#define HB_GRAPHITE_TAG_Silf HB_TAG('S','i','l','f')
-hb_bool_t
-hb_graphite_shape (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options);
+/* TODO add gr_font/face etc getters and other glue API */
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-icu.h b/third_party/harfbuzz-ng/src/hb-icu.h
index ecabec2..d22a8e1 100644
--- a/third_party/harfbuzz-ng/src/hb-icu.h
+++ b/third_party/harfbuzz-ng/src/hb-icu.h
@@ -30,6 +30,7 @@
#define HB_ICU_H
#include "hb.h"
+
#include <unicode/uscript.h>
diff --git a/third_party/harfbuzz-ng/src/hb-mutex-private.hh b/third_party/harfbuzz-ng/src/hb-mutex-private.hh
index 9855a565..44b48df 100644
--- a/third_party/harfbuzz-ng/src/hb-mutex-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-mutex-private.hh
@@ -35,27 +35,16 @@
#include "hb-private.hh"
-
/* mutex */
/* We need external help for these */
-#ifdef HAVE_GLIB
+#if 0
-#include <glib.h>
-typedef GStaticMutex hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT G_STATIC_MUTEX_INIT
-#define hb_mutex_impl_init(M) g_static_mutex_init (M)
-#define hb_mutex_impl_lock(M) g_static_mutex_lock (M)
-#define hb_mutex_impl_unlock(M) g_static_mutex_unlock (M)
-#define hb_mutex_impl_free(M) g_static_mutex_free (M)
-
-
-#elif defined(_MSC_VER) || defined(__MINGW32__)
+#elif !defined(HB_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
#include <windows.h>
-
typedef CRITICAL_SECTION hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT { NULL, 0, 0, NULL, NULL, 0 }
#define hb_mutex_impl_init(M) InitializeCriticalSection (M)
@@ -64,10 +53,31 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
#define hb_mutex_impl_free(M) DeleteCriticalSection (M)
-#else
+#elif !defined(HB_NO_MT) && defined(__APPLE__)
+
+#include <pthread.h>
+typedef pthread_mutex_t hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER
+#define hb_mutex_impl_init(M) pthread_mutex_init (M, NULL)
+#define hb_mutex_impl_lock(M) pthread_mutex_lock (M)
+#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M)
+#define hb_mutex_impl_free(M) pthread_mutex_destroy (M)
-#warning "Could not find any system to define platform macros, library will NOT be thread-safe"
+#elif !defined(HB_NO_MT) && defined(HAVE_GLIB)
+
+#include <glib.h>
+typedef GStaticMutex hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT G_STATIC_MUTEX_INIT
+#define hb_mutex_impl_init(M) g_static_mutex_init (M)
+#define hb_mutex_impl_lock(M) g_static_mutex_lock (M)
+#define hb_mutex_impl_unlock(M) g_static_mutex_unlock (M)
+#define hb_mutex_impl_free(M) g_static_mutex_free (M)
+
+
+#else
+
+#define HB_MUTEX_IMPL_NIL 1
typedef volatile int hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT 0
#define hb_mutex_impl_init(M) ((void) (*(M) = 0))
@@ -75,7 +85,6 @@ typedef volatile int hb_mutex_impl_t;
#define hb_mutex_impl_unlock(M) ((void) (*(M) = 0))
#define hb_mutex_impl_free(M) ((void) (*(M) = 2))
-
#endif
diff --git a/third_party/harfbuzz-ng/src/hb-object-private.hh b/third_party/harfbuzz-ng/src/hb-object-private.hh
index 2e4a385..e3c9d21 100644
--- a/third_party/harfbuzz-ng/src/hb-object-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-object-private.hh
@@ -34,10 +34,10 @@
#include "hb-private.hh"
+#include "hb-atomic-private.hh"
#include "hb-mutex-private.hh"
-
/* Debug */
#ifndef HB_DEBUG_OBJECT
@@ -45,76 +45,28 @@
#endif
-/* atomic_int */
-
-/* We need external help for these */
-
-#ifdef HAVE_GLIB
-
-#include <glib.h>
-
-typedef volatile int hb_atomic_int_t;
-#if GLIB_CHECK_VERSION(2,29,5)
-#define hb_atomic_int_add(AI, V) g_atomic_int_add (&(AI), V)
-#else
-#define hb_atomic_int_add(AI, V) g_atomic_int_exchange_and_add (&(AI), V)
-#endif
-#define hb_atomic_int_get(AI) g_atomic_int_get (&(AI))
-#define hb_atomic_int_set(AI, V) g_atomic_int_set (&(AI), V)
-
-
-#elif defined(_MSC_VER) && _MSC_VER >= 1600
-
-#include <intrin.h>
-
-typedef long hb_atomic_int_t;
-#define hb_atomic_int_add(AI, V) _InterlockedExchangeAdd (&(AI), V)
-#define hb_atomic_int_get(AI) (_ReadBarrier (), (AI))
-#define hb_atomic_int_set(AI, V) ((void) _InterlockedExchange (&(AI), (V)))
-
-
-#else
-
-#ifdef _MSC_VER
-#pragma message("Could not find any system to define atomic_int macros, library will NOT be thread-safe")
-#else
-#warning "Could not find any system to define atomic_int macros, library will NOT be thread-safe"
-#endif
-
-typedef volatile int hb_atomic_int_t;
-#define hb_atomic_int_add(AI, V) ((AI) += (V), (AI) - (V))
-#define hb_atomic_int_get(AI) (AI)
-#define hb_atomic_int_set(AI, V) ((void) ((AI) = (V)))
-
-
-#endif
-
-
-
-
/* reference_count */
-typedef struct {
+struct hb_reference_count_t
+{
hb_atomic_int_t ref_count;
#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1)
#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE}
- inline void init (int v) { ref_count = v; /* non-atomic is fine */ }
- inline int inc (void) { return hb_atomic_int_add (ref_count, 1); }
- inline int dec (void) { return hb_atomic_int_add (ref_count, -1); }
- inline void set (int v) { hb_atomic_int_set (ref_count, v); }
+ inline void init (int v) { const_cast<hb_atomic_int_t &> (ref_count) = v; }
+ inline int inc (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), 1); }
+ inline int dec (void) { return hb_atomic_int_add (const_cast<hb_atomic_int_t &> (ref_count), -1); }
- inline int get (void) const { return hb_atomic_int_get (ref_count); }
- inline bool is_invalid (void) const { return get () == HB_REFERENCE_COUNT_INVALID_VALUE; }
+ inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_INVALID_VALUE; }
-} hb_reference_count_t;
+};
/* user_data */
-struct hb_user_data_array_t {
-
+struct hb_user_data_array_t
+{
struct hb_user_data_item_t {
hb_user_data_key_t *key;
void *data;
@@ -141,9 +93,8 @@ struct hb_user_data_array_t {
/* object_header */
-typedef struct _hb_object_header_t hb_object_header_t;
-
-struct _hb_object_header_t {
+struct hb_object_header_t
+{
hb_reference_count_t ref_count;
hb_user_data_array_t user_data;
@@ -200,17 +151,18 @@ struct _hb_object_header_t {
}
inline void trace (const char *function) const {
+ if (unlikely (!this)) return;
+ /* XXX We cannot use DEBUG_MSG_FUNC here since that one currecntly only
+ * prints the class name and throws away the template info. */
DEBUG_MSG (OBJECT, (void *) this,
- "refcount=%d %s",
- this ? ref_count.get () : 0,
- function);
+ "%s refcount=%d",
+ function,
+ this ? ref_count.ref_count : 0);
}
};
-
-
/* object */
template <typename Type>
@@ -261,7 +213,4 @@ static inline void *hb_object_get_user_data (Type *obj,
}
-
-
-
#endif /* HB_OBJECT_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-open-file-private.hh b/third_party/harfbuzz-ng/src/hb-open-file-private.hh
index 62e1f17..ce18580 100644
--- a/third_party/harfbuzz-ng/src/hb-open-file-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-open-file-private.hh
@@ -1,5 +1,6 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2012 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
*/
#ifndef HB_OPEN_FILE_PRIVATE_HH
@@ -51,7 +53,7 @@ typedef struct TableRecord
{
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
}
Tag tag; /* 4-byte identifier. */
@@ -100,8 +102,7 @@ typedef struct OffsetTable
public:
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && c->check_array (tables, TableRecord::static_size, numTables);
+ return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
}
private:
@@ -129,7 +130,7 @@ struct TTCHeaderVersion1
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return table.sanitize (c, this);
+ return TRACE_RETURN (table.sanitize (c, this));
}
private:
@@ -168,11 +169,11 @@ struct TTCHeader
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (unlikely (!u.header.version.sanitize (c))) return false;
+ if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false);
switch (u.header.version.major) {
case 2: /* version 2 is compatible with version 1 */
- case 1: return u.version1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.version1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -230,14 +231,14 @@ struct OpenTypeFontFile
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (unlikely (!u.tag.sanitize (c))) return false;
+ if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false);
switch (u.tag) {
case CFFTag: /* All the non-collection tags */
case TrueTag:
case Typ1Tag:
- case TrueTypeTag: return u.fontFace.sanitize (c);
- case TTCTag: return u.ttcHeader.sanitize (c);
- default: return true;
+ case TrueTypeTag: return TRACE_RETURN (u.fontFace.sanitize (c));
+ case TTCTag: return TRACE_RETURN (u.ttcHeader.sanitize (c));
+ default: return TRACE_RETURN (true);
}
}
diff --git a/third_party/harfbuzz-ng/src/hb-open-type-private.hh b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
index 8143b28..f4a2ba9 100644
--- a/third_party/harfbuzz-ng/src/hb-open-type-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
@@ -1,5 +1,6 @@
/*
* Copyright © 2007,2008,2009,2010 Red Hat, Inc.
+ * Copyright © 2012 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
*/
#ifndef HB_OPEN_TYPE_PRIVATE_HH
@@ -153,7 +155,7 @@ ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
#define TRACE_SANITIZE() \
- hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", this, NULL, HB_FUNC);
+ hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", this, HB_FUNC, "");
struct hb_sanitize_context_t
@@ -164,24 +166,24 @@ struct hb_sanitize_context_t
this->writable = false;
}
- inline void setup (void)
+ inline void start_processing (void)
{
this->start = hb_blob_get_data (this->blob, NULL);
this->end = this->start + hb_blob_get_length (this->blob);
this->edit_count = 0;
this->debug_depth = 0;
- DEBUG_MSG (SANITIZE, this->blob,
- "init [%p..%p] (%lu bytes)",
- this->start, this->end,
- (unsigned long) (this->end - this->start));
+ DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1,
+ "start [%p..%p] (%lu bytes)",
+ this->start, this->end,
+ (unsigned long) (this->end - this->start));
}
- inline void finish (void)
+ inline void end_processing (void)
{
- DEBUG_MSG (SANITIZE, this->blob,
- "fini [%p..%p] %u edit requests",
- this->start, this->end, this->edit_count);
+ DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1,
+ "end [%p..%p] %u edit requests",
+ this->start, this->end, this->edit_count);
hb_blob_destroy (this->blob);
this->blob = NULL;
@@ -191,18 +193,13 @@ struct hb_sanitize_context_t
inline bool check_range (const void *base, unsigned int len) const
{
const char *p = (const char *) base;
- bool ret = this->start <= p &&
- p <= this->end &&
- (unsigned int) (this->end - p) >= len;
-
- DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
- "%-*d-> range [%p..%p] (%d bytes) in [%p..%p] -> %s",
- this->debug_depth, this->debug_depth,
- p, p + len, len,
- this->start, this->end,
- ret ? "pass" : "FAIL");
- return likely (ret);
+ hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
+ "check_range [%p..%p] (%d bytes) in [%p..%p]",
+ p, p + len, len,
+ this->start, this->end);
+
+ return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len));
}
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
@@ -210,14 +207,12 @@ struct hb_sanitize_context_t
const char *p = (const char *) base;
bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
- DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
- "%-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s",
- this->debug_depth, this->debug_depth,
- p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
- this->start, this->end,
- !overflows ? "does not overflow" : "OVERFLOWS FAIL");
+ hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
+ "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]",
+ p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
+ this->start, this->end);
- return likely (!overflows && this->check_range (base, record_size * len));
+ return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len)));
}
template <typename Type>
@@ -226,23 +221,21 @@ struct hb_sanitize_context_t
return likely (this->check_range (obj, obj->min_size));
}
- inline bool can_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
+ inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
{
const char *p = (const char *) base;
this->edit_count++;
- DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
- "%-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
- this->debug_depth, this->debug_depth,
- this->edit_count,
- p, p + len, len,
- this->start, this->end,
- this->writable ? "granted" : "REJECTED");
+ hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
+ "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
+ this->edit_count,
+ p, p + len, len,
+ this->start, this->end);
- return this->writable;
+ return TRACE_RETURN (this->writable);
}
- unsigned int debug_depth;
+ mutable unsigned int debug_depth;
const char *start, *end;
bool writable;
unsigned int edit_count;
@@ -266,10 +259,10 @@ struct Sanitizer
retry:
DEBUG_MSG_FUNC (SANITIZE, blob, "start");
- c->setup ();
+ c->start_processing ();
if (unlikely (!c->start)) {
- c->finish ();
+ c->end_processing ();
return blob;
}
@@ -303,7 +296,7 @@ struct Sanitizer
}
}
- c->finish ();
+ c->end_processing ();
DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
if (sane)
@@ -374,7 +367,7 @@ struct IntType
inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return likely (c->check_struct (this));
+ return TRACE_RETURN (likely (c->check_struct (this)));
}
protected:
BEInt<Type, sizeof (Type)> v;
@@ -404,7 +397,7 @@ struct LONGDATETIME
{
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return likely (c->check_struct (this));
+ return TRACE_RETURN (likely (c->check_struct (this)));
}
private:
LONG major;
@@ -468,7 +461,7 @@ struct FixedVersion
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
}
USHORT major;
@@ -496,26 +489,26 @@ struct GenericOffsetTo : OffsetType
inline bool sanitize (hb_sanitize_context_t *c, void *base) {
TRACE_SANITIZE ();
- if (unlikely (!c->check_struct (this))) return false;
+ if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
unsigned int offset = *this;
- if (unlikely (!offset)) return true;
+ if (unlikely (!offset)) return TRACE_RETURN (true);
Type &obj = StructAtOffset<Type> (base, offset);
- return likely (obj.sanitize (c)) || neuter (c);
+ return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
}
template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
TRACE_SANITIZE ();
- if (unlikely (!c->check_struct (this))) return false;
+ if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
unsigned int offset = *this;
- if (unlikely (!offset)) return true;
+ if (unlikely (!offset)) return TRACE_RETURN (true);
Type &obj = StructAtOffset<Type> (base, offset);
- return likely (obj.sanitize (c, user_data)) || neuter (c);
+ return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
}
private:
/* Set the offset to Null */
inline bool neuter (hb_sanitize_context_t *c) {
- if (c->can_edit (this, this->static_size)) {
+ if (c->may_edit (this, this->static_size)) {
this->set (0); /* 0 is Null offset */
return true;
}
@@ -561,7 +554,7 @@ struct GenericArrayOf
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (unlikely (!sanitize_shallow (c))) return false;
+ if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
/* Note: for structs that do not reference other structs,
* we do not need to call their sanitize() as we already did
@@ -572,33 +565,32 @@ struct GenericArrayOf
*/
(void) (false && array[0].sanitize (c));
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c, void *base) {
TRACE_SANITIZE ();
- if (unlikely (!sanitize_shallow (c))) return false;
+ if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!array[i].sanitize (c, base)))
- return false;
- return true;
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
}
template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
TRACE_SANITIZE ();
- if (unlikely (!sanitize_shallow (c))) return false;
+ if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!array[i].sanitize (c, base, user_data)))
- return false;
- return true;
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
}
private:
inline bool sanitize_shallow (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && c->check_array (this, Type::static_size, len);
+ return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
}
public:
@@ -640,12 +632,12 @@ struct OffsetListOf : OffsetArrayOf<Type>
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return OffsetArrayOf<Type>::sanitize (c, this);
+ return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
}
template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
TRACE_SANITIZE ();
- return OffsetArrayOf<Type>::sanitize (c, this, user_data);
+ return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
}
};
@@ -670,7 +662,7 @@ struct HeadlessArrayOf
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (unlikely (!sanitize_shallow (c))) return false;
+ if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
/* Note: for structs that do not reference other structs,
* we do not need to call their sanitize() as we already did
@@ -681,7 +673,7 @@ struct HeadlessArrayOf
*/
(void) (false && array[0].sanitize (c));
- return true;
+ return TRACE_RETURN (true);
}
USHORT len;
diff --git a/third_party/harfbuzz-ng/src/hb-ot-head-table.hh b/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
index a4d8d5f..32d64ca 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
@@ -1,5 +1,6 @@
/*
* Copyright © 2010 Red Hat, Inc.
+ * Copyright © 2012 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
*/
#ifndef HB_OT_HEAD_TABLE_HH
@@ -49,7 +51,7 @@ struct head
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this) && likely (version.major == 1);
+ return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
}
private:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
index 34bf494..2eea05a 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -44,7 +44,7 @@ struct hhea
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this) && likely (version.major == 1);
+ return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
}
private:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
index b58799c..35cfb48 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -54,7 +54,7 @@ struct hmtx
TRACE_SANITIZE ();
/* We don't check for anything specific here. The users of the
* struct do all the hard work... */
- return true;
+ return TRACE_RETURN (true);
}
private:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
index 5d19e08..2943a7f 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
@@ -1,6 +1,6 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
- * Copyright © 2010 Google, Inc.
+ * Copyright © 2010,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -30,11 +30,10 @@
#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
#include "hb-ot-layout-private.hh"
-
#include "hb-open-type-private.hh"
+#include "hb-set-private.hh"
-#define NO_CONTEXT ((unsigned int) 0x110000)
#define NOT_COVERED ((unsigned int) 0x110000)
#define MAX_NESTING_LEVEL 8
@@ -60,8 +59,7 @@ struct Record
inline bool sanitize (hb_sanitize_context_t *c, void *base) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && offset.sanitize (c, base);
+ return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base));
}
Tag tag; /* 4-byte Tag identifier */
@@ -115,7 +113,7 @@ struct RecordListOf : RecordArrayOf<Type>
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return RecordArrayOf<Type>::sanitize (c, this);
+ return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
}
};
@@ -129,7 +127,11 @@ struct RangeRecord
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
+ }
+
+ inline bool intersects (const hb_set_t *glyphs) const {
+ return glyphs->intersects (start, end);
}
GlyphID start; /* First GlyphID in the range */
@@ -184,8 +186,7 @@ struct LangSys
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && featureIndex.sanitize (c);
+ return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
}
Offset lookupOrder; /* = Null (reserved for an offset to a
@@ -223,8 +224,7 @@ struct Script
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return defaultLangSys.sanitize (c, this)
- && langSys.sanitize (c, this);
+ return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
}
private:
@@ -254,8 +254,7 @@ struct Feature
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && lookupIndex.sanitize (c);
+ return TRACE_RETURN (c->check_struct (this) && lookupIndex.sanitize (c));
}
Offset featureParams; /* Offset to Feature Parameters table (if one
@@ -272,7 +271,7 @@ typedef RecordListOf<Feature> FeatureList;
struct LookupFlag : USHORT
{
- enum {
+ enum Flags {
RightToLeft = 0x0001u,
IgnoreBaseGlyphs = 0x0002u,
IgnoreLigatures = 0x0004u,
@@ -309,14 +308,13 @@ struct Lookup
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
/* Real sanitize of the subtables is done by GSUB/GPOS/... */
- if (!(c->check_struct (this)
- && subTable.sanitize (c))) return false;
+ if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
if (unlikely (lookupFlag & LookupFlag::UseMarkFilteringSet))
{
USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
- if (!markFilteringSet.sanitize (c)) return false;
+ if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
}
- return true;
+ return TRACE_RETURN (true);
}
USHORT lookupType; /* Different enumerations for GSUB and GPOS */
@@ -352,9 +350,25 @@ struct CoverageFormat1
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return glyphArray.sanitize (c);
+ return TRACE_RETURN (glyphArray.sanitize (c));
}
+ inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
+ return glyphs->has (glyphArray[index]);
+ }
+
+ struct Iter {
+ inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
+ inline bool more (void) { return i < c->glyphArray.len; }
+ inline void next (void) { i++; }
+ inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
+ inline uint16_t get_coverage (void) { return i; }
+
+ private:
+ const struct CoverageFormat1 *c;
+ unsigned int i;
+ };
+
private:
USHORT coverageFormat; /* Format identifier--format = 1 */
SortedArrayOf<GlyphID>
@@ -380,9 +394,50 @@ struct CoverageFormat2
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return rangeRecord.sanitize (c);
+ return TRACE_RETURN (rangeRecord.sanitize (c));
+ }
+
+ inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
+ unsigned int i;
+ unsigned int count = rangeRecord.len;
+ for (i = 0; i < count; i++) {
+ const RangeRecord &range = rangeRecord[i];
+ if (range.value <= index &&
+ index < (unsigned int) range.value + (range.end - range.start) &&
+ range.intersects (glyphs))
+ return true;
+ else if (index < range.value)
+ return false;
+ }
+ return false;
}
+ struct Iter {
+ inline void init (const CoverageFormat2 &c_) {
+ c = &c_;
+ coverage = 0;
+ i = 0;
+ j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
+ }
+ inline bool more (void) { return i < c->rangeRecord.len; }
+ inline void next (void) {
+ coverage++;
+ if (j == c->rangeRecord[i].end) {
+ i++;
+ if (more ())
+ j = c->rangeRecord[i].start;
+ return;
+ }
+ j++;
+ }
+ inline uint16_t get_glyph (void) { return j; }
+ inline uint16_t get_coverage (void) { return coverage; }
+
+ private:
+ const struct CoverageFormat2 *c;
+ unsigned int i, j, coverage;
+ };
+
private:
USHORT coverageFormat; /* Format identifier--format = 2 */
SortedArrayOf<RangeRecord>
@@ -408,14 +463,79 @@ struct Coverage
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+ switch (u.format) {
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ default:return TRACE_RETURN (true);
+ }
+ }
+
+ inline bool intersects (const hb_set_t *glyphs) const {
+ /* TODO speed this up */
+ Coverage::Iter iter;
+ for (iter.init (*this); iter.more (); iter.next ()) {
+ if (glyphs->has (iter.get_glyph ()))
+ return true;
+ }
+ return false;
+ }
+
+ inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- default:return true;
+ case 1: return u.format1.intersects_coverage (glyphs, index);
+ case 2: return u.format2.intersects_coverage (glyphs, index);
+ default:return false;
}
}
+ struct Iter {
+ Iter (void) : format (0) {};
+ inline void init (const Coverage &c_) {
+ format = c_.u.format;
+ switch (format) {
+ case 1: return u.format1.init (c_.u.format1);
+ case 2: return u.format2.init (c_.u.format2);
+ default:return;
+ }
+ }
+ inline bool more (void) {
+ switch (format) {
+ case 1: return u.format1.more ();
+ case 2: return u.format2.more ();
+ default:return true;
+ }
+ }
+ inline void next (void) {
+ switch (format) {
+ case 1: u.format1.next (); break;
+ case 2: u.format2.next (); break;
+ default: break;
+ }
+ }
+ inline uint16_t get_glyph (void) {
+ switch (format) {
+ case 1: return u.format1.get_glyph ();
+ case 2: return u.format2.get_glyph ();
+ default:return true;
+ }
+ }
+ inline uint16_t get_coverage (void) {
+ switch (format) {
+ case 1: return u.format1.get_coverage ();
+ case 2: return u.format2.get_coverage ();
+ default:return true;
+ }
+ }
+
+ private:
+ unsigned int format;
+ union {
+ CoverageFormat1::Iter format1;
+ CoverageFormat2::Iter format2;
+ } u;
+ };
+
private:
union {
USHORT format; /* Format identifier */
@@ -445,8 +565,15 @@ struct ClassDefFormat1
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && classValue.sanitize (c);
+ return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
+ }
+
+ inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
+ unsigned int count = classValue.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (classValue[i] == klass && glyphs->has (startGlyph + i))
+ return true;
+ return false;
}
USHORT classFormat; /* Format identifier--format = 1 */
@@ -472,7 +599,15 @@ struct ClassDefFormat2
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return rangeRecord.sanitize (c);
+ return TRACE_RETURN (rangeRecord.sanitize (c));
+ }
+
+ inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
+ unsigned int count = rangeRecord.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
+ return true;
+ return false;
}
USHORT classFormat; /* Format identifier--format = 2 */
@@ -498,11 +633,19 @@ struct ClassDef
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
+ switch (u.format) {
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ default:return TRACE_RETURN (true);
+ }
+ }
+
+ inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- default:return true;
+ case 1: return u.format1.intersects_class (glyphs, klass);
+ case 2: return u.format2.intersects_class (glyphs, klass);
+ default:return false;
}
}
@@ -574,8 +717,7 @@ struct Device
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && c->check_range (this, this->get_size ());
+ return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
}
private:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
index ee9c508..f29fc14 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
@@ -1,6 +1,6 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
- * Copyright © 2010,2011 Google, Inc.
+ * Copyright © 2010,2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -71,8 +71,7 @@ struct AttachList
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && attachPoint.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
}
private:
@@ -102,7 +101,7 @@ struct CaretValueFormat1
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
}
private:
@@ -128,7 +127,7 @@ struct CaretValueFormat2
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
}
private:
@@ -151,8 +150,7 @@ struct CaretValueFormat3
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && deviceTable.sanitize (c, this);
+ return TRACE_RETURN (c->check_struct (this) && deviceTable.sanitize (c, this));
}
private:
@@ -180,12 +178,12 @@ struct CaretValue
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- case 3: return u.format3.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ case 3: return TRACE_RETURN (u.format3.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -221,7 +219,7 @@ struct LigGlyph
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return carets.sanitize (c, this);
+ return TRACE_RETURN (carets.sanitize (c, this));
}
private:
@@ -255,8 +253,7 @@ struct LigCaretList
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && ligGlyph.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
}
private:
@@ -278,7 +275,7 @@ struct MarkGlyphSetsFormat1
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this));
}
private:
@@ -302,10 +299,10 @@ struct MarkGlyphSets
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -327,7 +324,7 @@ struct GDEF
{
static const hb_tag_t Tag = HB_OT_TAG_GDEF;
- enum {
+ enum GlyphClasses {
UnclassifiedGlyph = 0,
BaseGlyph = 1,
LigatureGlyph = 2,
@@ -365,12 +362,13 @@ struct GDEF
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return version.sanitize (c) && likely (version.major == 1)
- && glyphClassDef.sanitize (c, this)
- && attachList.sanitize (c, this)
- && ligCaretList.sanitize (c, this)
- && markAttachClassDef.sanitize (c, this)
- && (version.to_int () < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this));
+ return TRACE_RETURN (version.sanitize (c) &&
+ likely (version.major == 1) &&
+ glyphClassDef.sanitize (c, this) &&
+ attachList.sanitize (c, this) &&
+ ligCaretList.sanitize (c, this) &&
+ markAttachClassDef.sanitize (c, this) &&
+ (version.to_int () < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this)));
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
index 412850b..71c13a2 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
@@ -1,6 +1,6 @@
/*
* Copyright © 2007,2008,2009,2010 Red Hat, Inc.
- * Copyright © 2010 Google, Inc.
+ * Copyright © 2010,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -46,8 +46,7 @@ typedef Value ValueRecord[VAR];
struct ValueFormat : USHORT
{
- enum
- {
+ enum Flags {
xPlacement = 0x0001, /* Includes horizontal adjustment for placement */
yPlacement = 0x0002, /* Includes vertical adjustment for placement */
xAdvance = 0x0004, /* Includes horizontal adjustment for advance */
@@ -172,40 +171,39 @@ struct ValueFormat : USHORT
inline bool sanitize_value (hb_sanitize_context_t *c, void *base, Value *values) {
TRACE_SANITIZE ();
- return c->check_range (values, get_size ())
- && (!has_device () || sanitize_value_devices (c, base, values));
+ return TRACE_RETURN (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
}
inline bool sanitize_values (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count) {
TRACE_SANITIZE ();
unsigned int len = get_len ();
- if (!c->check_array (values, get_size (), count)) return false;
+ if (!c->check_array (values, get_size (), count)) return TRACE_RETURN (false);
- if (!has_device ()) return true;
+ if (!has_device ()) return TRACE_RETURN (true);
for (unsigned int i = 0; i < count; i++) {
if (!sanitize_value_devices (c, base, values))
- return false;
+ return TRACE_RETURN (false);
values += len;
}
- return true;
+ return TRACE_RETURN (true);
}
/* Just sanitize referenced Device tables. Doesn't check the values themselves. */
inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count, unsigned int stride) {
TRACE_SANITIZE ();
- if (!has_device ()) return true;
+ if (!has_device ()) return TRACE_RETURN (true);
for (unsigned int i = 0; i < count; i++) {
if (!sanitize_value_devices (c, base, values))
- return false;
+ return TRACE_RETURN (false);
values += stride;
}
- return true;
+ return TRACE_RETURN (true);
}
};
@@ -224,7 +222,7 @@ struct AnchorFormat1
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
}
private:
@@ -256,7 +254,7 @@ struct AnchorFormat2
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
}
private:
@@ -287,9 +285,7 @@ struct AnchorFormat3
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && xDeviceTable.sanitize (c, this)
- && yDeviceTable.sanitize (c, this);
+ return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
}
private:
@@ -324,12 +320,12 @@ struct Anchor
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- case 3: return u.format3.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ case 3: return TRACE_RETURN (u.format3.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -354,13 +350,13 @@ struct AnchorMatrix
inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) {
TRACE_SANITIZE ();
- if (!c->check_struct (this)) return false;
- if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return false;
+ if (!c->check_struct (this)) return TRACE_RETURN (false);
+ if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false);
unsigned int count = rows * cols;
- if (!c->check_array (matrix, matrix[0].static_size, count)) return false;
+ if (!c->check_array (matrix, matrix[0].static_size, count)) return TRACE_RETURN (false);
for (unsigned int i = 0; i < count; i++)
- if (!matrix[i].sanitize (c, this)) return false;
- return true;
+ if (!matrix[i].sanitize (c, this)) return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
}
USHORT rows; /* Number of rows */
@@ -379,8 +375,7 @@ struct MarkRecord
inline bool sanitize (hb_sanitize_context_t *c, void *base) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && markAnchor.sanitize (c, base);
+ return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base));
}
private:
@@ -408,21 +403,21 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
hb_position_t mark_x, mark_y, base_x, base_y;
- mark_anchor.get_anchor (c->font, c->buffer->info[c->buffer->idx].codepoint, &mark_x, &mark_y);
+ mark_anchor.get_anchor (c->font, c->buffer->cur().codepoint, &mark_x, &mark_y);
glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y);
- hb_glyph_position_t &o = c->buffer->pos[c->buffer->idx];
+ hb_glyph_position_t &o = c->buffer->cur_pos();
o.x_offset = base_x - mark_x;
o.y_offset = base_y - mark_y;
o.attach_lookback() = c->buffer->idx - glyph_pos;
c->buffer->idx++;
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return ArrayOf<MarkRecord>::sanitize (c, this);
+ return TRACE_RETURN (ArrayOf<MarkRecord>::sanitize (c, this));
}
};
@@ -437,22 +432,19 @@ struct SinglePosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
valueFormat.apply_value (c->font, c->direction, this,
- values, c->buffer->pos[c->buffer->idx]);
+ values, c->buffer->cur_pos());
c->buffer->idx++;
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && coverage.sanitize (c, this)
- && valueFormat.sanitize_value (c, this, values);
+ return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_value (c, this, values));
}
private:
@@ -477,26 +469,22 @@ struct SinglePosFormat2
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
- if (likely (index >= valueCount))
- return false;
+ if (likely (index >= valueCount)) return TRACE_RETURN (false);
valueFormat.apply_value (c->font, c->direction, this,
&values[index * valueFormat.get_len ()],
- c->buffer->pos[c->buffer->idx]);
+ c->buffer->cur_pos());
c->buffer->idx++;
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && coverage.sanitize (c, this)
- && valueFormat.sanitize_values (c, this, values, valueCount);
+ return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_values (c, this, values, valueCount));
}
private:
@@ -522,19 +510,19 @@ struct SinglePos
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- case 2: return u.format2.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ case 2: return TRACE_RETURN (u.format2.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -581,18 +569,18 @@ struct PairSet
if (c->buffer->info[pos].codepoint == record->secondGlyph)
{
valueFormats[0].apply_value (c->font, c->direction, this,
- &record->values[0], c->buffer->pos[c->buffer->idx]);
+ &record->values[0], c->buffer->cur_pos());
valueFormats[1].apply_value (c->font, c->direction, this,
&record->values[len1], c->buffer->pos[pos]);
if (len2)
pos++;
c->buffer->idx = pos;
- return true;
+ return TRACE_RETURN (true);
}
record = &StructAtOffset<PairValueRecord> (record, record_size);
}
- return false;
+ return TRACE_RETURN (false);
}
struct sanitize_closure_t {
@@ -605,12 +593,12 @@ struct PairSet
inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) {
TRACE_SANITIZE ();
if (!(c->check_struct (this)
- && c->check_array (array, USHORT::static_size * closure->stride, len))) return false;
+ && c->check_array (array, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false);
unsigned int count = len;
PairValueRecord *record = CastP<PairValueRecord> (array);
- return closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride)
- && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride);
+ return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride)
+ && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
}
private:
@@ -630,17 +618,14 @@ struct PairPosFormat1
{
TRACE_APPLY ();
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
- if (skippy_iter.has_no_chance ())
- return false;
+ if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
- if (!skippy_iter.next ())
- return false;
+ if (!skippy_iter.next ()) return TRACE_RETURN (false);
- return (this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx);
+ return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -655,9 +640,7 @@ struct PairPosFormat1
1 + len1 + len2
};
- return c->check_struct (this)
- && coverage.sanitize (c, this)
- && pairSet.sanitize (c, this, &closure);
+ return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
}
private:
@@ -687,28 +670,24 @@ struct PairPosFormat2
{
TRACE_APPLY ();
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
- if (skippy_iter.has_no_chance ())
- return false;
+ if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
- if (!skippy_iter.next ())
- return false;
+ if (!skippy_iter.next ()) return TRACE_RETURN (false);
unsigned int len1 = valueFormat1.get_len ();
unsigned int len2 = valueFormat2.get_len ();
unsigned int record_len = len1 + len2;
- unsigned int klass1 = (this+classDef1) (c->buffer->info[c->buffer->idx].codepoint);
+ unsigned int klass1 = (this+classDef1) (c->buffer->cur().codepoint);
unsigned int klass2 = (this+classDef2) (c->buffer->info[skippy_iter.idx].codepoint);
- if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
- return false;
+ if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return TRACE_RETURN (false);
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
valueFormat1.apply_value (c->font, c->direction, this,
- v, c->buffer->pos[c->buffer->idx]);
+ v, c->buffer->cur_pos());
valueFormat2.apply_value (c->font, c->direction, this,
v + len1, c->buffer->pos[skippy_iter.idx]);
@@ -716,7 +695,7 @@ struct PairPosFormat2
if (len2)
c->buffer->idx++;
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -724,16 +703,16 @@ struct PairPosFormat2
if (!(c->check_struct (this)
&& coverage.sanitize (c, this)
&& classDef1.sanitize (c, this)
- && classDef2.sanitize (c, this))) return false;
+ && classDef2.sanitize (c, this))) return TRACE_RETURN (false);
unsigned int len1 = valueFormat1.get_len ();
unsigned int len2 = valueFormat2.get_len ();
unsigned int stride = len1 + len2;
unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
- return c->check_array (values, record_size, count) &&
- valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
- valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride);
+ return TRACE_RETURN (c->check_array (values, record_size, count) &&
+ valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
+ valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
}
private:
@@ -775,19 +754,19 @@ struct PairPos
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- case 2: return u.format2.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ case 2: return TRACE_RETURN (u.format2.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -806,8 +785,7 @@ struct EntryExitRecord
inline bool sanitize (hb_sanitize_context_t *c, void *base) {
TRACE_SANITIZE ();
- return entryAnchor.sanitize (c, base)
- && exitAnchor.sanitize (c, base);
+ return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
}
private:
@@ -833,23 +811,18 @@ struct CursivePosFormat1
TRACE_APPLY ();
/* We don't handle mark glyphs here. */
- if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)
- return false;
+ if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) return TRACE_RETURN (false);
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
- if (skippy_iter.has_no_chance ())
- return false;
+ if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
- const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->info[c->buffer->idx].codepoint)];
- if (!this_record.exitAnchor)
- return false;
+ const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->cur().codepoint)];
+ if (!this_record.exitAnchor) return TRACE_RETURN (false);
- if (!skippy_iter.next ())
- return false;
+ if (!skippy_iter.next ()) return TRACE_RETURN (false);
const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[skippy_iter.idx].codepoint)];
- if (!next_record.entryAnchor)
- return false;
+ if (!next_record.entryAnchor) return TRACE_RETURN (false);
unsigned int i = c->buffer->idx;
unsigned int j = skippy_iter.idx;
@@ -912,13 +885,12 @@ struct CursivePosFormat1
}
c->buffer->idx = j;
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && entryExitRecord.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
}
private:
@@ -942,17 +914,17 @@ struct CursivePos
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -977,34 +949,27 @@ struct MarkBasePosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (mark_index == NOT_COVERED))
- return false;
+ unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint);
+ if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
/* now we search backwards for a non-mark glyph */
unsigned int property;
hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
- if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks))
- return false;
+ if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RETURN (false);
/* The following assertion is too strong, so we've disabled it. */
- if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH))
- {/*return false;*/}
+ if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH)) {/*return TRACE_RETURN (false);*/}
unsigned int base_index = (this+baseCoverage) (c->buffer->info[skippy_iter.idx].codepoint);
- if (base_index == NOT_COVERED)
- return false;
+ if (base_index == NOT_COVERED) return TRACE_RETURN (false);
- return (this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx);
+ return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && markCoverage.sanitize (c, this)
- && baseCoverage.sanitize (c, this)
- && markArray.sanitize (c, this)
- && baseArray.sanitize (c, this, (unsigned int) classCount);
+ return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && baseCoverage.sanitize (c, this) &&
+ markArray.sanitize (c, this) && baseArray.sanitize (c, this, (unsigned int) classCount));
}
private:
@@ -1035,17 +1000,17 @@ struct MarkBasePos
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -1075,56 +1040,51 @@ struct MarkLigPosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (mark_index == NOT_COVERED))
- return false;
+ unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint);
+ if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
/* now we search backwards for a non-mark glyph */
unsigned int property;
hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
- if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks))
- return false;
+ if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RETURN (false);
/* The following assertion is too strong, so we've disabled it. */
- if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE))
- {/*return false;*/}
+ if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)) {/*return TRACE_RETURN (false);*/}
unsigned int j = skippy_iter.idx;
unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoint);
- if (lig_index == NOT_COVERED)
- return false;
+ if (lig_index == NOT_COVERED) return TRACE_RETURN (false);
const LigatureArray& lig_array = this+ligatureArray;
const LigatureAttach& lig_attach = lig_array[lig_index];
/* Find component to attach to */
unsigned int comp_count = lig_attach.rows;
- if (unlikely (!comp_count))
- return false;
+ if (unlikely (!comp_count)) return TRACE_RETURN (false);
+
unsigned int comp_index;
/* We must now check whether the ligature ID of the current mark glyph
* is identical to the ligature ID of the found ligature. If yes, we
* can directly use the component index. If not, we attach the mark
* glyph to the last component of the ligature. */
- if (c->buffer->info[j].lig_id() && c->buffer->info[j].lig_id() == c->buffer->info[c->buffer->idx].lig_id() && c->buffer->info[c->buffer->idx].lig_comp())
+ if (get_lig_id (c->buffer->info[j]) &&
+ get_lig_id (c->buffer->cur()) &&
+ get_lig_comp (c->buffer->cur()) > 0)
{
- comp_index = c->buffer->info[c->buffer->idx].lig_comp() - 1;
+ comp_index = get_lig_comp (c->buffer->cur()) - 1;
if (comp_index >= comp_count)
comp_index = comp_count - 1;
}
else
comp_index = comp_count - 1;
- return (this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j);
+ return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && markCoverage.sanitize (c, this)
- && ligatureCoverage.sanitize (c, this)
- && markArray.sanitize (c, this)
- && ligatureArray.sanitize (c, this, (unsigned int) classCount);
+ return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && ligatureCoverage.sanitize (c, this) &&
+ markArray.sanitize (c, this) && ligatureArray.sanitize (c, this, (unsigned int) classCount));
}
private:
@@ -1156,17 +1116,17 @@ struct MarkLigPos
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -1191,42 +1151,37 @@ struct MarkMarkPosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int mark1_index = (this+mark1Coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (mark1_index == NOT_COVERED))
- return false;
+ unsigned int mark1_index = (this+mark1Coverage) (c->buffer->cur().codepoint);
+ if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false);
/* now we search backwards for a suitable mark glyph until a non-mark glyph */
unsigned int property;
hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
- if (!skippy_iter.prev (&property))
- return false;
+ if (!skippy_iter.prev (&property)) return TRACE_RETURN (false);
- if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK))
- return false;
+ if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) return TRACE_RETURN (false);
unsigned int j = skippy_iter.idx;
/* Two marks match only if they belong to the same base, or same component
* of the same ligature. That is, the component numbers must match, and
* if those are non-zero, the ligid number should also match. */
- if ((c->buffer->info[j].lig_comp() != c->buffer->info[c->buffer->idx].lig_comp()) ||
- (c->buffer->info[j].lig_comp() && c->buffer->info[j].lig_id() != c->buffer->info[c->buffer->idx].lig_id()))
- return false;
+ if ((get_lig_comp (c->buffer->cur())) ||
+ (get_lig_comp (c->buffer->info[j]) > 0 &&
+ get_lig_id (c->buffer->cur())))
+ return TRACE_RETURN (false);
unsigned int mark2_index = (this+mark2Coverage) (c->buffer->info[j].codepoint);
- if (mark2_index == NOT_COVERED)
- return false;
+ if (mark2_index == NOT_COVERED) return TRACE_RETURN (false);
- return (this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j);
+ return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this)
- && mark1Coverage.sanitize (c, this)
- && mark2Coverage.sanitize (c, this)
- && mark1Array.sanitize (c, this)
- && mark2Array.sanitize (c, this, (unsigned int) classCount);
+ return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, this) &&
+ mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this)
+ && mark2Array.sanitize (c, this, (unsigned int) classCount));
}
private:
@@ -1259,17 +1214,17 @@ struct MarkMarkPos
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -1291,7 +1246,7 @@ struct ContextPos : Context
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- return Context::apply (c, position_lookup);
+ return TRACE_RETURN (Context::apply (c, position_lookup));
}
};
@@ -1303,7 +1258,7 @@ struct ChainContextPos : ChainContext
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- return ChainContext::apply (c, position_lookup);
+ return TRACE_RETURN (ChainContext::apply (c, position_lookup));
}
};
@@ -1336,7 +1291,7 @@ struct PosLookupSubTable
{
friend struct PosLookup;
- enum {
+ enum Type {
Single = 1,
Pair = 2,
Cursive = 3,
@@ -1352,32 +1307,32 @@ struct PosLookupSubTable
{
TRACE_APPLY ();
switch (lookup_type) {
- case Single: return u.single.apply (c);
- case Pair: return u.pair.apply (c);
- case Cursive: return u.cursive.apply (c);
- case MarkBase: return u.markBase.apply (c);
- case MarkLig: return u.markLig.apply (c);
- case MarkMark: return u.markMark.apply (c);
- case Context: return u.c.apply (c);
- case ChainContext: return u.chainContext.apply (c);
- case Extension: return u.extension.apply (c);
- default:return false;
+ case Single: return TRACE_RETURN (u.single.apply (c));
+ case Pair: return TRACE_RETURN (u.pair.apply (c));
+ case Cursive: return TRACE_RETURN (u.cursive.apply (c));
+ case MarkBase: return TRACE_RETURN (u.markBase.apply (c));
+ case MarkLig: return TRACE_RETURN (u.markLig.apply (c));
+ case MarkMark: return TRACE_RETURN (u.markMark.apply (c));
+ case Context: return TRACE_RETURN (u.c.apply (c));
+ case ChainContext: return TRACE_RETURN (u.chainContext.apply (c));
+ case Extension: return TRACE_RETURN (u.extension.apply (c));
+ default: return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
TRACE_SANITIZE ();
switch (lookup_type) {
- case Single: return u.single.sanitize (c);
- case Pair: return u.pair.sanitize (c);
- case Cursive: return u.cursive.sanitize (c);
- case MarkBase: return u.markBase.sanitize (c);
- case MarkLig: return u.markLig.sanitize (c);
- case MarkMark: return u.markMark.sanitize (c);
- case Context: return u.c.sanitize (c);
- case ChainContext: return u.chainContext.sanitize (c);
- case Extension: return u.extension.sanitize (c);
- default:return true;
+ case Single: return TRACE_RETURN (u.single.sanitize (c));
+ case Pair: return TRACE_RETURN (u.pair.sanitize (c));
+ case Cursive: return TRACE_RETURN (u.cursive.sanitize (c));
+ case MarkBase: return TRACE_RETURN (u.markBase.sanitize (c));
+ case MarkLig: return TRACE_RETURN (u.markLig.sanitize (c));
+ case MarkMark: return TRACE_RETURN (u.markMark.sanitize (c));
+ case Context: return TRACE_RETURN (u.c.sanitize (c));
+ case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
+ case Extension: return TRACE_RETURN (u.extension.sanitize (c));
+ default: return TRACE_RETURN (true);
}
}
@@ -1404,25 +1359,11 @@ struct PosLookup : Lookup
inline const PosLookupSubTable& get_subtable (unsigned int i) const
{ return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
- inline bool apply_once (hb_font_t *font,
- hb_buffer_t *buffer,
- hb_mask_t lookup_mask,
- unsigned int context_length,
- unsigned int nesting_level_left) const
+ inline bool apply_once (hb_apply_context_t *c) const
{
unsigned int lookup_type = get_type ();
- hb_apply_context_t c[1] = {{0}};
-
- c->font = font;
- c->face = font->face;
- c->buffer = buffer;
- c->direction = buffer->props.direction;
- c->lookup_mask = lookup_mask;
- c->context_length = context_length;
- c->nesting_level_left = nesting_level_left;
- c->lookup_props = get_props ();
-
- if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer->idx], c->lookup_props, &c->property))
+
+ if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->cur(), c->lookup_props, &c->property))
return false;
for (unsigned int i = 0; i < get_subtable_count (); i++)
@@ -1432,23 +1373,22 @@ struct PosLookup : Lookup
return false;
}
- inline bool apply_string (hb_font_t *font,
- hb_buffer_t *buffer,
- hb_mask_t mask) const
+ inline bool apply_string (hb_apply_context_t *c) const
{
bool ret = false;
- if (unlikely (!buffer->len))
+ if (unlikely (!c->buffer->len))
return false;
- buffer->idx = 0;
- while (buffer->idx < buffer->len)
+ c->set_lookup (*this);
+
+ c->buffer->idx = 0;
+ while (c->buffer->idx < c->buffer->len)
{
- if ((buffer->info[buffer->idx].mask & mask) &&
- apply_once (font, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+ if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c))
ret = true;
else
- buffer->idx++;
+ c->buffer->idx++;
}
return ret;
@@ -1456,9 +1396,9 @@ struct PosLookup : Lookup
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (unlikely (!Lookup::sanitize (c))) return false;
+ if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTable> > (subTable);
- return list.sanitize (c, this, get_type ());
+ return TRACE_RETURN (list.sanitize (c, this, get_type ()));
}
};
@@ -1475,20 +1415,17 @@ struct GPOS : GSUBGPOS
inline const PosLookup& get_lookup (unsigned int i) const
{ return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
- inline bool position_lookup (hb_font_t *font,
- hb_buffer_t *buffer,
- unsigned int lookup_index,
- hb_mask_t mask) const
- { return get_lookup (lookup_index).apply_string (font, buffer, mask); }
+ inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index) const
+ { return get_lookup (lookup_index).apply_string (c); }
static inline void position_start (hb_buffer_t *buffer);
static inline void position_finish (hb_buffer_t *buffer);
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (unlikely (!GSUBGPOS::sanitize (c))) return false;
+ if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
- return list.sanitize (c, this);
+ return TRACE_RETURN (list.sanitize (c, this));
}
public:
DEFINE_SIZE_STATIC (10);
@@ -1564,8 +1501,8 @@ GPOS::position_finish (hb_buffer_t *buffer)
for (unsigned int i = 0; i < len; i++)
fix_mark_attachment (pos, i, direction);
- HB_BUFFER_DEALLOCATE_VAR (buffer, lig_comp);
- HB_BUFFER_DEALLOCATE_VAR (buffer, lig_id);
+ HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
+ HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
HB_BUFFER_DEALLOCATE_VAR (buffer, props_cache);
}
@@ -1575,16 +1512,16 @@ GPOS::position_finish (hb_buffer_t *buffer)
inline bool ExtensionPos::apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- return get_subtable ().apply (c, get_type ());
+ return TRACE_RETURN (get_subtable ().apply (c, get_type ()));
}
inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c)
{
TRACE_SANITIZE ();
- if (unlikely (!Extension::sanitize (c))) return false;
+ if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false);
unsigned int offset = get_offset ();
- if (unlikely (!offset)) return true;
- return StructAtOffset<PosLookupSubTable> (this, offset).sanitize (c, get_type ());
+ if (unlikely (!offset)) return TRACE_RETURN (true);
+ return TRACE_RETURN (StructAtOffset<PosLookupSubTable> (this, offset).sanitize (c, get_type ()));
}
static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index)
@@ -1595,10 +1532,10 @@ static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
if (unlikely (c->nesting_level_left == 0))
return false;
- if (unlikely (c->context_length < 1))
- return false;
-
- return l.apply_once (c->font, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
+ hb_apply_context_t new_c (*c);
+ new_c.nesting_level_left--;
+ new_c.set_lookup (l);
+ return l.apply_once (&new_c);
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
index f7ec3cc..f6a7575 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
@@ -1,6 +1,6 @@
/*
* Copyright © 2007,2008,2009,2010 Red Hat, Inc.
- * Copyright © 2010 Google, Inc.
+ * Copyright © 2010,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -39,26 +39,40 @@ struct SingleSubstFormat1
private:
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ Coverage::Iter iter;
+ for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ hb_codepoint_t glyph_id = iter.get_glyph ();
+ if (c->glyphs->has (glyph_id))
+ c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF);
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t glyph_id) const
+ {
+ return (this+coverage) (glyph_id) != NOT_COVERED;
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint;
+ hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
unsigned int index = (this+coverage) (glyph_id);
- if (likely (index == NOT_COVERED))
- return false;
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
/* According to the Adobe Annotated OpenType Suite, result is always
* limited to 16bit. */
glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF;
c->replace_glyph (glyph_id);
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && deltaGlyphID.sanitize (c);
+ return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
}
private:
@@ -78,27 +92,39 @@ struct SingleSubstFormat2
private:
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ Coverage::Iter iter;
+ for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ if (c->glyphs->has (iter.get_glyph ()))
+ c->glyphs->add (substitute[iter.get_coverage ()]);
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t glyph_id) const
+ {
+ return (this+coverage) (glyph_id) != NOT_COVERED;
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint;
+ hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
unsigned int index = (this+coverage) (glyph_id);
- if (likely (index == NOT_COVERED))
- return false;
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
- if (unlikely (index >= substitute.len))
- return false;
+ if (unlikely (index >= substitute.len)) return TRACE_RETURN (false);
glyph_id = substitute[index];
c->replace_glyph (glyph_id);
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && substitute.sanitize (c);
+ return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c));
}
private:
@@ -119,23 +145,42 @@ struct SingleSubst
private:
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ switch (u.format) {
+ case 1: u.format1.closure (c); break;
+ case 2: u.format2.closure (c); break;
+ default: break;
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t glyph_id) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.would_apply (glyph_id);
+ case 2: return u.format2.would_apply (glyph_id);
+ default:return false;
+ }
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- case 2: return u.format2.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ case 2: return TRACE_RETURN (u.format2.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -153,23 +198,30 @@ struct Sequence
friend struct MultipleSubstFormat1;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ unsigned int count = substitute.len;
+ for (unsigned int i = 0; i < count; i++)
+ c->glyphs->add (substitute[i]);
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- if (unlikely (!substitute.len))
- return false;
+ if (unlikely (!substitute.len)) return TRACE_RETURN (false);
- if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)
- c->guess_glyph_class (HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH);
- c->replace_glyphs_be16 (1, substitute.len, (const uint16_t *) substitute.array);
+ unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ? HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH : 0;
+ c->replace_glyphs_be16 (1, substitute.len, (const uint16_t *) substitute.array, klass);
- return true;
+ return TRACE_RETURN (true);
}
public:
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return substitute.sanitize (c);
+ return TRACE_RETURN (substitute.sanitize (c));
}
private:
@@ -185,21 +237,34 @@ struct MultipleSubstFormat1
private:
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ Coverage::Iter iter;
+ for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ if (c->glyphs->has (iter.get_glyph ()))
+ (this+sequence[iter.get_coverage ()]).closure (c);
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t glyph_id) const
+ {
+ return (this+coverage) (glyph_id) != NOT_COVERED;
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
- return (this+sequence[index]).apply (c);
+ return TRACE_RETURN ((this+sequence[index]).apply (c));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && sequence.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this));
}
private:
@@ -220,21 +285,38 @@ struct MultipleSubst
private:
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ switch (u.format) {
+ case 1: u.format1.closure (c); break;
+ default: break;
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t glyph_id) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.would_apply (glyph_id);
+ default:return false;
+ }
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -255,40 +337,56 @@ struct AlternateSubstFormat1
private:
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ Coverage::Iter iter;
+ for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ if (c->glyphs->has (iter.get_glyph ())) {
+ const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
+ unsigned int count = alt_set.len;
+ for (unsigned int i = 0; i < count; i++)
+ c->glyphs->add (alt_set[i]);
+ }
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t glyph_id) const
+ {
+ return (this+coverage) (glyph_id) != NOT_COVERED;
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint;
- hb_mask_t glyph_mask = c->buffer->info[c->buffer->idx].mask;
- hb_mask_t lookup_mask = c->lookup_mask;
+ hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
unsigned int index = (this+coverage) (glyph_id);
- if (likely (index == NOT_COVERED))
- return false;
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const AlternateSet &alt_set = this+alternateSet[index];
- if (unlikely (!alt_set.len))
- return false;
+ if (unlikely (!alt_set.len)) return TRACE_RETURN (false);
+
+ hb_mask_t glyph_mask = c->buffer->cur().mask;
+ hb_mask_t lookup_mask = c->lookup_mask;
/* Note: This breaks badly if two features enabled this lookup together. */
unsigned int shift = _hb_ctz (lookup_mask);
unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
- if (unlikely (alt_index > alt_set.len || alt_index == 0))
- return false;
+ if (unlikely (alt_index > alt_set.len || alt_index == 0)) return TRACE_RETURN (false);
glyph_id = alt_set[alt_index - 1];
c->replace_glyph (glyph_id);
- return true;
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && alternateSet.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
}
private:
@@ -309,21 +407,38 @@ struct AlternateSubst
private:
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ switch (u.format) {
+ case 1: u.format1.closure (c); break;
+ default: break;
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t glyph_id) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.would_apply (glyph_id);
+ default:return false;
+ }
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -340,16 +455,30 @@ struct Ligature
friend struct LigatureSet;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ unsigned int count = component.len;
+ for (unsigned int i = 1; i < count; i++)
+ if (!c->glyphs->has (component[i]))
+ return;
+ c->glyphs->add (ligGlyph);
+ }
+
+ inline bool would_apply (hb_codepoint_t second) const
+ {
+ return component.len == 2 && component[1] == second;
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
unsigned int count = component.len;
- if (unlikely (count < 2))
- return false;
+ if (unlikely (count < 2)) return TRACE_RETURN (false);
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
- if (skippy_iter.has_no_chance ())
- return false;
+ if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
bool found_non_mark = false;
@@ -358,26 +487,22 @@ struct Ligature
{
unsigned int property;
- if (!skippy_iter.next (&property))
- return false;
+ if (!skippy_iter.next (&property)) return TRACE_RETURN (false);
found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
- if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i]))
- return false;
+ if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) return TRACE_RETURN (false);
}
- if (first_was_mark && found_non_mark)
- c->guess_glyph_class (HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE);
+ unsigned int klass = first_was_mark && found_non_mark ? HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE : 0;
/* Allocate new ligature id */
unsigned int lig_id = allocate_lig_id (c->buffer);
- c->buffer->info[c->buffer->idx].lig_comp() = 0;
- c->buffer->info[c->buffer->idx].lig_id() = lig_id;
+ set_lig_props (c->buffer->cur(), lig_id, 0);
if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */
{
- c->replace_glyphs_be16 (count, 1, (const uint16_t *) &ligGlyph);
+ c->replace_glyphs_be16 (count, 1, (const uint16_t *) &ligGlyph, klass);
}
else
{
@@ -394,9 +519,8 @@ struct Ligature
{
while (c->should_mark_skip_current_glyph ())
{
- c->buffer->info[c->buffer->idx].lig_comp() = i;
- c->buffer->info[c->buffer->idx].lig_id() = lig_id;
- c->replace_glyph (c->buffer->info[c->buffer->idx].codepoint);
+ set_lig_props (c->buffer->cur(), lig_id, i);
+ c->replace_glyph (c->buffer->cur().codepoint);
}
/* Skip the base glyph */
@@ -404,14 +528,13 @@ struct Ligature
}
}
- return true;
+ return TRACE_RETURN (true);
}
public:
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return ligGlyph.sanitize (c)
- && component.sanitize (c);
+ return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c));
}
private:
@@ -429,6 +552,27 @@ struct LigatureSet
friend struct LigatureSubstFormat1;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ unsigned int num_ligs = ligature.len;
+ for (unsigned int i = 0; i < num_ligs; i++)
+ (this+ligature[i]).closure (c);
+ }
+
+ inline bool would_apply (hb_codepoint_t second) const
+ {
+ unsigned int num_ligs = ligature.len;
+ for (unsigned int i = 0; i < num_ligs; i++)
+ {
+ const Ligature &lig = this+ligature[i];
+ if (lig.would_apply (second))
+ return true;
+ }
+ return false;
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
@@ -436,17 +580,16 @@ struct LigatureSet
for (unsigned int i = 0; i < num_ligs; i++)
{
const Ligature &lig = this+ligature[i];
- if (lig.apply (c))
- return true;
+ if (lig.apply (c)) return TRACE_RETURN (true);
}
- return false;
+ return TRACE_RETURN (false);
}
public:
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return ligature.sanitize (c, this);
+ return TRACE_RETURN (ligature.sanitize (c, this));
}
private:
@@ -462,23 +605,39 @@ struct LigatureSubstFormat1
friend struct LigatureSubst;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ Coverage::Iter iter;
+ for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ if (c->glyphs->has (iter.get_glyph ()))
+ (this+ligatureSet[iter.get_coverage ()]).closure (c);
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
+ {
+ unsigned int index;
+ return (index = (this+coverage) (first)) != NOT_COVERED &&
+ (this+ligatureSet[index]).would_apply (second);
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint;
+ hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
unsigned int index = (this+coverage) (glyph_id);
- if (likely (index == NOT_COVERED))
- return false;
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const LigatureSet &lig_set = this+ligatureSet[index];
- return lig_set.apply (c);
+ return TRACE_RETURN (lig_set.apply (c));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && ligatureSet.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
}
private:
@@ -498,21 +657,39 @@ struct LigatureSubst
friend struct SubstLookupSubTable;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ switch (u.format) {
+ case 1: u.format1.closure (c); break;
+ default: break;
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.would_apply (first, second);
+ default:return false;
+ }
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -525,16 +702,24 @@ struct LigatureSubst
static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index);
+static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_index);
struct ContextSubst : Context
{
friend struct SubstLookupSubTable;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ return Context::closure (c, closure_lookup);
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- return Context::apply (c, substitute_lookup);
+ return TRACE_RETURN (Context::apply (c, substitute_lookup));
}
};
@@ -543,10 +728,17 @@ struct ChainContextSubst : ChainContext
friend struct SubstLookupSubTable;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ return ChainContext::closure (c, closure_lookup);
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- return ChainContext::apply (c, substitute_lookup);
+ return TRACE_RETURN (ChainContext::apply (c, substitute_lookup));
}
};
@@ -564,6 +756,10 @@ struct ExtensionSubst : Extension
return StructAtOffset<SubstLookupSubTable> (this, offset);
}
+ inline void closure (hb_closure_context_t *c) const;
+ inline bool would_apply (hb_codepoint_t glyph_id) const;
+ inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const;
+
inline bool apply (hb_apply_context_t *c) const;
inline bool sanitize (hb_sanitize_context_t *c);
@@ -577,15 +773,40 @@ struct ReverseChainSingleSubstFormat1
friend struct ReverseChainSingleSubst;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+ unsigned int count;
+
+ count = backtrack.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+backtrack[i]).intersects (c->glyphs))
+ return;
+
+ count = lookahead.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+lookahead[i]).intersects (c->glyphs))
+ return;
+
+ const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
+ Coverage::Iter iter;
+ for (iter.init (this+coverage); iter.more (); iter.next ()) {
+ if (c->glyphs->has (iter.get_glyph ()))
+ c->glyphs->add (substitute[iter.get_coverage ()]);
+ }
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- if (unlikely (c->context_length != NO_CONTEXT))
- return false; /* No chaining to this type */
+ if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL))
+ return TRACE_RETURN (false); /* No chaining to this type */
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
@@ -598,24 +819,23 @@ struct ReverseChainSingleSubstFormat1
match_coverage, this,
1))
{
- c->buffer->info[c->buffer->idx].codepoint = substitute[index];
+ c->buffer->cur().codepoint = substitute[index];
c->buffer->idx--; /* Reverse! */
- return true;
+ return TRACE_RETURN (true);
}
- return false;
+ return TRACE_RETURN (false);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!(coverage.sanitize (c, this)
- && backtrack.sanitize (c, this)))
- return false;
+ if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
+ return TRACE_RETURN (false);
OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
if (!lookahead.sanitize (c, this))
- return false;
+ return TRACE_RETURN (false);
ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
- return substitute.sanitize (c);
+ return TRACE_RETURN (substitute.sanitize (c));
}
private:
@@ -643,21 +863,31 @@ struct ReverseChainSingleSubst
friend struct SubstLookupSubTable;
private:
+
+ inline void closure (hb_closure_context_t *c) const
+ {
+ TRACE_CLOSURE ();
+ switch (u.format) {
+ case 1: u.format1.closure (c); break;
+ default: break;
+ }
+ }
+
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -678,7 +908,7 @@ struct SubstLookupSubTable
{
friend struct SubstLookup;
- enum {
+ enum Type {
Single = 1,
Multiple = 2,
Alternate = 3,
@@ -689,34 +919,73 @@ struct SubstLookupSubTable
ReverseChainSingle = 8
};
+ inline void closure (hb_closure_context_t *c,
+ unsigned int lookup_type) const
+ {
+ TRACE_CLOSURE ();
+ switch (lookup_type) {
+ case Single: u.single.closure (c); break;
+ case Multiple: u.multiple.closure (c); break;
+ case Alternate: u.alternate.closure (c); break;
+ case Ligature: u.ligature.closure (c); break;
+ case Context: u.c.closure (c); break;
+ case ChainContext: u.chainContext.closure (c); break;
+ case Extension: u.extension.closure (c); break;
+ case ReverseChainSingle: u.reverseChainContextSingle.closure (c); break;
+ default: break;
+ }
+ }
+
+ inline bool would_apply (hb_codepoint_t glyph_id,
+ unsigned int lookup_type) const
+ {
+ switch (lookup_type) {
+ case Single: return u.single.would_apply (glyph_id);
+ case Multiple: return u.multiple.would_apply (glyph_id);
+ case Alternate: return u.alternate.would_apply (glyph_id);
+ case Extension: return u.extension.would_apply (glyph_id);
+ default: return false;
+ }
+ }
+ inline bool would_apply (hb_codepoint_t first,
+ hb_codepoint_t second,
+ unsigned int lookup_type) const
+ {
+ switch (lookup_type) {
+ case Ligature: return u.ligature.would_apply (first, second);
+ case Extension: return u.extension.would_apply (first, second);
+ default: return false;
+ }
+ }
+
inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const
{
TRACE_APPLY ();
switch (lookup_type) {
- case Single: return u.single.apply (c);
- case Multiple: return u.multiple.apply (c);
- case Alternate: return u.alternate.apply (c);
- case Ligature: return u.ligature.apply (c);
- case Context: return u.c.apply (c);
- case ChainContext: return u.chainContext.apply (c);
- case Extension: return u.extension.apply (c);
- case ReverseChainSingle: return u.reverseChainContextSingle.apply (c);
- default:return false;
+ case Single: return TRACE_RETURN (u.single.apply (c));
+ case Multiple: return TRACE_RETURN (u.multiple.apply (c));
+ case Alternate: return TRACE_RETURN (u.alternate.apply (c));
+ case Ligature: return TRACE_RETURN (u.ligature.apply (c));
+ case Context: return TRACE_RETURN (u.c.apply (c));
+ case ChainContext: return TRACE_RETURN (u.chainContext.apply (c));
+ case Extension: return TRACE_RETURN (u.extension.apply (c));
+ case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.apply (c));
+ default: return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
TRACE_SANITIZE ();
switch (lookup_type) {
- case Single: return u.single.sanitize (c);
- case Multiple: return u.multiple.sanitize (c);
- case Alternate: return u.alternate.sanitize (c);
- case Ligature: return u.ligature.sanitize (c);
- case Context: return u.c.sanitize (c);
- case ChainContext: return u.chainContext.sanitize (c);
- case Extension: return u.extension.sanitize (c);
- case ReverseChainSingle: return u.reverseChainContextSingle.sanitize (c);
- default:return true;
+ case Single: return TRACE_RETURN (u.single.sanitize (c));
+ case Multiple: return TRACE_RETURN (u.multiple.sanitize (c));
+ case Alternate: return TRACE_RETURN (u.alternate.sanitize (c));
+ case Ligature: return TRACE_RETURN (u.ligature.sanitize (c));
+ case Context: return TRACE_RETURN (u.c.sanitize (c));
+ case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
+ case Extension: return TRACE_RETURN (u.extension.sanitize (c));
+ case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.sanitize (c));
+ default: return TRACE_RETURN (true);
}
}
@@ -753,25 +1022,38 @@ struct SubstLookup : Lookup
return lookup_type_is_reverse (type);
}
+ inline void closure (hb_closure_context_t *c) const
+ {
+ unsigned int lookup_type = get_type ();
+ unsigned int count = get_subtable_count ();
+ for (unsigned int i = 0; i < count; i++)
+ get_subtable (i).closure (c, lookup_type);
+ }
- inline bool apply_once (hb_face_t *face,
- hb_buffer_t *buffer,
- hb_mask_t lookup_mask,
- unsigned int context_length,
- unsigned int nesting_level_left) const
+ inline bool would_apply (hb_codepoint_t glyph_id) const
+ {
+ unsigned int lookup_type = get_type ();
+ unsigned int count = get_subtable_count ();
+ for (unsigned int i = 0; i < count; i++)
+ if (get_subtable (i).would_apply (glyph_id, lookup_type))
+ return true;
+ return false;
+ }
+ inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
{
unsigned int lookup_type = get_type ();
- hb_apply_context_t c[1] = {{0}};
+ unsigned int count = get_subtable_count ();
+ for (unsigned int i = 0; i < count; i++)
+ if (get_subtable (i).would_apply (first, second, lookup_type))
+ return true;
+ return false;
+ }
- c->face = face;
- c->buffer = buffer;
- c->direction = buffer->props.direction;
- c->lookup_mask = lookup_mask;
- c->context_length = context_length;
- c->nesting_level_left = nesting_level_left;
- c->lookup_props = get_props ();
+ inline bool apply_once (hb_apply_context_t *c) const
+ {
+ unsigned int lookup_type = get_type ();
- if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer->idx], c->lookup_props, &c->property))
+ if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->cur(), c->lookup_props, &c->property))
return false;
if (unlikely (lookup_type == SubstLookupSubTable::Extension))
@@ -781,8 +1063,8 @@ struct SubstLookup : Lookup
*
* This is rather slow to do this here for every glyph,
* but it's easiest, and who uses extension lookups anyway?!*/
- unsigned int count = get_subtable_count ();
unsigned int type = get_subtable(0).u.extension.get_type ();
+ unsigned int count = get_subtable_count ();
for (unsigned int i = 1; i < count; i++)
if (get_subtable(i).u.extension.get_type () != type)
return false;
@@ -796,46 +1078,44 @@ struct SubstLookup : Lookup
return false;
}
- inline bool apply_string (hb_face_t *face,
- hb_buffer_t *buffer,
- hb_mask_t mask) const
+ inline bool apply_string (hb_apply_context_t *c) const
{
bool ret = false;
- if (unlikely (!buffer->len))
+ if (unlikely (!c->buffer->len))
return false;
+ c->set_lookup (*this);
+
if (likely (!is_reverse ()))
{
/* in/out forward substitution */
- buffer->clear_output ();
- buffer->idx = 0;
- while (buffer->idx < buffer->len)
+ c->buffer->clear_output ();
+ c->buffer->idx = 0;
+ while (c->buffer->idx < c->buffer->len)
{
- if ((buffer->info[buffer->idx].mask & mask) &&
- apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+ if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c))
ret = true;
else
- buffer->next_glyph ();
+ c->buffer->next_glyph ();
}
if (ret)
- buffer->swap_buffers ();
+ c->buffer->swap_buffers ();
}
else
{
/* in-place backward substitution */
- buffer->idx = buffer->len - 1;
+ c->buffer->idx = c->buffer->len - 1;
do
{
- if ((buffer->info[buffer->idx].mask & mask) &&
- apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+ if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c))
ret = true;
else
- buffer->idx--;
+ c->buffer->idx--;
}
- while ((int) buffer->idx >= 0);
+ while ((int) c->buffer->idx >= 0);
}
return ret;
@@ -843,9 +1123,9 @@ struct SubstLookup : Lookup
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (unlikely (!Lookup::sanitize (c))) return false;
+ if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable);
- return list.sanitize (c, this, get_type ());
+ return TRACE_RETURN (list.sanitize (c, this, get_type ()));
}
};
@@ -862,20 +1142,21 @@ struct GSUB : GSUBGPOS
inline const SubstLookup& get_lookup (unsigned int i) const
{ return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
- inline bool substitute_lookup (hb_face_t *face,
- hb_buffer_t *buffer,
- unsigned int lookup_index,
- hb_mask_t mask) const
- { return get_lookup (lookup_index).apply_string (face, buffer, mask); }
+ inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index) const
+ { return get_lookup (lookup_index).apply_string (c); }
static inline void substitute_start (hb_buffer_t *buffer);
static inline void substitute_finish (hb_buffer_t *buffer);
+ inline void closure_lookup (hb_closure_context_t *c,
+ unsigned int lookup_index) const
+ { return get_lookup (lookup_index).closure (c); }
+
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (unlikely (!GSUBGPOS::sanitize (c))) return false;
+ if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
- return list.sanitize (c, this);
+ return TRACE_RETURN (list.sanitize (c, this));
}
public:
DEFINE_SIZE_STATIC (10);
@@ -886,35 +1167,50 @@ void
GSUB::substitute_start (hb_buffer_t *buffer)
{
HB_BUFFER_ALLOCATE_VAR (buffer, props_cache);
- HB_BUFFER_ALLOCATE_VAR (buffer, lig_id);
- HB_BUFFER_ALLOCATE_VAR (buffer, lig_comp);
+ HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
- buffer->info[i].props_cache() = buffer->info[i].lig_id() = buffer->info[i].lig_comp() = 0;
+ buffer->info[i].props_cache() = buffer->info[i].lig_props() = buffer->info[i].syllable() = 0;
}
void
-GSUB::substitute_finish (hb_buffer_t *buffer)
+GSUB::substitute_finish (hb_buffer_t *buffer HB_UNUSED)
{
}
/* Out-of-class implementation for methods recursing */
+inline void ExtensionSubst::closure (hb_closure_context_t *c) const
+{
+ get_subtable ().closure (c, get_type ());
+}
+
+inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const
+{
+ return get_subtable ().would_apply (glyph_id, get_type ());
+}
+
+inline bool ExtensionSubst::would_apply (hb_codepoint_t first, hb_codepoint_t second) const
+{
+ return get_subtable ().would_apply (first, second, get_type ());
+}
+
inline bool ExtensionSubst::apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- return get_subtable ().apply (c, get_type ());
+ return TRACE_RETURN (get_subtable ().apply (c, get_type ()));
}
inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c)
{
TRACE_SANITIZE ();
- if (unlikely (!Extension::sanitize (c))) return false;
+ if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false);
unsigned int offset = get_offset ();
- if (unlikely (!offset)) return true;
- return StructAtOffset<SubstLookupSubTable> (this, offset).sanitize (c, get_type ());
+ if (unlikely (!offset)) return TRACE_RETURN (true);
+ return TRACE_RETURN (StructAtOffset<SubstLookupSubTable> (this, offset).sanitize (c, get_type ()));
}
inline bool ExtensionSubst::is_reverse (void) const
@@ -925,18 +1221,31 @@ inline bool ExtensionSubst::is_reverse (void) const
return SubstLookup::lookup_type_is_reverse (type);
}
-static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index)
+static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_index)
{
const GSUB &gsub = *(c->face->ot_layout->gsub);
const SubstLookup &l = gsub.get_lookup (lookup_index);
if (unlikely (c->nesting_level_left == 0))
- return false;
+ return;
+
+ c->nesting_level_left--;
+ l.closure (c);
+ c->nesting_level_left++;
+}
- if (unlikely (c->context_length < 1))
+static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index)
+{
+ const GSUB &gsub = *(c->face->ot_layout->gsub);
+ const SubstLookup &l = gsub.get_lookup (lookup_index);
+
+ if (unlikely (c->nesting_level_left == 0))
return false;
- return l.apply_once (c->face, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
+ hb_apply_context_t new_c (*c);
+ new_c.nesting_level_left--;
+ new_c.set_lookup (l);
+ return l.apply_once (&new_c);
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
index 13386c2..a2e4b2f 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
@@ -1,6 +1,6 @@
/*
* Copyright © 2007,2008,2009,2010 Red Hat, Inc.
- * Copyright © 2010 Google, Inc.
+ * Copyright © 2010,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -33,50 +33,112 @@
#include "hb-ot-layout-gdef-table.hh"
-/* buffer var allocations */
-#define lig_id() var2.u8[2] /* unique ligature id */
-#define lig_comp() var2.u8[3] /* component number in the ligature (0 = base) */
+
+/* unique ligature id */
+/* component number in the ligature (0 = base) */
+static inline void
+set_lig_props (hb_glyph_info_t &info, unsigned int lig_id, unsigned int lig_comp)
+{
+ info.lig_props() = (lig_id << 4) | (lig_comp & 0x0F);
+}
+static inline unsigned int
+get_lig_id (hb_glyph_info_t &info)
+{
+ return info.lig_props() >> 4;
+}
+static inline unsigned int
+get_lig_comp (hb_glyph_info_t &info)
+{
+ return info.lig_props() & 0x0F;
+}
static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
- uint8_t lig_id = buffer->next_serial ();
- if (unlikely (!lig_id)) lig_id = buffer->next_serial (); /* in case of overflow */
+ uint8_t lig_id = buffer->next_serial () & 0x0F;
+ if (unlikely (!lig_id))
+ lig_id = allocate_lig_id (buffer); /* in case of overflow */
return lig_id;
}
+#ifndef HB_DEBUG_CLOSURE
+#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
+#endif
+
+#define TRACE_CLOSURE() \
+ hb_auto_trace_t<HB_DEBUG_CLOSURE> trace (&c->debug_depth, "CLOSURE", this, HB_FUNC, "");
+
+
+/* TODO Add TRACE_RETURN annotation for would_apply */
+
+
+struct hb_closure_context_t
+{
+ hb_face_t *face;
+ hb_set_t *glyphs;
+ unsigned int nesting_level_left;
+ unsigned int debug_depth;
+
+
+ hb_closure_context_t (hb_face_t *face_,
+ hb_set_t *glyphs_,
+ unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
+ face (face_), glyphs (glyphs_),
+ nesting_level_left (nesting_level_left_),
+ debug_depth (0) {}
+};
+
+
+
#ifndef HB_DEBUG_APPLY
#define HB_DEBUG_APPLY (HB_DEBUG+0)
#endif
#define TRACE_APPLY() \
- hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", this, NULL, HB_FUNC);
+ hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", this, HB_FUNC, "idx %d codepoint %u", c->buffer->cur().codepoint);
struct hb_apply_context_t
{
- unsigned int debug_depth;
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
hb_direction_t direction;
hb_mask_t lookup_mask;
- unsigned int context_length;
unsigned int nesting_level_left;
unsigned int lookup_props;
unsigned int property; /* propety of first glyph */
+ unsigned int debug_depth;
+
+
+ hb_apply_context_t (hb_font_t *font_,
+ hb_face_t *face_,
+ hb_buffer_t *buffer_,
+ hb_mask_t lookup_mask_) :
+ font (font_), face (face_), buffer (buffer_),
+ direction (buffer_->props.direction),
+ lookup_mask (lookup_mask_),
+ nesting_level_left (MAX_NESTING_LEVEL),
+ lookup_props (0), property (0), debug_depth (0) {}
+
+ void set_lookup (const Lookup &l) {
+ lookup_props = l.get_props ();
+ }
struct mark_skipping_forward_iterator_t
{
inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
unsigned int start_index_,
- unsigned int num_items_)
+ unsigned int num_items_,
+ bool context_match = false)
{
c = c_;
idx = start_index_;
num_items = num_items_;
- end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
+ mask = context_match ? -1 : c->lookup_mask;
+ syllable = context_match ? 0 : c->buffer->cur().syllable ();
+ end = c->buffer->len;
}
inline bool has_no_chance (void) const
{
@@ -93,7 +155,7 @@ struct hb_apply_context_t
idx++;
} while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[idx], lookup_props, property_out));
num_items--;
- return true;
+ return (c->buffer->info[idx].mask & mask) && (!syllable || syllable == c->buffer->info[idx].syllable ());
}
inline bool next (unsigned int *property_out = NULL)
{
@@ -104,6 +166,8 @@ struct hb_apply_context_t
private:
hb_apply_context_t *c;
unsigned int num_items;
+ hb_mask_t mask;
+ uint8_t syllable;
unsigned int end;
};
@@ -111,11 +175,15 @@ struct hb_apply_context_t
{
inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
unsigned int start_index_,
- unsigned int num_items_)
+ unsigned int num_items_,
+ hb_mask_t mask_ = 0,
+ bool match_syllable_ = true)
{
c = c_;
idx = start_index_;
num_items = num_items_;
+ mask = mask_ ? mask_ : c->lookup_mask;
+ syllable = match_syllable_ ? c->buffer->cur().syllable () : 0;
}
inline bool has_no_chance (void) const
{
@@ -132,7 +200,7 @@ struct hb_apply_context_t
idx--;
} while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[idx], lookup_props, property_out));
num_items--;
- return true;
+ return (c->buffer->out_info[idx].mask & mask) && (!syllable || syllable == c->buffer->out_info[idx].syllable ());
}
inline bool prev (unsigned int *property_out = NULL)
{
@@ -143,69 +211,92 @@ struct hb_apply_context_t
private:
hb_apply_context_t *c;
unsigned int num_items;
+ hb_mask_t mask;
+ uint8_t syllable;
};
inline bool should_mark_skip_current_glyph (void) const
{
- return _hb_ot_layout_skip_mark (face, &buffer->info[buffer->idx], lookup_props, NULL);
+ return _hb_ot_layout_skip_mark (face, &buffer->cur(), lookup_props, NULL);
}
- inline void replace_glyph (hb_codepoint_t glyph_index) const
+ inline void replace_glyph (hb_codepoint_t glyph_index,
+ unsigned int klass = 0) const
{
- clear_property ();
+ buffer->cur().props_cache() = klass; /*XXX if has gdef? */
buffer->replace_glyph (glyph_index);
}
inline void replace_glyphs_be16 (unsigned int num_in,
unsigned int num_out,
- const uint16_t *glyph_data_be) const
+ const uint16_t *glyph_data_be,
+ unsigned int klass = 0) const
{
- clear_property ();
+ buffer->cur().props_cache() = klass; /* XXX if has gdef? */
buffer->replace_glyphs_be16 (num_in, num_out, glyph_data_be);
}
-
- inline void guess_glyph_class (unsigned int klass)
- {
- /* XXX if ! has gdef */
- buffer->info[buffer->idx].props_cache() = klass;
- }
-
- private:
- inline void clear_property (void) const
- {
- /* XXX if has gdef */
- buffer->info[buffer->idx].props_cache() = 0;
- }
};
+typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
+typedef void (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
-struct ContextFuncs
+struct ContextClosureFuncs
+{
+ intersects_func_t intersects;
+ closure_lookup_func_t closure;
+};
+struct ContextApplyFuncs
{
match_func_t match;
apply_lookup_func_t apply;
};
+static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
+{
+ return glyphs->has (value);
+}
+static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
+{
+ const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+ return class_def.intersects_class (glyphs, value);
+}
+static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
+{
+ const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+ return (data+coverage).intersects (glyphs);
+}
+
+static inline bool intersects_array (hb_closure_context_t *c,
+ unsigned int count,
+ const USHORT values[],
+ intersects_func_t intersects_func,
+ const void *intersects_data)
+{
+ for (unsigned int i = 0; i < count; i++)
+ if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
+ return false;
+ return true;
+}
+
static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
{
return glyph_id == value;
}
-
static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
return class_def.get_class (glyph_id) == value;
}
-
static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
{
const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
- return (data+coverage) (glyph_id) != NOT_COVERED;
+ return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
}
@@ -214,7 +305,7 @@ static inline bool match_input (hb_apply_context_t *c,
const USHORT input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data,
- unsigned int *context_length_out)
+ unsigned int *end_offset = NULL)
{
hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
if (skippy_iter.has_no_chance ())
@@ -229,7 +320,8 @@ static inline bool match_input (hb_apply_context_t *c,
return false;
}
- *context_length_out = skippy_iter.idx - c->buffer->idx + 1;
+ if (end_offset)
+ *end_offset = skippy_iter.idx - c->buffer->idx + 1;
return true;
}
@@ -240,7 +332,7 @@ static inline bool match_backtrack (hb_apply_context_t *c,
match_func_t match_func,
const void *match_data)
{
- hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count);
+ hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
if (skippy_iter.has_no_chance ())
return false;
@@ -263,7 +355,7 @@ static inline bool match_lookahead (hb_apply_context_t *c,
const void *match_data,
unsigned int offset)
{
- hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count);
+ hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
if (skippy_iter.has_no_chance ())
return false;
@@ -285,7 +377,7 @@ struct LookupRecord
{
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
}
USHORT sequenceIndex; /* Index into current glyph
@@ -297,6 +389,14 @@ struct LookupRecord
};
+static inline void closure_lookup (hb_closure_context_t *c,
+ unsigned int lookupCount,
+ const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
+ closure_lookup_func_t closure_func)
+{
+ for (unsigned int i = 0; i < lookupCount; i++)
+ closure_func (c, lookupRecord->lookupListIndex);
+}
static inline bool apply_lookup (hb_apply_context_t *c,
unsigned int count, /* Including the first glyph */
@@ -304,7 +404,7 @@ static inline bool apply_lookup (hb_apply_context_t *c,
const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
apply_lookup_func_t apply_func)
{
- unsigned int end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
+ unsigned int end = c->buffer->len;
if (unlikely (count == 0 || c->buffer->idx + count > end))
return false;
@@ -360,25 +460,45 @@ static inline bool apply_lookup (hb_apply_context_t *c,
/* Contextual lookups */
-struct ContextLookupContext
+struct ContextClosureLookupContext
{
- ContextFuncs funcs;
+ ContextClosureFuncs funcs;
+ const void *intersects_data;
+};
+
+struct ContextApplyLookupContext
+{
+ ContextApplyFuncs funcs;
const void *match_data;
};
-static inline bool context_lookup (hb_apply_context_t *c,
- unsigned int inputCount, /* Including the first glyph (not matched) */
- const USHORT input[], /* Array of input values--start with second glyph */
- unsigned int lookupCount,
- const LookupRecord lookupRecord[],
- ContextLookupContext &lookup_context)
+static inline void context_closure_lookup (hb_closure_context_t *c,
+ unsigned int inputCount, /* Including the first glyph (not matched) */
+ const USHORT input[], /* Array of input values--start with second glyph */
+ unsigned int lookupCount,
+ const LookupRecord lookupRecord[],
+ ContextClosureLookupContext &lookup_context)
+{
+ if (intersects_array (c,
+ inputCount ? inputCount - 1 : 0, input,
+ lookup_context.funcs.intersects, lookup_context.intersects_data))
+ closure_lookup (c,
+ lookupCount, lookupRecord,
+ lookup_context.funcs.closure);
+}
+
+
+static inline bool context_apply_lookup (hb_apply_context_t *c,
+ unsigned int inputCount, /* Including the first glyph (not matched) */
+ const USHORT input[], /* Array of input values--start with second glyph */
+ unsigned int lookupCount,
+ const LookupRecord lookupRecord[],
+ ContextApplyLookupContext &lookup_context)
{
- hb_apply_context_t new_context = *c;
return match_input (c,
inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data,
- &new_context.context_length)
- && apply_lookup (&new_context,
+ lookup_context.funcs.match, lookup_context.match_data)
+ && apply_lookup (c,
inputCount,
lookupCount, lookupRecord,
lookup_context.funcs.apply);
@@ -389,14 +509,22 @@ struct Rule
friend struct RuleSet;
private:
- inline bool apply (hb_apply_context_t *c, ContextLookupContext &lookup_context) const
+
+ inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
+ {
+ TRACE_CLOSURE ();
+ const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
+ context_closure_lookup (c,
+ inputCount, input,
+ lookupCount, lookupRecord,
+ lookup_context);
+ }
+
+ inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY ();
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
- return context_lookup (c,
- inputCount, input,
- lookupCount, lookupRecord,
- lookup_context);
+ return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
}
public:
@@ -405,13 +533,13 @@ struct Rule
return inputCount.sanitize (c)
&& lookupCount.sanitize (c)
&& c->check_range (input,
- input[0].static_size * inputCount
- + lookupRecordX[0].static_size * lookupCount);
+ input[0].static_size * inputCount
+ + lookupRecordX[0].static_size * lookupCount);
}
private:
USHORT inputCount; /* Total number of glyphs in input
- * glyph sequence--includes the first
+ * glyph sequence--includes the first
* glyph */
USHORT lookupCount; /* Number of LookupRecords */
USHORT input[VAR]; /* Array of match inputs--start with
@@ -424,22 +552,29 @@ struct Rule
struct RuleSet
{
- inline bool apply (hb_apply_context_t *c, ContextLookupContext &lookup_context) const
+ inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
+ {
+ TRACE_CLOSURE ();
+ unsigned int num_rules = rule.len;
+ for (unsigned int i = 0; i < num_rules; i++)
+ (this+rule[i]).closure (c, lookup_context);
+ }
+
+ inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY ();
unsigned int num_rules = rule.len;
for (unsigned int i = 0; i < num_rules; i++)
{
if ((this+rule[i]).apply (c, lookup_context))
- return true;
+ return TRACE_RETURN (true);
}
-
- return false;
+ return TRACE_RETURN (false);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return rule.sanitize (c, this);
+ return TRACE_RETURN (rule.sanitize (c, this));
}
private:
@@ -456,25 +591,44 @@ struct ContextFormat1
friend struct Context;
private:
+
+ inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+ {
+ TRACE_CLOSURE ();
+
+ const Coverage &cov = (this+coverage);
+
+ struct ContextClosureLookupContext lookup_context = {
+ {intersects_glyph, closure_func},
+ NULL
+ };
+
+ unsigned int count = ruleSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (cov.intersects_coverage (c->glyphs, i)) {
+ const RuleSet &rule_set = this+ruleSet[i];
+ rule_set.closure (c, lookup_context);
+ }
+ }
+
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
if (likely (index == NOT_COVERED))
- return false;
+ return TRACE_RETURN (false);
const RuleSet &rule_set = this+ruleSet[index];
- struct ContextLookupContext lookup_context = {
+ struct ContextApplyLookupContext lookup_context = {
{match_glyph, apply_func},
NULL
};
- return rule_set.apply (c, lookup_context);
+ return TRACE_RETURN (rule_set.apply (c, lookup_context));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && ruleSet.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
}
private:
@@ -495,28 +649,47 @@ struct ContextFormat2
friend struct Context;
private:
+
+ inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+ {
+ TRACE_CLOSURE ();
+ if (!(this+coverage).intersects (c->glyphs))
+ return;
+
+ const ClassDef &class_def = this+classDef;
+
+ struct ContextClosureLookupContext lookup_context = {
+ {intersects_class, closure_func},
+ NULL
+ };
+
+ unsigned int count = ruleSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (class_def.intersects_class (c->glyphs, i)) {
+ const RuleSet &rule_set = this+ruleSet[i];
+ rule_set.closure (c, lookup_context);
+ }
+ }
+
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const ClassDef &class_def = this+classDef;
- index = class_def (c->buffer->info[c->buffer->idx].codepoint);
+ index = class_def (c->buffer->cur().codepoint);
const RuleSet &rule_set = this+ruleSet[index];
- struct ContextLookupContext lookup_context = {
+ struct ContextApplyLookupContext lookup_context = {
{match_class, apply_func},
&class_def
};
- return rule_set.apply (c, lookup_context);
+ return TRACE_RETURN (rule_set.apply (c, lookup_context));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && classDef.sanitize (c, this)
- && ruleSet.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
}
private:
@@ -540,33 +713,47 @@ struct ContextFormat3
friend struct Context;
private:
+
+ inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+ {
+ TRACE_CLOSURE ();
+ if (!(this+coverage[0]).intersects (c->glyphs))
+ return;
+
+ const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
+ struct ContextClosureLookupContext lookup_context = {
+ {intersects_coverage, closure_func},
+ this
+ };
+ context_closure_lookup (c,
+ glyphCount, (const USHORT *) (coverage + 1),
+ lookupCount, lookupRecord,
+ lookup_context);
+ }
+
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage[0]) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage[0]) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
- struct ContextLookupContext lookup_context = {
+ struct ContextApplyLookupContext lookup_context = {
{match_coverage, apply_func},
this
};
- return context_lookup (c,
- glyphCount, (const USHORT *) (coverage + 1),
- lookupCount, lookupRecord,
- lookup_context);
+ return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!c->check_struct (this)) return false;
+ if (!c->check_struct (this)) return TRACE_RETURN (false);
unsigned int count = glyphCount;
- if (!c->check_array (coverage, coverage[0].static_size, count)) return false;
+ if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
for (unsigned int i = 0; i < count; i++)
- if (!coverage[i].sanitize (c, this)) return false;
+ if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
- return c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount);
+ return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
}
private:
@@ -586,25 +773,37 @@ struct ContextFormat3
struct Context
{
protected:
+
+ inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+ {
+ TRACE_CLOSURE ();
+ switch (u.format) {
+ case 1: u.format1.closure (c, closure_func); break;
+ case 2: u.format2.closure (c, closure_func); break;
+ case 3: u.format3.closure (c, closure_func); break;
+ default: break;
+ }
+ }
+
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c, apply_func);
- case 2: return u.format2.apply (c, apply_func);
- case 3: return u.format3.apply (c, apply_func);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c, apply_func));
+ case 2: return TRACE_RETURN (u.format2.apply (c, apply_func));
+ case 3: return TRACE_RETURN (u.format3.apply (c, apply_func));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- case 3: return u.format3.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ case 3: return TRACE_RETURN (u.format3.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -620,42 +819,67 @@ struct Context
/* Chaining Contextual lookups */
-struct ChainContextLookupContext
+struct ChainContextClosureLookupContext
+{
+ ContextClosureFuncs funcs;
+ const void *intersects_data[3];
+};
+
+struct ChainContextApplyLookupContext
{
- ContextFuncs funcs;
+ ContextApplyFuncs funcs;
const void *match_data[3];
};
-static inline bool chain_context_lookup (hb_apply_context_t *c,
- unsigned int backtrackCount,
- const USHORT backtrack[],
- unsigned int inputCount, /* Including the first glyph (not matched) */
- const USHORT input[], /* Array of input values--start with second glyph */
- unsigned int lookaheadCount,
- const USHORT lookahead[],
- unsigned int lookupCount,
- const LookupRecord lookupRecord[],
- ChainContextLookupContext &lookup_context)
+static inline void chain_context_closure_lookup (hb_closure_context_t *c,
+ unsigned int backtrackCount,
+ const USHORT backtrack[],
+ unsigned int inputCount, /* Including the first glyph (not matched) */
+ const USHORT input[], /* Array of input values--start with second glyph */
+ unsigned int lookaheadCount,
+ const USHORT lookahead[],
+ unsigned int lookupCount,
+ const LookupRecord lookupRecord[],
+ ChainContextClosureLookupContext &lookup_context)
{
- /* First guess */
- if (unlikely (c->buffer->backtrack_len () < backtrackCount ||
- c->buffer->idx + inputCount + lookaheadCount > c->buffer->len ||
- inputCount + lookaheadCount > c->context_length))
- return false;
+ if (intersects_array (c,
+ backtrackCount, backtrack,
+ lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+ && intersects_array (c,
+ inputCount ? inputCount - 1 : 0, input,
+ lookup_context.funcs.intersects, lookup_context.intersects_data[1])
+ && intersects_array (c,
+ lookaheadCount, lookahead,
+ lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
+ closure_lookup (c,
+ lookupCount, lookupRecord,
+ lookup_context.funcs.closure);
+}
- hb_apply_context_t new_context = *c;
+static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
+ unsigned int backtrackCount,
+ const USHORT backtrack[],
+ unsigned int inputCount, /* Including the first glyph (not matched) */
+ const USHORT input[], /* Array of input values--start with second glyph */
+ unsigned int lookaheadCount,
+ const USHORT lookahead[],
+ unsigned int lookupCount,
+ const LookupRecord lookupRecord[],
+ ChainContextApplyLookupContext &lookup_context)
+{
+ unsigned int lookahead_offset;
return match_backtrack (c,
backtrackCount, backtrack,
lookup_context.funcs.match, lookup_context.match_data[0])
&& match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data[1],
- &new_context.context_length)
+ &lookahead_offset)
&& match_lookahead (c,
lookaheadCount, lookahead,
lookup_context.funcs.match, lookup_context.match_data[2],
- new_context.context_length)
- && apply_lookup (&new_context,
+ lookahead_offset)
+ && apply_lookup (c,
inputCount,
lookupCount, lookupRecord,
lookup_context.funcs.apply);
@@ -666,30 +890,44 @@ struct ChainRule
friend struct ChainRuleSet;
private:
- inline bool apply (hb_apply_context_t *c, ChainContextLookupContext &lookup_context) const
+
+ inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
+ {
+ TRACE_CLOSURE ();
+ const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
+ const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+ chain_context_closure_lookup (c,
+ backtrack.len, backtrack.array,
+ input.len, input.array,
+ lookahead.len, lookahead.array,
+ lookup.len, lookup.array,
+ lookup_context);
+ }
+
+ inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY ();
const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
- return chain_context_lookup (c,
- backtrack.len, backtrack.array,
- input.len, input.array,
- lookahead.len, lookahead.array,
- lookup.len, lookup.array,
- lookup_context);
+ return TRACE_RETURN (chain_context_apply_lookup (c,
+ backtrack.len, backtrack.array,
+ input.len, input.array,
+ lookahead.len, lookahead.array, lookup.len,
+ lookup.array, lookup_context));
}
public:
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!backtrack.sanitize (c)) return false;
+ if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
- if (!input.sanitize (c)) return false;
+ if (!input.sanitize (c)) return TRACE_RETURN (false);
ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
- if (!lookahead.sanitize (c)) return false;
+ if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
- return lookup.sanitize (c);
+ return TRACE_RETURN (lookup.sanitize (c));
}
private:
@@ -712,22 +950,28 @@ struct ChainRule
struct ChainRuleSet
{
- inline bool apply (hb_apply_context_t *c, ChainContextLookupContext &lookup_context) const
+ inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
+ {
+ TRACE_CLOSURE ();
+ unsigned int num_rules = rule.len;
+ for (unsigned int i = 0; i < num_rules; i++)
+ (this+rule[i]).closure (c, lookup_context);
+ }
+
+ inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY ();
unsigned int num_rules = rule.len;
for (unsigned int i = 0; i < num_rules; i++)
- {
if ((this+rule[i]).apply (c, lookup_context))
- return true;
- }
+ return TRACE_RETURN (true);
- return false;
+ return TRACE_RETURN (false);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return rule.sanitize (c, this);
+ return TRACE_RETURN (rule.sanitize (c, this));
}
private:
@@ -743,25 +987,42 @@ struct ChainContextFormat1
friend struct ChainContext;
private:
+
+ inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+ {
+ TRACE_CLOSURE ();
+ const Coverage &cov = (this+coverage);
+
+ struct ChainContextClosureLookupContext lookup_context = {
+ {intersects_glyph, closure_func},
+ {NULL, NULL, NULL}
+ };
+
+ unsigned int count = ruleSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (cov.intersects_coverage (c->glyphs, i)) {
+ const ChainRuleSet &rule_set = this+ruleSet[i];
+ rule_set.closure (c, lookup_context);
+ }
+ }
+
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const ChainRuleSet &rule_set = this+ruleSet[index];
- struct ChainContextLookupContext lookup_context = {
+ struct ChainContextApplyLookupContext lookup_context = {
{match_glyph, apply_func},
{NULL, NULL, NULL}
};
- return rule_set.apply (c, lookup_context);
+ return TRACE_RETURN (rule_set.apply (c, lookup_context));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && ruleSet.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
}
private:
@@ -781,35 +1042,58 @@ struct ChainContextFormat2
friend struct ChainContext;
private:
+
+ inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+ {
+ TRACE_CLOSURE ();
+ if (!(this+coverage).intersects (c->glyphs))
+ return;
+
+ const ClassDef &backtrack_class_def = this+backtrackClassDef;
+ const ClassDef &input_class_def = this+inputClassDef;
+ const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+ struct ChainContextClosureLookupContext lookup_context = {
+ {intersects_class, closure_func},
+ {&backtrack_class_def,
+ &input_class_def,
+ &lookahead_class_def}
+ };
+
+ unsigned int count = ruleSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (input_class_def.intersects_class (c->glyphs, i)) {
+ const ChainRuleSet &rule_set = this+ruleSet[i];
+ rule_set.closure (c, lookup_context);
+ }
+ }
+
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const ClassDef &backtrack_class_def = this+backtrackClassDef;
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
- index = input_class_def (c->buffer->info[c->buffer->idx].codepoint);
+ index = input_class_def (c->buffer->cur().codepoint);
const ChainRuleSet &rule_set = this+ruleSet[index];
- struct ChainContextLookupContext lookup_context = {
+ struct ChainContextApplyLookupContext lookup_context = {
{match_class, apply_func},
{&backtrack_class_def,
&input_class_def,
&lookahead_class_def}
};
- return rule_set.apply (c, lookup_context);
+ return TRACE_RETURN (rule_set.apply (c, lookup_context));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return coverage.sanitize (c, this)
- && backtrackClassDef.sanitize (c, this)
- && inputClassDef.sanitize (c, this)
- && lookaheadClassDef.sanitize (c, this)
- && ruleSet.sanitize (c, this);
+ return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
+ inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
+ ruleSet.sanitize (c, this));
}
private:
@@ -842,38 +1126,58 @@ struct ChainContextFormat3
private:
+ inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+ {
+ TRACE_CLOSURE ();
+ const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+ if (!(this+input[0]).intersects (c->glyphs))
+ return;
+
+ const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+ struct ChainContextClosureLookupContext lookup_context = {
+ {intersects_coverage, closure_func},
+ {this, this, this}
+ };
+ chain_context_closure_lookup (c,
+ backtrack.len, (const USHORT *) backtrack.array,
+ input.len, (const USHORT *) input.array + 1,
+ lookahead.len, (const USHORT *) lookahead.array,
+ lookup.len, lookup.array,
+ lookup_context);
+ }
+
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
- unsigned int index = (this+input[0]) (c->buffer->info[c->buffer->idx].codepoint);
- if (likely (index == NOT_COVERED))
- return false;
+ unsigned int index = (this+input[0]) (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
- struct ChainContextLookupContext lookup_context = {
+ struct ChainContextApplyLookupContext lookup_context = {
{match_coverage, apply_func},
{this, this, this}
};
- return chain_context_lookup (c,
- backtrack.len, (const USHORT *) backtrack.array,
- input.len, (const USHORT *) input.array + 1,
- lookahead.len, (const USHORT *) lookahead.array,
- lookup.len, lookup.array,
- lookup_context);
+ return TRACE_RETURN (chain_context_apply_lookup (c,
+ backtrack.len, (const USHORT *) backtrack.array,
+ input.len, (const USHORT *) input.array + 1,
+ lookahead.len, (const USHORT *) lookahead.array,
+ lookup.len, lookup.array, lookup_context));
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!backtrack.sanitize (c, this)) return false;
+ if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
- if (!input.sanitize (c, this)) return false;
+ if (!input.sanitize (c, this)) return TRACE_RETURN (false);
OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
- if (!lookahead.sanitize (c, this)) return false;
+ if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
- return lookup.sanitize (c);
+ return TRACE_RETURN (lookup.sanitize (c));
}
private:
@@ -900,25 +1204,37 @@ struct ChainContextFormat3
struct ChainContext
{
protected:
+
+ inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
+ {
+ TRACE_CLOSURE ();
+ switch (u.format) {
+ case 1: u.format1.closure (c, closure_func); break;
+ case 2: u.format2.closure (c, closure_func); break;
+ case 3: u.format3.closure (c, closure_func); break;
+ default: break;
+ }
+ }
+
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
switch (u.format) {
- case 1: return u.format1.apply (c, apply_func);
- case 2: return u.format2.apply (c, apply_func);
- case 3: return u.format3.apply (c, apply_func);
- default:return false;
+ case 1: return TRACE_RETURN (u.format1.apply (c, apply_func));
+ case 2: return TRACE_RETURN (u.format2.apply (c, apply_func));
+ case 3: return TRACE_RETURN (u.format3.apply (c, apply_func));
+ default:return TRACE_RETURN (false);
}
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- case 2: return u.format2.sanitize (c);
- case 3: return u.format3.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ case 2: return TRACE_RETURN (u.format2.sanitize (c));
+ case 3: return TRACE_RETURN (u.format3.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -942,7 +1258,7 @@ struct ExtensionFormat1
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this);
+ return TRACE_RETURN (c->check_struct (this));
}
private:
@@ -975,10 +1291,10 @@ struct Extension
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- if (!u.format.sanitize (c)) return false;
+ if (!u.format.sanitize (c)) return TRACE_RETURN (false);
switch (u.format) {
- case 1: return u.format1.sanitize (c);
- default:return true;
+ case 1: return TRACE_RETURN (u.format1.sanitize (c));
+ default:return TRACE_RETURN (true);
}
}
@@ -1032,10 +1348,10 @@ struct GSUBGPOS
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return version.sanitize (c) && likely (version.major == 1)
- && scriptList.sanitize (c, this)
- && featureList.sanitize (c, this)
- && lookupList.sanitize (c, this);
+ return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
+ scriptList.sanitize (c, this) &&
+ featureList.sanitize (c, this) &&
+ lookupList.sanitize (c, this));
}
protected:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
index bf7e43b..f860e7b 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
@@ -33,6 +33,7 @@
#include "hb-font-private.hh"
#include "hb-buffer-private.hh"
+#include "hb-ot-shape-complex-private.hh"
@@ -40,9 +41,6 @@
* GDEF
*/
-/* buffer var allocations */
-#define props_cache() var1.u16[1] /* glyph_props cache */
-
/* XXX cleanup */
typedef enum {
HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED = 0x0001,
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.cc b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
index f3e0713..ded3dcc 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
@@ -460,7 +460,8 @@ hb_ot_layout_substitute_lookup (hb_face_t *face,
unsigned int lookup_index,
hb_mask_t mask)
{
- return _get_gsub (face).substitute_lookup (face, buffer, lookup_index, mask);
+ hb_apply_context_t c (NULL, face, buffer, mask);
+ return _get_gsub (face).substitute_lookup (&c, lookup_index);
}
void
@@ -469,6 +470,14 @@ hb_ot_layout_substitute_finish (hb_buffer_t *buffer HB_UNUSED)
GSUB::substitute_finish (buffer);
}
+void
+hb_ot_layout_substitute_closure_lookup (hb_face_t *face,
+ hb_set_t *glyphs,
+ unsigned int lookup_index)
+{
+ hb_closure_context_t c (face, glyphs);
+ _get_gsub (face).closure_lookup (&c, lookup_index);
+}
/*
* GPOS
@@ -492,7 +501,8 @@ hb_ot_layout_position_lookup (hb_font_t *font,
unsigned int lookup_index,
hb_mask_t mask)
{
- return _get_gpos (font->face).position_lookup (font, buffer, lookup_index, mask);
+ hb_apply_context_t c (font, font->face, buffer, mask);
+ return _get_gpos (font->face).position_lookup (&c, lookup_index);
}
void
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.h b/third_party/harfbuzz-ng/src/hb-ot-layout.h
index 447e35d..b8b5baf 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout.h
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout.h
@@ -24,12 +24,14 @@
* Red Hat Author(s): Behdad Esfahbod
*/
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
#ifndef HB_OT_LAYOUT_H
#define HB_OT_LAYOUT_H
-#include "hb-common.h"
-#include "hb-buffer.h"
-#include "hb-font.h"
+#include "hb.h"
#include "hb-ot-tag.h"
@@ -180,6 +182,12 @@ hb_ot_layout_substitute_lookup (hb_face_t *face,
void
hb_ot_layout_substitute_finish (hb_buffer_t *buffer);
+
+void
+hb_ot_layout_substitute_closure_lookup (hb_face_t *face,
+ hb_set_t *glyphs,
+ unsigned int lookup_index);
+
/*
* GPOS
*/
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
index 710cc0a..3811206 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
@@ -69,6 +69,10 @@ struct hb_ot_map_t
inline void position (hb_font_t *font, hb_buffer_t *buffer) const
{ apply (1, (hb_ot_map_t::apply_lookup_func_t) hb_ot_layout_position_lookup, font, buffer); }
+ HB_INTERNAL void substitute_closure (hb_face_t *face,
+ hb_set_t *glyphs) const;
+
+
inline void finish (void) {
features.finish ();
lookups[0].finish ();
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map.cc b/third_party/harfbuzz-ng/src/hb-ot-map.cc
index a54e306..bebf3ed 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-map.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-map.cc
@@ -95,6 +95,21 @@ void hb_ot_map_t::apply (unsigned int table_index,
apply_lookup_func (face_or_font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask);
}
+void hb_ot_map_t::substitute_closure (hb_face_t *face,
+ hb_set_t *glyphs) const
+{
+ unsigned int table_index = 0;
+ unsigned int i = 0;
+
+ for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; pause_index++) {
+ const pause_map_t *pause = &pauses[table_index][pause_index];
+ for (; i < pause->num_lookups; i++)
+ hb_ot_layout_substitute_closure_lookup (face, glyphs, lookups[table_index][i].index);
+ }
+
+ for (; i < lookups[table_index].len; i++)
+ hb_ot_layout_substitute_closure_lookup (face, glyphs, lookups[table_index][i].index);
+}
void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func, void *user_data)
{
diff --git a/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh b/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
index c3ac1c2..e270490 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -47,9 +47,8 @@ struct maxp
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this) &&
- likely (version.major == 1 ||
- (version.major == 0 && version.minor == 0x5000));
+ return TRACE_RETURN (c->check_struct (this) &&
+ likely (version.major == 1 || (version.major == 0 && version.minor == 0x5000)));
}
/* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-name-table.hh b/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
index 0e9f7a4..9077c8c 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -57,8 +57,7 @@ struct NameRecord
inline bool sanitize (hb_sanitize_context_t *c, void *base) {
TRACE_SANITIZE ();
/* We can check from base all the way up to the end of string... */
- return c->check_struct (this) &&
- c->check_range ((char *) base, (unsigned int) length + offset);
+ return TRACE_RETURN (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
}
USHORT platformID; /* Platform ID. */
@@ -102,16 +101,16 @@ struct name
char *string_pool = (char *) this + stringOffset;
unsigned int _count = count;
for (unsigned int i = 0; i < _count; i++)
- if (!nameRecord[i].sanitize (c, string_pool)) return false;
- return true;
+ if (!nameRecord[i].sanitize (c, string_pool)) return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
}
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- return c->check_struct (this) &&
- likely (format == 0 || format == 1) &&
- c->check_array (nameRecord, nameRecord[0].static_size, count) &&
- sanitize_records (c);
+ return TRACE_RETURN (c->check_struct (this) &&
+ likely (format == 0 || format == 1) &&
+ c->check_array (nameRecord, nameRecord[0].static_size, count) &&
+ sanitize_records (c));
}
/* We only implement format 0 for now. */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
index 5aa8716..df85086 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
@@ -1,46 +1,20 @@
-/*
- * Copyright © 2011 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-
-#include "hb-private.hh"
-
-
/* == Start of generated table == */
/*
* The following table is generated by running:
*
- * ./gen-arabic-table.py ArabicShaping.txt
+ * ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt
*
* on files with these headers:
*
* # ArabicShaping-6.1.0.txt
* # Date: 2011-04-15, 23:16:00 GMT [KW]
+ * UnicodeData.txt does not have a header.
*/
+
+#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
+#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
+
+
static const uint8_t joining_table[] =
{
@@ -752,7 +726,217 @@ static const uint8_t joining_table[] =
#define JOINING_TABLE_FIRST 0x0600
#define JOINING_TABLE_LAST 0x08AC
-/* == End of generated table == */
+
+static const uint16_t shaping_table[][4] =
+{
+ {0x0621, 0x0621, 0x0621, 0xFE80}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */
+ {0x0622, 0x0622, 0xFE82, 0xFE81}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
+ {0x0623, 0x0623, 0xFE84, 0xFE83}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
+ {0x0624, 0x0624, 0xFE86, 0xFE85}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
+ {0x0625, 0x0625, 0xFE88, 0xFE87}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
+ {0xFE8B, 0xFE8C, 0xFE8A, 0xFE89}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
+ {0x0627, 0x0627, 0xFE8E, 0xFE8D}, /* U+0627 ARABIC LETTER ALEF */
+ {0xFE91, 0xFE92, 0xFE90, 0xFE8F}, /* U+0628 ARABIC LETTER BEH */
+ {0x0629, 0x0629, 0xFE94, 0xFE93}, /* U+0629 ARABIC LETTER TEH MARBUTA */
+ {0xFE97, 0xFE98, 0xFE96, 0xFE95}, /* U+062A ARABIC LETTER TEH */
+ {0xFE9B, 0xFE9C, 0xFE9A, 0xFE99}, /* U+062B ARABIC LETTER THEH */
+ {0xFE9F, 0xFEA0, 0xFE9E, 0xFE9D}, /* U+062C ARABIC LETTER JEEM */
+ {0xFEA3, 0xFEA4, 0xFEA2, 0xFEA1}, /* U+062D ARABIC LETTER HAH */
+ {0xFEA7, 0xFEA8, 0xFEA6, 0xFEA5}, /* U+062E ARABIC LETTER KHAH */
+ {0x062F, 0x062F, 0xFEAA, 0xFEA9}, /* U+062F ARABIC LETTER DAL */
+ {0x0630, 0x0630, 0xFEAC, 0xFEAB}, /* U+0630 ARABIC LETTER THAL */
+ {0x0631, 0x0631, 0xFEAE, 0xFEAD}, /* U+0631 ARABIC LETTER REH */
+ {0x0632, 0x0632, 0xFEB0, 0xFEAF}, /* U+0632 ARABIC LETTER ZAIN */
+ {0xFEB3, 0xFEB4, 0xFEB2, 0xFEB1}, /* U+0633 ARABIC LETTER SEEN */
+ {0xFEB7, 0xFEB8, 0xFEB6, 0xFEB5}, /* U+0634 ARABIC LETTER SHEEN */
+ {0xFEBB, 0xFEBC, 0xFEBA, 0xFEB9}, /* U+0635 ARABIC LETTER SAD */
+ {0xFEBF, 0xFEC0, 0xFEBE, 0xFEBD}, /* U+0636 ARABIC LETTER DAD */
+ {0xFEC3, 0xFEC4, 0xFEC2, 0xFEC1}, /* U+0637 ARABIC LETTER TAH */
+ {0xFEC7, 0xFEC8, 0xFEC6, 0xFEC5}, /* U+0638 ARABIC LETTER ZAH */
+ {0xFECB, 0xFECC, 0xFECA, 0xFEC9}, /* U+0639 ARABIC LETTER AIN */
+ {0xFECF, 0xFED0, 0xFECE, 0xFECD}, /* U+063A ARABIC LETTER GHAIN */
+ {0x063B, 0x063B, 0x063B, 0x063B}, /* U+063B */
+ {0x063C, 0x063C, 0x063C, 0x063C}, /* U+063C */
+ {0x063D, 0x063D, 0x063D, 0x063D}, /* U+063D */
+ {0x063E, 0x063E, 0x063E, 0x063E}, /* U+063E */
+ {0x063F, 0x063F, 0x063F, 0x063F}, /* U+063F */
+ {0x0640, 0x0640, 0x0640, 0x0640}, /* U+0640 */
+ {0xFED3, 0xFED4, 0xFED2, 0xFED1}, /* U+0641 ARABIC LETTER FEH */
+ {0xFED7, 0xFED8, 0xFED6, 0xFED5}, /* U+0642 ARABIC LETTER QAF */
+ {0xFEDB, 0xFEDC, 0xFEDA, 0xFED9}, /* U+0643 ARABIC LETTER KAF */
+ {0xFEDF, 0xFEE0, 0xFEDE, 0xFEDD}, /* U+0644 ARABIC LETTER LAM */
+ {0xFEE3, 0xFEE4, 0xFEE2, 0xFEE1}, /* U+0645 ARABIC LETTER MEEM */
+ {0xFEE7, 0xFEE8, 0xFEE6, 0xFEE5}, /* U+0646 ARABIC LETTER NOON */
+ {0xFEEB, 0xFEEC, 0xFEEA, 0xFEE9}, /* U+0647 ARABIC LETTER HEH */
+ {0x0648, 0x0648, 0xFEEE, 0xFEED}, /* U+0648 ARABIC LETTER WAW */
+ {0xFBE8, 0xFBE9, 0xFEF0, 0xFEEF}, /* U+0649 ARABIC LETTER */
+ {0xFEF3, 0xFEF4, 0xFEF2, 0xFEF1}, /* U+064A ARABIC LETTER YEH */
+ {0x064B, 0x064B, 0x064B, 0x064B}, /* U+064B */
+ {0x064C, 0x064C, 0x064C, 0x064C}, /* U+064C */
+ {0x064D, 0x064D, 0x064D, 0x064D}, /* U+064D */
+ {0x064E, 0x064E, 0x064E, 0x064E}, /* U+064E */
+ {0x064F, 0x064F, 0x064F, 0x064F}, /* U+064F */
+ {0x0650, 0x0650, 0x0650, 0x0650}, /* U+0650 */
+ {0x0651, 0x0651, 0x0651, 0x0651}, /* U+0651 */
+ {0x0652, 0x0652, 0x0652, 0x0652}, /* U+0652 */
+ {0x0653, 0x0653, 0x0653, 0x0653}, /* U+0653 */
+ {0x0654, 0x0654, 0x0654, 0x0654}, /* U+0654 */
+ {0x0655, 0x0655, 0x0655, 0x0655}, /* U+0655 */
+ {0x0656, 0x0656, 0x0656, 0x0656}, /* U+0656 */
+ {0x0657, 0x0657, 0x0657, 0x0657}, /* U+0657 */
+ {0x0658, 0x0658, 0x0658, 0x0658}, /* U+0658 */
+ {0x0659, 0x0659, 0x0659, 0x0659}, /* U+0659 */
+ {0x065A, 0x065A, 0x065A, 0x065A}, /* U+065A */
+ {0x065B, 0x065B, 0x065B, 0x065B}, /* U+065B */
+ {0x065C, 0x065C, 0x065C, 0x065C}, /* U+065C */
+ {0x065D, 0x065D, 0x065D, 0x065D}, /* U+065D */
+ {0x065E, 0x065E, 0x065E, 0x065E}, /* U+065E */
+ {0x065F, 0x065F, 0x065F, 0x065F}, /* U+065F */
+ {0x0660, 0x0660, 0x0660, 0x0660}, /* U+0660 */
+ {0x0661, 0x0661, 0x0661, 0x0661}, /* U+0661 */
+ {0x0662, 0x0662, 0x0662, 0x0662}, /* U+0662 */
+ {0x0663, 0x0663, 0x0663, 0x0663}, /* U+0663 */
+ {0x0664, 0x0664, 0x0664, 0x0664}, /* U+0664 */
+ {0x0665, 0x0665, 0x0665, 0x0665}, /* U+0665 */
+ {0x0666, 0x0666, 0x0666, 0x0666}, /* U+0666 */
+ {0x0667, 0x0667, 0x0667, 0x0667}, /* U+0667 */
+ {0x0668, 0x0668, 0x0668, 0x0668}, /* U+0668 */
+ {0x0669, 0x0669, 0x0669, 0x0669}, /* U+0669 */
+ {0x066A, 0x066A, 0x066A, 0x066A}, /* U+066A */
+ {0x066B, 0x066B, 0x066B, 0x066B}, /* U+066B */
+ {0x066C, 0x066C, 0x066C, 0x066C}, /* U+066C */
+ {0x066D, 0x066D, 0x066D, 0x066D}, /* U+066D */
+ {0x066E, 0x066E, 0x066E, 0x066E}, /* U+066E */
+ {0x066F, 0x066F, 0x066F, 0x066F}, /* U+066F */
+ {0x0670, 0x0670, 0x0670, 0x0670}, /* U+0670 */
+ {0x0671, 0x0671, 0xFB51, 0xFB50}, /* U+0671 ARABIC LETTER ALEF WASLA */
+ {0x0672, 0x0672, 0x0672, 0x0672}, /* U+0672 */
+ {0x0673, 0x0673, 0x0673, 0x0673}, /* U+0673 */
+ {0x0674, 0x0674, 0x0674, 0x0674}, /* U+0674 */
+ {0x0675, 0x0675, 0x0675, 0x0675}, /* U+0675 */
+ {0x0676, 0x0676, 0x0676, 0x0676}, /* U+0676 */
+ {0x0677, 0x0677, 0x0677, 0xFBDD}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */
+ {0x0678, 0x0678, 0x0678, 0x0678}, /* U+0678 */
+ {0xFB68, 0xFB69, 0xFB67, 0xFB66}, /* U+0679 ARABIC LETTER TTEH */
+ {0xFB60, 0xFB61, 0xFB5F, 0xFB5E}, /* U+067A ARABIC LETTER TTEHEH */
+ {0xFB54, 0xFB55, 0xFB53, 0xFB52}, /* U+067B ARABIC LETTER BEEH */
+ {0x067C, 0x067C, 0x067C, 0x067C}, /* U+067C */
+ {0x067D, 0x067D, 0x067D, 0x067D}, /* U+067D */
+ {0xFB58, 0xFB59, 0xFB57, 0xFB56}, /* U+067E ARABIC LETTER PEH */
+ {0xFB64, 0xFB65, 0xFB63, 0xFB62}, /* U+067F ARABIC LETTER TEHEH */
+ {0xFB5C, 0xFB5D, 0xFB5B, 0xFB5A}, /* U+0680 ARABIC LETTER BEHEH */
+ {0x0681, 0x0681, 0x0681, 0x0681}, /* U+0681 */
+ {0x0682, 0x0682, 0x0682, 0x0682}, /* U+0682 */
+ {0xFB78, 0xFB79, 0xFB77, 0xFB76}, /* U+0683 ARABIC LETTER NYEH */
+ {0xFB74, 0xFB75, 0xFB73, 0xFB72}, /* U+0684 ARABIC LETTER DYEH */
+ {0x0685, 0x0685, 0x0685, 0x0685}, /* U+0685 */
+ {0xFB7C, 0xFB7D, 0xFB7B, 0xFB7A}, /* U+0686 ARABIC LETTER TCHEH */
+ {0xFB80, 0xFB81, 0xFB7F, 0xFB7E}, /* U+0687 ARABIC LETTER TCHEHEH */
+ {0x0688, 0x0688, 0xFB89, 0xFB88}, /* U+0688 ARABIC LETTER DDAL */
+ {0x0689, 0x0689, 0x0689, 0x0689}, /* U+0689 */
+ {0x068A, 0x068A, 0x068A, 0x068A}, /* U+068A */
+ {0x068B, 0x068B, 0x068B, 0x068B}, /* U+068B */
+ {0x068C, 0x068C, 0xFB85, 0xFB84}, /* U+068C ARABIC LETTER DAHAL */
+ {0x068D, 0x068D, 0xFB83, 0xFB82}, /* U+068D ARABIC LETTER DDAHAL */
+ {0x068E, 0x068E, 0xFB87, 0xFB86}, /* U+068E ARABIC LETTER DUL */
+ {0x068F, 0x068F, 0x068F, 0x068F}, /* U+068F */
+ {0x0690, 0x0690, 0x0690, 0x0690}, /* U+0690 */
+ {0x0691, 0x0691, 0xFB8D, 0xFB8C}, /* U+0691 ARABIC LETTER RREH */
+ {0x0692, 0x0692, 0x0692, 0x0692}, /* U+0692 */
+ {0x0693, 0x0693, 0x0693, 0x0693}, /* U+0693 */
+ {0x0694, 0x0694, 0x0694, 0x0694}, /* U+0694 */
+ {0x0695, 0x0695, 0x0695, 0x0695}, /* U+0695 */
+ {0x0696, 0x0696, 0x0696, 0x0696}, /* U+0696 */
+ {0x0697, 0x0697, 0x0697, 0x0697}, /* U+0697 */
+ {0x0698, 0x0698, 0xFB8B, 0xFB8A}, /* U+0698 ARABIC LETTER JEH */
+ {0x0699, 0x0699, 0x0699, 0x0699}, /* U+0699 */
+ {0x069A, 0x069A, 0x069A, 0x069A}, /* U+069A */
+ {0x069B, 0x069B, 0x069B, 0x069B}, /* U+069B */
+ {0x069C, 0x069C, 0x069C, 0x069C}, /* U+069C */
+ {0x069D, 0x069D, 0x069D, 0x069D}, /* U+069D */
+ {0x069E, 0x069E, 0x069E, 0x069E}, /* U+069E */
+ {0x069F, 0x069F, 0x069F, 0x069F}, /* U+069F */
+ {0x06A0, 0x06A0, 0x06A0, 0x06A0}, /* U+06A0 */
+ {0x06A1, 0x06A1, 0x06A1, 0x06A1}, /* U+06A1 */
+ {0x06A2, 0x06A2, 0x06A2, 0x06A2}, /* U+06A2 */
+ {0x06A3, 0x06A3, 0x06A3, 0x06A3}, /* U+06A3 */
+ {0xFB6C, 0xFB6D, 0xFB6B, 0xFB6A}, /* U+06A4 ARABIC LETTER VEH */
+ {0x06A5, 0x06A5, 0x06A5, 0x06A5}, /* U+06A5 */
+ {0xFB70, 0xFB71, 0xFB6F, 0xFB6E}, /* U+06A6 ARABIC LETTER PEHEH */
+ {0x06A7, 0x06A7, 0x06A7, 0x06A7}, /* U+06A7 */
+ {0x06A8, 0x06A8, 0x06A8, 0x06A8}, /* U+06A8 */
+ {0xFB90, 0xFB91, 0xFB8F, 0xFB8E}, /* U+06A9 ARABIC LETTER KEHEH */
+ {0x06AA, 0x06AA, 0x06AA, 0x06AA}, /* U+06AA */
+ {0x06AB, 0x06AB, 0x06AB, 0x06AB}, /* U+06AB */
+ {0x06AC, 0x06AC, 0x06AC, 0x06AC}, /* U+06AC */
+ {0xFBD5, 0xFBD6, 0xFBD4, 0xFBD3}, /* U+06AD ARABIC LETTER NG */
+ {0x06AE, 0x06AE, 0x06AE, 0x06AE}, /* U+06AE */
+ {0xFB94, 0xFB95, 0xFB93, 0xFB92}, /* U+06AF ARABIC LETTER GAF */
+ {0x06B0, 0x06B0, 0x06B0, 0x06B0}, /* U+06B0 */
+ {0xFB9C, 0xFB9D, 0xFB9B, 0xFB9A}, /* U+06B1 ARABIC LETTER NGOEH */
+ {0x06B2, 0x06B2, 0x06B2, 0x06B2}, /* U+06B2 */
+ {0xFB98, 0xFB99, 0xFB97, 0xFB96}, /* U+06B3 ARABIC LETTER GUEH */
+ {0x06B4, 0x06B4, 0x06B4, 0x06B4}, /* U+06B4 */
+ {0x06B5, 0x06B5, 0x06B5, 0x06B5}, /* U+06B5 */
+ {0x06B6, 0x06B6, 0x06B6, 0x06B6}, /* U+06B6 */
+ {0x06B7, 0x06B7, 0x06B7, 0x06B7}, /* U+06B7 */
+ {0x06B8, 0x06B8, 0x06B8, 0x06B8}, /* U+06B8 */
+ {0x06B9, 0x06B9, 0x06B9, 0x06B9}, /* U+06B9 */
+ {0x06BA, 0x06BA, 0xFB9F, 0xFB9E}, /* U+06BA ARABIC LETTER NOON GHUNNA */
+ {0xFBA2, 0xFBA3, 0xFBA1, 0xFBA0}, /* U+06BB ARABIC LETTER RNOON */
+ {0x06BC, 0x06BC, 0x06BC, 0x06BC}, /* U+06BC */
+ {0x06BD, 0x06BD, 0x06BD, 0x06BD}, /* U+06BD */
+ {0xFBAC, 0xFBAD, 0xFBAB, 0xFBAA}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
+ {0x06BF, 0x06BF, 0x06BF, 0x06BF}, /* U+06BF */
+ {0x06C0, 0x06C0, 0xFBA5, 0xFBA4}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */
+ {0xFBA8, 0xFBA9, 0xFBA7, 0xFBA6}, /* U+06C1 ARABIC LETTER HEH GOAL */
+ {0x06C2, 0x06C2, 0x06C2, 0x06C2}, /* U+06C2 */
+ {0x06C3, 0x06C3, 0x06C3, 0x06C3}, /* U+06C3 */
+ {0x06C4, 0x06C4, 0x06C4, 0x06C4}, /* U+06C4 */
+ {0x06C5, 0x06C5, 0xFBE1, 0xFBE0}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */
+ {0x06C6, 0x06C6, 0xFBDA, 0xFBD9}, /* U+06C6 ARABIC LETTER OE */
+ {0x06C7, 0x06C7, 0xFBD8, 0xFBD7}, /* U+06C7 ARABIC LETTER U */
+ {0x06C8, 0x06C8, 0xFBDC, 0xFBDB}, /* U+06C8 ARABIC LETTER YU */
+ {0x06C9, 0x06C9, 0xFBE3, 0xFBE2}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */
+ {0x06CA, 0x06CA, 0x06CA, 0x06CA}, /* U+06CA */
+ {0x06CB, 0x06CB, 0xFBDF, 0xFBDE}, /* U+06CB ARABIC LETTER VE */
+ {0xFBFE, 0xFBFF, 0xFBFD, 0xFBFC}, /* U+06CC ARABIC LETTER FARSI YEH */
+ {0x06CD, 0x06CD, 0x06CD, 0x06CD}, /* U+06CD */
+ {0x06CE, 0x06CE, 0x06CE, 0x06CE}, /* U+06CE */
+ {0x06CF, 0x06CF, 0x06CF, 0x06CF}, /* U+06CF */
+ {0xFBE6, 0xFBE7, 0xFBE5, 0xFBE4}, /* U+06D0 ARABIC LETTER E */
+ {0x06D1, 0x06D1, 0x06D1, 0x06D1}, /* U+06D1 */
+ {0x06D2, 0x06D2, 0xFBAF, 0xFBAE}, /* U+06D2 ARABIC LETTER YEH BARREE */
+ {0x06D3, 0x06D3, 0xFBB1, 0xFBB0}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */
+};
+
+#define SHAPING_TABLE_FIRST 0x0621
+#define SHAPING_TABLE_LAST 0x06D3
+
+
+static const struct {
+ uint16_t first;
+ struct {
+ uint16_t second;
+ uint16_t ligature;
+ } ligatures[4];
+} ligature_table[] =
+{
+ { 0xFEDF, {
+ { 0xFE88, 0xFEF9 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
+ { 0xFE82, 0xFEF5 }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
+ { 0xFE8E, 0xFEFB }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
+ { 0xFE84, 0xFEF7 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
+ }},
+ { 0xFEE0, {
+ { 0xFE88, 0xFEFA }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
+ { 0xFE82, 0xFEF6 }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
+ { 0xFE8E, 0xFEFC }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
+ { 0xFE84, 0xFEF8 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
+ }},
+};
#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH */
+
+/* == End of generated table == */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
index 2b863ef..54460f0 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
@@ -25,11 +25,12 @@
*/
#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-private.hh"
/* buffer var allocations */
-#define arabic_shaping_action() complex_var_temporary_u16() /* arabic shaping action */
+#define arabic_shaping_action() complex_var_temporary_u8() /* arabic shaping action */
/*
@@ -58,8 +59,6 @@ enum {
static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
{
- /* TODO Macroize the magic bit operations */
-
if (likely (hb_in_range<hb_codepoint_t> (u, JOINING_TABLE_FIRST, JOINING_TABLE_LAST))) {
unsigned int j_type = joining_table[u - JOINING_TABLE_FIRST];
if (likely (j_type != JOINING_TYPE_X))
@@ -82,7 +81,23 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_categ
JOINING_TYPE_T : JOINING_TYPE_U;
}
+static hb_codepoint_t get_arabic_shape (hb_codepoint_t u, unsigned int shape)
+{
+ if (likely (hb_in_range<hb_codepoint_t> (u, SHAPING_TABLE_FIRST, SHAPING_TABLE_LAST)) && shape < 4)
+ return shaping_table[u - SHAPING_TABLE_FIRST][shape];
+ return u;
+}
+static uint16_t get_ligature (hb_codepoint_t first, hb_codepoint_t second)
+{
+ if (unlikely (!second)) return 0;
+ for (unsigned i = 0; i < ARRAY_LENGTH (ligature_table); i++)
+ if (ligature_table[i].first == first)
+ for (unsigned j = 0; j < ARRAY_LENGTH (ligature_table[i].ligatures); j++)
+ if (ligature_table[i].ligatures[j].second == second)
+ return ligature_table[i].ligatures[j].ligature;
+ return 0;
+}
static const hb_tag_t arabic_syriac_features[] =
{
@@ -150,7 +165,8 @@ static const struct arabic_state_table_entry {
void
-_hb_ot_shape_complex_collect_features_arabic (hb_ot_map_builder_t *map, const hb_segment_properties_t *props)
+_hb_ot_shape_complex_collect_features_arabic (hb_ot_map_builder_t *map,
+ const hb_segment_properties_t *props)
{
/* For Language forms (in ArabicOT speak), we do the iso/fina/medi/init together,
* then rlig and calt each in their own stage. This makes IranNastaliq's ALLAH
@@ -183,14 +199,51 @@ _hb_ot_shape_complex_collect_features_arabic (hb_ot_map_builder_t *map, const hb
map->add_bool_feature (HB_TAG('c','s','w','h'));
}
-bool
-_hb_ot_shape_complex_prefer_decomposed_arabic (void)
+hb_ot_shape_normalization_mode_t
+_hb_ot_shape_complex_normalization_preference_arabic (void)
{
- return FALSE;
+ return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
+}
+
+
+static void
+arabic_fallback_shape (hb_font_t *font, hb_buffer_t *buffer)
+{
+ unsigned int count = buffer->len;
+ hb_codepoint_t glyph;
+
+ /* Shape to presentation forms */
+ for (unsigned int i = 0; i < count; i++) {
+ hb_codepoint_t u = buffer->info[i].codepoint;
+ hb_codepoint_t shaped = get_arabic_shape (u, buffer->info[i].arabic_shaping_action());
+ if (shaped != u && hb_font_get_glyph (font, shaped, 0, &glyph))
+ buffer->info[i].codepoint = shaped;
+ }
+
+ /* Mandatory ligatures */
+ buffer->clear_output ();
+ for (buffer->idx = 0; buffer->idx + 1 < count;) {
+ hb_codepoint_t ligature = get_ligature (buffer->cur().codepoint,
+ buffer->cur(+1).codepoint);
+ if (likely (!ligature) || !(hb_font_get_glyph (font, ligature, 0, &glyph))) {
+ buffer->next_glyph ();
+ continue;
+ }
+
+ buffer->replace_glyphs (2, 1, &ligature);
+
+ /* Technically speaking we can skip marks and stuff, like the GSUB path does.
+ * But who cares, we're in fallback! */
+ }
+ for (; buffer->idx < count;)
+ buffer->next_glyph ();
+ buffer->swap_buffers ();
}
void
-_hb_ot_shape_complex_setup_masks_arabic (hb_ot_map_t *map, hb_buffer_t *buffer)
+_hb_ot_shape_complex_setup_masks_arabic (hb_ot_map_t *map,
+ hb_buffer_t *buffer,
+ hb_font_t *font)
{
unsigned int count = buffer->len;
unsigned int prev = 0, state = 0;
@@ -199,7 +252,7 @@ _hb_ot_shape_complex_setup_masks_arabic (hb_ot_map_t *map, hb_buffer_t *buffer)
for (unsigned int i = 0; i < count; i++)
{
- unsigned int this_type = get_joining_type (buffer->info[i].codepoint, (hb_unicode_general_category_t) buffer->info[i].general_category());
+ unsigned int this_type = get_joining_type (buffer->info[i].codepoint, _hb_glyph_info_get_general_category (&buffer->info[i]));
if (unlikely (this_type == JOINING_TYPE_T)) {
buffer->info[i].arabic_shaping_action() = NONE;
@@ -218,12 +271,27 @@ _hb_ot_shape_complex_setup_masks_arabic (hb_ot_map_t *map, hb_buffer_t *buffer)
}
hb_mask_t mask_array[TOTAL_NUM_FEATURES + 1] = {0};
+ hb_mask_t total_masks = 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++)
+ for (unsigned int i = 0; i < num_masks; i++) {
mask_array[i] = map->get_1_mask (arabic_syriac_features[i]);
+ total_masks |= mask_array[i];
+ }
- for (unsigned int i = 0; i < count; i++)
- buffer->info[i].mask |= mask_array[buffer->info[i].arabic_shaping_action()];
+ if (total_masks) {
+ /* Has OpenType tables */
+ for (unsigned int i = 0; i < count; i++)
+ buffer->info[i].mask |= mask_array[buffer->info[i].arabic_shaping_action()];
+ } else if (buffer->props.script == HB_SCRIPT_ARABIC) {
+ /* Fallback Arabic shaping to Presentation Forms */
+ /* Pitfalls:
+ * - This path fires if user force-set init/medi/fina/isol off,
+ * - If font does not declare script 'arab', well, what to do?
+ * Most probably it's safe to assume that init/medi/fina/isol
+ * still mean Arabic shaping, although they do not have to.
+ */
+ arabic_fallback_shape (font, buffer);
+ }
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
index 5c42355..0e9a53d 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
@@ -1,7 +1,7 @@
#line 1 "hb-ot-shape-complex-indic-machine.rl"
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -36,174 +36,154 @@ HB_BEGIN_DECLS
#line 38 "hb-ot-shape-complex-indic-machine.hh.tmp"
static const unsigned char _indic_syllable_machine_trans_keys[] = {
- 0u, 0u, 5u, 5u, 1u, 2u, 1u, 2u, 5u, 5u, 1u, 5u, 5u, 5u, 1u, 2u,
- 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u,
- 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u,
- 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u,
- 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u,
- 0u, 12u, 0
+ 5u, 5u, 1u, 2u, 1u, 2u, 5u, 5u, 1u, 5u, 1u, 2u, 5u, 5u, 1u, 13u,
+ 4u, 11u, 4u, 11u, 5u, 11u, 1u, 10u, 1u, 10u, 10u, 10u, 10u, 10u, 4u, 10u,
+ 5u, 10u, 8u, 10u, 5u, 10u, 6u, 10u, 9u, 10u, 4u, 11u, 1u, 13u, 4u, 10u,
+ 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 8u, 10u, 10u, 10u, 10u, 10u, 4u, 10u,
+ 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 8u, 10u, 10u, 10u, 10u, 10u, 0
};
static const char _indic_syllable_machine_key_spans[] = {
- 0, 1, 2, 2, 1, 5, 1, 2,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13
+ 1, 2, 2, 1, 5, 2, 1, 13,
+ 8, 8, 7, 10, 10, 1, 1, 7,
+ 6, 3, 6, 5, 2, 8, 13, 7,
+ 7, 6, 7, 6, 3, 1, 1, 7,
+ 7, 6, 7, 6, 3, 1, 1
};
-static const short _indic_syllable_machine_index_offsets[] = {
- 0, 0, 2, 5, 8, 10, 16, 18,
- 21, 35, 49, 63, 77, 91, 105, 119,
- 133, 147, 161, 175, 189, 203, 217, 231,
- 245, 259, 273, 287, 301, 315, 329, 343,
- 357, 371, 385, 399, 413, 427, 441, 455,
- 469
+static const unsigned char _indic_syllable_machine_index_offsets[] = {
+ 0, 2, 5, 8, 10, 16, 19, 21,
+ 35, 44, 53, 61, 72, 83, 85, 87,
+ 95, 102, 106, 113, 119, 122, 131, 145,
+ 153, 161, 168, 176, 183, 187, 189, 191,
+ 199, 207, 214, 222, 229, 233, 235
};
static const char _indic_syllable_machine_indicies[] = {
- 0, 1, 2, 2, 1, 3, 3,
- 1, 4, 1, 2, 2, 1, 1, 0,
- 1, 5, 1, 6, 6, 1, 7, 6,
- 8, 9, 1, 1, 1, 1, 1, 1,
- 1, 1, 10, 1, 11, 12, 13, 14,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 15, 1, 16, 17, 18, 19, 20, 21,
- 22, 22, 23, 24, 25, 26, 27, 1,
- 16, 17, 18, 19, 20, 28, 22, 22,
- 23, 24, 25, 26, 27, 1, 29, 30,
- 31, 32, 33, 1, 34, 35, 36, 37,
- 38, 1, 39, 1, 29, 30, 31, 32,
- 1, 1, 34, 35, 36, 37, 38, 1,
- 39, 1, 29, 30, 31, 32, 1, 1,
- 1, 1, 36, 37, 38, 1, 39, 1,
- 29, 30, 31, 32, 40, 2, 1, 1,
- 36, 37, 38, 1, 39, 1, 29, 30,
- 31, 32, 1, 2, 1, 1, 36, 37,
- 38, 1, 39, 1, 29, 30, 31, 32,
- 1, 1, 1, 1, 1, 1, 38, 1,
- 39, 1, 29, 30, 31, 32, 1, 1,
- 1, 1, 1, 1, 41, 1, 39, 1,
- 29, 30, 31, 32, 1, 1, 1, 1,
- 1, 1, 1, 1, 39, 1, 42, 43,
- 44, 45, 46, 4, 47, 47, 48, 49,
- 50, 1, 51, 1, 42, 43, 44, 45,
- 1, 4, 47, 47, 48, 49, 50, 1,
- 51, 1, 42, 43, 44, 45, 1, 1,
- 1, 1, 48, 49, 50, 1, 51, 1,
- 42, 43, 44, 45, 52, 3, 1, 1,
- 48, 49, 50, 1, 51, 1, 42, 43,
- 44, 45, 1, 3, 1, 1, 48, 49,
- 50, 1, 51, 1, 42, 43, 44, 45,
- 1, 1, 1, 1, 1, 1, 50, 1,
- 51, 1, 42, 43, 44, 45, 1, 1,
- 1, 1, 1, 1, 53, 1, 51, 1,
- 42, 43, 44, 45, 1, 1, 1, 1,
- 1, 1, 1, 1, 51, 1, 16, 17,
- 18, 19, 1, 21, 22, 22, 23, 24,
- 25, 26, 27, 1, 16, 6, 6, 19,
- 1, 1, 54, 54, 1, 24, 25, 1,
- 27, 1, 16, 6, 6, 19, 1, 1,
- 1, 1, 1, 24, 25, 1, 27, 1,
- 16, 17, 18, 19, 1, 1, 1, 1,
- 1, 1, 25, 1, 27, 1, 16, 17,
- 18, 19, 1, 1, 1, 1, 1, 1,
- 55, 1, 27, 1, 16, 17, 18, 19,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 27, 1, 16, 17, 18, 19, 56, 57,
- 1, 1, 23, 24, 25, 1, 27, 1,
- 16, 17, 18, 19, 1, 57, 1, 1,
- 23, 24, 25, 1, 27, 1, 16, 17,
- 18, 19, 1, 1, 1, 1, 23, 24,
- 25, 1, 27, 1, 16, 17, 18, 19,
- 1, 58, 1, 1, 23, 24, 25, 1,
- 27, 1, 16, 17, 18, 19, 1, 1,
- 59, 59, 1, 24, 25, 1, 27, 1,
- 16, 17, 18, 19, 1, 1, 1, 1,
- 1, 24, 25, 1, 27, 1, 16, 6,
- 6, 9, 1, 1, 54, 54, 1, 24,
- 25, 1, 10, 1, 0
+ 1, 0, 2, 2, 0, 4, 4, 3,
+ 5, 3, 4, 4, 3, 3, 5, 3,
+ 7, 7, 6, 8, 6, 2, 10, 11,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 12, 12, 9, 14, 15, 16, 16, 17,
+ 18, 19, 20, 13, 21, 15, 16, 16,
+ 17, 18, 19, 20, 13, 15, 16, 16,
+ 17, 18, 19, 20, 13, 2, 2, 13,
+ 13, 13, 22, 22, 13, 18, 19, 13,
+ 2, 2, 13, 13, 13, 13, 13, 13,
+ 18, 19, 13, 19, 13, 23, 13, 24,
+ 25, 13, 13, 17, 18, 19, 13, 25,
+ 13, 13, 17, 18, 19, 13, 17, 18,
+ 19, 13, 26, 13, 13, 17, 18, 19,
+ 13, 27, 27, 13, 18, 19, 13, 18,
+ 19, 13, 14, 28, 16, 16, 17, 18,
+ 19, 20, 13, 2, 2, 11, 13, 13,
+ 22, 22, 13, 18, 19, 13, 12, 12,
+ 13, 30, 5, 31, 32, 33, 34, 35,
+ 29, 4, 5, 31, 32, 33, 34, 35,
+ 29, 5, 31, 32, 33, 34, 35, 29,
+ 36, 37, 29, 29, 33, 34, 35, 29,
+ 37, 29, 29, 33, 34, 35, 29, 33,
+ 34, 35, 29, 35, 29, 38, 29, 40,
+ 8, 41, 41, 42, 43, 44, 39, 7,
+ 8, 41, 41, 42, 43, 44, 39, 8,
+ 41, 41, 42, 43, 44, 39, 45, 46,
+ 39, 39, 42, 43, 44, 39, 46, 39,
+ 39, 42, 43, 44, 39, 42, 43, 44,
+ 39, 44, 39, 47, 39, 0
};
static const char _indic_syllable_machine_trans_targs[] = {
- 2, 0, 14, 22, 3, 7, 10, 9,
- 11, 12, 20, 9, 10, 11, 12, 20,
- 9, 10, 11, 12, 28, 29, 6, 34,
- 31, 32, 37, 20, 40, 9, 10, 11,
- 12, 13, 1, 5, 15, 17, 18, 20,
- 16, 19, 9, 10, 11, 12, 21, 4,
- 23, 25, 26, 20, 24, 27, 30, 33,
- 35, 36, 38, 39
+ 7, 1, 8, 7, 25, 2, 7, 33,
+ 5, 7, 21, 23, 31, 7, 9, 11,
+ 0, 15, 13, 14, 18, 10, 12, 7,
+ 16, 17, 19, 20, 22, 7, 24, 3,
+ 4, 26, 29, 30, 27, 28, 7, 7,
+ 32, 6, 34, 37, 38, 35, 36, 7
};
static const char _indic_syllable_machine_trans_actions[] = {
+ 1, 0, 2, 3, 2, 0, 4, 2,
+ 0, 7, 2, 2, 2, 8, 2, 0,
+ 0, 0, 0, 0, 0, 2, 0, 9,
+ 0, 0, 0, 0, 0, 10, 2, 0,
+ 0, 0, 0, 0, 0, 0, 11, 12,
+ 2, 0, 0, 0, 0, 0, 0, 13
+};
+
+static const char _indic_syllable_machine_to_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1,
- 2, 2, 2, 2, 0, 0, 0, 0,
- 0, 0, 0, 2, 0, 3, 3, 3,
- 3, 0, 0, 0, 0, 0, 0, 3,
- 0, 0, 4, 4, 4, 4, 0, 0,
- 0, 0, 0, 4, 0, 0, 0, 0,
- 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
};
-static const char _indic_syllable_machine_eof_actions[] = {
+static const char _indic_syllable_machine_from_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 2, 3, 3, 3, 3,
- 3, 3, 3, 3, 4, 4, 4, 4,
- 4, 4, 4, 4, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2
+ 0, 0, 0, 0, 0, 0, 0
};
-static const int indic_syllable_machine_start = 8;
-static const int indic_syllable_machine_first_final = 8;
-static const int indic_syllable_machine_error = 0;
+static const unsigned char _indic_syllable_machine_eof_trans[] = {
+ 1, 1, 4, 4, 4, 7, 7, 0,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 30,
+ 30, 30, 30, 30, 30, 30, 30, 40,
+ 40, 40, 40, 40, 40, 40, 40
+};
+
+static const int indic_syllable_machine_start = 7;
+static const int indic_syllable_machine_first_final = 7;
+static const int indic_syllable_machine_error = -1;
-static const int indic_syllable_machine_en_main = 8;
+static const int indic_syllable_machine_en_main = 7;
#line 38 "hb-ot-shape-complex-indic-machine.rl"
-#line 83 "hb-ot-shape-complex-indic-machine.rl"
+#line 79 "hb-ot-shape-complex-indic-machine.rl"
-
-static void
-set_cluster (hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- unsigned int cluster = buffer->info[start].cluster;
-
- for (unsigned int i = start + 1; i < end; i++)
- cluster = MIN (cluster, buffer->info[i].cluster);
- for (unsigned int i = start; i < end; i++)
- buffer->info[i].cluster = cluster;
-}
+#define process_syllable(func) \
+ HB_STMT_START { \
+ /* fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #func); */ \
+ for (unsigned int i = last; i < p+1; i++) \
+ info[i].syllable() = syllable_serial; \
+ PASTE (initial_reordering_, func) (map, buffer, mask_array, last, p+1); \
+ last = p+1; \
+ syllable_serial++; \
+ if (unlikely (!syllable_serial)) syllable_serial++; \
+ } HB_STMT_END
static void
find_syllables (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array)
{
- unsigned int p, pe, eof;
+ unsigned int p, pe, eof, ts, te, act;
int cs;
+ hb_glyph_info_t *info = buffer->info;
-#line 194 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 170 "hb-ot-shape-complex-indic-machine.hh.tmp"
{
cs = indic_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
}
-#line 106 "hb-ot-shape-complex-indic-machine.rl"
+#line 101 "hb-ot-shape-complex-indic-machine.rl"
p = 0;
pe = eof = buffer->len;
unsigned int last = 0;
+ uint8_t syllable_serial = 1;
-#line 207 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 187 "hb-ot-shape-complex-indic-machine.hh.tmp"
{
int _slen;
int _trans;
@@ -211,17 +191,24 @@ find_syllables (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_arr
const char *_inds;
if ( p == pe )
goto _test_eof;
- if ( cs == 0 )
- goto _out;
_resume:
+ switch ( _indic_syllable_machine_from_state_actions[cs] ) {
+ case 6:
+#line 1 "hb-ot-shape-complex-indic-machine.rl"
+ {ts = p;}
+ break;
+#line 201 "hb-ot-shape-complex-indic-machine.hh.tmp"
+ }
+
_keys = _indic_syllable_machine_trans_keys + (cs<<1);
_inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
_slen = _indic_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( buffer->info[p].indic_category()) &&
- ( buffer->info[p].indic_category()) <= _keys[1] ?
- ( buffer->info[p].indic_category()) - _keys[0] : _slen ];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
+ ( info[p].indic_category()) <= _keys[1] ?
+ ( info[p].indic_category()) - _keys[0] : _slen ];
+_eof_trans:
cs = _indic_syllable_machine_trans_targs[_trans];
if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
@@ -229,73 +216,75 @@ _resume:
switch ( _indic_syllable_machine_trans_actions[_trans] ) {
case 2:
-#line 62 "hb-ot-shape-complex-indic-machine.rl"
- { found_consonant_syllable (map, buffer, mask_array, last, p); }
-#line 67 "hb-ot-shape-complex-indic-machine.rl"
- { set_cluster (buffer, p, last); last = p; }
+#line 1 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p+1;}
break;
- case 3:
-#line 63 "hb-ot-shape-complex-indic-machine.rl"
- { found_vowel_syllable (map, buffer, mask_array, last, p); }
-#line 67 "hb-ot-shape-complex-indic-machine.rl"
- { set_cluster (buffer, p, last); last = p; }
+ case 9:
+#line 72 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p+1;{ process_syllable (consonant_syllable); }}
break;
- case 4:
-#line 64 "hb-ot-shape-complex-indic-machine.rl"
- { found_standalone_cluster (map, buffer, mask_array, last, p); }
-#line 67 "hb-ot-shape-complex-indic-machine.rl"
- { set_cluster (buffer, p, last); last = p; }
+ case 11:
+#line 73 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p+1;{ process_syllable (vowel_syllable); }}
+ break;
+ case 13:
+#line 74 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p+1;{ process_syllable (standalone_cluster); }}
+ break;
+ case 7:
+#line 75 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p+1;{ process_syllable (non_indic); }}
+ break;
+ case 8:
+#line 72 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ process_syllable (consonant_syllable); }}
+ break;
+ case 10:
+#line 73 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ process_syllable (vowel_syllable); }}
+ break;
+ case 12:
+#line 74 "hb-ot-shape-complex-indic-machine.rl"
+ {te = p;p--;{ process_syllable (standalone_cluster); }}
break;
case 1:
-#line 65 "hb-ot-shape-complex-indic-machine.rl"
- { found_non_indic (map, buffer, mask_array, last, p); }
-#line 67 "hb-ot-shape-complex-indic-machine.rl"
- { set_cluster (buffer, p, last); last = p; }
+#line 72 "hb-ot-shape-complex-indic-machine.rl"
+ {{p = ((te))-1;}{ process_syllable (consonant_syllable); }}
+ break;
+ case 3:
+#line 73 "hb-ot-shape-complex-indic-machine.rl"
+ {{p = ((te))-1;}{ process_syllable (vowel_syllable); }}
+ break;
+ case 4:
+#line 74 "hb-ot-shape-complex-indic-machine.rl"
+ {{p = ((te))-1;}{ process_syllable (standalone_cluster); }}
break;
-#line 256 "hb-ot-shape-complex-indic-machine.hh.tmp"
+#line 263 "hb-ot-shape-complex-indic-machine.hh.tmp"
}
_again:
- if ( cs == 0 )
- goto _out;
+ switch ( _indic_syllable_machine_to_state_actions[cs] ) {
+ case 5:
+#line 1 "hb-ot-shape-complex-indic-machine.rl"
+ {ts = 0;}
+ break;
+#line 272 "hb-ot-shape-complex-indic-machine.hh.tmp"
+ }
+
if ( ++p != pe )
goto _resume;
_test_eof: {}
if ( p == eof )
{
- switch ( _indic_syllable_machine_eof_actions[cs] ) {
- case 2:
-#line 62 "hb-ot-shape-complex-indic-machine.rl"
- { found_consonant_syllable (map, buffer, mask_array, last, p); }
-#line 67 "hb-ot-shape-complex-indic-machine.rl"
- { set_cluster (buffer, p, last); last = p; }
- break;
- case 3:
-#line 63 "hb-ot-shape-complex-indic-machine.rl"
- { found_vowel_syllable (map, buffer, mask_array, last, p); }
-#line 67 "hb-ot-shape-complex-indic-machine.rl"
- { set_cluster (buffer, p, last); last = p; }
- break;
- case 4:
-#line 64 "hb-ot-shape-complex-indic-machine.rl"
- { found_standalone_cluster (map, buffer, mask_array, last, p); }
-#line 67 "hb-ot-shape-complex-indic-machine.rl"
- { set_cluster (buffer, p, last); last = p; }
- break;
- case 1:
-#line 65 "hb-ot-shape-complex-indic-machine.rl"
- { found_non_indic (map, buffer, mask_array, last, p); }
-#line 67 "hb-ot-shape-complex-indic-machine.rl"
- { set_cluster (buffer, p, last); last = p; }
- break;
-#line 292 "hb-ot-shape-complex-indic-machine.hh.tmp"
+ if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _indic_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
}
}
- _out: {}
}
-#line 114 "hb-ot-shape-complex-indic-machine.rl"
+#line 110 "hb-ot-shape-complex-indic-machine.rl"
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh
new file mode 100644
index 0000000..64af0da
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh
@@ -0,0 +1,270 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
+#define HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
+
+#include "hb-private.hh"
+
+
+#include "hb-ot-shape-complex-private.hh"
+
+
+/* buffer var allocations */
+#define indic_category() complex_var_persistent_u8_0() /* indic_category_t */
+#define indic_position() complex_var_persistent_u8_1() /* indic_matra_category_t */
+
+#define INDIC_TABLE_ELEMENT_TYPE uint8_t
+
+/* Cateories used in the OpenType spec:
+ * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx
+ */
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum indic_category_t {
+ OT_X = 0,
+ OT_C,
+ OT_Ra, /* Not explicitly listed in the OT spec, but used in the grammar. */
+ OT_V,
+ OT_N,
+ OT_H,
+ OT_ZWNJ,
+ OT_ZWJ,
+ OT_M,
+ OT_SM,
+ OT_VD,
+ OT_A,
+ OT_NBSP,
+ OT_DOTTEDCIRCLE /* Not in the spec, but special in Uniscribe. /Very very/ special! */
+};
+
+/* Visual positions in a syllable from left to right. */
+enum indic_position_t {
+ POS_RA_TO_BECOME_REPH,
+ POS_PRE_M,
+ POS_PRE_C,
+ POS_BASE_C,
+ POS_ABOVE_C,
+ POS_BELOW_C,
+ POS_ABOVE_M,
+ POS_BELOW_M,
+ POS_POST_C,
+ POS_POST_M,
+ POS_SMVD
+};
+
+/* Categories used in IndicSyllabicCategory.txt from UCD. */
+enum indic_syllabic_category_t {
+ INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
+
+ INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_X,
+ INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA = OT_C,
+ INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
+ INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
+ INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_X,
+ INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
+ INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_X,
+ INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
+ INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM,
+ INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V,
+ INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M,
+ INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V
+};
+
+/* Categories used in IndicSMatraCategory.txt from UCD */
+enum indic_matra_category_t {
+ INDIC_MATRA_CATEGORY_NOT_APPLICABLE = POS_BASE_C,
+
+ INDIC_MATRA_CATEGORY_LEFT = POS_PRE_M,
+ INDIC_MATRA_CATEGORY_TOP = POS_ABOVE_M,
+ INDIC_MATRA_CATEGORY_BOTTOM = POS_BELOW_M,
+ INDIC_MATRA_CATEGORY_RIGHT = POS_POST_M,
+
+ /* We don't really care much about these since we decompose them
+ * in the generic pre-shaping layer. They will only be used if
+ * the font does not cover the decomposition. In which case, we
+ * define these as aliases to the place we want the split-matra
+ * glyph to show up. Quite arbitrary.
+ *
+ * TODO: There are some split matras without Unicode decompositions.
+ * We have to figure out what to do with them.
+ */
+ INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT = POS_POST_M,
+ INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT = POS_PRE_M,
+ INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM = POS_BELOW_M,
+ INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT = POS_POST_M,
+ INDIC_MATRA_CATEGORY_TOP_AND_LEFT = POS_PRE_M,
+ INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = POS_PRE_M,
+ INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = POS_POST_M,
+
+ INDIC_MATRA_CATEGORY_INVISIBLE = INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
+ INDIC_MATRA_CATEGORY_OVERSTRUCK = INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
+ INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = INDIC_MATRA_CATEGORY_NOT_APPLICABLE
+};
+
+/* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and the comma operation
+ * because gcc fails to optimize the latter and fills the table in at runtime. */
+#define INDIC_COMBINE_CATEGORIES(S,M) \
+ (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || (S == INDIC_SYLLABIC_CATEGORY_VIRAMA || S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT)) + \
+ ASSERT_STATIC_EXPR_ZERO (S < 16 && M < 16) + \
+ ((M << 4) | S))
+
+
+#include "hb-ot-shape-complex-indic-table.hh"
+
+/* XXX
+ * This is a hack for now. We should:
+ * 1. Move this data into the main Indic table,
+ * and/or
+ * 2. Probe font lookups to determine consonant positions.
+ */
+static const struct consonant_position_t {
+ hb_codepoint_t u;
+ indic_position_t position;
+} consonant_positions[] = {
+ {0x0930, POS_BELOW_C},
+ {0x09AC, POS_BELOW_C},
+ {0x09AF, POS_POST_C},
+ {0x09B0, POS_BELOW_C},
+ {0x09F0, POS_BELOW_C},
+ {0x0A2F, POS_POST_C},
+ {0x0A30, POS_BELOW_C},
+ {0x0A35, POS_BELOW_C},
+ {0x0A39, POS_BELOW_C},
+ {0x0AB0, POS_BELOW_C},
+ {0x0B24, POS_BELOW_C},
+ {0x0B28, POS_BELOW_C},
+ {0x0B2C, POS_BELOW_C},
+ {0x0B2D, POS_BELOW_C},
+ {0x0B2E, POS_BELOW_C},
+ {0x0B2F, POS_POST_C},
+ {0x0B30, POS_BELOW_C},
+ {0x0B32, POS_BELOW_C},
+ {0x0B33, POS_BELOW_C},
+ {0x0B5F, POS_POST_C},
+ {0x0B71, POS_BELOW_C},
+ {0x0C15, POS_BELOW_C},
+ {0x0C16, POS_BELOW_C},
+ {0x0C17, POS_BELOW_C},
+ {0x0C18, POS_BELOW_C},
+ {0x0C19, POS_BELOW_C},
+ {0x0C1A, POS_BELOW_C},
+ {0x0C1B, POS_BELOW_C},
+ {0x0C1C, POS_BELOW_C},
+ {0x0C1D, POS_BELOW_C},
+ {0x0C1E, POS_BELOW_C},
+ {0x0C1F, POS_BELOW_C},
+ {0x0C20, POS_BELOW_C},
+ {0x0C21, POS_BELOW_C},
+ {0x0C22, POS_BELOW_C},
+ {0x0C23, POS_BELOW_C},
+ {0x0C24, POS_BELOW_C},
+ {0x0C25, POS_BELOW_C},
+ {0x0C26, POS_BELOW_C},
+ {0x0C27, POS_BELOW_C},
+ {0x0C28, POS_BELOW_C},
+ {0x0C2A, POS_BELOW_C},
+ {0x0C2B, POS_BELOW_C},
+ {0x0C2C, POS_BELOW_C},
+ {0x0C2D, POS_BELOW_C},
+ {0x0C2E, POS_BELOW_C},
+ {0x0C2F, POS_BELOW_C},
+ {0x0C30, POS_BELOW_C},
+ {0x0C32, POS_BELOW_C},
+ {0x0C33, POS_BELOW_C},
+ {0x0C35, POS_BELOW_C},
+ {0x0C36, POS_BELOW_C},
+ {0x0C37, POS_BELOW_C},
+ {0x0C38, POS_BELOW_C},
+ {0x0C39, POS_BELOW_C},
+ {0x0C95, POS_BELOW_C},
+ {0x0C96, POS_BELOW_C},
+ {0x0C97, POS_BELOW_C},
+ {0x0C98, POS_BELOW_C},
+ {0x0C99, POS_BELOW_C},
+ {0x0C9A, POS_BELOW_C},
+ {0x0C9B, POS_BELOW_C},
+ {0x0C9C, POS_BELOW_C},
+ {0x0C9D, POS_BELOW_C},
+ {0x0C9E, POS_BELOW_C},
+ {0x0C9F, POS_BELOW_C},
+ {0x0CA0, POS_BELOW_C},
+ {0x0CA1, POS_BELOW_C},
+ {0x0CA2, POS_BELOW_C},
+ {0x0CA3, POS_BELOW_C},
+ {0x0CA4, POS_BELOW_C},
+ {0x0CA5, POS_BELOW_C},
+ {0x0CA6, POS_BELOW_C},
+ {0x0CA7, POS_BELOW_C},
+ {0x0CA8, POS_BELOW_C},
+ {0x0CAA, POS_BELOW_C},
+ {0x0CAB, POS_BELOW_C},
+ {0x0CAC, POS_BELOW_C},
+ {0x0CAD, POS_BELOW_C},
+ {0x0CAE, POS_BELOW_C},
+ {0x0CAF, POS_BELOW_C},
+ {0x0CB0, POS_BELOW_C},
+ {0x0CB2, POS_BELOW_C},
+ {0x0CB3, POS_BELOW_C},
+ {0x0CB5, POS_BELOW_C},
+ {0x0CB6, POS_BELOW_C},
+ {0x0CB7, POS_BELOW_C},
+ {0x0CB8, POS_BELOW_C},
+ {0x0CB9, POS_BELOW_C},
+ {0x0CDE, POS_BELOW_C},
+ {0x0D2F, POS_POST_C},
+ {0x0D30, POS_POST_C},
+ {0x0D32, POS_BELOW_C},
+ {0x0D35, POS_POST_C},
+};
+
+/* XXX
+ * This is a hack for now. We should move this data into the main Indic table.
+ * Or completely remove it and just check in the tables.
+ */
+static const hb_codepoint_t ra_chars[] = {
+ 0x0930, /* Devanagari */
+ 0x09B0, /* Bengali */
+ 0x09F0, /* Bengali */
+ 0x0A30, /* Gurmukhi */ /* No Reph */
+ 0x0AB0, /* Gujarati */
+ 0x0B30, /* Oriya */
+ 0x0BB0, /* Tamil */ /* No Reph */
+ 0x0C30, /* Telugu */ /* No Reph */
+ 0x0CB0, /* Kannada */
+ 0x0D30, /* Malayalam */ /* No Reph */
+};
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh
index 5077e8a..5b4b344 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh
@@ -1,35 +1,3 @@
-/*
- * Copyright © 2011 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH
-
-#include "hb-private.hh"
-
-
/* == Start of generated table == */
/*
* The following table is generated by running:
@@ -38,57 +6,60 @@
*
* on files with these headers:
*
- * # IndicSyllabicCategory-6.0.0.txt
- * # Date: 2010-05-25, 11:45:00 PDT [KW]
- * # IndicMatraCategory-6.0.0.txt
- * # Date: 2010-07-14, 15:03:00 PDT [KW]
- * # Blocks-6.0.0.txt
- * # Date: 2010-06-04, 11:12:00 PDT [KW]
+ * # IndicSyllabicCategory-6.1.0.txt
+ * # Date: 2011-08-31, 23:54:00 GMT [KW]
+ * # IndicMatraCategory-6.1.0.txt
+ * # Date: 2011-08-31, 23:50:00 GMT [KW]
+ * # Blocks-6.1.0.txt
+ * # Date: 2011-06-14, 18:26:00 GMT [KW, LI]
*/
+#ifndef HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH
+#define HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH
-#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 9 chars; Avagraha */
-#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 31 chars; Bindu */
-#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 116 chars; Consonant */
+
+#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 11 chars; Avagraha */
+#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 34 chars; Bindu */
+#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 123 chars; Consonant */
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 2 chars; Consonant_Dead */
-#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 16 chars; Consonant_Final */
+#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 17 chars; Consonant_Final */
#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 1 chars; Consonant_Head_Letter */
#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 12 chars; Consonant_Medial */
#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 4 chars; Consonant_Placeholder */
#define ISC_CR INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA /* 5 chars; Consonant_Repha */
-#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 9 chars; Consonant_Subjoined */
+#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 10 chars; Consonant_Subjoined */
#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
-#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 11 chars; Nukta */
+#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 12 chars; Nukta */
#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 1 chars; Register_Shifter */
#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 3 chars; Tone_Letter */
#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 16 chars; Tone_Mark */
-#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 29 chars; Virama */
-#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 19 chars; Visarga */
+#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 34 chars; Virama */
+#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 25 chars; Visarga */
#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 5 chars; Vowel */
-#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 161 chars; Vowel_Dependent */
-#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 53 chars; Vowel_Independent */
+#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 165 chars; Vowel_Dependent */
+#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 59 chars; Vowel_Independent */
-#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 60 chars; Bottom */
+#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 65 chars; Bottom */
#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */
-#define IMC_I INDIC_MATRA_CATEGORY_INVISIBLE /* 4 chars; Invisible */
-#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 25 chars; Left */
+#define IMC_I INDIC_MATRA_CATEGORY_INVISIBLE /* 6 chars; Invisible */
+#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 30 chars; Left */
#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 8 chars; Left_And_Right */
#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 2 chars; Overstruck */
-#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 70 chars; Right */
-#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 74 chars; Top */
-#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 5 chars; Top_And_Bottom */
+#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 75 chars; Right */
+#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 83 chars; Top */
+#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 6 chars; Top_And_Bottom */
#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 4 chars; Top_And_Left */
#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 2 chars; Top_And_Left_And_Right */
-#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 7 chars; Top_And_Right */
+#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 8 chars; Top_And_Right */
#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 5 chars; Visual_Order_Left */
#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
-static const INDIC_TABLE_ELEMENT_TYPE indic_table[4080] = {
+static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
#define indic_offset_0x0900 0
@@ -534,9 +505,9 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[4080] = {
/* 1B90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1B98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* 1BA0 */ _(C,x), _(CS,x), _(CS,x), _(CS,x), _(M,T), _(M,B), _(M,L), _(M,R),
- /* 1BA8 */ _(M,T), _(M,T), _(V,R), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
+ /* 1BA8 */ _(M,T), _(M,T), _(V,R), _(V,x), _(CS,x), _(CS,x), _(C,x), _(C,x),
/* 1BB0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 1BB8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1BB8 */ _(x,x), _(x,x), _(A,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x),
/* Batak (1BC0..1BFF) */
@@ -562,7 +533,19 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[4080] = {
/* 1C40 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 1C48 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x),
-#define indic_offset_0xa800 2976
+#define indic_offset_0x1cd0 2976
+
+
+ /* Vedic Extensions (1CD0..1CFF) */
+
+ /* 1CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1CE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0xa800 3024
/* Syloti Nagri (A800..A82F) */
@@ -696,21 +679,28 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[4080] = {
/* AAD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* AAD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0xabc0 3712
+ /* Meetei Mayek Extensions (AAE0..AAFF) */
+
+ /* AAE0 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AAE8 */ _(C,x), _(C,x), _(C,x), _(M,L), _(M,B), _(M,T), _(M,L), _(M,R),
+ /* AAF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Vs,x), _(V,I), _(x,x),
+ /* AAF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0xabc0 3792
/* Meetei Mayek (ABC0..ABFF) */
/* ABC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* ABC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* ABD0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* ABC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x),
+ /* ABD0 */ _(C,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
/* ABD8 */ _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
/* ABE0 */ _(CF,x), _(CF,x), _(CF,x), _(M,R), _(M,R), _(M,T), _(M,R), _(M,R),
/* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,x), _(V,B), _(x,x), _(x,x),
/* ABF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* ABF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0x10a00 3776
+#define indic_offset_0x10a00 3856
/* Kharoshthi (10A00..10A5F) */
@@ -728,7 +718,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[4080] = {
/* 10A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 10A58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_0x11000 3872
+#define indic_offset_0x11000 3952
/* Brahmi (11000..1107F) */
@@ -763,9 +753,59 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[4080] = {
/* 110C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
/* 110C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-#define indic_offset_total 4080
+#define indic_offset_0x11100 4160
+
+
+ /* Chakma (11100..1114F) */
+
+ /* 11100 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x),
+ /* 11108 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11110 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11118 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11120 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T),
+ /* 11128 */ _(M,T), _(M,T), _(M,B), _(M,B), _(M,L), _(M,T), _(M,TB), _(M,TB),
+ /* 11130 */ _(M,T), _(M,B), _(M,B), _(V,I), _(V,T), _(x,x), _(x,x), _(x,x),
+ /* 11138 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11140 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11148 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x11180 4240
+
+
+ /* Sharada (11180..111DF) */
+
+ /* 11180 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11188 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11190 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11198 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 111A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 111A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 111B0 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,L), _(M,R), _(M,B), _(M,B),
+ /* 111B8 */ _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,TR),
+ /* 111C0 */ _(V,R), _(A,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 111C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 111D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 111D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-};
+#define indic_offset_0x11680 4336
+
+
+ /* Takri (11680..116CF) */
+
+ /* 11680 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11688 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11690 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11698 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 116A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 116A8 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(Vs,x), _(M,T), _(M,L), _(M,R),
+ /* 116B0 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(N,x),
+ /* 116B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 116C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 116C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_total 4416
+
+}; /* Table occupancy: 60% */
static INDIC_TABLE_ELEMENT_TYPE
get_indic_categories (hb_codepoint_t u)
@@ -774,10 +814,14 @@ get_indic_categories (hb_codepoint_t u)
if (0x1700 <= u && u <= 0x1800) return indic_table[u - 0x1700 + indic_offset_0x1700];
if (0x1900 <= u && u <= 0x1AB0) return indic_table[u - 0x1900 + indic_offset_0x1900];
if (0x1B00 <= u && u <= 0x1C50) return indic_table[u - 0x1B00 + indic_offset_0x1b00];
- if (0xA800 <= u && u <= 0xAAE0) return indic_table[u - 0xA800 + indic_offset_0xa800];
+ if (0x1CD0 <= u && u <= 0x1D00) return indic_table[u - 0x1CD0 + indic_offset_0x1cd0];
+ if (0xA800 <= u && u <= 0xAB00) return indic_table[u - 0xA800 + indic_offset_0xa800];
if (0xABC0 <= u && u <= 0xAC00) return indic_table[u - 0xABC0 + indic_offset_0xabc0];
if (0x10A00 <= u && u <= 0x10A60) return indic_table[u - 0x10A00 + indic_offset_0x10a00];
if (0x11000 <= u && u <= 0x110D0) return indic_table[u - 0x11000 + indic_offset_0x11000];
+ if (0x11100 <= u && u <= 0x11150) return indic_table[u - 0x11100 + indic_offset_0x11100];
+ if (0x11180 <= u && u <= 0x111E0) return indic_table[u - 0x11180 + indic_offset_0x11180];
+ if (0x11680 <= u && u <= 0x116D0) return indic_table[u - 0x11680 + indic_offset_0x11680];
if (unlikely (u == 0x00A0)) return _(CP,x);
if (unlikely (u == 0x25CC)) return _(CP,x);
return _(x,x);
@@ -823,8 +867,6 @@ get_indic_categories (hb_codepoint_t u)
#undef IMC_TR
#undef IMC_VOL
+#endif /* HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH */
/* == End of generated table == */
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
index 9f50ef2..0c5479e 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,231 +24,19 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex-indic-private.hh"
+#include "hb-ot-shape-private.hh"
+static const struct indic_options_t
+{
+ indic_options_t (void)
+ {
+ char *c = getenv ("HB_OT_INDIC_OPTIONS");
+ uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
+ }
-
-/* buffer var allocations */
-#define indic_category() complex_var_persistent_u8_0() /* indic_category_t */
-#define indic_position() complex_var_persistent_u8_1() /* indic_matra_category_t */
-
-#define INDIC_TABLE_ELEMENT_TYPE uint8_t
-
-/* Cateories used in the OpenType spec:
- * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum indic_category_t {
- OT_X = 0,
- OT_C,
- OT_Ra, /* Not explicitly listed in the OT spec, but used in the grammar. */
- OT_V,
- OT_N,
- OT_H,
- OT_ZWNJ,
- OT_ZWJ,
- OT_M,
- OT_SM,
- OT_VD,
- OT_A,
- OT_NBSP
-};
-
-/* Visual positions in a syllable from left to right. */
-enum indic_position_t {
- POS_PRE,
- POS_BASE,
- POS_ABOVE,
- POS_BELOW,
- POS_POST
-};
-
-/* Categories used in IndicSyllabicCategory.txt from UCD */
-/* The assignments are guesswork */
-enum indic_syllabic_category_t {
- INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
-
- INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_X,
- INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA = OT_C,
- INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
- INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_X,
- INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
- INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM,
- INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V,
- INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M,
- INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V
-};
-
-/* Categories used in IndicSMatraCategory.txt from UCD */
-enum indic_matra_category_t {
- INDIC_MATRA_CATEGORY_NOT_APPLICABLE = POS_BASE,
-
- INDIC_MATRA_CATEGORY_LEFT = POS_PRE,
- INDIC_MATRA_CATEGORY_TOP = POS_ABOVE,
- INDIC_MATRA_CATEGORY_BOTTOM = POS_BELOW,
- INDIC_MATRA_CATEGORY_RIGHT = POS_POST,
-
- /* We don't really care much about these since we decompose them
- * in the generic pre-shaping layer. They will only be used if
- * the font does not cover the decomposition. In which case, we
- * define these as aliases to the place we want the split-matra
- * glyph to show up. Quite arbitrary. */
- INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_LEFT,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT = INDIC_MATRA_CATEGORY_LEFT,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_LEFT,
- INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
-
- INDIC_MATRA_CATEGORY_INVISIBLE = INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
- INDIC_MATRA_CATEGORY_OVERSTRUCK = INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
- INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = INDIC_MATRA_CATEGORY_NOT_APPLICABLE
-};
-
-/* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and the comma operation
- * because gcc fails to optimize the latter and fills the table in at runtime. */
-#define INDIC_COMBINE_CATEGORIES(S,M) \
- (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || (S == INDIC_SYLLABIC_CATEGORY_VIRAMA || S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT)) + \
- ASSERT_STATIC_EXPR_ZERO (S < 16 && M < 16) + \
- ((M << 4) | S))
-
-#include "hb-ot-shape-complex-indic-table.hh"
-
-/* XXX
- * This is a hack for now. We should:
- * 1. Move this data into the main Indic table,
- * and/or
- * 2. Probe font lookups to determine consonant positions.
- */
-static const struct consonant_position_t {
- hb_codepoint_t u;
- indic_position_t position;
-} consonant_positions[] = {
- {0x0930, POS_BELOW},
- {0x09AC, POS_BELOW},
- {0x09AF, POS_POST},
- {0x09B0, POS_BELOW},
- {0x09F0, POS_BELOW},
- {0x0A2F, POS_POST},
- {0x0A30, POS_BELOW},
- {0x0A35, POS_BELOW},
- {0x0A39, POS_BELOW},
- {0x0AB0, POS_BELOW},
- {0x0B24, POS_BELOW},
- {0x0B28, POS_BELOW},
- {0x0B2C, POS_BELOW},
- {0x0B2D, POS_BELOW},
- {0x0B2E, POS_BELOW},
- {0x0B2F, POS_POST},
- {0x0B30, POS_BELOW},
- {0x0B32, POS_BELOW},
- {0x0B33, POS_BELOW},
- {0x0B5F, POS_POST},
- {0x0B71, POS_BELOW},
- {0x0C15, POS_BELOW},
- {0x0C16, POS_BELOW},
- {0x0C17, POS_BELOW},
- {0x0C18, POS_BELOW},
- {0x0C19, POS_BELOW},
- {0x0C1A, POS_BELOW},
- {0x0C1B, POS_BELOW},
- {0x0C1C, POS_BELOW},
- {0x0C1D, POS_BELOW},
- {0x0C1E, POS_BELOW},
- {0x0C1F, POS_BELOW},
- {0x0C20, POS_BELOW},
- {0x0C21, POS_BELOW},
- {0x0C22, POS_BELOW},
- {0x0C23, POS_BELOW},
- {0x0C24, POS_BELOW},
- {0x0C25, POS_BELOW},
- {0x0C26, POS_BELOW},
- {0x0C27, POS_BELOW},
- {0x0C28, POS_BELOW},
- {0x0C2A, POS_BELOW},
- {0x0C2B, POS_BELOW},
- {0x0C2C, POS_BELOW},
- {0x0C2D, POS_BELOW},
- {0x0C2E, POS_BELOW},
- {0x0C2F, POS_BELOW},
- {0x0C30, POS_BELOW},
- {0x0C32, POS_BELOW},
- {0x0C33, POS_BELOW},
- {0x0C35, POS_BELOW},
- {0x0C36, POS_BELOW},
- {0x0C37, POS_BELOW},
- {0x0C38, POS_BELOW},
- {0x0C39, POS_BELOW},
- {0x0C95, POS_BELOW},
- {0x0C96, POS_BELOW},
- {0x0C97, POS_BELOW},
- {0x0C98, POS_BELOW},
- {0x0C99, POS_BELOW},
- {0x0C9A, POS_BELOW},
- {0x0C9B, POS_BELOW},
- {0x0C9C, POS_BELOW},
- {0x0C9D, POS_BELOW},
- {0x0C9E, POS_BELOW},
- {0x0C9F, POS_BELOW},
- {0x0CA0, POS_BELOW},
- {0x0CA1, POS_BELOW},
- {0x0CA2, POS_BELOW},
- {0x0CA3, POS_BELOW},
- {0x0CA4, POS_BELOW},
- {0x0CA5, POS_BELOW},
- {0x0CA6, POS_BELOW},
- {0x0CA7, POS_BELOW},
- {0x0CA8, POS_BELOW},
- {0x0CAA, POS_BELOW},
- {0x0CAB, POS_BELOW},
- {0x0CAC, POS_BELOW},
- {0x0CAD, POS_BELOW},
- {0x0CAE, POS_BELOW},
- {0x0CAF, POS_BELOW},
- {0x0CB0, POS_BELOW},
- {0x0CB2, POS_BELOW},
- {0x0CB3, POS_BELOW},
- {0x0CB5, POS_BELOW},
- {0x0CB6, POS_BELOW},
- {0x0CB7, POS_BELOW},
- {0x0CB8, POS_BELOW},
- {0x0CB9, POS_BELOW},
- {0x0CDE, POS_BELOW},
- {0x0D2F, POS_POST},
- {0x0D30, POS_POST},
- {0x0D32, POS_BELOW},
- {0x0D35, POS_POST},
-};
-
-/* XXX
- * This is a hack for now. We should move this data into the main Indic table.
- */
-static const hb_codepoint_t ra_chars[] = {
- 0x0930, /* Devanagari */
- 0x09B0, /* Bengali */
- 0x09F0, /* Bengali */
-//0x09F1, /* Bengali */
-//0x0A30, /* Gurmukhi */
- 0x0AB0, /* Gujarati */
- 0x0B30, /* Oriya */
-//0x0BB0, /* Tamil */
-//0x0C30, /* Telugu */
- 0x0CB0, /* Kannada */
-//0x0D30, /* Malayalam */
-};
+ bool uniscribe_bug_compatible;
+} options;
static int
compare_codepoint (const void *pa, const void *pb)
@@ -269,7 +57,7 @@ consonant_position (hb_codepoint_t u)
sizeof (consonant_positions[0]),
compare_codepoint);
- return record ? record->position : POS_BASE;
+ return record ? record->position : POS_BASE_C;
}
static bool
@@ -290,24 +78,32 @@ is_joiner (const hb_glyph_info_t &info)
static bool
is_consonant (const hb_glyph_info_t &info)
{
- return !!(FLAG (info.indic_category()) & (FLAG (OT_C) | FLAG (OT_Ra)));
+ /* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
+ * cannot happen in a consonant syllable. The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right! */
+ return !!(FLAG (info.indic_category()) & (FLAG (OT_C) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE)));
}
-static const struct {
+struct feature_list_t {
hb_tag_t tag;
hb_bool_t is_global;
-} indic_basic_features[] =
+};
+
+static const feature_list_t
+indic_basic_features[] =
{
{HB_TAG('n','u','k','t'), true},
{HB_TAG('a','k','h','n'), false},
{HB_TAG('r','p','h','f'), false},
- {HB_TAG('r','k','r','f'), false},
+ {HB_TAG('r','k','r','f'), true},
{HB_TAG('p','r','e','f'), false},
{HB_TAG('b','l','w','f'), false},
{HB_TAG('h','a','l','f'), false},
- {HB_TAG('v','a','t','u'), true},
{HB_TAG('p','s','t','f'), false},
{HB_TAG('c','j','c','t'), false},
+ {HB_TAG('v','a','t','u'), true},
};
/* Same order as the indic_basic_features array */
@@ -315,26 +111,33 @@ enum {
_NUKT,
AKHN,
RPHF,
- RKRF,
+ _RKRF,
PREF,
BLWF,
HALF,
- _VATU,
PSTF,
- CJCT
+ CJCT,
+ VATU
};
-static const hb_tag_t indic_other_features[] =
+static const feature_list_t
+indic_other_features[] =
{
- HB_TAG('p','r','e','s'),
- HB_TAG('a','b','v','s'),
- HB_TAG('b','l','w','s'),
- HB_TAG('p','s','t','s'),
- HB_TAG('h','a','l','n'),
-
- HB_TAG('d','i','s','t'),
- HB_TAG('a','b','v','m'),
- HB_TAG('b','l','w','m'),
+ {HB_TAG('i','n','i','t'), false},
+ {HB_TAG('p','r','e','s'), true},
+ {HB_TAG('a','b','v','s'), true},
+ {HB_TAG('b','l','w','s'), true},
+ {HB_TAG('p','s','t','s'), true},
+ {HB_TAG('h','a','l','n'), true},
+
+ {HB_TAG('d','i','s','t'), true},
+ {HB_TAG('a','b','v','m'), true},
+ {HB_TAG('b','l','w','m'), true},
+};
+
+/* Same order as the indic_other_features array */
+enum {
+ INIT
};
@@ -350,7 +153,8 @@ final_reordering (const hb_ot_map_t *map,
void *user_data HB_UNUSED);
void
-_hb_ot_shape_complex_collect_features_indic (hb_ot_map_builder_t *map, const hb_segment_properties_t *props)
+_hb_ot_shape_complex_collect_features_indic (hb_ot_map_builder_t *map,
+ const hb_segment_properties_t *props HB_UNUSED)
{
map->add_bool_feature (HB_TAG('l','o','c','l'));
/* The Indic specs do not require ccmp, but we apply it here since if
@@ -359,26 +163,32 @@ _hb_ot_shape_complex_collect_features_indic (hb_ot_map_builder_t *map, const hb_
map->add_gsub_pause (initial_reordering, NULL);
- for (unsigned int i = 0; i < ARRAY_LENGTH (indic_basic_features); i++)
+ for (unsigned int i = 0; i < ARRAY_LENGTH (indic_basic_features); i++) {
map->add_bool_feature (indic_basic_features[i].tag, indic_basic_features[i].is_global);
+ map->add_gsub_pause (NULL, NULL);
+ }
map->add_gsub_pause (final_reordering, NULL);
- for (unsigned int i = 0; i < ARRAY_LENGTH (indic_other_features); i++)
- map->add_bool_feature (indic_other_features[i], true);
+ for (unsigned int i = 0; i < ARRAY_LENGTH (indic_other_features); i++) {
+ map->add_bool_feature (indic_other_features[i].tag, indic_other_features[i].is_global);
+ map->add_gsub_pause (NULL, NULL);
+ }
}
-bool
-_hb_ot_shape_complex_prefer_decomposed_indic (void)
+hb_ot_shape_normalization_mode_t
+_hb_ot_shape_complex_normalization_preference_indic (void)
{
/* We want split matras decomposed by the common shaping logic. */
- return TRUE;
+ return HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED;
}
void
-_hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map, hb_buffer_t *buffer)
+_hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
{
HB_BUFFER_ALLOCATE_VAR (buffer, indic_category);
HB_BUFFER_ALLOCATE_VAR (buffer, indic_position);
@@ -389,19 +199,36 @@ _hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map, hb_buffer_t *buffer)
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
{
- unsigned int type = get_indic_categories (buffer->info[i].codepoint);
-
- buffer->info[i].indic_category() = type & 0x0F;
- buffer->info[i].indic_position() = type >> 4;
-
- if (buffer->info[i].indic_category() == OT_C) {
- buffer->info[i].indic_position() = consonant_position (buffer->info[i].codepoint);
- if (is_ra (buffer->info[i].codepoint))
- buffer->info[i].indic_category() = OT_Ra;
- } else if (buffer->info[i].codepoint == 0x200C)
- buffer->info[i].indic_category() = OT_ZWNJ;
- else if (buffer->info[i].codepoint == 0x200D)
- buffer->info[i].indic_category() = OT_ZWJ;
+ hb_glyph_info_t &info = buffer->info[i];
+ unsigned int type = get_indic_categories (info.codepoint);
+
+ info.indic_category() = type & 0x0F;
+ info.indic_position() = type >> 4;
+
+ /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe
+ * treats U+0951..U+0952 all as OT_VD.
+ * TESTS:
+ * U+092E,U+0947,U+0952
+ * U+092E,U+0952,U+0947
+ * U+092E,U+0947,U+0951
+ * U+092E,U+0951,U+0947
+ * */
+ if (unlikely (hb_in_range<hb_codepoint_t> (info.codepoint, 0x0951, 0x0954)))
+ info.indic_category() = OT_VD;
+
+ if (info.indic_category() == OT_C) {
+ info.indic_position() = consonant_position (info.codepoint);
+ if (is_ra (info.codepoint))
+ info.indic_category() = OT_Ra;
+ } else if (info.indic_category() == OT_SM ||
+ info.indic_category() == OT_VD) {
+ info.indic_position() = POS_SMVD;
+ } else if (unlikely (info.codepoint == 0x200C))
+ info.indic_category() = OT_ZWNJ;
+ else if (unlikely (info.codepoint == 0x200D))
+ info.indic_category() = OT_ZWJ;
+ else if (unlikely (info.codepoint == 0x25CC))
+ info.indic_category() = OT_DOTTEDCIRCLE;
}
}
@@ -414,15 +241,15 @@ compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
return a < b ? -1 : a == b ? 0 : +1;
}
+/* Rules from:
+ * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */
+
static void
-found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
- unsigned int start, unsigned int end)
+initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
+ unsigned int start, unsigned int end)
{
- unsigned int i;
hb_glyph_info_t *info = buffer->info;
- /* Comments from:
- * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */
/* 1. Find base consonant:
*
@@ -439,52 +266,65 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t
*/
unsigned int base = end;
+ bool has_reph = false;
- /* -> starting from the end of the syllable, move backwards */
- i = end;
- unsigned int limit = start;
- if (info[start].indic_category() == OT_Ra && start + 2 <= end) {
- limit += 2;
- base = start;
- };
- do {
- i--;
- /* -> until a consonant is found */
- if (is_consonant (info[i]))
+ {
+ /* -> If the syllable starts with Ra + Halant (in a script that has Reph)
+ * and has more than one consonant, Ra is excluded from candidates for
+ * base consonants. */
+ unsigned int limit = start;
+ if (mask_array[RPHF] &&
+ start + 3 <= end &&
+ info[start].indic_category() == OT_Ra &&
+ info[start + 1].indic_category() == OT_H &&
+ !is_joiner (info[start + 2]))
{
- /* -> that does not have a below-base or post-base form
- * (post-base forms have to follow below-base forms), */
- if (info[i].indic_position() != POS_BELOW &&
- info[i].indic_position() != POS_POST)
+ limit += 2;
+ base = start;
+ has_reph = true;
+ };
+
+ /* -> starting from the end of the syllable, move backwards */
+ unsigned int i = end;
+ do {
+ i--;
+ /* -> until a consonant is found */
+ if (is_consonant (info[i]))
{
- base = i;
- break;
- }
-
- /* -> or that is not a pre-base reordering Ra,
- *
- * TODO
- */
+ /* -> that does not have a below-base or post-base form
+ * (post-base forms have to follow below-base forms), */
+ if (info[i].indic_position() != POS_BELOW_C &&
+ info[i].indic_position() != POS_POST_C)
+ {
+ base = i;
+ break;
+ }
- /* -> o If the syllable starts with Ra + Halant (in a script that has Reph)
- * and has more than one consonant, Ra is excluded from candidates for
- * base consonants.
- *
- * IMPLEMENTATION NOTES:
- *
- * We do this by adjusting limit accordingly before entering the loop.
- */
+ /* -> or that is not a pre-base reordering Ra,
+ *
+ * TODO
+ */
- /* -> or arrive at the first consonant. The consonant stopped at will
- * be the base. */
- base = i;
+ /* -> or arrive at the first consonant. The consonant stopped at will
+ * be the base. */
+ base = i;
+ }
+ else
+ if (is_joiner (info[i]))
+ break;
+ } while (i > limit);
+ if (base < start)
+ base = start; /* Just in case... */
+
+
+ /* -> If the syllable starts with Ra + Halant (in a script that has Reph)
+ * and has more than one consonant, Ra is excluded from candidates for
+ * base consonants. */
+ if (has_reph && base == start) {
+ /* Have no other consonant, so Reph is not formed and Ra becomes base. */
+ has_reph = false;
}
- else
- if (is_joiner (info[i]))
- break;
- } while (i > limit);
- if (base < start)
- base = start; /* Just in case... */
+ }
/* 2. Decompose and reorder Matras:
@@ -521,30 +361,23 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t
/* Reorder characters */
- for (i = start; i < base; i++)
- info[i].indic_position() = POS_PRE;
- info[base].indic_position() = POS_BASE;
-
+ for (unsigned int i = start; i < base; i++)
+ info[i].indic_position() = POS_PRE_C;
+ info[base].indic_position() = POS_BASE_C;
/* Handle beginning Ra */
- if (start + 3 <= end &&
- info[start].indic_category() == OT_Ra &&
- info[start + 1].indic_category() == OT_H &&
- !is_joiner (info[start + 2]))
- {
- info[start].indic_position() = POS_POST;
- info[start].mask = mask_array[RPHF];
- }
+ if (has_reph)
+ info[start].indic_position() = POS_RA_TO_BECOME_REPH;
/* For old-style Indic script tags, move the first post-base Halant after
* last consonant. */
if ((map->get_chosen_script (0) & 0x000000FF) != '2') {
/* We should only do this for Indic scripts which have a version two I guess. */
- for (i = base + 1; i < end; i++)
+ for (unsigned int i = base + 1; i < end; i++)
if (info[i].indic_category() == OT_H) {
unsigned int j;
for (j = end - 1; j > i; j--)
- if ((FLAG (info[j].indic_category()) & (FLAG (OT_C) | FLAG (OT_Ra))))
+ if (is_consonant (info[j]))
break;
if (j > i) {
/* Move Halant to after last consonant. */
@@ -557,38 +390,68 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t
}
/* Attach ZWJ, ZWNJ, nukta, and halant to previous char to move with them. */
- for (i = start + 1; i < end; i++)
- if ((FLAG (info[i].indic_category()) &
- (FLAG (OT_ZWNJ) | FLAG (OT_ZWJ) | FLAG (OT_N) | FLAG (OT_H))))
- info[i].indic_position() = info[i - 1].indic_position();
+ if (!options.uniscribe_bug_compatible)
+ {
+ /* Please update the Uniscribe branch when touching this! */
+ for (unsigned int i = start + 1; i < end; i++)
+ if ((FLAG (info[i].indic_category()) & (FLAG (OT_ZWNJ) | FLAG (OT_ZWJ) | FLAG (OT_N) | FLAG (OT_H))))
+ info[i].indic_position() = info[i - 1].indic_position();
+ } else {
+ /*
+ * Uniscribe doesn't move the Halant with Left Matra.
+ * TEST: U+092B,U+093F,U+094DE
+ */
+ /* Please update the non-Uniscribe branch when touching this! */
+ for (unsigned int i = start + 1; i < end; i++)
+ if ((FLAG (info[i].indic_category()) & (FLAG (OT_ZWNJ) | FLAG (OT_ZWJ) | FLAG (OT_N) | FLAG (OT_H)))) {
+ info[i].indic_position() = info[i - 1].indic_position();
+ if (info[i].indic_category() == OT_H && info[i].indic_position() == POS_PRE_M)
+ for (unsigned int j = i; j > start; j--)
+ if (info[j - 1].indic_position() != POS_PRE_M) {
+ info[i].indic_position() = info[j - 1].indic_position();
+ break;
+ }
+ }
+ }
/* We do bubble-sort, skip malicious clusters attempts */
- if (end - start > 20)
- return;
-
- /* Sit tight, rock 'n roll! */
- hb_bubble_sort (info + start, end - start, compare_indic_order);
+ if (end - start < 64)
+ {
+ /* Sit tight, rock 'n roll! */
+ hb_bubble_sort (info + start, end - start, compare_indic_order);
+ /* Find base again */
+ base = end;
+ for (unsigned int i = start; i < end; i++)
+ if (info[i].indic_position() == POS_BASE_C) {
+ base = i;
+ break;
+ }
+ }
/* Setup masks now */
{
hb_mask_t mask;
+ /* Reph */
+ for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++)
+ info[i].mask |= mask_array[RPHF];
+
/* Pre-base */
mask = mask_array[HALF] | mask_array[AKHN] | mask_array[CJCT];
- for (i = start; i < base; i++)
+ for (unsigned int i = start; i < base; i++)
info[i].mask |= mask;
/* Base */
mask = mask_array[AKHN] | mask_array[CJCT];
info[base].mask |= mask;
/* Post-base */
mask = mask_array[BLWF] | mask_array[PSTF] | mask_array[CJCT];
- for (i = base + 1; i < end; i++)
+ for (unsigned int i = base + 1; i < end; i++)
info[i].mask |= mask;
}
/* Apply ZWJ/ZWNJ effects */
- for (i = start + 1; i < end; i++)
+ for (unsigned int i = start + 1; i < end; i++)
if (is_joiner (info[i])) {
bool non_joiner = info[i].indic_category() == OT_ZWNJ;
unsigned int j = i;
@@ -596,14 +459,9 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t
do {
j--;
- /* Reading the Unicode and OpenType specs, I think the following line
- * is correct, but this is not what the test suite expects currently.
- * The test suite has been drinking, not me... But disable while
- * investigating.
- */
- //info[j].mask &= !mask_array[CJCT];
+ info[j].mask &= ~mask_array[CJCT];
if (non_joiner)
- info[j].mask &= !mask_array[HALF];
+ info[j].mask &= ~mask_array[HALF];
} while (j > start && !is_consonant (info[j]));
}
@@ -611,28 +469,41 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t
static void
-found_vowel_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
- unsigned int start, unsigned int end)
+initial_reordering_vowel_syllable (const hb_ot_map_t *map,
+ hb_buffer_t *buffer,
+ hb_mask_t *mask_array,
+ unsigned int start, unsigned int end)
{
- /* TODO
- * Not clear to me how this should work. Do the matras move to before the
- * independent vowel? No idea.
- */
+ /* We made the vowels look like consonants. So let's call the consonant logic! */
+ initial_reordering_consonant_syllable (map, buffer, mask_array, start, end);
}
static void
-found_standalone_cluster (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
- unsigned int start, unsigned int end)
+initial_reordering_standalone_cluster (const hb_ot_map_t *map,
+ hb_buffer_t *buffer,
+ hb_mask_t *mask_array,
+ unsigned int start, unsigned int end)
{
- /* TODO
- * Easiest thing to do here is to convert the NBSP to consonant and
- * call found_consonant_syllable.
- */
+ /* We treat NBSP/dotted-circle as if they are consonants, so we should just chain.
+ * Only if not in compatibility mode that is... */
+
+ if (options.uniscribe_bug_compatible)
+ {
+ /* For dotted-circle, this is what Uniscribe does:
+ * If dotted-circle is the last glyph, it just does nothing.
+ * Ie. It doesn't form Reph. */
+ if (buffer->info[end - 1].indic_category() == OT_DOTTEDCIRCLE)
+ return;
+ }
+
+ initial_reordering_consonant_syllable (map, buffer, mask_array, start, end);
}
static void
-found_non_indic (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
- unsigned int start, unsigned int end)
+initial_reordering_non_indic (const hb_ot_map_t *map HB_UNUSED,
+ hb_buffer_t *buffer HB_UNUSED,
+ hb_mask_t *mask_array HB_UNUSED,
+ unsigned int start HB_UNUSED, unsigned int end HB_UNUSED)
{
/* Nothing to do right now. If we ever switch to using the output
* buffer in the reordering process, we'd need to next_glyph() here. */
@@ -641,26 +512,8 @@ found_non_indic (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_ar
#include "hb-ot-shape-complex-indic-machine.hh"
static void
-remove_joiners (hb_buffer_t *buffer)
-{
- /* For now we remove joiners. However, Uniscbire seems to keep them
- * and output a zero-width space glyph for them. It is not clear to
- * me how that is supposed to interact with GSUB. */
-
- buffer->clear_output ();
- unsigned int count = buffer->len;
- for (buffer->idx = 0; buffer->idx < count;)
- if (unlikely (is_joiner (buffer->info[buffer->idx])))
- buffer->skip_glyph ();
- else
- buffer->next_glyph ();
-
- buffer->swap_buffers ();
-}
-
-static void
initial_reordering (const hb_ot_map_t *map,
- hb_face_t *face,
+ hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer,
void *user_data HB_UNUSED)
{
@@ -670,24 +523,40 @@ initial_reordering (const hb_ot_map_t *map,
mask_array[i] = map->get_1_mask (indic_basic_features[i].tag);
find_syllables (map, buffer, mask_array);
-
- remove_joiners (buffer);
}
static void
-final_reordering (const hb_ot_map_t *map,
- hb_face_t *face,
- hb_buffer_t *buffer,
- void *user_data HB_UNUSED)
+final_reordering_syllable (hb_buffer_t *buffer, hb_mask_t *mask_array,
+ unsigned int start, unsigned int end)
{
+ hb_glyph_info_t *info = buffer->info;
+
/* 4. Final reordering:
*
* After the localized forms and basic shaping forms GSUB features have been
* applied (see below), the shaping engine performs some final glyph
* reordering before applying all the remaining font features to the entire
* cluster.
- *
- * o Reorder matras:
+ */
+
+ /* Find base again */
+ unsigned int base = end;
+ for (unsigned int i = start; i < end; i++)
+ if (info[i].indic_position() == POS_BASE_C) {
+ base = i;
+ break;
+ }
+
+ if (base == start) {
+ /* There's no Reph, and no left Matra to reposition. Just merge the cluster
+ * and go home. */
+ buffer->merge_clusters (start, end);
+ return;
+ }
+
+ unsigned int start_of_last_cluster = base;
+
+ /* o Reorder matras:
*
* If a pre-base matra character had been reordered before applying basic
* features, the glyph can be moved closer to the main consonant based on
@@ -695,49 +564,197 @@ final_reordering (const hb_ot_map_t *map,
* defined as “after last standalone halant glyph, after initial matra
* position and before the main consonant”. If ZWJ or ZWNJ follow this
* halant, position is moved after it.
- *
- * o Reorder reph:
+ */
+
+ {
+ unsigned int new_matra_pos = base - 1;
+ while (new_matra_pos > start &&
+ !(FLAG (info[new_matra_pos].indic_category()) & (FLAG (OT_M) | FLAG (OT_H))))
+ new_matra_pos--;
+ /* If we found no Halant we are done. Otherwise only proceed if the Halant does
+ * not belong to the Matra itself! */
+ if (info[new_matra_pos].indic_category() == OT_H &&
+ info[new_matra_pos].indic_position() != POS_PRE_M) {
+ /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
+ if (new_matra_pos + 1 < end && is_joiner (info[new_matra_pos + 1]))
+ new_matra_pos++;
+
+ /* Now go see if there's actually any matras... */
+ for (unsigned int i = new_matra_pos; i > start; i--)
+ if (info[i - 1].indic_position () == POS_PRE_M)
+ {
+ unsigned int old_matra_pos = i - 1;
+ hb_glyph_info_t matra = info[old_matra_pos];
+ memmove (&info[old_matra_pos], &info[old_matra_pos + 1], (new_matra_pos - old_matra_pos) * sizeof (info[0]));
+ info[new_matra_pos] = matra;
+ start_of_last_cluster = MIN (new_matra_pos, start_of_last_cluster);
+ new_matra_pos--;
+ }
+ }
+ }
+
+
+ /* o Reorder reph:
*
* Reph’s original position is always at the beginning of the syllable,
* (i.e. it is not reordered at the character reordering stage). However,
* it will be reordered according to the basic-forms shaping results.
* Possible positions for reph, depending on the script, are; after main,
* before post-base consonant forms, and after post-base consonant forms.
- *
- * 1. If reph should be positioned after post-base consonant forms,
- * proceed to step 5.
- *
- * 2. If the reph repositioning class is not after post-base: target
- * position is after the first explicit halant glyph between the
- * first post-reph consonant and last main consonant. If ZWJ or ZWNJ
- * are following this halant, position is moved after it. If such
- * position is found, this is the target position. Otherwise,
- * proceed to the next step.
- *
- * Note: in old-implementation fonts, where classifications were
- * fixed in shaping engine, there was no case where reph position
- * will be found on this step.
- *
- * 3. If reph should be repositioned after the main consonant: from the
- * first consonant not ligated with main, or find the first
- * consonant that is not a potential pre-base reordering Ra.
- *
- *
- * 4. If reph should be positioned before post-base consonant, find
- * first post-base classified consonant not ligated with main. If no
- * consonant is found, the target position should be before the
- * first matra, syllable modifier sign or vedic sign.
- *
- * 5. If no consonant is found in steps 3 or 4, move reph to a position
- * immediately before the first post-base matra, syllable modifier
- * sign or vedic sign that has a reordering class after the intended
- * reph position. For example, if the reordering position for reph
- * is post-main, it will skip above-base matras that also have a
- * post-main position.
- *
- * 6. Otherwise, reorder reph to the end of the syllable.
- *
- * o Reorder pre-base reordering consonants:
+ */
+
+ /* If there's anything after the Ra that has the REPH pos, it ought to be halant.
+ * Which means that the font has failed to ligate the Reph. In which case, we
+ * shouldn't move. */
+ if (start + 1 < end &&
+ info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
+ info[start + 1].indic_position() != POS_RA_TO_BECOME_REPH)
+ {
+ unsigned int new_reph_pos;
+
+ enum reph_position_t {
+ REPH_AFTER_MAIN,
+ REPH_BEFORE_SUBSCRIPT,
+ REPH_AFTER_SUBSCRIPT,
+ REPH_BEFORE_POSTSCRIPT,
+ REPH_AFTER_POSTSCRIPT,
+ } reph_pos;
+
+ /* XXX Figure out old behavior too */
+ switch ((hb_tag_t) buffer->props.script)
+ {
+ case HB_SCRIPT_MALAYALAM:
+ case HB_SCRIPT_ORIYA:
+ reph_pos = REPH_AFTER_MAIN;
+ break;
+
+ case HB_SCRIPT_GURMUKHI:
+ reph_pos = REPH_BEFORE_SUBSCRIPT;
+ break;
+
+ case HB_SCRIPT_BENGALI:
+ reph_pos = REPH_AFTER_SUBSCRIPT;
+ break;
+
+ default:
+ case HB_SCRIPT_DEVANAGARI:
+ case HB_SCRIPT_GUJARATI:
+ reph_pos = REPH_BEFORE_POSTSCRIPT;
+ break;
+
+ case HB_SCRIPT_KANNADA:
+ case HB_SCRIPT_TAMIL:
+ case HB_SCRIPT_TELUGU:
+ reph_pos = REPH_AFTER_POSTSCRIPT;
+ break;
+ }
+
+ /* 1. If reph should be positioned after post-base consonant forms,
+ * proceed to step 5.
+ */
+ if (reph_pos == REPH_AFTER_POSTSCRIPT)
+ {
+ goto reph_step_5;
+ }
+
+ /* 2. If the reph repositioning class is not after post-base: target
+ * position is after the first explicit halant glyph between the
+ * first post-reph consonant and last main consonant. If ZWJ or ZWNJ
+ * are following this halant, position is moved after it. If such
+ * position is found, this is the target position. Otherwise,
+ * proceed to the next step.
+ *
+ * Note: in old-implementation fonts, where classifications were
+ * fixed in shaping engine, there was no case where reph position
+ * will be found on this step.
+ */
+ {
+ new_reph_pos = start + 1;
+ while (new_reph_pos < base && info[new_reph_pos].indic_category() != OT_H)
+ new_reph_pos++;
+
+ if (new_reph_pos < base && info[new_reph_pos].indic_category() == OT_H) {
+ /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */
+ if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1]))
+ new_reph_pos++;
+ goto reph_move;
+ }
+ }
+
+ /* 3. If reph should be repositioned after the main consonant: find the
+ * first consonant not ligated with main, or find the first
+ * consonant that is not a potential pre-base reordering Ra.
+ */
+ if (reph_pos == REPH_AFTER_MAIN)
+ {
+ /* XXX */
+ }
+
+ /* 4. If reph should be positioned before post-base consonant, find
+ * first post-base classified consonant not ligated with main. If no
+ * consonant is found, the target position should be before the
+ * first matra, syllable modifier sign or vedic sign.
+ */
+ /* This is our take on what step 4 is trying to say (and failing, BADLY). */
+ if (reph_pos == REPH_AFTER_SUBSCRIPT)
+ {
+ new_reph_pos = base;
+ while (new_reph_pos < end &&
+ !( FLAG (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_POST_M) | FLAG (POS_SMVD))))
+ new_reph_pos++;
+ if (new_reph_pos < end)
+ goto reph_move;
+ }
+
+ /* 5. If no consonant is found in steps 3 or 4, move reph to a position
+ * immediately before the first post-base matra, syllable modifier
+ * sign or vedic sign that has a reordering class after the intended
+ * reph position. For example, if the reordering position for reph
+ * is post-main, it will skip above-base matras that also have a
+ * post-main position.
+ */
+ reph_step_5:
+ {
+ /* XXX */
+ }
+
+ /* 6. Otherwise, reorder reph to the end of the syllable.
+ */
+ {
+ new_reph_pos = end - 1;
+ while (new_reph_pos > start && info[new_reph_pos].indic_position() == POS_SMVD)
+ new_reph_pos--;
+
+ /*
+ * If the Reph is to be ending up after a Matra,Halant sequence,
+ * position it before that Halant so it can interact with the Matra.
+ * However, if it's a plain Consonant,Halant we shouldn't do that.
+ * Uniscribe doesn't do this.
+ * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
+ */
+ if (!options.uniscribe_bug_compatible &&
+ unlikely (info[new_reph_pos].indic_category() == OT_H)) {
+ for (unsigned int i = base + 1; i < new_reph_pos; i++)
+ if (info[i].indic_category() == OT_M) {
+ /* Ok, got it. */
+ new_reph_pos--;
+ }
+ }
+ goto reph_move;
+ }
+
+ reph_move:
+ {
+ /* Move */
+ hb_glyph_info_t reph = info[start];
+ memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0]));
+ info[new_reph_pos] = reph;
+ start_of_last_cluster = start; /* Yay, one big cluster! */
+ }
+ }
+
+
+ /* o Reorder pre-base reordering consonants:
*
* If a pre-base reordering consonant is found, reorder it according to
* the following rules:
@@ -757,6 +774,69 @@ final_reordering (const hb_ot_map_t *map,
+ /* Apply 'init' to the Left Matra if it's a word start. */
+ if (info[start].indic_position () == POS_PRE_M &&
+ (!start ||
+ !(FLAG (_hb_glyph_info_get_general_category (&info[start - 1])) &
+ (FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))))
+ info[start].mask |= mask_array[INIT];
+
+
+
+ /* Finish off the clusters and go home! */
+
+ if (!options.uniscribe_bug_compatible)
+ {
+ /* This is what Uniscribe does. Ie. add cluster boundaries after Halant,ZWNJ.
+ * This means, half forms are submerged into the main consonants cluster.
+ * This is unnecessary, and makes cursor positioning harder, but that's what
+ * Uniscribe does. */
+ unsigned int cluster_start = start;
+ for (unsigned int i = start + 1; i < start_of_last_cluster; i++)
+ if (info[i - 1].indic_category() == OT_H && info[i].indic_category() == OT_ZWNJ) {
+ i++;
+ buffer->merge_clusters (cluster_start, i);
+ cluster_start = i;
+ }
+ start_of_last_cluster = cluster_start;
+ }
+
+ buffer->merge_clusters (start_of_last_cluster, end);
+}
+
+
+static void
+final_reordering (const hb_ot_map_t *map,
+ hb_face_t *face HB_UNUSED,
+ hb_buffer_t *buffer,
+ void *user_data HB_UNUSED)
+{
+ unsigned int count = buffer->len;
+ if (!count) return;
+
+ hb_mask_t mask_array[ARRAY_LENGTH (indic_other_features)] = {0};
+ unsigned int num_masks = ARRAY_LENGTH (indic_other_features);
+ for (unsigned int i = 0; i < num_masks; i++)
+ mask_array[i] = map->get_1_mask (indic_other_features[i].tag);
+
+ hb_glyph_info_t *info = buffer->info;
+ unsigned int last = 0;
+ unsigned int last_syllable = info[0].syllable();
+ for (unsigned int i = 1; i < count; i++)
+ if (last_syllable != info[i].syllable()) {
+ final_reordering_syllable (buffer, mask_array, last, i);
+ last = i;
+ last_syllable = info[last].syllable();
+ }
+ final_reordering_syllable (buffer, mask_array, last, count);
+
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc
index 230704f..d93d4c6 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc
@@ -27,7 +27,7 @@
#include "hb-ot-shape-complex-private.hh"
-/* TODO Add kana, hangul, and other small sahpers here */
+/* TODO Add kana, and other small shapers here */
/* When adding trivial shapers, eg. kana, hangul, etc, we can either
* add a full shaper enum value for them, or switch on the script in
@@ -37,19 +37,157 @@
*/
void
-_hb_ot_shape_complex_collect_features_default (hb_ot_map_builder_t *map, const hb_segment_properties_t *props)
+_hb_ot_shape_complex_collect_features_default (hb_ot_map_builder_t *map HB_UNUSED,
+ const hb_segment_properties_t *props HB_UNUSED)
{
}
-bool
-_hb_ot_shape_complex_prefer_decomposed_default (void)
+hb_ot_shape_normalization_mode_t
+_hb_ot_shape_complex_normalization_preference_default (void)
{
- return FALSE;
+ return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
}
void
-_hb_ot_shape_complex_setup_masks_default (hb_ot_map_t *map, hb_buffer_t *buffer)
+_hb_ot_shape_complex_setup_masks_default (hb_ot_map_t *map HB_UNUSED,
+ hb_buffer_t *buffer HB_UNUSED,
+ hb_font_t *font HB_UNUSED)
{
}
+
+/* Hangul shaper */
+
+static const hb_tag_t hangul_features[] =
+{
+ HB_TAG('l','j','m','o'),
+ HB_TAG('v','j','m','o'),
+ HB_TAG('t','j','m','o'),
+};
+
+void
+_hb_ot_shape_complex_collect_features_hangul (hb_ot_map_builder_t *map,
+ const hb_segment_properties_t *props HB_UNUSED)
+{
+ for (unsigned int i = 0; i < ARRAY_LENGTH (hangul_features); i++)
+ map->add_bool_feature (hangul_features[i]);
+}
+
+hb_ot_shape_normalization_mode_t
+_hb_ot_shape_complex_normalization_preference_hangul (void)
+{
+ return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL;
+}
+
+void
+_hb_ot_shape_complex_setup_masks_hangul (hb_ot_map_t *map HB_UNUSED,
+ hb_buffer_t *buffer HB_UNUSED,
+ hb_font_t *font HB_UNUSED)
+{
+}
+
+
+
+/* Thai / Lao shaper */
+
+void
+_hb_ot_shape_complex_collect_features_thai (hb_ot_map_builder_t *map HB_UNUSED,
+ const hb_segment_properties_t *props HB_UNUSED)
+{
+}
+
+hb_ot_shape_normalization_mode_t
+_hb_ot_shape_complex_normalization_preference_thai (void)
+{
+ return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL;
+}
+
+void
+_hb_ot_shape_complex_setup_masks_thai (hb_ot_map_t *map HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
+{
+ /* The following is NOT specified in the MS OT Thai spec, however, it seems
+ * to be what Uniscribe and other engines implement. According to Eric Muller:
+ *
+ * When you have a sara am, decompose it in nikhahit + sara a, *and* mode the
+ * nihka hit backwards over any *tone* mark (0E48-0E4B).
+ *
+ * <0E14, 0E4B, 0E33> -> <0E14, 0E4D, 0E4B, 0E32>
+ *
+ * This reordering is legit only when the nikhahit comes from a sara am, not
+ * when it's there to start with. The string <0E14, 0E4B, 0E4D> is probably
+ * not what a u↪ser wanted, but the rendering is nevertheless nikhahit above
+ * chattawa.
+ *
+ * Same for Lao.
+ */
+
+ /*
+ * Here are the characters of significance:
+ *
+ * Thai Lao
+ * SARA AM: U+0E33 U+0EB3
+ * SARA AA: U+0E32 U+0EB2
+ * Nikhahit: U+0E4D U+0ECD
+ *
+ * Tone marks:
+ * Thai: <0E48..0E4B> CCC=107
+ * Lao: <0EC8..0ECB> CCC=122
+ *
+ * Note how the Lao versions are the same as Thai + 0x80.
+ */
+
+ /* We only get one script at a time, so a script-agnostic implementation
+ * is adequate here. */
+#define IS_SARA_AM(x) (((x) & ~0x0080) == 0x0E33)
+#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0xE33 + 0xE4D)
+#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
+#define IS_TONE_MARK(x) (((x) & ~0x0083) == 0x0E48)
+
+ buffer->clear_output ();
+ unsigned int count = buffer->len;
+ for (buffer->idx = 0; buffer->idx < count;)
+ {
+ hb_codepoint_t u = buffer->cur().codepoint;
+ if (likely (!IS_SARA_AM (u))) {
+ buffer->next_glyph ();
+ continue;
+ }
+
+ /* Is SARA AM. Decompose and reorder. */
+ hb_codepoint_t decomposed[2] = {hb_codepoint_t (NIKHAHIT_FROM_SARA_AM (u)),
+ hb_codepoint_t (SARA_AA_FROM_SARA_AM (u))};
+ buffer->replace_glyphs (1, 2, decomposed);
+ if (unlikely (buffer->in_error))
+ return;
+
+ /* Ok, let's see... */
+ unsigned int end = buffer->out_len;
+ unsigned int start = end - 2;
+ while (start > 0 && IS_TONE_MARK (buffer->out_info[start - 1].codepoint))
+ start--;
+
+ /* Move Nikhahit (end-2) to the beginning */
+ hb_glyph_info_t t = buffer->out_info[end - 2];
+ memmove (buffer->out_info + start + 1,
+ buffer->out_info + start,
+ sizeof (buffer->out_info[0]) * (end - start - 2));
+ buffer->out_info[start] = t;
+
+ /* XXX Make this easier! */
+ /* Make cluster */
+ for (; start > 0 && buffer->out_info[start - 1].cluster == buffer->out_info[start].cluster; start--)
+ ;
+ for (; buffer->idx < count;)
+ if (buffer->cur().cluster == buffer->prev().cluster)
+ buffer->next_glyph ();
+ else
+ break;
+ end = buffer->out_len;
+
+ buffer->merge_out_clusters (start, end);
+ }
+ buffer->swap_buffers ();
+}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
index 8b775fb..ba962b5 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright © 2010,2011 Google, Inc.
+ * Copyright © 2010,2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -30,26 +30,31 @@
#include "hb-private.hh"
#include "hb-ot-map-private.hh"
+#include "hb-ot-shape-normalize-private.hh"
/* buffer var allocations, used during the entire shaping process */
-#define general_category() var1.u8[0] /* unicode general_category (hb_unicode_general_category_t) */
-#define combining_class() var1.u8[1] /* unicode combining_class (uint8_t) */
+#define unicode_props0() var1.u8[0]
+#define unicode_props1() var1.u8[1]
+
+/* buffer var allocations, used during the GSUB/GPOS processing */
+#define props_cache() var1.u16[1] /* GSUB/GPOS glyph_props cache */
+#define syllable() var2.u8[0] /* GSUB/GPOS shaping boundaries */
+#define lig_props() var2.u8[1] /* GSUB/GPOS ligature tracking */
/* buffer var allocations, used by complex shapers */
-#define complex_var_persistent_u8_0() var2.u8[0]
-#define complex_var_persistent_u8_1() var2.u8[1]
-#define complex_var_persistent_u16() var2.u16[0]
-#define complex_var_temporary_u8_0() var2.u8[2]
-#define complex_var_temporary_u8_1() var2.u8[3]
-#define complex_var_temporary_u16() var2.u16[1]
+#define complex_var_persistent_u8_0() var2.u8[2]
+#define complex_var_persistent_u8_1() var2.u8[3]
+#define complex_var_temporary_u8() var2.u8[0]
#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
+ HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
+ HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
/* ^--- Add new shapers here */
enum hb_ot_complex_shaper_t {
@@ -63,78 +68,152 @@ enum hb_ot_complex_shaper_t {
static inline hb_ot_complex_shaper_t
hb_ot_shape_complex_categorize (const hb_segment_properties_t *props)
{
- switch ((int) props->script)
+ switch ((hb_tag_t) props->script)
{
default:
return hb_ot_complex_shaper_default;
+
+ /* Unicode-1.1 additions */
case HB_SCRIPT_ARABIC:
- case HB_SCRIPT_MANDAIC:
case HB_SCRIPT_MONGOLIAN:
- case HB_SCRIPT_NKO:
case HB_SCRIPT_SYRIAC:
+
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_NKO:
+
+ /* Unicode-6.0 additions */
+ case HB_SCRIPT_MANDAIC:
+
return hb_ot_complex_shaper_arabic;
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_HANGUL:
+
+ return hb_ot_complex_shaper_hangul;
+
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_THAI:
+ case HB_SCRIPT_LAO:
+
+ return hb_ot_complex_shaper_thai;
+
+
+
+ /* ^--- Add new shapers here */
+
+
#if 0
/* Note:
*
* These disabled scripts are listed in ucd/IndicSyllabicCategory.txt, but according
- * to Martin Hosken do not require complex shaping.
+ * to Martin Hosken and Jonathan Kew do not require complex shaping.
+ *
+ * TODO We should automate figuring out which scripts do not need complex shaping
*
* TODO We currently keep data for these scripts in our indic table. Need to fix the
* generator to not do that.
*/
+
/* Simple? */
- case HB_SCRIPT_BATAK:
- case HB_SCRIPT_BRAHMI:
+
+ /* Unicode-3.2 additions */
+ case HB_SCRIPT_BUHID:
case HB_SCRIPT_HANUNOO:
- case HB_SCRIPT_MEETEI_MAYEK:
+
+ /* Unicode-5.1 additions */
case HB_SCRIPT_SAURASHTRA:
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK:
+
+ /* Unicode-6.0 additions */
+ case HB_SCRIPT_BATAK:
+ case HB_SCRIPT_BRAHMI:
+
+
/* Simple */
- case HB_SCRIPT_KAYAH_LI:
+
+ /* Unicode-1.1 additions */
+ /* These have their own shaper now. */
case HB_SCRIPT_LAO:
- case HB_SCRIPT_LIMBU:
- case HB_SCRIPT_PHAGS_PA:
- case HB_SCRIPT_SYLOTI_NAGRI:
+ case HB_SCRIPT_THAI:
+
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN:
+
+ /* Unicode-3.2 additions */
case HB_SCRIPT_TAGALOG:
case HB_SCRIPT_TAGBANWA:
+
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU:
case HB_SCRIPT_TAI_LE:
+
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI:
+
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA:
+
+ /* Unicode-5.1 additions */
+ case HB_SCRIPT_KAYAH_LI:
+
+ /* Unicode-5.2 additions */
case HB_SCRIPT_TAI_VIET:
- case HB_SCRIPT_THAI:
- case HB_SCRIPT_TIBETAN:
+
/* May need Indic treatment in the future? */
+
+ /* Unicode-3.0 additions */
case HB_SCRIPT_MYANMAR:
+
+
#endif
- case HB_SCRIPT_BALINESE:
+ /* Unicode-1.1 additions */
case HB_SCRIPT_BENGALI:
- case HB_SCRIPT_BUGINESE:
- case HB_SCRIPT_BUHID:
- case HB_SCRIPT_CHAM:
case HB_SCRIPT_DEVANAGARI:
case HB_SCRIPT_GUJARATI:
case HB_SCRIPT_GURMUKHI:
- case HB_SCRIPT_JAVANESE:
- case HB_SCRIPT_KAITHI:
case HB_SCRIPT_KANNADA:
- case HB_SCRIPT_KHAROSHTHI:
- case HB_SCRIPT_KHMER:
- case HB_SCRIPT_LEPCHA:
case HB_SCRIPT_MALAYALAM:
- case HB_SCRIPT_NEW_TAI_LUE:
case HB_SCRIPT_ORIYA:
- case HB_SCRIPT_REJANG:
+ case HB_SCRIPT_TAMIL:
+ case HB_SCRIPT_TELUGU:
+
+ /* Unicode-3.0 additions */
+ case HB_SCRIPT_KHMER:
case HB_SCRIPT_SINHALA:
+
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_BUGINESE:
+ case HB_SCRIPT_KHAROSHTHI:
+ case HB_SCRIPT_NEW_TAI_LUE:
+
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_BALINESE:
+
+ /* Unicode-5.1 additions */
+ case HB_SCRIPT_CHAM:
+ case HB_SCRIPT_LEPCHA:
+ case HB_SCRIPT_REJANG:
case HB_SCRIPT_SUNDANESE:
+
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_JAVANESE:
+ case HB_SCRIPT_KAITHI:
case HB_SCRIPT_TAI_THAM:
- case HB_SCRIPT_TAMIL:
- case HB_SCRIPT_TELUGU:
- return hb_ot_complex_shaper_indic;
- /* ^--- Add new shapers here */
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_CHAKMA:
+ case HB_SCRIPT_SHARADA:
+ case HB_SCRIPT_TAKRI:
+
+ return hb_ot_complex_shaper_indic;
}
}
@@ -170,26 +249,26 @@ hb_ot_shape_complex_collect_features (hb_ot_complex_shaper_t shaper,
/*
- * prefer_decomposed()
+ * normalization_preference()
*
* Called during shape_execute().
*
* Shapers should return TRUE if it prefers decomposed (NFD) input rather than precomposed (NFC).
*/
-typedef bool hb_ot_shape_complex_prefer_decomposed_func_t (void);
+typedef hb_ot_shape_normalization_mode_t hb_ot_shape_complex_normalization_preference_func_t (void);
#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
- HB_INTERNAL hb_ot_shape_complex_prefer_decomposed_func_t _hb_ot_shape_complex_prefer_decomposed_##name;
+ HB_INTERNAL hb_ot_shape_complex_normalization_preference_func_t _hb_ot_shape_complex_normalization_preference_##name;
HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
#undef HB_COMPLEX_SHAPER_IMPLEMENT
-static inline bool
-hb_ot_shape_complex_prefer_decomposed (hb_ot_complex_shaper_t shaper)
+static inline hb_ot_shape_normalization_mode_t
+hb_ot_shape_complex_normalization_preference (hb_ot_complex_shaper_t shaper)
{
switch (shaper) {
default:
#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
- case hb_ot_complex_shaper_##name: return _hb_ot_shape_complex_prefer_decomposed_##name ();
+ case hb_ot_complex_shaper_##name: return _hb_ot_shape_complex_normalization_preference_##name ();
HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
#undef HB_COMPLEX_SHAPER_IMPLEMENT
}
@@ -203,7 +282,7 @@ hb_ot_shape_complex_prefer_decomposed (hb_ot_complex_shaper_t shaper)
* Shapers should use map to get feature masks and set on buffer.
*/
-typedef void hb_ot_shape_complex_setup_masks_func_t (hb_ot_map_t *map, hb_buffer_t *buffer);
+typedef void hb_ot_shape_complex_setup_masks_func_t (hb_ot_map_t *map, hb_buffer_t *buffer, hb_font_t *font);
#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
HB_INTERNAL hb_ot_shape_complex_setup_masks_func_t _hb_ot_shape_complex_setup_masks_##name;
HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
@@ -212,12 +291,13 @@ typedef void hb_ot_shape_complex_setup_masks_func_t (hb_ot_map_t *map, hb_buffer
static inline void
hb_ot_shape_complex_setup_masks (hb_ot_complex_shaper_t shaper,
hb_ot_map_t *map,
- hb_buffer_t *buffer)
+ hb_buffer_t *buffer,
+ hb_font_t *font)
{
switch (shaper) {
default:
#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
- case hb_ot_complex_shaper_##name: _hb_ot_shape_complex_setup_masks_##name (map, buffer); return;
+ case hb_ot_complex_shaper_##name: _hb_ot_shape_complex_setup_masks_##name (map, buffer, font); return;
HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
#undef HB_COMPLEX_SHAPER_IMPLEMENT
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh
new file mode 100644
index 0000000..bb81f00
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
+#define HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
+
+#include "hb-private.hh"
+
+#include "hb-font.h"
+#include "hb-buffer.h"
+
+
+enum hb_ot_shape_normalization_mode_t {
+ HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL /* including base-to-base composition */
+};
+
+HB_INTERNAL void _hb_ot_shape_normalize (hb_font_t *font,
+ hb_buffer_t *buffer,
+ hb_ot_shape_normalization_mode_t mode);
+
+#endif /* HB_OT_SHAPE_NORMALIZE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
index eb9f32a..a9019fb 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,8 +24,8 @@
* Google Author(s): Behdad Esfahbod
*/
+#include "hb-ot-shape-normalize-private.hh"
#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-complex-private.hh"
/*
@@ -34,8 +34,10 @@
* This file exports one main function: _hb_ot_shape_normalize().
*
* This function closely reflects the Unicode Normalization Algorithm,
- * yet it's different. The shaper an either prefer decomposed (NFD) or
- * composed (NFC).
+ * yet it's different.
+ *
+ * Each shaper specifies whether it prefers decomposed (NFD) or composed (NFC).
+ * The logic however tries to use whatever the font can support.
*
* In general what happens is that: each grapheme is decomposed in a chain
* of 1:2 decompositions, marks reordered, and then recomposed if desired,
@@ -56,8 +58,8 @@
* which typically has better mark positioning.
*
* - When a font does not support a combining mark, but supports it precomposed
- * with previous base. This needs the itemizer to have this knowledge too.
- * We need ot provide assistance to the itemizer.
+ * with previous base, use that. This needs the itemizer to have this
+ * knowledge too. We need to provide assistance to the itemizer.
*
* - When a font does not support a character but supports its decomposition,
* well, use the decomposition.
@@ -67,45 +69,42 @@
*/
static void
-output_glyph (hb_ot_shape_context_t *c,
- hb_codepoint_t glyph)
+output_glyph (hb_buffer_t *buffer, hb_codepoint_t glyph)
{
- hb_buffer_t *buffer = c->buffer;
-
buffer->output_glyph (glyph);
- hb_glyph_info_set_unicode_props (&buffer->out_info[buffer->out_len - 1], buffer->unicode);
+ _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer->unicode);
}
static bool
-decompose (hb_ot_shape_context_t *c,
+decompose (hb_font_t *font, hb_buffer_t *buffer,
bool shortest,
hb_codepoint_t ab)
{
hb_codepoint_t a, b, glyph;
- if (!hb_unicode_decompose (c->buffer->unicode, ab, &a, &b) ||
- (b && !hb_font_get_glyph (c->font, b, 0, &glyph)))
+ if (!hb_unicode_decompose (buffer->unicode, ab, &a, &b) ||
+ (b && !hb_font_get_glyph (font, b, 0, &glyph)))
return FALSE;
- bool has_a = hb_font_get_glyph (c->font, a, 0, &glyph);
+ bool has_a = hb_font_get_glyph (font, a, 0, &glyph);
if (shortest && has_a) {
/* Output a and b */
- output_glyph (c, a);
+ output_glyph (buffer, a);
if (b)
- output_glyph (c, b);
+ output_glyph (buffer, b);
return TRUE;
}
- if (decompose (c, shortest, a)) {
+ if (decompose (font, buffer, shortest, a)) {
if (b)
- output_glyph (c, b);
+ output_glyph (buffer, b);
return TRUE;
}
if (has_a) {
- output_glyph (c, a);
+ output_glyph (buffer, a);
if (b)
- output_glyph (c, b);
+ output_glyph (buffer, b);
return TRUE;
}
@@ -113,60 +112,60 @@ decompose (hb_ot_shape_context_t *c,
}
static void
-decompose_current_glyph (hb_ot_shape_context_t *c,
+decompose_current_glyph (hb_font_t *font, hb_buffer_t *buffer,
bool shortest)
{
- if (decompose (c, shortest, c->buffer->info[c->buffer->idx].codepoint))
- c->buffer->skip_glyph ();
+ if (decompose (font, buffer, shortest, buffer->cur().codepoint))
+ buffer->skip_glyph ();
else
- c->buffer->next_glyph ();
+ buffer->next_glyph ();
}
static void
-decompose_single_char_cluster (hb_ot_shape_context_t *c,
+decompose_single_char_cluster (hb_font_t *font, hb_buffer_t *buffer,
bool will_recompose)
{
hb_codepoint_t glyph;
/* If recomposing and font supports this, we're good to go */
- if (will_recompose && hb_font_get_glyph (c->font, c->buffer->info[c->buffer->idx].codepoint, 0, &glyph)) {
- c->buffer->next_glyph ();
+ if (will_recompose && hb_font_get_glyph (font, buffer->cur().codepoint, 0, &glyph)) {
+ buffer->next_glyph ();
return;
}
- decompose_current_glyph (c, will_recompose);
+ decompose_current_glyph (font, buffer, will_recompose);
}
static void
-decompose_multi_char_cluster (hb_ot_shape_context_t *c,
+decompose_multi_char_cluster (hb_font_t *font, hb_buffer_t *buffer,
unsigned int end)
{
/* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
- for (unsigned int i = c->buffer->idx; i < end; i++)
- if (unlikely (is_variation_selector (c->buffer->info[i].codepoint))) {
- while (c->buffer->idx < end)
- c->buffer->next_glyph ();
+ for (unsigned int i = buffer->idx; i < end; i++)
+ if (unlikely (_hb_unicode_is_variation_selector (buffer->info[i].codepoint))) {
+ while (buffer->idx < end)
+ buffer->next_glyph ();
return;
}
- while (c->buffer->idx < end)
- decompose_current_glyph (c, FALSE);
+ while (buffer->idx < end)
+ decompose_current_glyph (font, buffer, FALSE);
}
static int
compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
{
- unsigned int a = pa->combining_class();
- unsigned int b = pb->combining_class();
+ unsigned int a = _hb_glyph_info_get_modified_combining_class (pa);
+ unsigned int b = _hb_glyph_info_get_modified_combining_class (pb);
return a < b ? -1 : a == b ? 0 : +1;
}
void
-_hb_ot_shape_normalize (hb_ot_shape_context_t *c)
+_hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer,
+ hb_ot_shape_normalization_mode_t mode)
{
- hb_buffer_t *buffer = c->buffer;
- bool recompose = !hb_ot_shape_complex_prefer_decomposed (c->plan->shaper);
+ bool recompose = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED;
bool has_multichar_clusters = FALSE;
unsigned int count;
@@ -185,31 +184,20 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c)
{
unsigned int end;
for (end = buffer->idx + 1; end < count; end++)
- if (buffer->info[buffer->idx].cluster != buffer->info[end].cluster)
+ if (buffer->cur().cluster != buffer->info[end].cluster)
break;
if (buffer->idx + 1 == end)
- decompose_single_char_cluster (c, recompose);
+ decompose_single_char_cluster (font, buffer, recompose);
else {
- decompose_multi_char_cluster (c, end);
+ decompose_multi_char_cluster (font, buffer, end);
has_multichar_clusters = TRUE;
}
}
buffer->swap_buffers ();
- /* Technically speaking, two characters with ccc=0 may combine. But all
- * those cases are in languages that the indic module handles (which expects
- * decomposed), or in Hangul jamo, which again, we want decomposed anyway.
- * So we don't bother combining across cluster boundaries. This is a huge
- * performance saver if the compose() callback is slow.
- *
- * TODO: Am I right about Hangul? If I am, we should add a Hangul module
- * that requests decomposed. If for Hangul we end up wanting composed, we
- * can do that in the Hangul module.
- */
-
- if (!has_multichar_clusters)
+ if (mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL && !has_multichar_clusters)
return; /* Done! */
@@ -218,12 +206,12 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c)
count = buffer->len;
for (unsigned int i = 0; i < count; i++)
{
- if (buffer->info[i].combining_class() == 0)
+ if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
continue;
unsigned int end;
for (end = i + 1; end < count; end++)
- if (buffer->info[end].combining_class() == 0)
+ if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
break;
/* We are going to do a bubble-sort. Only do this if the
@@ -254,33 +242,38 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c)
buffer->next_glyph ();
while (buffer->idx < count)
{
- if (buffer->info[buffer->idx].combining_class() == 0) {
- starter = buffer->out_len;
- buffer->next_glyph ();
- continue;
- }
-
hb_codepoint_t composed, glyph;
- if ((buffer->out_info[buffer->out_len - 1].combining_class() >=
- buffer->info[buffer->idx].combining_class()) ||
- !hb_unicode_compose (c->buffer->unicode,
- buffer->out_info[starter].codepoint,
- buffer->info[buffer->idx].codepoint,
- &composed) ||
- !hb_font_get_glyph (c->font, composed, 0, &glyph))
+ if (/* If mode is NOT COMPOSED_FULL (ie. it's COMPOSED_DIACRITICS), we don't try to
+ * compose a CCC=0 character with it's preceding starter. */
+ (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL ||
+ _hb_glyph_info_get_modified_combining_class (&buffer->cur()) != 0) &&
+ /* If there's anything between the starter and this char, they should have CCC
+ * smaller than this character's. */
+ (starter == buffer->out_len - 1 ||
+ _hb_glyph_info_get_modified_combining_class (&buffer->prev()) < _hb_glyph_info_get_modified_combining_class (&buffer->cur())) &&
+ /* And compose. */
+ hb_unicode_compose (buffer->unicode,
+ buffer->out_info[starter].codepoint,
+ buffer->cur().codepoint,
+ &composed) &&
+ /* And the font has glyph for the composite. */
+ hb_font_get_glyph (font, composed, 0, &glyph))
{
- /* Blocked, or doesn't compose. */
- buffer->next_glyph ();
+ /* Composes. Modify starter and carry on. */
+ buffer->out_info[starter].codepoint = composed;
+ /* XXX update cluster */
+ _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode);
+
+ buffer->skip_glyph ();
continue;
}
- /* Composes. Modify starter and carry on. */
- buffer->out_info[starter].codepoint = composed;
- hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode);
+ /* Blocked, or doesn't compose. */
+ buffer->next_glyph ();
- buffer->skip_glyph ();
+ if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0)
+ starter = buffer->out_len - 1;
}
buffer->swap_buffers ();
}
-
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
index c49c2b0..df0c705 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
@@ -29,19 +29,12 @@
#include "hb-private.hh"
-#include "hb-ot-shape.h"
-
#include "hb-ot-map-private.hh"
#include "hb-ot-shape-complex-private.hh"
-
-enum hb_ot_complex_shaper_t;
-
struct hb_ot_shape_plan_t
{
- friend struct hb_ot_shape_planner_t;
-
hb_ot_map_t map;
hb_ot_complex_shaper_t shaper;
@@ -52,78 +45,39 @@ struct hb_ot_shape_plan_t
NO_COPY (hb_ot_shape_plan_t);
};
-struct hb_ot_shape_planner_t
-{
- hb_ot_map_builder_t map;
- hb_ot_complex_shaper_t shaper;
-
- hb_ot_shape_planner_t (void) : map () {}
- ~hb_ot_shape_planner_t (void) { map.finish (); }
- inline void compile (hb_face_t *face,
- const hb_segment_properties_t *props,
- struct hb_ot_shape_plan_t &plan)
- {
- plan.shaper = shaper;
- map.compile (face, props, plan.map);
- }
- private:
- NO_COPY (hb_ot_shape_planner_t);
-};
+HB_INTERNAL hb_bool_t
+_hb_ot_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features);
-struct hb_ot_shape_context_t
+inline void
+_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
{
- /* Input to hb_ot_shape_execute() */
- hb_ot_shape_plan_t *plan;
- hb_font_t *font;
- hb_face_t *face;
- hb_buffer_t *buffer;
- const hb_feature_t *user_features;
- unsigned int num_user_features;
-
- /* Transient stuff */
- hb_direction_t target_direction;
- hb_bool_t applied_substitute_complex;
- hb_bool_t applied_position_complex;
-};
-
+ info->unicode_props0() = ((unsigned int) hb_unicode_general_category (unicode, info->codepoint)) |
+ (_hb_unicode_is_zero_width (info->codepoint) ? 0x80 : 0);
+ info->unicode_props1() = _hb_unicode_modified_combining_class (unicode, info->codepoint);
+}
-static inline hb_bool_t
-is_variation_selector (hb_codepoint_t unicode)
+inline hb_unicode_general_category_t
+_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
{
- return unlikely ((unicode >= 0x180B && unicode <= 0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
- (unicode >= 0xFE00 && unicode <= 0xFE0F) || /* VARIATION SELECTOR-1..16 */
- (unicode >= 0xE0100 && unicode <= 0xE01EF)); /* VARIATION SELECTOR-17..256 */
+ return (hb_unicode_general_category_t) (info->unicode_props0() & 0x7F);
}
-static inline unsigned int
-_hb_unicode_modified_combining_class (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode)
+inline unsigned int
+_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
{
- int c = hb_unicode_combining_class (ufuncs, unicode);
-
- /* Modify the combining-class to suit Arabic better. See:
- * http://unicode.org/faq/normalization.html#8
- * http://unicode.org/faq/normalization.html#9
- */
- if (unlikely (hb_in_range<int> (c, 27, 33)))
- c = c == 33 ? 27 : c + 1;
-
- return c;
+ return info->unicode_props1();
}
-static inline void
-hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
+inline hb_bool_t
+_hb_glyph_info_is_zero_width (const hb_glyph_info_t *info)
{
- info->general_category() = hb_unicode_general_category (unicode, info->codepoint);
- info->combining_class() = _hb_unicode_modified_combining_class (unicode, info->codepoint);
+ return !!(info->unicode_props0() & 0x80);
}
-HB_INTERNAL void _hb_set_unicode_props (hb_buffer_t *buffer);
-
-HB_INTERNAL void _hb_ot_shape_normalize (hb_ot_shape_context_t *c);
-
-
#endif /* HB_OT_SHAPE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.cc b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
index 4275afc..8b1d670 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
@@ -27,26 +27,28 @@
*/
#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-normalize-private.hh"
#include "hb-font-private.hh"
+#include "hb-set-private.hh"
hb_tag_t common_features[] = {
HB_TAG('c','c','m','p'),
+ HB_TAG('l','i','g','a'),
HB_TAG('l','o','c','l'),
HB_TAG('m','a','r','k'),
HB_TAG('m','k','m','k'),
HB_TAG('r','l','i','g'),
};
+
hb_tag_t horizontal_features[] = {
HB_TAG('c','a','l','t'),
HB_TAG('c','l','i','g'),
HB_TAG('c','u','r','s'),
HB_TAG('k','e','r','n'),
- HB_TAG('l','i','g','a'),
};
/* Note:
@@ -62,6 +64,28 @@ hb_tag_t vertical_features[] = {
HB_TAG('v','r','t','2'),
};
+
+
+struct hb_ot_shape_planner_t
+{
+ hb_ot_map_builder_t map;
+ hb_ot_complex_shaper_t shaper;
+
+ hb_ot_shape_planner_t (void) : map () {}
+ ~hb_ot_shape_planner_t (void) { map.finish (); }
+
+ inline void compile (hb_face_t *face,
+ const hb_segment_properties_t *props,
+ struct hb_ot_shape_plan_t &plan)
+ {
+ plan.shaper = shaper;
+ map.compile (face, props, plan.map);
+ }
+
+ private:
+ NO_COPY (hb_ot_shape_planner_t);
+};
+
static void
hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
const hb_segment_properties_t *props,
@@ -108,13 +132,28 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
}
+struct hb_ot_shape_context_t
+{
+ /* Input to hb_ot_shape_execute() */
+ hb_ot_shape_plan_t *plan;
+ hb_font_t *font;
+ hb_face_t *face;
+ hb_buffer_t *buffer;
+ const hb_feature_t *user_features;
+ unsigned int num_user_features;
+
+ /* Transient stuff */
+ hb_direction_t target_direction;
+ hb_bool_t applied_position_complex;
+};
+
static void
hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
{
hb_mask_t global_mask = c->plan->map.get_global_mask ();
c->buffer->reset_masks (global_mask);
- hb_ot_shape_complex_setup_masks (c->plan->shaper, &c->plan->map, c->buffer);
+ hb_ot_shape_complex_setup_masks (c->plan->shaper, &c->plan->map, c->buffer, c->font);
for (unsigned int i = 0; i < c->num_user_features; i++)
{
@@ -132,12 +171,12 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
/* Prepare */
-void
-_hb_set_unicode_props (hb_buffer_t *buffer)
+static void
+hb_set_unicode_props (hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
- for (unsigned int i = 1; i < count; i++)
- hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode);
+ for (unsigned int i = 0; i < count; i++)
+ _hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode);
}
static void
@@ -145,11 +184,11 @@ hb_form_clusters (hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
for (unsigned int i = 1; i < count; i++)
- if (FLAG (buffer->info[i].general_category()) &
+ if (FLAG (_hb_glyph_info_get_general_category (&buffer->info[i])) &
(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
- buffer->info[i].cluster = buffer->info[i - 1].cluster;
+ buffer->info[i].cluster = buffer->info[i - 1].cluster; /* XXX do the min() here */
}
static void
@@ -205,17 +244,16 @@ hb_map_glyphs (hb_font_t *font,
unsigned int count = buffer->len - 1;
for (buffer->idx = 0; buffer->idx < count;) {
- if (unlikely (is_variation_selector (buffer->info[buffer->idx + 1].codepoint))) {
- hb_font_get_glyph (font, buffer->info[buffer->idx].codepoint, buffer->info[buffer->idx + 1].codepoint, &glyph);
- buffer->replace_glyph (glyph);
- buffer->skip_glyph ();
+ if (unlikely (_hb_unicode_is_variation_selector (buffer->cur(+1).codepoint))) {
+ hb_font_get_glyph (font, buffer->cur().codepoint, buffer->cur(+1).codepoint, &glyph);
+ buffer->replace_glyphs (2, 1, &glyph);
} else {
- hb_font_get_glyph (font, buffer->info[buffer->idx].codepoint, 0, &glyph);
+ hb_font_get_glyph (font, buffer->cur().codepoint, 0, &glyph);
buffer->replace_glyph (glyph);
}
}
if (likely (buffer->idx < buffer->len)) {
- hb_font_get_glyph (font, buffer->info[buffer->idx].codepoint, 0, &glyph);
+ hb_font_get_glyph (font, buffer->cur().codepoint, 0, &glyph);
buffer->replace_glyph (glyph);
}
buffer->swap_buffers ();
@@ -236,7 +274,6 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
{
if (hb_ot_layout_has_substitution (c->face)) {
c->plan->map.substitute (c->face, c->buffer);
- c->applied_substitute_complex = TRUE;
}
hb_ot_layout_substitute_finish (c->buffer);
@@ -244,12 +281,6 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
return;
}
-static void
-hb_substitute_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
-{
- /* TODO Arabic */
-}
-
/* Position */
@@ -342,6 +373,23 @@ hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
hb_truetype_kern (c);
}
+static void
+hb_hide_zerowidth (hb_ot_shape_context_t *c)
+{
+ /* TODO Save the space character in the font? */
+ hb_codepoint_t space;
+ if (!hb_font_get_glyph (c->font, ' ', 0, &space))
+ return; /* No point! */
+
+ unsigned int count = c->buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (_hb_glyph_info_is_zero_width (&c->buffer->info[i]))) {
+ c->buffer->info[i].codepoint = space;
+ c->buffer->pos[i].x_advance = 0;
+ c->buffer->pos[i].y_advance = 0;
+ }
+}
+
/* Do it! */
@@ -353,16 +401,16 @@ hb_ot_shape_execute_internal (hb_ot_shape_context_t *c)
/* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
- HB_BUFFER_ALLOCATE_VAR (c->buffer, general_category);
- HB_BUFFER_ALLOCATE_VAR (c->buffer, combining_class);
+ HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props0);
+ HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props1);
- _hb_set_unicode_props (c->buffer); /* BUFFER: Set general_category and combining_class */
+ hb_set_unicode_props (c->buffer);
hb_form_clusters (c->buffer);
hb_ensure_native_direction (c->buffer);
- _hb_ot_shape_normalize (c);
+ _hb_ot_shape_normalize (c->font, c->buffer, hb_ot_shape_complex_normalization_preference (c->plan->shaper));
hb_ot_shape_setup_masks (c);
@@ -371,9 +419,6 @@ hb_ot_shape_execute_internal (hb_ot_shape_context_t *c)
hb_substitute_default (c);
hb_ot_substitute_complex (c);
-
- if (!c->applied_substitute_complex)
- hb_substitute_complex_fallback (c);
}
/* POSITION */
@@ -393,8 +438,10 @@ hb_ot_shape_execute_internal (hb_ot_shape_context_t *c)
hb_position_complex_fallback_visual (c);
}
- HB_BUFFER_DEALLOCATE_VAR (c->buffer, combining_class);
- HB_BUFFER_DEALLOCATE_VAR (c->buffer, general_category);
+ hb_hide_zerowidth (c);
+
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1);
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0);
c->buffer->props.direction = c->target_direction;
@@ -410,6 +457,8 @@ hb_ot_shape_plan_internal (hb_ot_shape_plan_t *plan,
{
hb_ot_shape_planner_t planner;
+ assert (HB_DIRECTION_IS_VALID (props->direction));
+
planner.shaper = hb_ot_shape_complex_categorize (props);
hb_ot_shape_collect_features (&planner, props, user_features, num_user_features);
@@ -429,11 +478,10 @@ hb_ot_shape_execute (hb_ot_shape_plan_t *plan,
}
hb_bool_t
-hb_ot_shape (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options)
+_hb_ot_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features)
{
hb_ot_shape_plan_t plan;
@@ -446,3 +494,35 @@ hb_ot_shape (hb_font_t *font,
}
+void
+hb_ot_shape_glyphs_closure (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ hb_set_t *glyphs)
+{
+ hb_ot_shape_plan_t plan;
+
+ buffer->guess_properties ();
+
+ hb_ot_shape_plan_internal (&plan, font->face, &buffer->props, features, num_features);
+
+ /* TODO: normalization? have shapers do closure()? */
+ /* TODO: Deal with mirrored chars? */
+ hb_map_glyphs (font, buffer);
+
+ /* Seed it. It's user's responsibility to have cleard glyphs
+ * if that's what they desire. */
+ unsigned int count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ hb_set_add (glyphs, buffer->info[i].codepoint);
+
+ /* And find transitive closure. */
+ hb_set_t copy;
+ copy.init ();
+
+ do {
+ copy.set (glyphs);
+ plan.map.substitute_closure (font->face, glyphs);
+ } while (!copy.equal (glyphs));
+}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-tag.h b/third_party/harfbuzz-ng/src/hb-ot-tag.h
index 427a069..1bf12ab 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-tag.h
+++ b/third_party/harfbuzz-ng/src/hb-ot-tag.h
@@ -24,10 +24,14 @@
* Red Hat Author(s): Behdad Esfahbod
*/
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
#ifndef HB_OT_TAG_H
#define HB_OT_TAG_H
-#include "hb-common.h"
+#include "hb.h"
HB_BEGIN_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ot.h b/third_party/harfbuzz-ng/src/hb-ot.h
index fd6dd58..2d750c3 100644
--- a/third_party/harfbuzz-ng/src/hb-ot.h
+++ b/third_party/harfbuzz-ng/src/hb-ot.h
@@ -26,14 +26,23 @@
#ifndef HB_OT_H
#define HB_OT_H
+#define HB_OT_H_IN
#include "hb.h"
#include "hb-ot-layout.h"
-#include "hb-ot-shape.h"
#include "hb-ot-tag.h"
HB_BEGIN_DECLS
+
+void
+hb_ot_shape_glyphs_closure (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ hb_set_t *glyphs);
+
HB_END_DECLS
+#undef HB_OT_H_IN
#endif /* HB_OT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-private.hh b/third_party/harfbuzz-ng/src/hb-private.hh
index c757e2dc..aa86072 100644
--- a/third_party/harfbuzz-ng/src/hb-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-private.hh
@@ -1,6 +1,6 @@
/*
* Copyright © 2007,2008,2009 Red Hat, Inc.
- * Copyright © 2011 Google, Inc.
+ * Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -33,7 +33,12 @@
#include "config.h"
#endif
-#include "hb-common.h"
+#include "hb.h"
+#define HB_H_IN
+#ifdef HAVE_OT
+#include "hb-ot.h"
+#define HB_OT_H_IN
+#endif
#include <stdlib.h>
#include <stddef.h>
@@ -86,6 +91,8 @@ template <typename Type> static inline Type MAX (const Type &a, const Type &b) {
#define ASSERT_STATIC_EXPR(_cond) ((void) sizeof (char[(_cond) ? 1 : -1]))
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1]))
+#define _PASTE1(a,b) a##b
+#define PASTE(a,b) _PASTE1(a,b)
/* Lets assert int types. Saves trouble down the road. */
@@ -437,6 +444,14 @@ static inline uint16_t hb_be_uint16 (const uint16_t v)
return (uint16_t) (V[0] << 8) + V[1];
}
+/* Note, of the following macros, uint16_get is the one called many many times.
+ * If there is any optimizations to be done, it's in that macro. However, I
+ * already confirmed that on my T400 ThinkPad at least, using bswap_16(), which
+ * results in a single ror instruction, does NOT speed this up. In fact, it
+ * resulted in a minor slowdown. At any rate, note that v may not be correctly
+ * aligned, so I think the current implementation is optimal.
+ */
+
#define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END
#define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1])
#define hb_be_uint16_eq(a,b) (a[0] == b[0] && a[1] == b[1])
@@ -488,62 +503,106 @@ _hb_debug (unsigned int level,
#define DEBUG_LEVEL(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
#define DEBUG(WHAT) (DEBUG_LEVEL (WHAT, 0))
-template <int max_level> inline bool /* always returns TRUE */
+template <int max_level> inline void
+_hb_debug_msg_va (const char *what,
+ const void *obj,
+ const char *func,
+ bool indented,
+ unsigned int level,
+ int level_dir,
+ const char *message,
+ va_list ap)
+{
+ if (!_hb_debug (level, max_level))
+ return;
+
+ fprintf (stderr, "%-10s", what ? what : "");
+
+ if (obj)
+ fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
+ else
+ fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), "");
+
+ if (indented) {
+ static const char bars[] = "││││││││││││││││││││││││││││││││││││││││";
+ fprintf (stderr, "%2d %s├%s",
+ level,
+ bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), 3 * level),
+ level_dir ? (level_dir > 0 ? "╮" : "╯") : "╴");
+ } else
+ fprintf (stderr, " ├╴");
+
+ if (func) {
+ /* If there's a class name, just write that. */
+ const char *dotdot = strstr (func, "::");
+ const char *space = strchr (func, ' ');
+ if (space && dotdot && space < dotdot)
+ func = space + 1;
+ unsigned int func_len = dotdot ? dotdot - func : strlen (func);
+ fprintf (stderr, "%.*s: ", func_len, func);
+ }
+
+ if (message)
+ vfprintf (stderr, message, ap);
+
+ fprintf (stderr, "\n");
+}
+template <> inline void
+_hb_debug_msg_va<0> (const char *what HB_UNUSED,
+ const void *obj HB_UNUSED,
+ const char *func HB_UNUSED,
+ bool indented HB_UNUSED,
+ unsigned int level HB_UNUSED,
+ int level_dir HB_UNUSED,
+ const char *message HB_UNUSED,
+ va_list ap HB_UNUSED) {}
+
+template <int max_level> inline void
_hb_debug_msg (const char *what,
const void *obj,
const char *func,
bool indented,
- int level,
+ unsigned int level,
+ int level_dir,
const char *message,
- ...) HB_PRINTF_FUNC(6, 7);
-template <int max_level> inline bool /* always returns TRUE */
+ ...) HB_PRINTF_FUNC(7, 8);
+template <int max_level> inline void
_hb_debug_msg (const char *what,
const void *obj,
const char *func,
bool indented,
- int level,
+ unsigned int level,
+ int level_dir,
const char *message,
...)
{
va_list ap;
va_start (ap, message);
-
- (void) (_hb_debug (level, max_level) &&
- fprintf (stderr, "%s", what) &&
- (obj && fprintf (stderr, "(%p)", obj), TRUE) &&
- fprintf (stderr, ": ") &&
- (func && fprintf (stderr, "%s: ", func), TRUE) &&
- (indented && fprintf (stderr, "%-*d-> ", level + 1, level), TRUE) &&
- vfprintf (stderr, message, ap) &&
- fprintf (stderr, "\n"));
-
+ _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
va_end (ap);
-
- return TRUE;
-}
-template <> inline bool /* always returns TRUE */
-_hb_debug_msg<0> (const char *what,
- const void *obj,
- const char *func,
- bool indented,
- int level,
- const char *message,
- ...) HB_PRINTF_FUNC(6, 7);
-template <> inline bool /* always returns TRUE */
-_hb_debug_msg<0> (const char *what,
- const void *obj,
- const char *func,
- bool indented,
- int level,
- const char *message,
- ...)
-{
- return TRUE;
}
-
-#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, FALSE, (LEVEL), __VA_ARGS__)
-#define DEBUG_MSG(WHAT, OBJ, ...) DEBUG_MSG_LEVEL (WHAT, OBJ, 0, __VA_ARGS__)
-#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, FALSE, 0, __VA_ARGS__)
+template <> inline void
+_hb_debug_msg<0> (const char *what HB_UNUSED,
+ const void *obj HB_UNUSED,
+ const char *func HB_UNUSED,
+ bool indented HB_UNUSED,
+ unsigned int level HB_UNUSED,
+ int level_dir HB_UNUSED,
+ const char *message HB_UNUSED,
+ ...) HB_PRINTF_FUNC(7, 8);
+template <> inline void
+_hb_debug_msg<0> (const char *what HB_UNUSED,
+ const void *obj HB_UNUSED,
+ const char *func HB_UNUSED,
+ bool indented HB_UNUSED,
+ unsigned int level HB_UNUSED,
+ int level_dir HB_UNUSED,
+ const char *message HB_UNUSED,
+ ...) {}
+
+#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, TRUE, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
+#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, FALSE, 0, 0, __VA_ARGS__)
+#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, FALSE, 0, 0, __VA_ARGS__)
/*
@@ -553,29 +612,64 @@ _hb_debug_msg<0> (const char *what,
template <int max_level>
struct hb_auto_trace_t {
explicit inline hb_auto_trace_t (unsigned int *plevel_,
- const char *what,
- const void *obj,
+ const char *what_,
+ const void *obj_,
const char *func,
- const char *message) : plevel(plevel_)
+ const char *message,
+ ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
+ {
+ if (plevel) ++*plevel;
+
+ va_list ap;
+ va_start (ap, message);
+ _hb_debug_msg_va<max_level> (what, obj, func, TRUE, plevel ? *plevel : 0, +1, message, ap);
+ va_end (ap);
+ }
+ inline ~hb_auto_trace_t (void)
{
- if (max_level) ++*plevel;
- /* TODO support variadic args here */
- _hb_debug_msg<max_level> (what, obj, func, TRUE, *plevel, "%s", message);
+ if (unlikely (!returned)) {
+ fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN. This is a bug, please report. Level was %d.\n", plevel ? *plevel : -1);
+ _hb_debug_msg<max_level> (what, obj, NULL, TRUE, plevel ? *plevel : 1, -1, " ");
+ return;
+ }
+
+ if (plevel) --*plevel;
+ }
+
+ inline bool ret (bool v)
+ {
+ if (unlikely (returned)) {
+ fprintf (stderr, "OUCH, double calls to TRACE_RETURN. This is a bug, please report.\n");
+ return v;
+ }
+
+ _hb_debug_msg<max_level> (what, obj, NULL, TRUE, plevel ? *plevel : 1, -1, "return %s", v ? "true" : "false");
+ if (plevel) --*plevel;
+ plevel = NULL;
+ returned = true;
+ return v;
}
- ~hb_auto_trace_t (void) { if (max_level) --*plevel; }
private:
unsigned int *plevel;
+ bool returned;
+ const char *what;
+ const void *obj;
};
template <> /* Optimize when tracing is disabled */
struct hb_auto_trace_t<0> {
- explicit inline hb_auto_trace_t (unsigned int *plevel_,
- const char *what,
- const void *obj,
- const char *func,
- const char *message) {}
+ explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED,
+ const char *what HB_UNUSED,
+ const void *obj HB_UNUSED,
+ const char *func HB_UNUSED,
+ const char *message HB_UNUSED,
+ ...) {}
+
+ template <typename T>
+ inline T ret (T v) { return v; }
};
+#define TRACE_RETURN(RET) trace.ret (RET)
/* Misc */
diff --git a/third_party/harfbuzz-ng/src/hb-set-private.hh b/third_party/harfbuzz-ng/src/hb-set-private.hh
new file mode 100644
index 0000000..9d8ba4a
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-set-private.hh
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SET_PRIVATE_HH
+#define HB_SET_PRIVATE_HH
+
+#include "hb-private.hh"
+#include "hb-set.h"
+#include "hb-object-private.hh"
+
+
+/* TODO Make this faster and memmory efficient. */
+
+struct _hb_set_t
+{
+ inline void init (void) {
+ clear ();
+ }
+ inline void fini (void) {
+ }
+ inline void clear (void) {
+ memset (elts, 0, sizeof elts);
+ }
+ inline bool empty (void) const {
+ for (unsigned int i = 0; i < ARRAY_LENGTH (elts); i++)
+ if (elts[i])
+ return false;
+ return true;
+ }
+ inline void add (hb_codepoint_t g)
+ {
+ if (unlikely (g == SENTINEL)) return;
+ if (unlikely (g > MAX_G)) return;
+ elt (g) |= mask (g);
+ }
+ inline void del (hb_codepoint_t g)
+ {
+ if (unlikely (g > MAX_G)) return;
+ elt (g) &= ~mask (g);
+ }
+ inline bool has (hb_codepoint_t g) const
+ {
+ if (unlikely (g > MAX_G)) return false;
+ return !!(elt (g) & mask (g));
+ }
+ inline bool intersects (hb_codepoint_t first,
+ hb_codepoint_t last) const
+ {
+ if (unlikely (first > MAX_G)) return false;
+ if (unlikely (last > MAX_G)) last = MAX_G;
+ unsigned int end = last + 1;
+ for (hb_codepoint_t i = first; i < end; i++)
+ if (has (i))
+ return true;
+ return false;
+ }
+ inline bool equal (const hb_set_t *other) const
+ {
+ for (unsigned int i = 0; i < ELTS; i++)
+ if (elts[i] != other->elts[i])
+ return false;
+ return true;
+ }
+ inline void set (const hb_set_t *other)
+ {
+ for (unsigned int i = 0; i < ELTS; i++)
+ elts[i] = other->elts[i];
+ }
+ inline void union_ (const hb_set_t *other)
+ {
+ for (unsigned int i = 0; i < ELTS; i++)
+ elts[i] |= other->elts[i];
+ }
+ inline void intersect (const hb_set_t *other)
+ {
+ for (unsigned int i = 0; i < ELTS; i++)
+ elts[i] &= other->elts[i];
+ }
+ inline void subtract (const hb_set_t *other)
+ {
+ for (unsigned int i = 0; i < ELTS; i++)
+ elts[i] &= ~other->elts[i];
+ }
+ inline void symmetric_difference (const hb_set_t *other)
+ {
+ for (unsigned int i = 0; i < ELTS; i++)
+ elts[i] ^= other->elts[i];
+ }
+ inline bool next (hb_codepoint_t *codepoint)
+ {
+ if (unlikely (*codepoint == SENTINEL)) {
+ hb_codepoint_t i = get_min ();
+ if (i != SENTINEL) {
+ *codepoint = i;
+ return true;
+ } else
+ return false;
+ }
+ for (hb_codepoint_t i = *codepoint + 1; i < MAX_G + 1; i++)
+ if (has (i)) {
+ *codepoint = i;
+ return true;
+ }
+ return false;
+ }
+ inline hb_codepoint_t get_min (void) const
+ {
+ for (unsigned int i = 0; i < ELTS; i++)
+ if (elts[i])
+ for (unsigned int j = 0; i < BITS; j++)
+ if (elts[i] & (1 << j))
+ return i * BITS + j;
+ return SENTINEL;
+ }
+ inline hb_codepoint_t get_max (void) const
+ {
+ for (unsigned int i = ELTS; i; i--)
+ if (elts[i - 1])
+ for (unsigned int j = BITS; j; j--)
+ if (elts[i - 1] & (1 << (j - 1)))
+ return (i - 1) * BITS + (j - 1);
+ return SENTINEL;
+ }
+
+ typedef uint32_t elt_t;
+ static const unsigned int MAX_G = 65536 - 1; /* XXX Fix this... */
+ static const unsigned int SHIFT = 5;
+ static const unsigned int BITS = (1 << SHIFT);
+ static const unsigned int MASK = BITS - 1;
+ static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS;
+ static const hb_codepoint_t SENTINEL = (hb_codepoint_t) -1;
+
+ elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
+ elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
+ elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
+
+ hb_object_header_t header;
+ elt_t elts[ELTS]; /* XXX 8kb */
+
+ ASSERT_STATIC (sizeof (elt_t) * 8 == BITS);
+ ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G);
+};
+
+
+
+#endif /* HB_SET_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-set.cc b/third_party/harfbuzz-ng/src/hb-set.cc
new file mode 100644
index 0000000..5045386
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-set.cc
@@ -0,0 +1,191 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-set-private.hh"
+
+
+
+/* Public API */
+
+static hb_set_t _hb_set_nil = {
+ HB_OBJECT_HEADER_STATIC,
+
+ {0} /* elts */
+};
+
+
+hb_set_t *
+hb_set_create ()
+{
+ hb_set_t *set;
+
+ if (!(set = hb_object_create<hb_set_t> ()))
+ return &_hb_set_nil;
+
+ set->clear ();
+
+ return set;
+}
+
+hb_set_t *
+hb_set_get_empty (void)
+{
+ return &_hb_set_nil;
+}
+
+hb_set_t *
+hb_set_reference (hb_set_t *set)
+{
+ return hb_object_reference (set);
+}
+
+void
+hb_set_destroy (hb_set_t *set)
+{
+ if (!hb_object_destroy (set)) return;
+
+ set->fini ();
+
+ free (set);
+}
+
+hb_bool_t
+hb_set_set_user_data (hb_set_t *set,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (set, key, data, destroy, replace);
+}
+
+void *
+hb_set_get_user_data (hb_set_t *set,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (set, key);
+}
+
+
+hb_bool_t
+hb_set_allocation_successful (hb_set_t *set HB_UNUSED)
+{
+ return TRUE;
+}
+
+void
+hb_set_clear (hb_set_t *set)
+{
+ set->clear ();
+}
+
+hb_bool_t
+hb_set_empty (hb_set_t *set)
+{
+ return set->empty ();
+}
+
+hb_bool_t
+hb_set_has (hb_set_t *set,
+ hb_codepoint_t codepoint)
+{
+ return set->has (codepoint);
+}
+
+void
+hb_set_add (hb_set_t *set,
+ hb_codepoint_t codepoint)
+{
+ set->add (codepoint);
+}
+
+void
+hb_set_del (hb_set_t *set,
+ hb_codepoint_t codepoint)
+{
+ set->del (codepoint);
+}
+
+hb_bool_t
+hb_set_equal (hb_set_t *set,
+ hb_set_t *other)
+{
+ return set->equal (other);
+}
+
+void
+hb_set_set (hb_set_t *set,
+ hb_set_t *other)
+{
+ set->set (other);
+}
+
+void
+hb_set_union (hb_set_t *set,
+ hb_set_t *other)
+{
+ set->union_ (other);
+}
+
+void
+hb_set_intersect (hb_set_t *set,
+ hb_set_t *other)
+{
+ set->intersect (other);
+}
+
+void
+hb_set_subtract (hb_set_t *set,
+ hb_set_t *other)
+{
+ set->subtract (other);
+}
+
+void
+hb_set_symmetric_difference (hb_set_t *set,
+ hb_set_t *other)
+{
+ set->symmetric_difference (other);
+}
+
+hb_codepoint_t
+hb_set_min (hb_set_t *set)
+{
+ return set->get_min ();
+}
+
+hb_codepoint_t
+hb_set_max (hb_set_t *set)
+{
+ return set->get_max ();
+}
+
+hb_bool_t
+hb_set_next (hb_set_t *set,
+ hb_codepoint_t *codepoint)
+{
+ return set->next (codepoint);
+}
diff --git a/third_party/harfbuzz-ng/src/hb-set.h b/third_party/harfbuzz-ng/src/hb-set.h
new file mode 100644
index 0000000..97e68e4
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-set.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
+#ifndef HB_SET_H
+#define HB_SET_H
+
+#include "hb-common.h"
+
+HB_BEGIN_DECLS
+
+
+typedef struct _hb_set_t hb_set_t;
+
+
+hb_set_t *
+hb_set_create (void);
+
+hb_set_t *
+hb_set_get_empty (void);
+
+hb_set_t *
+hb_set_reference (hb_set_t *set);
+
+void
+hb_set_destroy (hb_set_t *set);
+
+hb_bool_t
+hb_set_set_user_data (hb_set_t *set,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+void *
+hb_set_get_user_data (hb_set_t *set,
+ hb_user_data_key_t *key);
+
+
+/* Returns FALSE if allocation has failed before */
+hb_bool_t
+hb_set_allocation_successful (hb_set_t *set);
+
+void
+hb_set_clear (hb_set_t *set);
+
+hb_bool_t
+hb_set_empty (hb_set_t *set);
+
+hb_bool_t
+hb_set_has (hb_set_t *set,
+ hb_codepoint_t codepoint);
+
+/* Right now limited to 16-bit integers. Eventually will do full codepoint range, sans -1
+ * which we will use as a sentinel. */
+void
+hb_set_add (hb_set_t *set,
+ hb_codepoint_t codepoint);
+
+void
+hb_set_del (hb_set_t *set,
+ hb_codepoint_t codepoint);
+
+hb_bool_t
+hb_set_equal (hb_set_t *set,
+ hb_set_t *other);
+
+void
+hb_set_set (hb_set_t *set,
+ hb_set_t *other);
+
+void
+hb_set_union (hb_set_t *set,
+ hb_set_t *other);
+
+void
+hb_set_intersect (hb_set_t *set,
+ hb_set_t *other);
+
+void
+hb_set_subtract (hb_set_t *set,
+ hb_set_t *other);
+
+void
+hb_set_symmetric_difference (hb_set_t *set,
+ hb_set_t *other);
+
+/* Returns -1 if set empty. */
+hb_codepoint_t
+hb_set_min (hb_set_t *set);
+
+/* Returns -1 if set empty. */
+hb_codepoint_t
+hb_set_max (hb_set_t *set);
+
+/* Pass -1 in to get started. */
+hb_bool_t
+hb_set_next (hb_set_t *set,
+ hb_codepoint_t *codepoint);
+
+/* TODO: Add faster iteration API? */
+
+
+HB_END_DECLS
+
+#endif /* HB_SET_H */
diff --git a/third_party/harfbuzz-ng/src/hb-shape.cc b/third_party/harfbuzz-ng/src/hb-shape.cc
index 9357f81..d97028e 100644
--- a/third_party/harfbuzz-ng/src/hb-shape.cc
+++ b/third_party/harfbuzz-ng/src/hb-shape.cc
@@ -31,30 +31,29 @@
#include "hb-buffer-private.hh"
#ifdef HAVE_GRAPHITE
-#include "hb-graphite2.h"
+#include "hb-graphite2-private.hh"
#endif
#ifdef HAVE_UNISCRIBE
-# include "hb-uniscribe.h"
+# include "hb-uniscribe-private.hh"
#endif
#ifdef HAVE_OT
-# include "hb-ot-shape.h"
+# include "hb-ot-shape-private.hh"
#endif
#include "hb-fallback-shape-private.hh"
typedef hb_bool_t (*hb_shape_func_t) (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options);
+ unsigned int num_features);
-#define HB_SHAPER_IMPLEMENT(name) {#name, hb_##name##_shape}
+#define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape}
static struct hb_shaper_pair_t {
char name[16];
hb_shape_func_t func;
} shapers[] = {
/* v--- Add new shapers in the right place here */
#ifdef HAVE_GRAPHITE
- HB_SHAPER_IMPLEMENT (graphite),
+ HB_SHAPER_IMPLEMENT (graphite2),
#endif
#ifdef HAVE_UNISCRIBE
HB_SHAPER_IMPLEMENT (uniscribe),
@@ -120,22 +119,19 @@ hb_shape_full (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features,
- const char * const *shaper_options,
const char * const *shaper_list)
{
+ hb_font_make_immutable (font); /* So we can safely cache stuff on it */
+
if (likely (!shaper_list)) {
for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++)
- if (likely (shapers[i].func (font, buffer,
- features, num_features,
- shaper_options)))
+ if (likely (shapers[i].func (font, buffer, features, num_features)))
return TRUE;
} else {
while (*shaper_list) {
for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++)
if (0 == strcmp (*shaper_list, shapers[i].name)) {
- if (likely (shapers[i].func (font, buffer,
- features, num_features,
- shaper_options)))
+ if (likely (shapers[i].func (font, buffer, features, num_features)))
return TRUE;
break;
}
@@ -151,5 +147,5 @@ hb_shape (hb_font_t *font,
const hb_feature_t *features,
unsigned int num_features)
{
- hb_shape_full (font, buffer, features, num_features, NULL, NULL);
+ hb_shape_full (font, buffer, features, num_features, NULL);
}
diff --git a/third_party/harfbuzz-ng/src/hb-shape.h b/third_party/harfbuzz-ng/src/hb-shape.h
index 685b11d..1a0d6cf 100644
--- a/third_party/harfbuzz-ng/src/hb-shape.h
+++ b/third_party/harfbuzz-ng/src/hb-shape.h
@@ -24,6 +24,10 @@
* Red Hat Author(s): Behdad Esfahbod
*/
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
#ifndef HB_SHAPE_H
#define HB_SHAPE_H
@@ -53,7 +57,6 @@ hb_shape_full (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features,
- const char * const *shaper_options,
const char * const *shaper_list);
const char **
diff --git a/third_party/harfbuzz-ng/src/hb-tt-font.cc b/third_party/harfbuzz-ng/src/hb-tt-font.cc
index ccd86e1..b2f24f6 100644
--- a/third_party/harfbuzz-ng/src/hb-tt-font.cc
+++ b/third_party/harfbuzz-ng/src/hb-tt-font.cc
@@ -24,12 +24,13 @@
* Google Author(s): Behdad Esfahbod
*/
+#include "hb-font-private.hh" /* Shall be first since may include windows.h */
+
#include "hb-open-type-private.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-hmtx-table.hh"
-#include "hb-font-private.hh"
#include "hb-blob.h"
#include <string.h>
diff --git a/third_party/harfbuzz-ng/src/hb-unicode-private.hh b/third_party/harfbuzz-ng/src/hb-unicode-private.hh
index 2ad8a49..ddba1ac 100644
--- a/third_party/harfbuzz-ng/src/hb-unicode-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-unicode-private.hh
@@ -97,11 +97,62 @@ extern HB_INTERNAL hb_unicode_funcs_t _hb_glib_unicode_funcs;
extern HB_INTERNAL hb_unicode_funcs_t _hb_icu_unicode_funcs;
#define _hb_unicode_funcs_default _hb_icu_unicode_funcs
#else
+#define HB_UNICODE_FUNCS_NIL 1
extern HB_INTERNAL hb_unicode_funcs_t _hb_unicode_funcs_nil;
#define _hb_unicode_funcs_default _hb_unicode_funcs_nil
#endif
+HB_INTERNAL unsigned int
+_hb_unicode_modified_combining_class (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
+static inline hb_bool_t
+_hb_unicode_is_variation_selector (hb_codepoint_t unicode)
+{
+ return unlikely ((unicode >= 0x180B && unicode <= 0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
+ (unicode >= 0xFE00 && unicode <= 0xFE0F) || /* VARIATION SELECTOR-1..16 */
+ (unicode >= 0xE0100 && unicode <= 0xE01EF)); /* VARIATION SELECTOR-17..256 */
+}
+
+/* Zero-Width invisible characters:
+ *
+ * 00AD SOFT HYPHEN
+ * 034F COMBINING GRAPHEME JOINER
+ *
+ * 200B ZERO WIDTH SPACE
+ * 200C ZERO WIDTH NON-JOINER
+ * 200D ZERO WIDTH JOINER
+ * 200E LEFT-TO-RIGHT MARK
+ * 200F RIGHT-TO-LEFT MARK
+ *
+ * 2028 LINE SEPARATOR
+ *
+ * 202A LEFT-TO-RIGHT EMBEDDING
+ * 202B RIGHT-TO-LEFT EMBEDDING
+ * 202C POP DIRECTIONAL FORMATTING
+ * 202D LEFT-TO-RIGHT OVERRIDE
+ * 202E RIGHT-TO-LEFT OVERRIDE
+ *
+ * 2060 WORD JOINER
+ * 2061 FUNCTION APPLICATION
+ * 2062 INVISIBLE TIMES
+ * 2063 INVISIBLE SEPARATOR
+ *
+ * FEFF ZERO WIDTH NO-BREAK SPACE
+ */
+static inline hb_bool_t
+_hb_unicode_is_zero_width (hb_codepoint_t ch)
+{
+ return ((ch & ~0x007F) == 0x2000 && (
+ (ch >= 0x200B && ch <= 0x200F) ||
+ (ch >= 0x202A && ch <= 0x202E) ||
+ (ch >= 0x2060 && ch <= 0x2063) ||
+ (ch == 0x2028)
+ )) || unlikely (ch == 0x0009
+ || ch == 0x00AD
+ || ch == 0x034F
+ || ch == 0xFEFF);
+}
#endif /* HB_UNICODE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-unicode.cc b/third_party/harfbuzz-ng/src/hb-unicode.cc
index 4b285c5..f2fbebb 100644
--- a/third_party/harfbuzz-ng/src/hb-unicode.cc
+++ b/third_party/harfbuzz-ng/src/hb-unicode.cc
@@ -85,7 +85,6 @@ hb_unicode_compose_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
hb_codepoint_t *ab HB_UNUSED,
void *user_data HB_UNUSED)
{
- /* TODO handle Hangul jamo here? */
return FALSE;
}
@@ -96,7 +95,6 @@ hb_unicode_decompose_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
hb_codepoint_t *b HB_UNUSED,
void *user_data HB_UNUSED)
{
- /* TODO handle Hangul jamo here? */
return FALSE;
}
@@ -271,3 +269,58 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
return ufuncs->func.decompose (ufuncs, ab, a, b, ufuncs->user_data.decompose);
}
+
+
+unsigned int
+_hb_unicode_modified_combining_class (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode)
+{
+ int c = hb_unicode_combining_class (ufuncs, unicode);
+
+ if (unlikely (hb_in_range<int> (c, 27, 33)))
+ {
+ /* Modify the combining-class to suit Arabic better. See:
+ * http://unicode.org/faq/normalization.html#8
+ * http://unicode.org/faq/normalization.html#9
+ */
+ c = c == 33 ? 27 : c + 1;
+ }
+ else if (unlikely (hb_in_range<int> (c, 10, 25)))
+ {
+ /* The equivalent fix for Hebrew is more complex.
+ *
+ * We permute the "fixed-position" classes 10-25 into the order
+ * described in the SBL Hebrew manual:
+ *
+ * http://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
+ *
+ * (as recommended by:
+ * http://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering-t6751.0.html)
+ *
+ * More details here:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
+ */
+ static const int permuted_hebrew_classes[25 - 10 + 1] = {
+ /* 10 sheva */ 22,
+ /* 11 hataf segol */ 15,
+ /* 12 hataf patah */ 16,
+ /* 13 hataf qamats */ 17,
+ /* 14 hiriq */ 23,
+ /* 15 tsere */ 18,
+ /* 16 segol */ 19,
+ /* 17 patah */ 20,
+ /* 18 qamats */ 21,
+ /* 19 holam */ 14,
+ /* 20 qubuts */ 24,
+ /* 21 dagesh */ 12,
+ /* 22 meteg */ 25,
+ /* 23 rafe */ 13,
+ /* 24 shin dot */ 10,
+ /* 25 sin dot */ 11,
+ };
+ c = permuted_hebrew_classes[c - 10];
+ }
+
+ return c;
+}
+
diff --git a/third_party/harfbuzz-ng/src/hb-unicode.h b/third_party/harfbuzz-ng/src/hb-unicode.h
index 13886df..205e4c7 100644
--- a/third_party/harfbuzz-ng/src/hb-unicode.h
+++ b/third_party/harfbuzz-ng/src/hb-unicode.h
@@ -28,6 +28,10 @@
* Google Author(s): Behdad Esfahbod
*/
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
#ifndef HB_UNICODE_H
#define HB_UNICODE_H
diff --git a/third_party/harfbuzz-ng/src/hb-uniscribe-private.hh b/third_party/harfbuzz-ng/src/hb-uniscribe-private.hh
new file mode 100644
index 0000000..239ab0c
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-uniscribe-private.hh
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_UNISCRIBE_PRIVATE_HH
+#define HB_UNISCRIBE_PRIVATE_HH
+
+#include "hb-private.hh"
+
+#include "hb-uniscribe.h"
+
+
+HB_INTERNAL hb_bool_t
+_hb_uniscribe_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features);
+
+
+#endif /* HB_UNISCRIBE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-uniscribe.cc b/third_party/harfbuzz-ng/src/hb-uniscribe.cc
index ce86074..584d641 100644
--- a/third_party/harfbuzz-ng/src/hb-uniscribe.cc
+++ b/third_party/harfbuzz-ng/src/hb-uniscribe.cc
@@ -223,11 +223,10 @@ hb_uniscribe_font_get_hfont (hb_font_t *font)
hb_bool_t
-hb_uniscribe_shape (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options)
+_hb_uniscribe_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features)
{
buffer->guess_properties ();
@@ -360,6 +359,9 @@ retry:
glyph_props + glyphs_offset,
(int *) &glyphs_len);
+ for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
+ log_clusters[j] += glyphs_offset;
+
if (unlikely (items[i].a.fNoGlyphIndex))
FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
if (unlikely (hr == E_OUTOFMEMORY))
diff --git a/third_party/harfbuzz-ng/src/hb-uniscribe.h b/third_party/harfbuzz-ng/src/hb-uniscribe.h
index dbcacd7..216610e 100644
--- a/third_party/harfbuzz-ng/src/hb-uniscribe.h
+++ b/third_party/harfbuzz-ng/src/hb-uniscribe.h
@@ -27,8 +27,7 @@
#ifndef HB_UNISCRIBE_H
#define HB_UNISCRIBE_H
-#include "hb-common.h"
-#include "hb-shape.h"
+#include "hb.h"
#define _WIN32_WINNT 0x0500
#include <windows.h>
@@ -36,13 +35,6 @@
HB_BEGIN_DECLS
-hb_bool_t
-hb_uniscribe_shape (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features,
- const char * const *shaper_options);
-
LOGFONTW *
hb_uniscribe_font_get_logfontw (hb_font_t *font);
diff --git a/third_party/harfbuzz-ng/src/hb-version.h b/third_party/harfbuzz-ng/src/hb-version.h
index c1e3cab..43ec9cf 100644
--- a/third_party/harfbuzz-ng/src/hb-version.h
+++ b/third_party/harfbuzz-ng/src/hb-version.h
@@ -24,6 +24,10 @@
* Google Author(s): Behdad Esfahbod
*/
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
#ifndef HB_VERSION_H
#define HB_VERSION_H
@@ -33,10 +37,10 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 0
-#define HB_VERSION_MINOR 7
+#define HB_VERSION_MINOR 9
#define HB_VERSION_MICRO 0
-#define HB_VERSION_STRING "0.7.0"
+#define HB_VERSION_STRING "0.9.0"
#define HB_VERSION_CHECK(major,minor,micro) \
((major)*10000+(minor)*100+(micro) >= \
diff --git a/third_party/harfbuzz-ng/src/hb-warning.cc b/third_party/harfbuzz-ng/src/hb-warning.cc
new file mode 100644
index 0000000..c13731b
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-warning.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-atomic-private.hh"
+#include "hb-mutex-private.hh"
+
+
+#if !defined(HB_NO_MT) && defined(HB_ATOMIC_INT_NIL)
+#ifdef _MSC_VER
+#pragma message("Could not find any system to define atomic_int macros, library will NOT be thread-safe")
+#else
+#warning "Could not find any system to define atomic_int macros, library will NOT be thread-safe"
+#endif
+#endif
+
+#if !defined(HB_NO_MT) && defined(HB_MUTEX_IMPL_NIL)
+#ifdef _MSC_VER
+#pragma message("Could not find any system to define mutex macros, library will NOT be thread-safe")
+#else
+#warning "Could not find any system to define mutex macros, library will NOT be thread-safe"
+#endif
+#endif
+
+#if !defined(HB_NO_MT) && (defined(HB_ATOMIC_INT_NIL) || defined(HB_MUTEX_IMPL_NIL))
+#ifdef _MSC_VER
+#pragma message("To suppress these warnings, define HB_NO_MT")
+#else
+#warning "To suppress these warnings, define HB_NO_MT"
+#endif
+#endif
+
+
+#include "hb-unicode-private.hh"
+
+#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
+#ifdef _MSC_VER
+#pragma message("Could not find any Unicode functions implementation, you have to provide your own")
+#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS")
+#else
+#warning "Could not find any Unicode functions implementation, you have to provide your own"
+#warning "To suppress this warning, define HB_NO_UNICODE_FUNCS"
+#endif
+#endif
diff --git a/third_party/harfbuzz-ng/src/hb.h b/third_party/harfbuzz-ng/src/hb.h
index 0a2ebd9..d36040e2 100644
--- a/third_party/harfbuzz-ng/src/hb.h
+++ b/third_party/harfbuzz-ng/src/hb.h
@@ -26,11 +26,13 @@
#ifndef HB_H
#define HB_H
+#define HB_H_IN
#include "hb-blob.h"
#include "hb-buffer.h"
#include "hb-common.h"
#include "hb-font.h"
+#include "hb-set.h"
#include "hb-shape.h"
#include "hb-unicode.h"
#include "hb-version.h"
@@ -38,4 +40,5 @@
HB_BEGIN_DECLS
HB_END_DECLS
+#undef HB_H_IN
#endif /* HB_H */
diff --git a/third_party/harfbuzz-ng/src/indic.cc b/third_party/harfbuzz-ng/src/indic.cc
new file mode 100644
index 0000000..e00311d
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/indic.cc
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-ot-shape-complex-indic-private.hh"
+
+int
+main (void)
+{
+ hb_unicode_funcs_t *funcs = hb_unicode_funcs_get_default ();
+
+ printf ("There are split matras without a Unicode decomposition:\n");
+ for (hb_codepoint_t u = 0; u < 0x110000; u++)
+ {
+ unsigned int type = get_indic_categories (u);
+
+ unsigned int category = type & 0x0F;
+ unsigned int position = type >> 4;
+
+ hb_codepoint_t a, b;
+ if (!hb_unicode_decompose (funcs, u, &a, &b))
+ printf ("U+%04X\n", u);
+ }
+}
diff --git a/third_party/harfbuzz-ng/src/main.cc b/third_party/harfbuzz-ng/src/main.cc
index 442b1b9..03b6e6c 100644
--- a/third_party/harfbuzz-ng/src/main.cc
+++ b/third_party/harfbuzz-ng/src/main.cc
@@ -124,10 +124,11 @@ main (int argc, char **argv)
const LangSys &langsys = n_langsys == -1
? script.get_default_lang_sys ()
: script.get_lang_sys (n_langsys);
- printf (n_langsys == -1
- ? " Default Language System\n"
- : " Language System %2d of %2d: %.4s\n", n_langsys, num_langsys,
- (const char *)script.get_lang_sys_tag (n_langsys));
+ if (n_langsys == -1)
+ printf (" Default Language System\n");
+ else
+ printf (" Language System %2d of %2d: %.4s\n", n_langsys, num_langsys,
+ (const char *)script.get_lang_sys_tag (n_langsys));
if (langsys.get_required_feature_index () == Index::NOT_FOUND_INDEX)
printf (" No required feature\n");