struct hb_atomic_ptr_t
{
- typedef typename hb_remove_pointer::value T;
+ typedef typename hb_remove_pointer (P) T;
inline void init (T* v_ = nullptr) { set_relaxed (v_); }
inline void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
diff --git a/src/hb-blob.hh b/src/hb-blob.hh
index 802b1f07e..bf2132bda 100644
--- a/src/hb-blob.hh
+++ b/src/hb-blob.hh
@@ -60,7 +60,7 @@ struct hb_blob_t
template
inline const Type* as (void) const
{
- return length < Type::min_size ? &Null(Type) : reinterpret_cast (data);
+ return length < hb_null_size (Type) ? &Null(Type) : reinterpret_cast (data);
}
inline hb_bytes_t as_bytes (void) const
{
@@ -86,7 +86,7 @@ struct hb_blob_t
template
struct hb_blob_ptr_t
{
- typedef typename hb_remove_pointer::value T;
+ typedef typename hb_remove_pointer (P) T;
inline hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {}
inline hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; }
diff --git a/src/hb-common.cc b/src/hb-common.cc
index 37be8a34e..c3cffccb1 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -204,7 +204,7 @@ static const char canon_map[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0,
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
- '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-',
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
@@ -276,7 +276,7 @@ struct hb_language_item_t {
static hb_atomic_ptr_t langs;
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
static void
free_langs (void)
{
@@ -323,7 +323,7 @@ retry:
goto retry;
}
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
if (!first_lang)
atexit (free_langs); /* First person registers atexit() callback. */
#endif
@@ -780,18 +780,18 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv)
#ifdef USE_XLOCALE
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
static void free_static_C_locale (void);
#endif
-static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t::value,
+static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t
{
static inline HB_LOCALE_T create (void)
{
HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
atexit (free_static_C_locale);
#endif
@@ -807,7 +807,7 @@ static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
+ _hb_debug_msg (what, obj, func, true, plevel ? *plevel : 1, -1,
"return %s (line %d)",
hb_printer_t().print (v), line);
if (plevel) --*plevel;
@@ -325,17 +327,21 @@ struct hb_auto_trace_t<0, ret_t>
const char *message,
...) HB_PRINTF_FUNC(6, 7) {}
- inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
+ inline ret_t ret (ret_t v,
+ const char *func HB_UNUSED = 0,
+ unsigned int line HB_UNUSED = 0) { return v; }
};
/* For disabled tracing; optimize out everything.
* https://github.com/harfbuzz/harfbuzz/pull/605 */
template
struct hb_no_trace_t {
- inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
+ inline ret_t ret (ret_t v,
+ const char *func HB_UNUSED = "",
+ unsigned int line HB_UNUSED = 0) { return v; }
};
-#define return_trace(RET) return trace.ret (RET, __LINE__)
+#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
/*
diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h
index e39b79f74..a74431f05 100644
--- a/src/hb-deprecated.h
+++ b/src/hb-deprecated.h
@@ -241,6 +241,43 @@ HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) hb_tag_t
hb_ot_tag_from_language (hb_language_t language);
+typedef unsigned int hb_ot_name_id_t; /* Since is in hb-ot.h */
+
+/**
+ * HB_OT_VAR_NO_AXIS_INDEX:
+ *
+ * Since: 1.4.2
+ * Deprecated: REPLACEME
+ */
+#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu
+
+/**
+ * hb_ot_var_axis_t:
+ *
+ * Since: 1.4.2
+ * Deprecated: REPLACEME
+ */
+typedef struct hb_ot_var_axis_t
+{
+ hb_tag_t tag;
+ hb_ot_name_id_t name_id;
+ float min_value;
+ float default_value;
+ float max_value;
+} hb_ot_var_axis_t;
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos) unsigned int
+hb_ot_var_get_axes (hb_face_t *face,
+ unsigned int start_offset,
+ unsigned int *axes_count /* IN/OUT */,
+ hb_ot_var_axis_t *axes_array /* OUT */);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_find_axis_info) hb_bool_t
+hb_ot_var_find_axis (hb_face_t *face,
+ hb_tag_t axis_tag,
+ unsigned int *axis_index,
+ hb_ot_var_axis_t *axis_info);
+
#endif
HB_END_DECLS
diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index da8aad013..577359601 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -559,10 +559,16 @@ struct hb_bytes_t
unsigned int len;
};
+template
+struct hb_sorted_array_t;
+
template
struct hb_array_t
{
+ static_assert ((bool) (unsigned) hb_static_size (Type), "");
+
inline hb_array_t (void) : arrayZ (nullptr), len (0) {}
+ inline hb_array_t (const hb_array_t &o) : arrayZ (o.arrayZ), len (o.len) {}
inline hb_array_t (Type *array_, unsigned int len_) : arrayZ (array_), len (len_) {}
inline Type& operator [] (unsigned int i) const
@@ -571,39 +577,160 @@ struct hb_array_t
return arrayZ[i];
}
- inline unsigned int get_size (void) const { return len * sizeof (Type); }
-
- template
- inline bool sanitize (hb_sanitize_context_t *c) const
- { return c->check_array (arrayZ, len); }
-
template inline operator T * (void) const { return arrayZ; }
inline Type * operator & (void) const { return arrayZ; }
- inline hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
+ inline unsigned int get_size (void) const { return len * sizeof (Type); }
+
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
{
+ if (!seg_count) return hb_array_t ();
+
unsigned int count = len;
if (unlikely (start_offset > count))
count = 0;
else
count -= start_offset;
- count = MIN (count, seg_count);
+ count = *seg_count = MIN (count, *seg_count);
return hb_array_t (arrayZ + start_offset, count);
}
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
+ { return sub_array (start_offset, &seg_count); }
inline hb_bytes_t as_bytes (void) const
+ { return hb_bytes_t (arrayZ, len * sizeof (Type)); }
+
+ template
+ inline Type *lsearch (const T &x,
+ Type *not_found = nullptr)
{
- return hb_bytes_t (arrayZ, len * sizeof (Type));
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!this->arrayZ[i].cmp (x))
+ return &this->arrayZ[i];
+ return not_found;
+ }
+ template
+ inline const Type *lsearch (const T &x,
+ const Type *not_found = nullptr) const
+ {
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!this->arrayZ[i].cmp (x))
+ return &this->arrayZ[i];
+ return not_found;
}
- inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
+ inline hb_sorted_array_t qsort (int (*cmp)(const void*, const void*))
+ {
+ ::qsort (arrayZ, len, sizeof (Type), cmp);
+ return hb_sorted_array_t (*this);
+ }
+ inline hb_sorted_array_t qsort (void)
+ {
+ ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
+ return hb_sorted_array_t (*this);
+ }
+ inline void qsort (unsigned int start, unsigned int end)
+ {
+ end = MIN (end, len);
+ assert (start <= end);
+ ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
+ }
+ inline void free (void)
+ { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
+
+ template
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ { return c->check_array (arrayZ, len); }
+
+ public:
Type *arrayZ;
unsigned int len;
};
template
-inline hb_array_t hb_array (T *array, unsigned int len) { return hb_array_t (array, len); }
+inline hb_array_t hb_array (T *array, unsigned int len)
+{ return hb_array_t (array, len); }
+
+enum hb_bfind_not_found_t
+{
+ HB_BFIND_NOT_FOUND_DONT_STORE,
+ HB_BFIND_NOT_FOUND_STORE,
+ HB_BFIND_NOT_FOUND_STORE_CLOSEST,
+};
+
+template
+struct hb_sorted_array_t : hb_array_t
+{
+ inline hb_sorted_array_t (void) : hb_array_t () {}
+ inline hb_sorted_array_t (const hb_array_t &o) : hb_array_t (o) {}
+ inline hb_sorted_array_t (Type *array_, unsigned int len_) : hb_array_t (array_, len_) {}
+
+ inline hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
+ { return hb_sorted_array_t (((const hb_array_t *) (this))->sub_array (start_offset, seg_count)); }
+ inline hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
+ { return sub_array (start_offset, &seg_count); }
+
+ template
+ inline Type *bsearch (const T &x, Type *not_found = nullptr)
+ {
+ unsigned int i;
+ return bfind (x, &i) ? &this->arrayZ[i] : not_found;
+ }
+ template
+ inline const Type *bsearch (const T &x, const Type *not_found = nullptr) const
+ {
+ unsigned int i;
+ return bfind (x, &i) ? &this->arrayZ[i] : not_found;
+ }
+ template
+ inline bool bfind (const T &x, unsigned int *i = nullptr,
+ hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+ unsigned int to_store = (unsigned int) -1) const
+ {
+ int min = 0, max = (int) this->len - 1;
+ const Type *array = this->arrayZ;
+ while (min <= max)
+ {
+ int mid = ((unsigned int) min + (unsigned int) max) / 2;
+ int c = array[mid].cmp (x);
+ if (c < 0)
+ max = mid - 1;
+ else if (c > 0)
+ min = mid + 1;
+ else
+ {
+ if (i)
+ *i = mid;
+ return true;
+ }
+ }
+ if (i)
+ {
+ switch (not_found)
+ {
+ case HB_BFIND_NOT_FOUND_DONT_STORE:
+ break;
+
+ case HB_BFIND_NOT_FOUND_STORE:
+ *i = to_store;
+ break;
+
+ case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
+ if (max < 0 || (max < (int) this->len && array[max].cmp (x) > 0))
+ max++;
+ *i = max;
+ break;
+ }
+ }
+ return false;
+ }
+};
+template
+inline hb_sorted_array_t hb_sorted_array (T *array, unsigned int len)
+{ return hb_sorted_array_t (array, len); }
struct HbOpOr
diff --git a/src/hb-face.cc b/src/hb-face.cc
index e23842fb1..5b33784f4 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -588,10 +588,10 @@ struct hb_face_builder_data_t
{
struct table_entry_t
{
- inline int cmp (const hb_tag_t *t) const
+ inline int cmp (hb_tag_t t) const
{
- if (*t < tag) return -1;
- if (*t > tag) return -1;
+ if (t < tag) return -1;
+ if (t > tag) return -1;
return 0;
}
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 9b9d787de..633e0ecd2 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -478,7 +478,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
return true;
}
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
static void free_static_ft_funcs (void);
#endif
@@ -504,7 +504,7 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t::value,
+static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t
{
static inline FT_Library create (void)
@@ -757,7 +757,7 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_tu._member.static_size) + sizeof(this->u._member) == (size)); \
- static const unsigned int min_size = (size)
+ DEFINE_COMPILES_ASSERTION ((void) this->u._member.static_size) \
+ DEFINE_INSTANCE_ASSERTION (sizeof(this->u._member) == (size)) \
+ enum { null_size = (size) }; \
+ enum { min_size = (size) }
#define DEFINE_SIZE_MIN(size) \
- DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
- static const unsigned int min_size = (size)
+ DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
+ enum { null_size = (size) }; \
+ enum { min_size = (size) }
+
+#define DEFINE_SIZE_UNBOUNDED(size) \
+ DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
+ enum { min_size = (size) }
#define DEFINE_SIZE_ARRAY(size, array) \
- DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0])); \
DEFINE_COMPILES_ASSERTION ((void) (array)[0].static_size) \
+ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0])) \
+ enum { null_size = (size) }; \
enum { min_size = (size) }
#define DEFINE_SIZE_ARRAY_SIZED(size, array) \
- inline unsigned int get_size (void) const { return (size - (array).min_size + (array).get_size ()); } \
- DEFINE_SIZE_ARRAY(size, array)
-
-#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
- DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
- DEFINE_COMPILES_ASSERTION ((void) (array1)[0].static_size; (void) (array2)[0].static_size) \
- static const unsigned int min_size = (size)
+ inline unsigned int get_size (void) const { return (size - (array).min_size + (array).get_size ()); } \
+ DEFINE_SIZE_ARRAY(size, array)
/*
@@ -256,26 +259,36 @@ struct hb_sanitize_context_t :
inline void set_max_ops (int max_ops_) { max_ops = max_ops_; }
- /* TODO
- * This set_object() thing is to use sanitize at runtime lookup
- * application time. This is very distinct from the regular
- * sanitizer operation, so, eventually, separate into another
- * type and make hb_aat_apply_context_t use that one instead
- * of abusing this one.
- */
template
- inline void set_object (const T& obj)
+ inline void set_object (const T *obj)
{
- this->start = (const char *) &obj;
- this->end = (const char *) &obj + obj.get_size ();
+ reset_object ();
+
+ if (!obj) return;
+
+ const char *obj_start = (const char *) obj;
+ const char *obj_end = (const char *) obj + obj->get_size ();
+ assert (obj_start <= obj_end); /* Must not overflow. */
+
+ if (unlikely (obj_end < this->start || this->end < obj_start))
+ this->start = this->end = nullptr;
+ else
+ {
+ this->start = MAX (this->start, obj_start);
+ this->end = MIN (this->end , obj_end );
+ }
+ }
+
+ inline void reset_object (void)
+ {
+ this->start = this->blob->data;
+ this->end = this->start + this->blob->length;
assert (this->start <= this->end); /* Must not overflow. */
}
inline void start_processing (void)
{
- this->start = this->blob->data;
- this->end = this->start + this->blob->length;
- assert (this->start <= this->end); /* Must not overflow. */
+ reset_object ();
this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
(unsigned) HB_SANITIZE_MAX_OPS_MIN);
this->edit_count = 0;
@@ -469,6 +482,23 @@ struct hb_sanitize_context_t :
bool num_glyphs_set;
};
+struct hb_sanitize_with_object_t
+{
+ template
+ inline hb_sanitize_with_object_t (hb_sanitize_context_t *c,
+ const T& obj) : c (c)
+ {
+ c->set_object (obj);
+ }
+ inline ~hb_sanitize_with_object_t (void)
+ {
+ c->reset_object ();
+ }
+
+ private:
+ hb_sanitize_context_t *c;
+};
+
/*
* Serialize
@@ -691,6 +721,12 @@ struct BEInt
}
inline operator Type (void) const
{
+#if defined(__GNUC__) || defined(__clang__)
+ /* Spoon-feed the compiler a big-endian integer with alignment 1.
+ * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+ struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
+ return __builtin_bswap16 (((packed_uint16_t *) this)->v);
+#endif
return (v[0] << 8)
+ (v[1] );
}
diff --git a/src/hb-null.hh b/src/hb-null.hh
index bc9438d5c..080e0b542 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -38,21 +38,60 @@
#define HB_NULL_POOL_SIZE 9880
+/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
+ * otherwise return sizeof(T). */
+
+/* The hard way...
+ * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
+ */
+
+template struct _hb_bool_type {};
+
+template
+struct _hb_null_size
+{ enum { value = sizeof (T) }; };
+template
+struct _hb_null_size >
+{ enum { value = T::null_size }; };
+
+template
+struct hb_null_size
+{ enum { value = _hb_null_size >::value }; };
+#define hb_null_size(T) hb_null_size::value
+
+/* This doesn't belong here, but since is copy/paste from above, put it here. */
+
+template
+struct _hb_static_size
+{ enum { value = sizeof (T) }; };
+template
+struct _hb_static_size >
+{ enum { value = T::static_size }; };
+
+template
+struct hb_static_size
+{ enum { value = _hb_static_size >::value }; };
+#define hb_static_size(T) hb_static_size::value
+
+
+/*
+ * Null()
+ */
extern HB_INTERNAL
hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
/* Generic nul-content Null objects. */
template
static inline Type const & Null (void) {
- static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+ static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
return *reinterpret_cast (_hb_NullPool);
}
-#define Null(Type) Null::value>::value>()
+#define Null(Type) Null ()
/* Specializations for arbitrary-content Null objects expressed in bytes. */
#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
} /* Close namespace. */ \
- extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \
+ extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
template <> \
/*static*/ inline const Namespace::Type& Null (void) { \
return *reinterpret_cast (_hb_Null_##Namespace##_##Type); \
@@ -60,7 +99,7 @@ static inline Type const & Null (void) {
namespace Namespace { \
static_assert (true, "Just so we take semicolon after.")
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
- const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
+ const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
#define DECLARE_NULL_INSTANCE(Type) \
@@ -85,12 +124,12 @@ extern HB_INTERNAL
/* CRAP pool: Common Region for Access Protection. */
template
static inline Type& Crap (void) {
- static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+ static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
Type *obj = reinterpret_cast (_hb_CrapPool);
memcpy (obj, &Null(Type), sizeof (*obj));
return *obj;
}
-#define Crap(Type) Crap::value>::value>()
+#define Crap(Type) Crap ()
template
struct CrapOrNull {
@@ -110,7 +149,7 @@ struct CrapOrNull {
template
struct hb_nonnull_ptr_t
{
- typedef typename hb_remove_pointer::value T;
+ typedef typename hb_remove_pointer (P) T;
inline hb_nonnull_ptr_t (T *v_ = nullptr) : v (v_) {}
inline T * operator = (T *v_) { return v = v_; }
diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh
index 2ef6d775f..af68892ab 100644
--- a/src/hb-open-file.hh
+++ b/src/hb-open-file.hh
@@ -111,12 +111,7 @@ typedef struct OffsetTable
{
Tag t;
t.set (tag);
- /* Linear-search for small tables to work around fonts with unsorted
- * table list. */
- int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
- if (table_index)
- *table_index = i == -1 ? (unsigned) Index::NOT_FOUND_INDEX : (unsigned) i;
- return i != -1;
+ return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
}
inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
{
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index b1fcd6877..f4d0238ea 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -231,22 +231,31 @@ struct FixedVersion
* Use: (base+offset)
*/
-template struct assert_has_min_size { static_assert (Type::min_size > 0, ""); };
-template struct assert_has_min_size {};
+template
+struct _hb_has_null
+{
+ static inline const Type *get_null (void) { return nullptr; }
+ static inline Type *get_crap (void) { return nullptr; }
+};
+template
+struct _hb_has_null
+{
+ static inline const Type *get_null (void) { return &Null(Type); }
+ static inline Type *get_crap (void) { return &Crap(Type); }
+};
template
struct OffsetTo : Offset
{
- static_assert (sizeof (assert_has_min_size) || true, "");
-
inline const Type& operator () (const void *base) const
{
- if (unlikely (this->is_null ())) return Null (Type);
+ if (unlikely (this->is_null ())) return *_hb_has_null::get_null ();
return StructAtOffset (base, *this);
}
inline Type& operator () (void *base) const
{
if (unlikely (this->is_null ())) return Crap (Type);
+ if (unlikely (this->is_null ())) return *_hb_has_null::get_crap ();
return StructAtOffset (base, *this);
}
@@ -322,6 +331,7 @@ struct OffsetTo : Offset
DEFINE_SIZE_STATIC (sizeof (OffsetType));
};
template struct LOffsetTo : OffsetTo {};
+
template
static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); }
template
@@ -335,6 +345,8 @@ static inline Type& operator + (Base &base, OffsetTo
template
struct UnsizedArrayOf
{
+ static_assert ((bool) (unsigned) hb_static_size (Type), "");
+
enum { item_size = Type::static_size };
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
@@ -358,8 +370,20 @@ struct UnsizedArrayOf
inline unsigned int get_size (unsigned int len) const
{ return len * Type::static_size; }
- inline hb_array_t as_array (unsigned int len) { return hb_array_t (arrayZ, len); }
- inline hb_array_t as_array (unsigned int len) const { return hb_array_t (arrayZ, len); }
+ inline hb_array_t as_array (unsigned int len)
+ { return hb_array (arrayZ, len); }
+ inline hb_array_t as_array (unsigned int len) const
+ { return hb_array (arrayZ, len); }
+
+ template
+ inline Type &lsearch (unsigned int len, const T &x, Type ¬_found = Crap (Type))
+ { return *as_array (len).lsearch (x, ¬_found); }
+ template
+ inline const Type &lsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const
+ { return *as_array (len).lsearch (x, ¬_found); }
+
+ inline void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
+ { as_array (len).qsort (start, end); }
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
@@ -406,7 +430,7 @@ struct UnsizedArrayOf
public:
Type arrayZ[VAR];
public:
- DEFINE_SIZE_ARRAY (0, arrayZ);
+ DEFINE_SIZE_UNBOUNDED (0);
};
/* Unsized array of offset's */
@@ -419,8 +443,17 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf
{
inline const Type& operator [] (unsigned int i) const
{
- return this+this->arrayZ[i];
+ const OffsetTo *p = &this->arrayZ[i];
+ if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
+ return this+*p;
}
+ inline Type& operator [] (unsigned int i)
+ {
+ const OffsetTo *p = &this->arrayZ[i];
+ if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
+ return this+*p;
+ }
+
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
@@ -435,26 +468,39 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf
}
};
+/* An array with sorted elements. Supports binary searching. */
+template
+struct SortedUnsizedArrayOf : UnsizedArrayOf
+{
+ inline hb_sorted_array_t as_array (unsigned int len)
+ { return hb_sorted_array (this->arrayZ, len); }
+ inline hb_sorted_array_t as_array (unsigned int len) const
+ { return hb_sorted_array (this->arrayZ, len); }
+
+ template
+ inline Type &bsearch (unsigned int len, const T &x, Type ¬_found = Crap (Type))
+ { return *as_array (len).bsearch (x, ¬_found); }
+ template
+ inline const Type &bsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const
+ { return *as_array (len).bsearch (x, ¬_found); }
+ template
+ inline bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr,
+ hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+ unsigned int to_store = (unsigned int) -1) const
+ { return as_array (len).bfind (x, i, not_found, to_store); }
+};
+
+
/* An array with a number of elements. */
template
struct ArrayOf
{
+ static_assert ((bool) (unsigned) hb_static_size (Type), "");
+
enum { item_size = Type::static_size };
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType);
- inline const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
- {
- unsigned int count = len;
- if (unlikely (start_offset > count))
- count = 0;
- else
- count -= start_offset;
- count = MIN (count, *pcount);
- *pcount = count;
- return arrayZ + start_offset;
- }
-
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= len)) return Null (Type);
@@ -469,6 +515,20 @@ struct ArrayOf
inline unsigned int get_size (void) const
{ return len.static_size + len * Type::static_size; }
+ inline hb_array_t as_array (void)
+ { return hb_array (arrayZ, len); }
+ inline hb_array_t as_array (void) const
+ { return hb_array (arrayZ, len); }
+
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int count) const
+ { return as_array ().sub_array (start_offset, count);}
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int *count /* IN/OUT */) const
+ { return as_array ().sub_array (start_offset, count);}
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int count)
+ { return as_array ().sub_array (start_offset, count);}
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int *count /* IN/OUT */)
+ { return as_array ().sub_array (start_offset, count);}
+
inline bool serialize (hb_serialize_context_t *c,
unsigned int items_len)
{
@@ -528,20 +588,15 @@ struct ArrayOf
return_trace (true);
}
- template
- inline int lsearch (const SearchType &x) const
- {
- unsigned int count = len;
- for (unsigned int i = 0; i < count; i++)
- if (!this->arrayZ[i].cmp (x))
- return i;
- return -1;
- }
+ template
+ inline Type &lsearch (const T &x, Type ¬_found = Crap (Type))
+ { return *as_array ().lsearch (x, ¬_found); }
+ template
+ inline const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const
+ { return *as_array ().lsearch (x, ¬_found); }
- inline void qsort (void)
- {
- ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
- }
+ inline void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+ { as_array ().qsort (start, end); }
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
@@ -723,22 +778,31 @@ struct ArrayOfM1
template
struct SortedArrayOf : ArrayOf
{
- template
- inline int bsearch (const SearchType &x) const
- {
- /* Hand-coded bsearch here since this is in the hot inner loop. */
- const Type *arr = this->arrayZ;
- int min = 0, max = (int) this->len - 1;
- while (min <= max)
- {
- int mid = ((unsigned int) min + (unsigned int) max) / 2;
- int c = arr[mid].cmp (x);
- if (c < 0) max = mid - 1;
- else if (c > 0) min = mid + 1;
- else return mid;
- }
- return -1;
- }
+ inline hb_sorted_array_t as_array (void)
+ { return hb_sorted_array (this->arrayZ, this->len); }
+ inline hb_sorted_array_t as_array (void) const
+ { return hb_sorted_array (this->arrayZ, this->len); }
+
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int count) const
+ { return as_array ().sub_array (start_offset, count);}
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int *count /* IN/OUT */) const
+ { return as_array ().sub_array (start_offset, count);}
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int count)
+ { return as_array ().sub_array (start_offset, count);}
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int *count /* IN/OUT */)
+ { return as_array ().sub_array (start_offset, count);}
+
+ template
+ inline Type &bsearch (const T &x, Type ¬_found = Crap (Type))
+ { return *as_array ().bsearch (x, ¬_found); }
+ template
+ inline const Type &bsearch (const T &x, const Type ¬_found = Null (Type)) const
+ { return *as_array ().bsearch (x, ¬_found); }
+ template
+ inline bool bfind (const T &x, unsigned int *i = nullptr,
+ hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+ unsigned int to_store = (unsigned int) -1) const
+ { return as_array ().bfind (x, i, not_found, to_store); }
};
/*
@@ -810,15 +874,36 @@ struct VarSizedBinSearchArrayOf
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
+ inline bool last_is_terminator (void) const
+ {
+ if (unlikely (!header.nUnits)) return false;
+
+ /* Gah.
+ *
+ * "The number of termination values that need to be included is table-specific.
+ * The value that indicates binary search termination is 0xFFFF." */
+ const HBUINT16 *words = &StructAtOffset (&bytesZ, (header.nUnits - 1) * header.unitSize);
+ unsigned int count = Type::TerminationWordCount;
+ for (unsigned int i = 0; i < count; i++)
+ if (words[i] != 0xFFFFu)
+ return false;
+ return true;
+ }
+
inline const Type& operator [] (unsigned int i) const
{
- if (unlikely (i >= header.nUnits)) return Null (Type);
+ if (unlikely (i >= get_length ())) return Null (Type);
return StructAtOffset (&bytesZ, i * header.unitSize);
}
inline Type& operator [] (unsigned int i)
{
+ if (unlikely (i >= get_length ())) return Crap (Type);
return StructAtOffset (&bytesZ, i * header.unitSize);
}
+ inline unsigned int get_length (void) const
+ {
+ return header.nUnits - last_is_terminator ();
+ }
inline unsigned int get_size (void) const
{ return header.static_size + header.nUnits * header.unitSize; }
@@ -842,7 +927,7 @@ struct VarSizedBinSearchArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- unsigned int count = header.nUnits;
+ unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(*this)[i].sanitize (c, base)))
return_trace (false);
@@ -853,7 +938,7 @@ struct VarSizedBinSearchArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- unsigned int count = header.nUnits;
+ unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(*this)[i].sanitize (c, base, user_data)))
return_trace (false);
@@ -864,7 +949,7 @@ struct VarSizedBinSearchArrayOf
inline const Type *bsearch (const T &key) const
{
unsigned int size = header.unitSize;
- int min = 0, max = (int) header.nUnits - 1;
+ int min = 0, max = (int) get_length () - 1;
while (min <= max)
{
int mid = ((unsigned int) min + (unsigned int) max) / 2;
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index b7d17018a..cdc610be3 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -417,6 +417,7 @@ struct CmapSubtableLongGroup
public:
DEFINE_SIZE_STATIC (12);
};
+DECLARE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup);
template
struct CmapSubtableTrimmed
@@ -467,10 +468,7 @@ struct CmapSubtableLongSegmented
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
- int i = groups.bsearch (codepoint);
- if (i == -1)
- return false;
- hb_codepoint_t gid = T::group_get_glyph (groups[i], codepoint);
+ hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
if (!gid)
return false;
*glyph = gid;
@@ -517,7 +515,8 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented
{
static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
hb_codepoint_t u)
- { return group.glyphID + (u - group.startCharCode); }
+ { return likely (group.startCharCode <= group.endCharCode) ?
+ group.glyphID + (u - group.startCharCode) : 0; }
bool serialize (hb_serialize_context_t *c,
@@ -673,16 +672,12 @@ struct VariationSelectorRecord
hb_codepoint_t *glyph,
const void *base) const
{
- int i;
- const DefaultUVS &defaults = base+defaultUVS;
- i = defaults.bsearch (codepoint);
- if (i != -1)
+ if ((base+defaultUVS).bfind (codepoint))
return GLYPH_VARIANT_USE_DEFAULT;
- const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
- i = nonDefaults.bsearch (codepoint);
- if (i != -1 && nonDefaults[i].glyphID)
+ const UVSMapping &nonDefault = (base+nonDefaultUVS).bsearch (codepoint);
+ if (nonDefault.glyphID)
{
- *glyph = nonDefaults[i].glyphID;
+ *glyph = nonDefault.glyphID;
return GLYPH_VARIANT_FOUND;
}
return GLYPH_VARIANT_NOT_FOUND;
@@ -722,7 +717,7 @@ struct CmapSubtableFormat14
hb_codepoint_t variation_selector,
hb_codepoint_t *glyph) const
{
- return record[record.bsearch (variation_selector)].get_glyph (codepoint, glyph, this);
+ return record.bsearch (variation_selector).get_glyph (codepoint, glyph, this);
}
inline void collect_variation_selectors (hb_set_t *out) const
@@ -734,7 +729,7 @@ struct CmapSubtableFormat14
inline void collect_variation_unicodes (hb_codepoint_t variation_selector,
hb_set_t *out) const
{
- record[record.bsearch (variation_selector)].collect_unicodes (out, this);
+ record.bsearch (variation_selector).collect_unicodes (out, this);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -863,14 +858,6 @@ struct cmap
hb_vector_t format12_groups;
};
- inline bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- likely (version == 0) &&
- encodingRecord.sanitize (c, this));
- }
-
inline bool _create_plan (const hb_subset_plan_t *plan,
subset_plan *cmap_plan) const
{
@@ -1164,11 +1151,21 @@ struct cmap
key.platformID.set (platform_id);
key.encodingID.set (encoding_id);
- int result = encodingRecord.bsearch (key);
- if (result == -1 || !encodingRecord[result].subtable)
+ const EncodingRecord &result = encodingRecord.bsearch (key);
+ if (!result.subtable)
return nullptr;
- return &(this+encodingRecord[result].subtable);
+ return &(this+result.subtable);
+ }
+
+ public:
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ likely (version == 0) &&
+ encodingRecord.sanitize (c, this));
}
protected:
diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh
index fa40223b7..84c343325 100644
--- a/src/hb-ot-color-colr-table.hh
+++ b/src/hb-ot-color-colr-table.hh
@@ -66,13 +66,6 @@ struct BaseGlyphRecord
inline int cmp (hb_codepoint_t g) const
{ return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
- static int cmp (const void *pa, const void *pb)
- {
- const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
- const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
- return b->cmp (*a);
- }
-
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -103,12 +96,7 @@ struct COLR
unsigned int *count, /* IN/OUT. May be NULL. */
hb_ot_color_layer_t *layers /* OUT. May be NULL. */) const
{
- const BaseGlyphRecord *rec = (BaseGlyphRecord *) bsearch (&glyph,
- &(this+baseGlyphsZ),
- numBaseGlyphs,
- sizeof (BaseGlyphRecord),
- BaseGlyphRecord::cmp);
- const BaseGlyphRecord &record = rec ? *rec : Null (BaseGlyphRecord);
+ const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph);
hb_array_t all_layers ((this+layersZ).arrayZ, numLayers);
hb_array_t glyph_layers = all_layers.sub_array (record.firstLayerIdx,
@@ -137,7 +125,7 @@ struct COLR
protected:
HBUINT16 version; /* Table version number (starts at 0). */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
- LOffsetTo, false>
+ LOffsetTo, false>
baseGlyphsZ; /* Offset to Base Glyph records. */
LOffsetTo, false>
layersZ; /* Offset to Layer Records. */
diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh
index bad8ef549..ad3551035 100644
--- a/src/hb-ot-color-svg-table.hh
+++ b/src/hb-ot-color-svg-table.hh
@@ -103,8 +103,7 @@ struct SVG
inline const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
{
- const SortedArrayOf &docs = this+svgDocEntries;
- return docs[docs.bsearch (glyph_id)];
+ return (this+svgDocEntries).bsearch (glyph_id);
}
inline bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh
index 7cefdb765..27042c190 100644
--- a/src/hb-ot-face.hh
+++ b/src/hb-ot-face.hh
@@ -67,6 +67,7 @@
HB_OT_TABLE(AAT, trak) \
HB_OT_TABLE(AAT, lcar) \
HB_OT_TABLE(AAT, ltag) \
+ HB_OT_TABLE(AAT, feat) \
/* OpenType variations. */ \
HB_OT_TABLE(OT, fvar) \
HB_OT_TABLE(OT, avar) \
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 4ddee4f86..3491b605d 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -249,7 +249,7 @@ hb_ot_get_font_v_extents (hb_font_t *font,
return vmtx.has_font_extents;
}
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
static void free_static_ot_funcs (void);
#endif
@@ -275,7 +275,7 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t dataZ; /* Location data. */
public:
- DEFINE_SIZE_ARRAY (0, dataZ);
+ DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+ * check the size externally, allow Null() object of it by
+ * defining it MIN() instead. */
};
@@ -465,7 +467,9 @@ struct glyf
protected:
UnsizedArrayOf dataZ; /* Glyphs data. */
public:
- DEFINE_SIZE_ARRAY (0, dataZ);
+ DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+ * check the size externally, allow Null() object of it by
+ * defining it MIN() instead. */
};
struct glyf_accelerator_t : glyf::accelerator_t {};
diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh
index 14e065684..b57ebaea8 100644
--- a/src/hb-ot-kern-table.hh
+++ b/src/hb-ot-kern-table.hh
@@ -154,7 +154,7 @@ struct KernSubTable
KernSubTableFormat3 format3;
} u;
public:
- DEFINE_SIZE_MIN (0);
+ DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
};
@@ -274,6 +274,15 @@ struct kern
inline bool has_data (void) const { return u.version32; }
inline unsigned int get_type (void) const { return u.major; }
+ inline bool has_state_machine (void) const
+ {
+ switch (get_type ()) {
+ case 0: return u.ot.has_state_machine ();
+ case 1: return u.aat.has_state_machine ();
+ default:return false;
+ }
+ }
+
inline bool has_cross_stream (void) const
{
switch (get_type ()) {
diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh
index 36faf6bb6..cc1af1572 100644
--- a/src/hb-ot-layout-common.hh
+++ b/src/hb-ot-layout-common.hh
@@ -128,15 +128,7 @@ struct RecordArrayOf : SortedArrayOf >
}
inline bool find_index (hb_tag_t tag, unsigned int *index) const
{
- /* If we want to allow non-sorted data, we can lsearch(). */
- int i = this->/*lsearch*/bsearch (tag);
- if (i != -1) {
- if (index) *index = i;
- return true;
- } else {
- if (index) *index = Index::NOT_FOUND_INDEX;
- return false;
- }
+ return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
}
};
@@ -802,11 +794,11 @@ struct Lookup
HBUINT16 lookupFlag; /* Lookup qualifiers */
ArrayOf
subTable; /* Array of SubTables */
- HBUINT16 markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
+/*HBUINT16 markFilteringSetX[VAR];*//* Index (base 0) into GDEF mark glyph sets
* structure. This field is only present if bit
* UseMarkFilteringSet of lookup flags is set. */
public:
- DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
+ DEFINE_SIZE_ARRAY (6, subTable);
};
typedef OffsetListOf LookupList;
@@ -823,8 +815,8 @@ struct CoverageFormat1
private:
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
{
- int i = glyphArray.bsearch (glyph_id);
- static_assert ((((unsigned int) -1) == NOT_COVERED), "");
+ unsigned int i;
+ glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
return i;
}
@@ -896,12 +888,10 @@ struct CoverageFormat2
private:
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
{
- int i = rangeRecord.bsearch (glyph_id);
- if (i != -1) {
- const RangeRecord &range = rangeRecord[i];
- return (unsigned int) range.value + (glyph_id - range.start);
- }
- return NOT_COVERED;
+ const RangeRecord &range = rangeRecord.bsearch (glyph_id);
+ return likely (range.start <= range.end) ?
+ (unsigned int) range.value + (glyph_id - range.start) :
+ NOT_COVERED;
}
inline bool serialize (hb_serialize_context_t *c,
@@ -1194,10 +1184,7 @@ struct ClassDefFormat1
private:
inline unsigned int get_class (hb_codepoint_t glyph_id) const
{
- unsigned int i = (unsigned int) (glyph_id - startGlyph);
- if (unlikely (i < classValue.len))
- return classValue[i];
- return 0;
+ return classValue[(unsigned int) (glyph_id - startGlyph)];
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -1265,10 +1252,10 @@ struct ClassDefFormat1
}
protected:
- HBUINT16 classFormat; /* Format identifier--format = 1 */
- GlyphID startGlyph; /* First GlyphID of the classValueArray */
+ HBUINT16 classFormat; /* Format identifier--format = 1 */
+ GlyphID startGlyph; /* First GlyphID of the classValueArray */
ArrayOf
- classValue; /* Array of Class Values--one per GlyphID */
+ classValue; /* Array of Class Values--one per GlyphID */
public:
DEFINE_SIZE_ARRAY (6, classValue);
};
@@ -1280,10 +1267,7 @@ struct ClassDefFormat2
private:
inline unsigned int get_class (hb_codepoint_t glyph_id) const
{
- int i = rangeRecord.bsearch (glyph_id);
- if (unlikely (i != -1))
- return rangeRecord[i].value;
- return 0;
+ return rangeRecord.bsearch (glyph_id).value;
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -1586,9 +1570,9 @@ struct VarData
HBUINT16 itemCount;
HBUINT16 shortCount;
ArrayOf regionIndices;
- UnsizedArrayOfbytesX;
+/*UnsizedArrayOfbytesX;*/
public:
- DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
+ DEFINE_SIZE_ARRAY (6, regionIndices);
};
struct VariationStore
diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh
index 22e07f7a4..a0ae27e75 100644
--- a/src/hb-ot-layout-gdef-table.hh
+++ b/src/hb-ot-layout-gdef-table.hh
@@ -61,9 +61,10 @@ struct AttachList
const AttachPoint &points = this+attachPoint[index];
- if (point_count) {
- const HBUINT16 *array = points.sub_array (start_offset, point_count);
- unsigned int count = *point_count;
+ if (point_count)
+ {
+ hb_array_t array = points.sub_array (start_offset, point_count);
+ unsigned int count = array.len;
for (unsigned int i = 0; i < count; i++)
point_array[i] = array[i];
}
@@ -216,9 +217,10 @@ struct LigGlyph
unsigned int *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
{
- if (caret_count) {
- const OffsetTo *array = carets.sub_array (start_offset, caret_count);
- unsigned int count = *caret_count;
+ if (caret_count)
+ {
+ hb_array_t > array = carets.sub_array (start_offset, caret_count);
+ unsigned int count = array.len;
for (unsigned int i = 0; i < count; i++)
caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
}
@@ -406,9 +408,20 @@ struct GDEF
}
}
+ HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
struct accelerator_t
{
- HB_INTERNAL void init (hb_face_t *face);
+ inline void init (hb_face_t *face)
+ {
+ this->table = hb_sanitize_context_t().reference_table (face);
+ if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
+ {
+ hb_blob_destroy (this->table.get_blob ());
+ this->table = hb_blob_get_empty ();
+ }
+ }
inline void fini (void)
{
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 907fd4631..2589218de 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1643,6 +1643,9 @@ struct GPOS : GSUBGPOS
inline bool sanitize (hb_sanitize_context_t *c) const
{ return GSUBGPOS::sanitize (c); }
+ HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
typedef GSUBGPOS::accelerator_t accelerator_t;
};
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 715317b59..27bd440da 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1449,7 +1449,10 @@ struct SubstLookup : Lookup
hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
- c->flush ();
+ /* While in theory we should flush here, it will cause timeouts because a recursive
+ * lookup can keep growing the glyph set. Skip, and outer loop will retry up to
+ * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
+ //c->flush ();
return ret;
}
@@ -1483,6 +1486,9 @@ struct GSUB : GSUBGPOS
inline bool sanitize (hb_sanitize_context_t *c) const
{ return GSUBGPOS::sanitize (c); }
+ HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
typedef GSUBGPOS::accelerator_t accelerator_t;
};
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index 3d70c55c2..a9bfee155 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -2753,6 +2753,11 @@ struct GSUBGPOS
inline void init (hb_face_t *face)
{
this->table = hb_sanitize_context_t().reference_table (face);
+ if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
+ {
+ hb_blob_destroy (this->table.get_blob ());
+ this->table = hb_blob_get_empty ();
+ }
this->lookup_count = table->get_lookup_count ();
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 092633c5d..d0b22efe3 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -34,15 +34,17 @@
#include "hb-ot-map.hh"
#include "hb-map.hh"
+#include "hb-ot-kern-table.hh"
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise
#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise
-#include "hb-ot-kern-table.hh"
#include "hb-ot-name-table.hh"
+#include "hb-ot-os2-table.hh"
#include "hb-aat-layout-lcar-table.hh"
+#include "hb-aat-layout-morx-table.hh"
/**
@@ -65,6 +67,12 @@ hb_ot_layout_has_kerning (hb_face_t *face)
return face->table.kern->has_data ();
}
+bool
+hb_ot_layout_has_machine_kerning (hb_face_t *face)
+{
+ return face->table.kern->has_state_machine ();
+}
+
bool
hb_ot_layout_has_cross_kerning (hb_face_t *face)
{
@@ -89,10 +97,9 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
* GDEF
*/
-static bool
-_hb_ot_blacklist_gdef (unsigned int gdef_len,
- unsigned int gsub_len,
- unsigned int gpos_len)
+bool
+OT::GDEF::is_blacklisted (hb_blob_t *blob,
+ hb_face_t *face) const
{
/* The ugly business of blacklisting individual fonts' tables happen here!
* See this thread for why we finally had to bend in and do this:
@@ -111,8 +118,10 @@ _hb_ot_blacklist_gdef (unsigned int gdef_len,
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
*/
-#define ENCODE(x,y,z) ((int64_t) (x) << 32 | (int64_t) (y) << 16 | (z))
- switch ENCODE(gdef_len, gsub_len, gpos_len)
+#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z))
+ switch ENCODE(blob->length,
+ face->table.GSUB->table.get_length (),
+ face->table.GPOS->table.get_length ())
{
/* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
case ENCODE (442, 2874, 42038):
@@ -191,20 +200,6 @@ _hb_ot_blacklist_gdef (unsigned int gdef_len,
return false;
}
-void
-OT::GDEF::accelerator_t::init (hb_face_t *face)
-{
- this->table = hb_sanitize_context_t().reference_table (face);
-
- if (unlikely (_hb_ot_blacklist_gdef (this->table.get_length (),
- face->table.GSUB->table.get_length (),
- face->table.GPOS->table.get_length ())))
- {
- hb_blob_destroy (this->table.get_blob ());
- this->table = hb_blob_get_empty ();
- }
-}
-
static void
_hb_ot_layout_set_glyph_props (hb_font_t *font,
hb_buffer_t *buffer)
@@ -291,6 +286,38 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
* GSUB/GPOS
*/
+bool
+OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
+ hb_face_t *face) const
+{
+ /* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts,
+ * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
+ * GSUB/GPOS tables. Some have GSUB with zero scripts, those are ignored by
+ * our morx/GSUB preference code. But if GSUB has non-zero scripts, we tend
+ * to prefer it over morx because we want to be consistent with other OpenType
+ * shapers.
+ *
+ * To work around broken Indic Mac system fonts, we ignore GSUB table if
+ * OS/2 VendorId is 'MUTF' and font has morx table as well.
+ *
+ * https://github.com/harfbuzz/harfbuzz/issues/1410
+ * https://github.com/harfbuzz/harfbuzz/issues/1348
+ * https://github.com/harfbuzz/harfbuzz/issues/1391
+ */
+ if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') &&
+ face->table.morx->has_data ()))
+ return true;
+
+ return false;
+}
+
+bool
+OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
+ hb_face_t *face HB_UNUSED) const
+{
+ return false;
+}
+
static const OT::GSUBGPOS&
get_gsubgpos_table (hb_face_t *face,
hb_tag_t table_tag)
diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh
index db85508d2..a00b940b2 100644
--- a/src/hb-ot-layout.hh
+++ b/src/hb-ot-layout.hh
@@ -48,6 +48,9 @@ struct hb_ot_shape_plan_t;
HB_INTERNAL bool
hb_ot_layout_has_kerning (hb_face_t *face);
+HB_INTERNAL bool
+hb_ot_layout_has_machine_kerning (hb_face_t *face);
+
HB_INTERNAL bool
hb_ot_layout_has_cross_kerning (hb_face_t *face);
diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh
index 8e1f5aa8c..0a5a4fbcb 100644
--- a/src/hb-ot-map.hh
+++ b/src/hb-ot-map.hh
@@ -57,8 +57,8 @@ struct hb_ot_map_t
unsigned int auto_zwj : 1;
unsigned int random : 1;
- inline int cmp (const hb_tag_t *tag_) const
- { return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; }
+ inline int cmp (const hb_tag_t tag_) const
+ { return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
};
struct lookup_map_t {
diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh
index b87304979..153a41795 100644
--- a/src/hb-ot-math-table.hh
+++ b/src/hb-ot-math-table.hh
@@ -509,9 +509,8 @@ struct MathGlyphAssembly
if (parts_count)
{
int scale = font->dir_scale (direction);
- const MathGlyphPartRecord *arr =
- partRecords.sub_array (start_offset, parts_count);
- unsigned int count = *parts_count;
+ hb_array_t arr = partRecords.sub_array (start_offset, parts_count);
+ unsigned int count = arr.len;
for (unsigned int i = 0; i < count; i++)
arr[i].extract (parts[i], scale, font);
}
@@ -556,9 +555,8 @@ struct MathGlyphConstruction
if (variants_count)
{
int scale = font->dir_scale (direction);
- const MathGlyphVariantRecord *arr =
- mathGlyphVariantRecord.sub_array (start_offset, variants_count);
- unsigned int count = *variants_count;
+ hb_array_t arr = mathGlyphVariantRecord.sub_array (start_offset, variants_count);
+ unsigned int count = arr.len;
for (unsigned int i = 0; i < count; i++)
{
variants[i].glyph = arr[i].variantGlyph;
diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh
index f80303cc8..98df3e780 100644
--- a/src/hb-ot-post-table.hh
+++ b/src/hb-ot-post-table.hh
@@ -61,12 +61,12 @@ struct postV2Tail
ArrayOf glyphNameIndex; /* This is not an offset, but is the
* ordinal number of the glyph in 'post'
* string tables. */
- UnsizedArrayOf
- namesX; /* Glyph names with length bytes [variable]
+/*UnsizedArrayOf
+ namesX;*/ /* Glyph names with length bytes [variable]
* (a Pascal string). */
public:
- DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
+ DEFINE_SIZE_ARRAY (2, glyphNameIndex);
};
struct post
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc
index ca7b5a9b2..8fdf2f4bc 100644
--- a/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -391,27 +391,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
};
-/* Uniscribe seems to have a shaper for 'mymr' that is like the
- * generic shaper, except that it zeros mark advances GDEF_LATE. */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
-{
- nullptr, /* collect_features */
- nullptr, /* override_features */
- nullptr, /* data_create */
- nullptr, /* data_destroy */
- nullptr, /* preprocess_text */
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
- nullptr, /* decompose */
- nullptr, /* compose */
- nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
- true, /* fallback_position */
-};
-
-
/* Ugly Zawgyi encoding.
* Disable all auto processing.
* https://github.com/harfbuzz/harfbuzz/issues/1162 */
diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc
index bfc92d3b5..2f3eb703e 100644
--- a/src/hb-ot-shape-complex-use-table.cc
+++ b/src/hb-ot-shape-complex-use-table.cc
@@ -544,7 +544,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
- /* 111C0 */ H, B, R, R, O, O, O, O, O, FM, CMBlw, VAbv, VBlw, O, O, O,
+ /* 111C0 */ H, B, R, R, O, O, O, O, GB, FBlw, CMBlw, VAbv, VBlw, O, O, O,
/* 111D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
/* Sinhala Archaic Numbers */
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index af25b07f8..2e3f202f5 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -432,7 +432,8 @@ record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
static inline bool
is_halant (const hb_glyph_info_t &info)
{
- return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
+ return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
+ !_hb_glyph_info_ligated (&info);
}
static void
@@ -449,19 +450,38 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
hb_glyph_info_t *info = buffer->info;
-#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB))
+#define POST_BASE_FLAGS64 (FLAG64 (USE_FM) | \
+ FLAG64 (USE_FAbv) | \
+ FLAG64 (USE_FBlw) | \
+ FLAG64 (USE_FPst) | \
+ FLAG64 (USE_MAbv) | \
+ FLAG64 (USE_MBlw) | \
+ FLAG64 (USE_MPst) | \
+ FLAG64 (USE_MPre) | \
+ FLAG64 (USE_VAbv) | \
+ FLAG64 (USE_VBlw) | \
+ FLAG64 (USE_VPst) | \
+ FLAG64 (USE_VPre) | \
+ FLAG64 (USE_VMAbv) | \
+ FLAG64 (USE_VMBlw) | \
+ FLAG64 (USE_VMPst) | \
+ FLAG64 (USE_VMPre))
/* Move things forward. */
if (info[start].use_category() == USE_R && end - start > 1)
{
- /* Got a repha. Reorder it to after first base, before first halant. */
+ /* Got a repha. Reorder it towards the end, but before the first post-base
+ * glyph. */
for (unsigned int i = start + 1; i < end; i++)
- if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
+ {
+ bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
+ is_halant (info[i]);
+ if (is_post_base_glyph || i == end - 1)
{
- /* If we hit a halant, move before it; otherwise it's a base: move to it's
- * place, and shift things in between backward. */
+ /* If we hit a post-base glyph, move before it; otherwise move to the
+ * end. Shift things in between backward. */
- if (is_halant (info[i]))
+ if (is_post_base_glyph)
i--;
buffer->merge_clusters (start, i + 1);
@@ -471,21 +491,19 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
break;
}
+ }
}
/* Move things back. */
- unsigned int j = end;
+ unsigned int j = start;
for (unsigned int i = start; i < end; i++)
{
uint32_t flag = FLAG_UNSAFE (info[i].use_category());
- if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
+ if (is_halant (info[i]))
{
- /* If we hit a halant, move after it; otherwise it's a base: move to it's
- * place, and shift things in between backward. */
- if (is_halant (info[i]))
- j = i + 1;
- else
- j = i;
+ /* If we hit a halant, move after it; otherwise move to the beginning, and
+ * shift things in between forward. */
+ j = i + 1;
}
else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
/* Only move the first component of a MultipleSubst. */
diff --git a/src/hb-ot-shape-complex.hh b/src/hb-ot-shape-complex.hh
index 2944d745c..a2499de9c 100644
--- a/src/hb-ot-shape-complex.hh
+++ b/src/hb-ot-shape-complex.hh
@@ -57,7 +57,6 @@ enum hb_ot_shape_zero_width_marks_type_t {
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
- HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
HB_COMPLEX_SHAPER_IMPLEMENT (use) \
@@ -269,12 +268,25 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
return &_hb_ot_complex_shaper_khmer;
case HB_SCRIPT_MYANMAR:
- if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
- return &_hb_ot_complex_shaper_myanmar;
- else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
- return &_hb_ot_complex_shaper_myanmar_old;
- else
+ /* If the designer designed the font for the 'DFLT' script,
+ * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+ * Otherwise, use the specific shaper.
+ *
+ * If designer designed for 'mymr' tag, also send to default
+ * shaper. That's tag used from before Myanmar shaping spec
+ * was developed. The shaping spec uses 'mym2' tag. */
+ if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+ planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
+ planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
return &_hb_ot_complex_shaper_default;
+ else
+ return &_hb_ot_complex_shaper_myanmar;
+
+
+ /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
+ case HB_SCRIPT_MYANMAR_ZAWGYI:
+
+ return &_hb_ot_complex_shaper_myanmar_zawgyi;
/* Unicode-2.0 additions */
@@ -375,10 +387,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
return &_hb_ot_complex_shaper_default;
else
return &_hb_ot_complex_shaper_use;
-
- /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
- case HB_SCRIPT_MYANMAR_ZAWGYI:
- return &_hb_ot_complex_shaper_myanmar_zawgyi;
}
}
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index ccee8d343..ef9743578 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -76,10 +76,16 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
props (*props),
map (face, props),
aat_map (face, props),
- apply_morx (_hb_apply_morx (face)),
- shaper (apply_morx ?
- &_hb_ot_complex_shaper_default :
- hb_ot_shape_complex_categorize (this)) {}
+ apply_morx (_hb_apply_morx (face))
+{
+ shaper = hb_ot_shape_complex_categorize (this);
+
+ script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
+ script_fallback_mark_positioning = shaper->fallback_position;
+
+ if (apply_morx)
+ shaper = &_hb_ot_complex_shaper_default;
+}
void
hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
@@ -140,10 +146,17 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
plan.apply_kern = true;
}
- bool has_kern_mark = plan.apply_kern && hb_ot_layout_has_cross_kerning (face);
- plan.zero_marks = !plan.apply_morx && !plan.apply_kerx && !has_kern_mark;
+ plan.zero_marks = script_zero_marks &&
+ !plan.apply_kerx &&
+ (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face));
plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
- plan.fallback_mark_positioning = !plan.apply_gpos && plan.zero_marks;
+
+ plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
+ !plan.apply_kerx &&
+ (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face));
+
+ plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
+ script_fallback_mark_positioning;
/* Currently we always apply trak. */
plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
@@ -158,6 +171,7 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
hb_ot_shape_planner_t planner (face,
&key->props);
+
hb_ot_shape_collect_features (&planner,
key->user_features,
key->num_user_features);
@@ -811,17 +825,16 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
hb_glyph_info_t *info = c->buffer->info;
hb_glyph_position_t *pos = c->buffer->pos;
- /* If the font has no GPOS, AND, no fallback positioning will
- * happen, AND, direction is forward, then when zeroing mark
- * widths, we shift the mark with it, such that the mark
- * is positioned hanging over the previous glyph. When
+ /* If the font has no GPOS and direction is forward, then when
+ * zeroing mark widths, we shift the mark with it, such that the
+ * mark is positioned hanging over the previous glyph. When
* direction is backward we don't shift and it will end up
* hanging over the next glyph after the final reordering.
- * If fallback positinoing happens or GPOS is present, we don't
- * care.
+ *
+ * Note: If fallback positinoing happens, we don't care about
+ * this as it will be overriden.
*/
- bool adjust_offsets_when_zeroing = c->plan->fallback_mark_positioning &&
- !c->plan->shaper->fallback_position &&
+ bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
/* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
@@ -877,7 +890,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
&pos[i].x_offset,
&pos[i].y_offset);
- if (c->plan->fallback_mark_positioning && c->plan->shaper->fallback_position)
+ if (c->plan->fallback_mark_positioning)
_hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer);
}
diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh
index 397634c25..6e1478d00 100644
--- a/src/hb-ot-shape.hh
+++ b/src/hb-ot-shape.hh
@@ -77,6 +77,7 @@ struct hb_ot_shape_plan_t
bool zero_marks : 1;
bool fallback_glyph_classes : 1;
bool fallback_mark_positioning : 1;
+ bool adjust_mark_positioning_when_zeroing : 1;
bool apply_gpos : 1;
bool apply_kerx : 1;
@@ -113,6 +114,8 @@ struct hb_ot_shape_planner_t
hb_ot_map_builder_t map;
hb_aat_map_builder_t aat_map;
bool apply_morx : 1;
+ bool script_zero_marks : 1;
+ bool script_fallback_mark_positioning : 1;
const struct hb_ot_complex_shaper_t *shaper;
HB_INTERNAL hb_ot_shape_planner_t (hb_face_t *face,
diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh
index 47c2516f3..fed334e8a 100644
--- a/src/hb-ot-var-fvar-table.hh
+++ b/src/hb-ot-var-fvar-table.hh
@@ -65,7 +65,7 @@ struct InstanceRecord
// * instance. */
public:
- DEFINE_SIZE_ARRAY (4, coordinatesZ);
+ DEFINE_SIZE_UNBOUNDED (4);
};
struct AxisRecord
@@ -109,40 +109,46 @@ struct fvar
axisSize == 20 && /* Assumed in our code. */
instanceSize >= axisCount * 4 + 4 &&
get_axes ().sanitize (c) &&
- c->check_range (&get_instance (0), instanceCount, instanceSize));
+ c->check_range (get_instance (0), instanceCount, instanceSize));
}
inline unsigned int get_axis_count (void) const
{ return axisCount; }
- inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const
+ inline void get_axis_deprecated (unsigned int axis_index,
+ hb_ot_var_axis_t *info) const
{
- if (info)
- {
- const AxisRecord &axis = get_axes ()[index];
- info->tag = axis.axisTag;
- info->name_id = axis.axisNameID;
- info->default_value = axis.defaultValue / 65536.;
- /* Ensure order, to simplify client math. */
- info->min_value = MIN (info->default_value, axis.minValue / 65536.);
- info->max_value = MAX (info->default_value, axis.maxValue / 65536.);
- }
-
- return true;
+ const AxisRecord &axis = get_axes ()[axis_index];
+ info->tag = axis.axisTag;
+ info->name_id = axis.axisNameID;
+ info->default_value = axis.defaultValue / 65536.;
+ /* Ensure order, to simplify client math. */
+ info->min_value = MIN (info->default_value, axis.minValue / 65536.);
+ info->max_value = MAX (info->default_value, axis.maxValue / 65536.);
}
- inline hb_ot_var_axis_flags_t get_axis_flags (unsigned int index) const
+ inline void get_axis_info (unsigned int axis_index,
+ hb_ot_var_axis_info_t *info) const
{
- const AxisRecord &axis = get_axes ()[index];
- return (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
+ const AxisRecord &axis = get_axes ()[axis_index];
+ info->axis_index = axis_index;
+ info->tag = axis.axisTag;
+ info->name_id = axis.axisNameID;
+ info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
+ info->default_value = axis.defaultValue / 65536.;
+ /* Ensure order, to simplify client math. */
+ info->min_value = MIN (info->default_value, axis.minValue / 65536.);
+ info->max_value = MAX (info->default_value, axis.maxValue / 65536.);
+ info->reserved = 0;
}
- inline unsigned int get_axis_infos (unsigned int start_offset,
- unsigned int *axes_count /* IN/OUT */,
- hb_ot_var_axis_t *axes_array /* OUT */) const
+ inline unsigned int get_axes_deprecated (unsigned int start_offset,
+ unsigned int *axes_count /* IN/OUT */,
+ hb_ot_var_axis_t *axes_array /* OUT */) const
{
if (axes_count)
{
+ /* TODO Rewrite as hb_array_t<>::sub-array() */
unsigned int count = axisCount;
start_offset = MIN (start_offset, count);
@@ -153,32 +159,70 @@ struct fvar
*axes_count = count;
for (unsigned int i = 0; i < count; i++)
- get_axis (start_offset + i, axes_array + i);
+ get_axis_deprecated (start_offset + i, axes_array + i);
}
return axisCount;
}
- inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const
+ inline unsigned int get_axis_infos (unsigned int start_offset,
+ unsigned int *axes_count /* IN/OUT */,
+ hb_ot_var_axis_info_t *axes_array /* OUT */) const
+ {
+ if (axes_count)
+ {
+ /* TODO Rewrite as hb_array_t<>::sub-array() */
+ unsigned int count = axisCount;
+ start_offset = MIN (start_offset, count);
+
+ count -= start_offset;
+ axes_array += start_offset;
+
+ count = MIN (count, *axes_count);
+ *axes_count = count;
+
+ for (unsigned int i = 0; i < count; i++)
+ get_axis_info (start_offset + i, axes_array + i);
+ }
+ return axisCount;
+ }
+
+ inline bool find_axis_deprecated (hb_tag_t tag,
+ unsigned int *axis_index,
+ hb_ot_var_axis_t *info) const
{
const AxisRecord *axes = get_axes ();
unsigned int count = get_axis_count ();
for (unsigned int i = 0; i < count; i++)
if (axes[i].axisTag == tag)
{
- if (index)
- *index = i;
- return get_axis (i, info);
+ if (axis_index)
+ *axis_index = i;
+ get_axis_deprecated (i, info);
+ return true;
+ }
+ if (axis_index)
+ *axis_index = HB_OT_VAR_NO_AXIS_INDEX;
+ return false;
+ }
+
+ inline bool find_axis_info (hb_tag_t tag,
+ hb_ot_var_axis_info_t *info) const
+ {
+ const AxisRecord *axes = get_axes ();
+ unsigned int count = get_axis_count ();
+ for (unsigned int i = 0; i < count; i++)
+ if (axes[i].axisTag == tag)
+ {
+ get_axis_info (i, info);
+ return true;
}
- if (index)
- *index = HB_OT_VAR_NO_AXIS_INDEX;
return false;
}
inline int normalize_axis_value (unsigned int axis_index, float v) const
{
- hb_ot_var_axis_t axis;
- if (!get_axis (axis_index, &axis))
- return 0;
+ hb_ot_var_axis_info_t axis;
+ get_axis_info (axis_index, &axis);
v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
@@ -194,25 +238,28 @@ struct fvar
inline unsigned int get_instance_count (void) const
{ return instanceCount; }
- inline hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int index) const
+ inline hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int instance_index) const
{
- const InstanceRecord &instance = get_instance (index);
- return instance.subfamilyNameID;
+ const InstanceRecord *instance = get_instance (instance_index);
+ if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
+ return instance->subfamilyNameID;
}
- inline hb_ot_name_id_t get_instance_postscript_name_id (unsigned int index) const
+ inline hb_ot_name_id_t get_instance_postscript_name_id (unsigned int instance_index) const
{
- const InstanceRecord &instance = get_instance (index);
+ const InstanceRecord *instance = get_instance (instance_index);
+ if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
if (instanceSize >= axisCount * 4 + 6)
- return StructAfter (instance.get_coordinates (axisCount));
+ return StructAfter (instance->get_coordinates (axisCount));
return HB_OT_NAME_ID_INVALID;
}
- inline unsigned int get_instance_coords (unsigned int index,
+ inline unsigned int get_instance_coords (unsigned int instance_index,
unsigned int *coords_length, /* IN/OUT */
float *coords /* OUT */) const
{
- if (unlikely (index >= instanceCount))
+ const InstanceRecord *instance = get_instance (instance_index);
+ if (unlikely (!instance))
{
if (coords_length)
*coords_length = 0;
@@ -221,9 +268,8 @@ struct fvar
if (coords_length && *coords_length)
{
- const InstanceRecord &instance = get_instance (index);
- hb_array_t instanceCoords = instance.get_coordinates (axisCount)
- .sub_array (0, *coords_length);
+ hb_array_t instanceCoords = instance->get_coordinates (axisCount)
+ .sub_array (0, *coords_length);
for (unsigned int i = 0; i < instanceCoords.len; i++)
coords[i] = instanceCoords.arrayZ[i].to_float ();
}
@@ -234,12 +280,11 @@ struct fvar
inline hb_array_t get_axes (void) const
{ return hb_array (&(this+firstAxis), axisCount); }
- inline const InstanceRecord &get_instance (unsigned int i) const
+ inline const InstanceRecord *get_instance (unsigned int i) const
{
- if (unlikely (i >= instanceCount)) return Null (InstanceRecord);
-
- return StructAtOffset (&StructAfter (get_axes ()),
- i * instanceSize);
+ if (unlikely (i >= instanceCount)) return nullptr;
+ return &StructAtOffset (&StructAfter (get_axes ()),
+ i * instanceSize);
}
protected:
diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc
index 9ad2f861e..56d248178 100644
--- a/src/hb-ot-var.cc
+++ b/src/hb-ot-var.cc
@@ -53,7 +53,6 @@
* @face: #hb_face_t to test
*
* This function allows to verify the presence of OpenType variation data on the face.
- * Alternatively, use hb_ot_var_get_axis_count().
*
* Return value: true if face has a `fvar' table and false otherwise
*
@@ -80,6 +79,7 @@ hb_ot_var_get_axis_count (hb_face_t *face)
* hb_ot_var_get_axes:
*
* Since: 1.4.2
+ * Deprecated: REPLACEME
**/
unsigned int
hb_ot_var_get_axes (hb_face_t *face,
@@ -87,13 +87,14 @@ hb_ot_var_get_axes (hb_face_t *face,
unsigned int *axes_count /* IN/OUT */,
hb_ot_var_axis_t *axes_array /* OUT */)
{
- return face->table.fvar->get_axis_infos (start_offset, axes_count, axes_array);
+ return face->table.fvar->get_axes_deprecated (start_offset, axes_count, axes_array);
}
/**
* hb_ot_var_find_axis:
*
* Since: 1.4.2
+ * Deprecated: REPLACEME
**/
hb_bool_t
hb_ot_var_find_axis (hb_face_t *face,
@@ -101,21 +102,37 @@ hb_ot_var_find_axis (hb_face_t *face,
unsigned int *axis_index,
hb_ot_var_axis_t *axis_info)
{
- return face->table.fvar->find_axis (axis_tag, axis_index, axis_info);
+ return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info);
}
/**
- * hb_ot_var_axis_get_flags:
+ * hb_ot_var_get_axis_infos:
*
* Since: REPLACEME
**/
-hb_ot_var_axis_flags_t
-hb_ot_var_axis_get_flags (hb_face_t *face,
- unsigned int axis_index)
+HB_EXTERN unsigned int
+hb_ot_var_get_axis_infos (hb_face_t *face,
+ unsigned int start_offset,
+ unsigned int *axes_count /* IN/OUT */,
+ hb_ot_var_axis_info_t *axes_array /* OUT */)
{
- return face->table.fvar->get_axis_flags (axis_index);
+ return face->table.fvar->get_axis_infos (start_offset, axes_count, axes_array);
}
+/**
+ * hb_ot_var_find_axis_info:
+ *
+ * Since: REPLACEME
+ **/
+HB_EXTERN hb_bool_t
+hb_ot_var_find_axis_info (hb_face_t *face,
+ hb_tag_t axis_tag,
+ hb_ot_var_axis_info_t *axis_info)
+{
+ return face->table.fvar->find_axis_info (axis_tag, axis_info);
+}
+
+
/*
* Named instances.
*/
@@ -168,10 +185,10 @@ hb_ot_var_normalize_variations (hb_face_t *face,
const OT::fvar &fvar = *face->table.fvar;
for (unsigned int i = 0; i < variations_length; i++)
{
- unsigned int axis_index;
- if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, nullptr) &&
- axis_index < coords_length)
- coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
+ hb_ot_var_axis_info_t info;
+ if (hb_ot_var_find_axis_info (face, variations[i].tag, &info) &&
+ info.axis_index < coords_length)
+ coords[info.axis_index] = fvar.normalize_axis_value (info.axis_index, variations[i].value);
}
face->table.avar->map_coords (coords, coords_length);
diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h
index 79ce7d72b..779be1043 100644
--- a/src/hb-ot-var.h
+++ b/src/hb-ot-var.h
@@ -47,19 +47,6 @@ HB_BEGIN_DECLS
* fvar / avar
*/
-/**
- * hb_ot_var_axis_t:
- *
- * Since: 1.4.2
- */
-typedef struct hb_ot_var_axis_t {
- hb_tag_t tag;
- hb_ot_name_id_t name_id;
- float min_value;
- float default_value;
- float max_value;
-} hb_ot_var_axis_t;
-
HB_EXTERN hb_bool_t
hb_ot_var_has_data (hb_face_t *face);
@@ -68,28 +55,10 @@ hb_ot_var_has_data (hb_face_t *face);
* Variation axes.
*/
-/**
- * HB_OT_VAR_NO_AXIS_INDEX:
- *
- * Since: 1.4.2
- */
-#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu
HB_EXTERN unsigned int
hb_ot_var_get_axis_count (hb_face_t *face);
-HB_EXTERN unsigned int
-hb_ot_var_get_axes (hb_face_t *face,
- unsigned int start_offset,
- unsigned int *axes_count /* IN/OUT */,
- hb_ot_var_axis_t *axes_array /* OUT */);
-
-HB_EXTERN hb_bool_t
-hb_ot_var_find_axis (hb_face_t *face,
- hb_tag_t axis_tag,
- unsigned int *axis_index,
- hb_ot_var_axis_t *axis_info);
-
/**
* hb_ot_var_axis_flags_t:
* @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces.
@@ -97,12 +66,39 @@ hb_ot_var_find_axis (hb_face_t *face,
* Since: REPLACEME
*/
typedef enum { /*< flags >*/
- HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x0001u,
+ HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x00000001u,
+
+ _HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
} hb_ot_var_axis_flags_t;
-HB_EXTERN hb_ot_var_axis_flags_t
-hb_ot_var_axis_get_flags (hb_face_t *face,
- unsigned int axis_index);
+/**
+ * hb_ot_var_axis_info_t:
+ *
+ * Since: REPLACEME
+ */
+typedef struct hb_ot_var_axis_info_t
+{
+ unsigned int axis_index;
+ hb_tag_t tag;
+ hb_ot_name_id_t name_id;
+ hb_ot_var_axis_flags_t flags;
+ float min_value;
+ float default_value;
+ float max_value;
+ /*< private >*/
+ unsigned int reserved;
+} hb_ot_var_axis_info_t;
+
+HB_EXTERN unsigned int
+hb_ot_var_get_axis_infos (hb_face_t *face,
+ unsigned int start_offset,
+ unsigned int *axes_count /* IN/OUT */,
+ hb_ot_var_axis_info_t *axes_array /* OUT */);
+
+HB_EXTERN hb_bool_t
+hb_ot_var_find_axis_info (hb_face_t *face,
+ hb_tag_t axis_tag,
+ hb_ot_var_axis_info_t *axis_info);
/*
diff --git a/src/hb-ot-vorg-table.hh b/src/hb-ot-vorg-table.hh
index a4a24bbbd..5a00bfc35 100644
--- a/src/hb-ot-vorg-table.hh
+++ b/src/hb-ot-vorg-table.hh
@@ -63,11 +63,10 @@ struct VORG
inline int get_y_origin (hb_codepoint_t glyph) const
{
- int i = vertYOrigins.bsearch (glyph);
- if (i != -1)
- return vertYOrigins[i].vertOriginY;
-
- return defaultVertOriginY;
+ unsigned int i;
+ if (!vertYOrigins.bfind (glyph, &i))
+ return defaultVertOriginY;
+ return vertYOrigins[i].vertOriginY;
}
inline bool _subset (const hb_subset_plan_t *plan HB_UNUSED,
diff --git a/src/hb-set.hh b/src/hb-set.hh
index bc26ed3c0..8b7a0f3d0 100644
--- a/src/hb-set.hh
+++ b/src/hb-set.hh
@@ -45,7 +45,7 @@ struct hb_set_t
struct page_map_t
{
- inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; }
+ inline int cmp (const page_map_t &o) const { return (int) o.major - (int) major; }
uint32_t major;
uint32_t index;
@@ -341,11 +341,11 @@ struct hb_set_t
{
/* TODO perform op even if !successful. */
if (unlikely (!successful)) return;
- page_t *p = page_for (g);
- if (!p)
+ page_t *page = page_for (g);
+ if (!page)
return;
dirty ();
- p->del (g);
+ page->del (g);
}
inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
{
@@ -357,10 +357,10 @@ struct hb_set_t
}
inline bool has (hb_codepoint_t g) const
{
- const page_t *p = page_for (g);
- if (!p)
+ const page_t *page = page_for (g);
+ if (!page)
return false;
- return p->has (g);
+ return page->has (g);
}
inline bool intersects (hb_codepoint_t first,
hb_codepoint_t last) const
@@ -544,7 +544,7 @@ struct hb_set_t
page_map_t map = {get_major (*codepoint), 0};
unsigned int i;
- page_map.bfind (map, &i);
+ page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
if (i < page_map.len && page_map[i].major == map.major)
{
if (pages[page_map[i].index].next (codepoint))
@@ -575,7 +575,7 @@ struct hb_set_t
page_map_t map = {get_major (*codepoint), 0};
unsigned int i;
- page_map.bfind (map, &i);
+ page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
if (i < page_map.len && page_map[i].major == map.major)
{
if (pages[page_map[i].index].previous (codepoint))
@@ -670,7 +670,7 @@ struct hb_set_t
{
page_map_t map = {get_major (g), pages.len};
unsigned int i;
- if (!page_map.bfind (map, &i))
+ if (!page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST))
{
if (!resize (pages.len + 1))
return nullptr;
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index 270da3d77..45f3a6916 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -48,7 +48,7 @@
**/
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
static void free_static_shaper_list (void);
#endif
@@ -69,7 +69,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_tinit ();
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
atexit (free_static_uniscribe_shaper_funcs);
#endif
@@ -261,7 +261,7 @@ static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t
+template
struct hb_vector_t
{
+ static_assert ((bool) (unsigned) hb_static_size (Type), "");
+
typedef Type ItemType;
enum { item_size = sizeof (Type) };
- HB_NO_COPY_ASSIGN_TEMPLATE2 (hb_vector_t, Type, StaticSize);
+ HB_NO_COPY_ASSIGN_TEMPLATE2 (hb_vector_t, Type, PreallocedCount);
inline hb_vector_t (void) { init (); }
inline ~hb_vector_t (void) { fini (); }
@@ -45,7 +47,7 @@ struct hb_vector_t
private:
unsigned int allocated; /* == 0 means allocation failed. */
Type *arrayZ_;
- Type static_array[StaticSize];
+ Type static_array[PreallocedCount];
public:
void init (void)
@@ -89,6 +91,16 @@ struct hb_vector_t
return arrayZ()[i];
}
+ inline hb_array_t as_array (void)
+ { return hb_array (arrayZ(), len); }
+ inline hb_array_t as_array (void) const
+ { return hb_array (arrayZ(), len); }
+
+ inline hb_sorted_array_t as_sorted_array (void)
+ { return hb_sorted_array (arrayZ(), len); }
+ inline hb_sorted_array_t as_sorted_array (void) const
+ { return hb_sorted_array (arrayZ(), len); }
+
template inline operator T * (void) { return arrayZ(); }
template inline operator const T * (void) const { return arrayZ(); }
@@ -209,75 +221,28 @@ struct hb_vector_t
}
inline void qsort (int (*cmp)(const void*, const void*))
- {
- ::qsort (arrayZ(), len, sizeof (Type), cmp);
- }
-
- inline void qsort (void)
- {
- ::qsort (arrayZ(), len, sizeof (Type), Type::cmp);
- }
-
- inline void qsort (unsigned int start, unsigned int end)
- {
- ::qsort (arrayZ() + start, end - start, sizeof (Type), Type::cmp);
- }
+ { as_array ().qsort (cmp); }
+ inline void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+ { as_array ().qsort (start, end); }
template
- inline Type *lsearch (const T &x)
- {
- Type *array = arrayZ();
- for (unsigned int i = 0; i < len; i++)
- if (0 == array[i].cmp (&x))
- return &array[i];
- return nullptr;
- }
+ inline Type *lsearch (const T &x, Type *not_found = nullptr)
+ { return as_array ().lsearch (x, not_found); }
template
- inline const Type *lsearch (const T &x) const
- {
- const Type *array = arrayZ();
- for (unsigned int i = 0; i < len; i++)
- if (0 == array[i].cmp (&x))
- return &array[i];
- return nullptr;
- }
+ inline const Type *lsearch (const T &x, const Type *not_found = nullptr) const
+ { return as_array ().lsearch (x, not_found); }
template
- inline Type *bsearch (const T &x)
- {
- unsigned int i;
- return bfind (x, &i) ? &arrayZ()[i] : nullptr;
- }
+ inline Type *bsearch (const T &x, Type *not_found = nullptr)
+ { return as_sorted_array ().bsearch (x, not_found); }
template
- inline const Type *bsearch (const T &x) const
- {
- unsigned int i;
- return bfind (x, &i) ? &arrayZ()[i] : nullptr;
- }
+ inline const Type *bsearch (const T &x, const Type *not_found = nullptr) const
+ { return as_sorted_array ().bsearch (x, not_found); }
template
- inline bool bfind (const T &x, unsigned int *i) const
- {
- int min = 0, max = (int) this->len - 1;
- const Type *array = this->arrayZ();
- while (min <= max)
- {
- int mid = ((unsigned int) min + (unsigned int) max) / 2;
- int c = array[mid].cmp (&x);
- if (c < 0)
- max = mid - 1;
- else if (c > 0)
- min = mid + 1;
- else
- {
- *i = mid;
- return true;
- }
- }
- if (max < 0 || (max < (int) this->len && array[max].cmp (&x) > 0))
- max++;
- *i = max;
- return false;
- }
+ inline bool bfind (const T &x, unsigned int *i = nullptr,
+ hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+ unsigned int to_store = (unsigned int) -1) const
+ { return as_sorted_array ().bfind (x, i, not_found, to_store); }
};
diff --git a/src/hb.hh b/src/hb.hh
index 16ccf87ce..6df0a55b1 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -47,6 +47,10 @@
#define HB_H_IN
#include "hb-ot.h"
#define HB_OT_H_IN
+#include "hb-aat.h"
+#define HB_AAT_H_IN
+
+#include "hb-aat.h"
#include
#include
@@ -281,7 +285,7 @@ static int errno = 0; /* Use something better? */
# endif
#endif
-#if HAVE_ATEXIT
+#if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
/* atexit() is only safe to be called from shared libraries on certain
* platforms. Whitelist.
* https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
@@ -313,6 +317,9 @@ static int errno = 0; /* Use something better? */
#ifdef HB_NO_ATEXIT
# undef HB_USE_ATEXIT
#endif
+#ifndef HB_USE_ATEXIT
+# define HB_USE_ATEXIT 0
+#endif
#define HB_STMT_START do
#define HB_STMT_END while (0)
@@ -443,9 +450,11 @@ typedef uint64_t hb_vector_size_impl_t;
* For example, for testing "x ∈ {x1, x2, x3}" use:
* (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
*/
-#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
-#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
+#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
+#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
+#define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
+#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
/* Size signifying variable-sized array */
@@ -503,10 +512,13 @@ _hb_memalign(void **memptr, size_t alignment, size_t size)
/* Some really basic things everyone wants. */
template struct hb_remove_const { typedef T value; };
template