Merge branch 'master' into cff-subset
This commit is contained in:
commit
161ece4c30
|
@ -208,10 +208,12 @@ hb_font_funcs_set_glyph_contour_point_func
|
|||
hb_font_funcs_set_glyph_extents_func
|
||||
hb_font_funcs_set_glyph_from_name_func
|
||||
hb_font_funcs_set_glyph_h_advance_func
|
||||
hb_font_funcs_set_glyph_h_advances_func
|
||||
hb_font_funcs_set_glyph_h_kerning_func
|
||||
hb_font_funcs_set_glyph_h_origin_func
|
||||
hb_font_funcs_set_glyph_name_func
|
||||
hb_font_funcs_set_glyph_v_advance_func
|
||||
hb_font_funcs_set_glyph_v_advances_func
|
||||
hb_font_funcs_set_glyph_v_kerning_func
|
||||
hb_font_funcs_set_glyph_v_origin_func
|
||||
hb_font_funcs_set_nominal_glyph_func
|
||||
|
@ -233,6 +235,8 @@ hb_font_get_glyph_from_name
|
|||
hb_font_get_glyph_from_name_func_t
|
||||
hb_font_get_glyph_h_advance
|
||||
hb_font_get_glyph_h_advance_func_t
|
||||
hb_font_get_glyph_h_advances
|
||||
hb_font_get_glyph_h_advances_func_t
|
||||
hb_font_get_glyph_h_kerning
|
||||
hb_font_get_glyph_h_kerning_func_t
|
||||
hb_font_get_glyph_h_origin
|
||||
|
@ -245,6 +249,8 @@ hb_font_get_glyph_origin_for_direction
|
|||
hb_font_get_glyph_origin_func_t
|
||||
hb_font_get_glyph_v_advance
|
||||
hb_font_get_glyph_v_advance_func_t
|
||||
hb_font_get_glyph_v_advances
|
||||
hb_font_get_glyph_v_advances_func_t
|
||||
hb_font_get_glyph_v_kerning
|
||||
hb_font_get_glyph_v_kerning_func_t
|
||||
hb_font_get_glyph_v_origin
|
||||
|
|
|
@ -19,6 +19,7 @@ HB_BASE_sources = \
|
|||
hb-map.cc \
|
||||
hb-machinery-private.hh \
|
||||
hb-mutex-private.hh \
|
||||
hb-null.hh \
|
||||
hb-object-private.hh \
|
||||
hb-open-file-private.hh \
|
||||
hb-open-type-private.hh \
|
||||
|
@ -53,6 +54,7 @@ HB_BASE_sources = \
|
|||
hb-string-array.hh \
|
||||
hb-unicode-private.hh \
|
||||
hb-unicode.cc \
|
||||
hb-vector-private.hh \
|
||||
hb-utf-private.hh \
|
||||
hb-warning.cc \
|
||||
$(NULL)
|
||||
|
|
|
@ -52,9 +52,9 @@ _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
|
|||
return Null(AAT::morx);
|
||||
}
|
||||
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||
const AAT::morx& morx = *(layout->morx.get ());
|
||||
const AAT::morx& morx = *(layout->table.morx.get ());
|
||||
if (blob)
|
||||
*blob = layout->morx.get_blob ();
|
||||
*blob = layout->table.morx.get_blob ();
|
||||
return morx;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ struct hb_blob_t
|
|||
void *user_data;
|
||||
hb_destroy_func_t destroy;
|
||||
};
|
||||
DECLARE_NULL_INSTANCE (hb_blob_t);
|
||||
|
||||
|
||||
#endif /* HB_BLOB_PRIVATE_HH */
|
||||
|
|
|
@ -45,6 +45,20 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
|
||||
DEFINE_NULL_INSTANCE (hb_blob_t) =
|
||||
{
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
nullptr, /* data */
|
||||
0, /* length */
|
||||
HB_MEMORY_MODE_READONLY, /* mode */
|
||||
|
||||
nullptr, /* user_data */
|
||||
nullptr /* destroy */
|
||||
};
|
||||
|
||||
/**
|
||||
* hb_blob_create: (skip)
|
||||
* @data: Pointer to blob data.
|
||||
|
@ -182,20 +196,7 @@ hb_blob_copy_writable_or_fail (hb_blob_t *blob)
|
|||
hb_blob_t *
|
||||
hb_blob_get_empty (void)
|
||||
{
|
||||
static const hb_blob_t _hb_blob_nil = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
nullptr, /* data */
|
||||
0, /* length */
|
||||
HB_MEMORY_MODE_READONLY, /* mode */
|
||||
|
||||
nullptr, /* user_data */
|
||||
nullptr /* destroy */
|
||||
};
|
||||
|
||||
return const_cast<hb_blob_t *> (&_hb_blob_nil);
|
||||
return const_cast<hb_blob_t *> (&Null(hb_blob_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -83,7 +83,8 @@ HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
|
|||
* hb_buffer_t
|
||||
*/
|
||||
|
||||
struct hb_buffer_t {
|
||||
struct hb_buffer_t
|
||||
{
|
||||
hb_object_header_t header;
|
||||
ASSERT_POD ();
|
||||
|
||||
|
@ -352,6 +353,7 @@ struct hb_buffer_t {
|
|||
info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
}
|
||||
};
|
||||
DECLARE_NULL_INSTANCE (hb_buffer_t);
|
||||
|
||||
|
||||
/* Loop over clusters. Duplicated in foreach_syllable(). */
|
||||
|
|
|
@ -701,6 +701,28 @@ hb_buffer_t::guess_segment_properties (void)
|
|||
|
||||
/* Public API */
|
||||
|
||||
DEFINE_NULL_INSTANCE (hb_buffer_t) =
|
||||
{
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
const_cast<hb_unicode_funcs_t *> (&_hb_Null_hb_unicode_funcs_t),
|
||||
HB_BUFFER_FLAG_DEFAULT,
|
||||
HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
|
||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
|
||||
HB_BUFFER_MAX_LEN_DEFAULT,
|
||||
HB_BUFFER_MAX_OPS_DEFAULT,
|
||||
|
||||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||
false, /* successful */
|
||||
true, /* have_output */
|
||||
true /* have_positions */
|
||||
|
||||
/* Zero is good enough for everything else. */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* hb_buffer_create: (Xconstructor)
|
||||
*
|
||||
|
@ -743,27 +765,7 @@ hb_buffer_create (void)
|
|||
hb_buffer_t *
|
||||
hb_buffer_get_empty (void)
|
||||
{
|
||||
static const hb_buffer_t _hb_buffer_nil = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
|
||||
HB_BUFFER_FLAG_DEFAULT,
|
||||
HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
|
||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
|
||||
HB_BUFFER_MAX_LEN_DEFAULT,
|
||||
HB_BUFFER_MAX_OPS_DEFAULT,
|
||||
|
||||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||
false, /* successful */
|
||||
true, /* have_output */
|
||||
true /* have_positions */
|
||||
|
||||
/* Zero is good enough for everything else. */
|
||||
};
|
||||
|
||||
return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
|
||||
return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
340
src/hb-dsalgs.hh
340
src/hb-dsalgs.hh
|
@ -232,6 +232,18 @@ hb_ctz (T v)
|
|||
* Tiny stuff.
|
||||
*/
|
||||
|
||||
/* ASCII tag/character handling */
|
||||
static inline bool ISALPHA (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
|
||||
static inline bool ISALNUM (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
|
||||
static inline bool ISSPACE (unsigned char c)
|
||||
{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
|
||||
static inline unsigned char TOUPPER (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
|
||||
static inline unsigned char TOLOWER (unsigned char c)
|
||||
{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
|
||||
|
||||
#undef MIN
|
||||
template <typename Type>
|
||||
static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
|
||||
|
@ -262,6 +274,37 @@ hb_ceil_to_4 (unsigned int v)
|
|||
return ((v - 1) | 3) + 1;
|
||||
}
|
||||
|
||||
template <typename T> class hb_assert_unsigned_t;
|
||||
template <> class hb_assert_unsigned_t<unsigned char> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned short> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned int> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned long> {};
|
||||
|
||||
template <typename T> static inline bool
|
||||
hb_in_range (T u, T lo, T hi)
|
||||
{
|
||||
/* The sizeof() is here to force template instantiation.
|
||||
* I'm sure there are better ways to do this but can't think of
|
||||
* one right now. Declaring a variable won't work as HB_UNUSED
|
||||
* is unusable on some platforms and unused types are less likely
|
||||
* to generate a warning than unused variables. */
|
||||
static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
|
||||
|
||||
/* The casts below are important as if T is smaller than int,
|
||||
* the subtract results will become a signed int! */
|
||||
return (T)(u - lo) <= (T)(hi - lo);
|
||||
}
|
||||
template <typename T> static inline bool
|
||||
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
|
||||
{
|
||||
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
|
||||
}
|
||||
template <typename T> static inline bool
|
||||
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
|
||||
{
|
||||
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sort and search.
|
||||
|
@ -445,303 +488,6 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
|
|||
}
|
||||
|
||||
|
||||
#define HB_VECTOR_INIT {0, 0, false, nullptr}
|
||||
template <typename Type, unsigned int StaticSize=8>
|
||||
struct hb_vector_t
|
||||
{
|
||||
unsigned int len;
|
||||
unsigned int allocated; /* == 0 means allocation failed. */
|
||||
Type *arrayZ;
|
||||
Type static_array[StaticSize];
|
||||
|
||||
void init (void)
|
||||
{
|
||||
len = 0;
|
||||
allocated = ARRAY_LENGTH (static_array);
|
||||
arrayZ = static_array;
|
||||
}
|
||||
|
||||
inline Type& operator [] (unsigned int i)
|
||||
{
|
||||
if (unlikely (i >= len))
|
||||
return Crap (Type);
|
||||
return arrayZ[i];
|
||||
}
|
||||
inline const Type& operator [] (unsigned int i) const
|
||||
{
|
||||
if (unlikely (i >= len))
|
||||
return Null(Type);
|
||||
return arrayZ[i];
|
||||
}
|
||||
|
||||
inline Type *push (void)
|
||||
{
|
||||
if (unlikely (!resize (len + 1)))
|
||||
return &Crap(Type);
|
||||
return &arrayZ[len - 1];
|
||||
}
|
||||
inline Type *push (const Type& v)
|
||||
{
|
||||
Type *p = push ();
|
||||
*p = v;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Allocate for size but don't adjust len. */
|
||||
inline bool alloc (unsigned int size)
|
||||
{
|
||||
if (unlikely (!allocated))
|
||||
return false;
|
||||
|
||||
if (likely (size <= allocated))
|
||||
return true;
|
||||
|
||||
/* Reallocate */
|
||||
|
||||
unsigned int new_allocated = allocated;
|
||||
while (size >= new_allocated)
|
||||
new_allocated += (new_allocated >> 1) + 8;
|
||||
|
||||
Type *new_array = nullptr;
|
||||
|
||||
if (arrayZ == static_array)
|
||||
{
|
||||
new_array = (Type *) calloc (new_allocated, sizeof (Type));
|
||||
if (new_array)
|
||||
memcpy (new_array, arrayZ, len * sizeof (Type));
|
||||
}
|
||||
else
|
||||
{
|
||||
bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
|
||||
if (likely (!overflows))
|
||||
new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
|
||||
}
|
||||
|
||||
if (unlikely (!new_array))
|
||||
{
|
||||
allocated = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
arrayZ = new_array;
|
||||
allocated = new_allocated;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool resize (int size_)
|
||||
{
|
||||
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
|
||||
if (!alloc (size))
|
||||
return false;
|
||||
|
||||
if (size > len)
|
||||
memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
|
||||
|
||||
len = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void pop (void)
|
||||
{
|
||||
if (!len) return;
|
||||
len--;
|
||||
}
|
||||
|
||||
inline void remove (unsigned int i)
|
||||
{
|
||||
if (unlikely (i >= len))
|
||||
return;
|
||||
memmove (static_cast<void *> (&arrayZ[i]),
|
||||
static_cast<void *> (&arrayZ[i + 1]),
|
||||
(len - i - 1) * sizeof (Type));
|
||||
len--;
|
||||
}
|
||||
|
||||
inline void shrink (int size_)
|
||||
{
|
||||
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
|
||||
if (size < len)
|
||||
len = size;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Type *find (T v) {
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (arrayZ[i] == v)
|
||||
return &arrayZ[i];
|
||||
return nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
inline const Type *find (T v) const {
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (arrayZ[i] == v)
|
||||
return &arrayZ[i];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Type *lsearch (const T &x)
|
||||
{
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (0 == this->arrayZ[i].cmp (&x))
|
||||
return &arrayZ[i];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Type *bsearch (const T &x)
|
||||
{
|
||||
unsigned int i;
|
||||
return bfind (x, &i) ? &arrayZ[i] : nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
inline const Type *bsearch (const T &x) const
|
||||
{
|
||||
unsigned int i;
|
||||
return bfind (x, &i) ? &arrayZ[i] : nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
inline bool bfind (const T &x, unsigned int *i) const
|
||||
{
|
||||
int min = 0, max = (int) this->len - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int c = this->arrayZ[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 && this->arrayZ[max].cmp (&x) > 0))
|
||||
max++;
|
||||
*i = max;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
if (arrayZ != static_array)
|
||||
free (arrayZ);
|
||||
arrayZ = nullptr;
|
||||
allocated = len = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT}
|
||||
template <typename item_t, typename lock_t>
|
||||
struct hb_lockable_set_t
|
||||
{
|
||||
hb_vector_t <item_t, 1> items;
|
||||
|
||||
inline void init (void) { items.init (); }
|
||||
|
||||
template <typename T>
|
||||
inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
|
||||
{
|
||||
l.lock ();
|
||||
item_t *item = items.find (v);
|
||||
if (item) {
|
||||
if (replace) {
|
||||
item_t old = *item;
|
||||
*item = v;
|
||||
l.unlock ();
|
||||
old.fini ();
|
||||
}
|
||||
else {
|
||||
item = nullptr;
|
||||
l.unlock ();
|
||||
}
|
||||
} else {
|
||||
item = items.push (v);
|
||||
l.unlock ();
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void remove (T v, lock_t &l)
|
||||
{
|
||||
l.lock ();
|
||||
item_t *item = items.find (v);
|
||||
if (item) {
|
||||
item_t old = *item;
|
||||
*item = items[items.len - 1];
|
||||
items.pop ();
|
||||
l.unlock ();
|
||||
old.fini ();
|
||||
} else {
|
||||
l.unlock ();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool find (T v, item_t *i, lock_t &l)
|
||||
{
|
||||
l.lock ();
|
||||
item_t *item = items.find (v);
|
||||
if (item)
|
||||
*i = *item;
|
||||
l.unlock ();
|
||||
return !!item;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline item_t *find_or_insert (T v, lock_t &l)
|
||||
{
|
||||
l.lock ();
|
||||
item_t *item = items.find (v);
|
||||
if (!item) {
|
||||
item = items.push (v);
|
||||
}
|
||||
l.unlock ();
|
||||
return item;
|
||||
}
|
||||
|
||||
inline void fini (lock_t &l)
|
||||
{
|
||||
if (!items.len) {
|
||||
/* No need for locking. */
|
||||
items.fini ();
|
||||
return;
|
||||
}
|
||||
l.lock ();
|
||||
while (items.len) {
|
||||
item_t old = items[items.len - 1];
|
||||
items.pop ();
|
||||
l.unlock ();
|
||||
old.fini ();
|
||||
l.lock ();
|
||||
}
|
||||
items.fini ();
|
||||
l.unlock ();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename Type>
|
||||
struct hb_auto_t : Type
|
||||
{
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
* hb_face_t
|
||||
*/
|
||||
|
||||
struct hb_face_t {
|
||||
struct hb_face_t
|
||||
{
|
||||
hb_object_header_t header;
|
||||
ASSERT_POD ();
|
||||
|
||||
|
@ -55,16 +56,13 @@ struct hb_face_t {
|
|||
|
||||
struct hb_shaper_data_t shaper_data; /* Various shaper data. */
|
||||
|
||||
/* Various non-shaping data. */
|
||||
/* ... */
|
||||
|
||||
/* Cache */
|
||||
struct plan_node_t {
|
||||
struct plan_node_t
|
||||
{
|
||||
hb_shape_plan_t *shape_plan;
|
||||
plan_node_t *next;
|
||||
} *shape_plans;
|
||||
|
||||
|
||||
inline hb_blob_t *reference_table (hb_tag_t tag) const
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
|
@ -97,8 +95,7 @@ struct hb_face_t {
|
|||
HB_INTERNAL void load_upem (void) const;
|
||||
HB_INTERNAL void load_num_glyphs (void) const;
|
||||
};
|
||||
|
||||
extern HB_INTERNAL const hb_face_t _hb_face_nil;
|
||||
DECLARE_NULL_INSTANCE (hb_face_t);
|
||||
|
||||
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
|
||||
|
|
|
@ -63,7 +63,8 @@ hb_face_count (hb_blob_t *blob)
|
|||
* hb_face_t
|
||||
*/
|
||||
|
||||
const hb_face_t _hb_face_nil = {
|
||||
DEFINE_NULL_INSTANCE (hb_face_t) =
|
||||
{
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
@ -215,7 +216,7 @@ hb_face_create (hb_blob_t *blob,
|
|||
hb_face_t *
|
||||
hb_face_get_empty (void)
|
||||
{
|
||||
return const_cast<hb_face_t *> (&_hb_face_nil);
|
||||
return const_cast<hb_face_t *> (&Null(hb_face_t));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "hb-shaper-private.hh"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* hb_font_funcs_t
|
||||
*/
|
||||
|
@ -47,6 +46,8 @@
|
|||
HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
|
||||
HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
|
||||
|
@ -57,7 +58,8 @@
|
|||
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
|
||||
/* ^--- Add new callbacks here */
|
||||
|
||||
struct hb_font_funcs_t {
|
||||
struct hb_font_funcs_t
|
||||
{
|
||||
hb_object_header_t header;
|
||||
ASSERT_POD ();
|
||||
|
||||
|
@ -89,14 +91,15 @@ struct hb_font_funcs_t {
|
|||
]) (void);
|
||||
} get;
|
||||
};
|
||||
|
||||
DECLARE_NULL_INSTANCE (hb_font_funcs_t);
|
||||
|
||||
|
||||
/*
|
||||
* hb_font_t
|
||||
*/
|
||||
|
||||
struct hb_font_t {
|
||||
struct hb_font_t
|
||||
{
|
||||
hb_object_header_t header;
|
||||
ASSERT_POD ();
|
||||
|
||||
|
@ -233,6 +236,32 @@ struct hb_font_t {
|
|||
klass->user_data.glyph_v_advance);
|
||||
}
|
||||
|
||||
inline void get_glyph_h_advances (unsigned int count,
|
||||
hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned int advance_stride)
|
||||
{
|
||||
return klass->get.f.glyph_h_advances (this, user_data,
|
||||
count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride,
|
||||
klass->user_data.glyph_h_advances);
|
||||
}
|
||||
|
||||
inline void get_glyph_v_advances (unsigned int count,
|
||||
hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned int advance_stride)
|
||||
{
|
||||
return klass->get.f.glyph_v_advances (this, user_data,
|
||||
count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride,
|
||||
klass->user_data.glyph_v_advances);
|
||||
}
|
||||
|
||||
inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
|
@ -553,6 +582,7 @@ struct hb_font_t {
|
|||
return (float) v * scale / face->get_upem ();
|
||||
}
|
||||
};
|
||||
DECLARE_NULL_INSTANCE (hb_font_t);
|
||||
|
||||
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
|
||||
|
|
328
src/hb-font.cc
328
src/hb-font.cc
|
@ -29,6 +29,7 @@
|
|||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
#include "hb-machinery-private.hh"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -45,10 +46,10 @@ hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_font_h_extents_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_font_h_extents_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_font_h_extents (metrics);
|
||||
if (ret) {
|
||||
|
@ -69,10 +70,10 @@ hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_font_v_extents_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_font_v_extents_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_font_v_extents (metrics);
|
||||
if (ret) {
|
||||
|
@ -94,11 +95,11 @@ hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_nominal_glyph_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_nominal_glyph_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent->get_nominal_glyph (unicode, glyph);
|
||||
}
|
||||
|
@ -115,12 +116,12 @@ hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_variation_glyph_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_variation_glyph_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
|
||||
}
|
||||
|
@ -129,16 +130,16 @@ hb_font_get_variation_glyph_parent (hb_font_t *font,
|
|||
static hb_position_t
|
||||
hb_font_get_glyph_h_advance_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_codepoint_t glyph HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->x_scale;
|
||||
}
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_h_advance_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_h_advance_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
|
||||
}
|
||||
|
@ -146,21 +147,117 @@ hb_font_get_glyph_h_advance_parent (hb_font_t *font,
|
|||
static hb_position_t
|
||||
hb_font_get_glyph_v_advance_nil (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_codepoint_t glyph HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO use font_extents.ascender+descender */
|
||||
return font->y_scale;
|
||||
}
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_v_advance_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_v_advance_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
|
||||
}
|
||||
|
||||
static void
|
||||
hb_font_get_glyph_h_advances_nil (hb_font_t* font,
|
||||
void* font_data HB_UNUSED,
|
||||
unsigned int count,
|
||||
hb_codepoint_t *first_glyph HB_UNUSED,
|
||||
unsigned int glyph_stride HB_UNUSED,
|
||||
hb_position_t *first_advance,
|
||||
unsigned int advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->get_glyph_h_advance (*first_glyph);
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
static void
|
||||
hb_font_get_glyph_h_advances_default (hb_font_t* font,
|
||||
void* font_data HB_UNUSED,
|
||||
unsigned int count,
|
||||
hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned int advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->has_glyph_h_advance_func ())
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->get_glyph_h_advance (*first_glyph);
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
font->parent->get_glyph_h_advances (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->parent_scale_x_distance (*first_advance);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hb_font_get_glyph_v_advances_nil (hb_font_t* font,
|
||||
void* font_data HB_UNUSED,
|
||||
unsigned int count,
|
||||
hb_codepoint_t *first_glyph HB_UNUSED,
|
||||
unsigned int glyph_stride HB_UNUSED,
|
||||
hb_position_t *first_advance,
|
||||
unsigned int advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->get_glyph_v_advance (*first_glyph);
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
static void
|
||||
hb_font_get_glyph_v_advances_default (hb_font_t* font,
|
||||
void* font_data HB_UNUSED,
|
||||
unsigned int count,
|
||||
hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned int advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->has_glyph_v_advance_func ())
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->get_glyph_v_advance (*first_glyph);
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
font->parent->get_glyph_v_advances (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->parent_scale_y_distance (*first_advance);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
|
@ -173,12 +270,12 @@ hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
|
|||
return true;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_h_origin_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_h_origin_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
|
||||
if (ret)
|
||||
|
@ -198,12 +295,12 @@ hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_v_origin_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_v_origin_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
|
||||
if (ret)
|
||||
|
@ -221,11 +318,11 @@ hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
|
|||
return 0;
|
||||
}
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t left_glyph,
|
||||
hb_codepoint_t right_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_h_kerning_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t left_glyph,
|
||||
hb_codepoint_t right_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
|
||||
}
|
||||
|
@ -240,11 +337,11 @@ hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
|
|||
return 0;
|
||||
}
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t top_glyph,
|
||||
hb_codepoint_t bottom_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_v_kerning_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t top_glyph,
|
||||
hb_codepoint_t bottom_glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
|
||||
}
|
||||
|
@ -260,11 +357,11 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_extents_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_extents_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
|
||||
if (ret) {
|
||||
|
@ -287,13 +384,13 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_contour_point_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned int point_index,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_contour_point_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned int point_index,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
|
||||
if (ret)
|
||||
|
@ -312,11 +409,11 @@ hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_name_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
char *name, unsigned int size,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_name_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
char *name, unsigned int size,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent->get_glyph_name (glyph, name, size);
|
||||
}
|
||||
|
@ -332,16 +429,17 @@ hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
|
|||
return false;
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_from_name_parent (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
const char *name, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_font_get_glyph_from_name_default (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
const char *name, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return font->parent->get_glyph_from_name (name, len, glyph);
|
||||
}
|
||||
|
||||
static const hb_font_funcs_t _hb_font_funcs_nil = {
|
||||
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
|
||||
{
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
@ -364,7 +462,8 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
|
|||
}
|
||||
}
|
||||
};
|
||||
static const hb_font_funcs_t _hb_font_funcs_parent = {
|
||||
|
||||
static const hb_font_funcs_t _hb_font_funcs_default = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
@ -381,7 +480,7 @@ static const hb_font_funcs_t _hb_font_funcs_parent = {
|
|||
},
|
||||
{
|
||||
{
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
|
||||
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
}
|
||||
|
@ -406,7 +505,7 @@ hb_font_funcs_create (void)
|
|||
if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
|
||||
return hb_font_funcs_get_empty ();
|
||||
|
||||
ffuncs->get = _hb_font_funcs_parent.get;
|
||||
ffuncs->get = _hb_font_funcs_default.get;
|
||||
|
||||
return ffuncs;
|
||||
}
|
||||
|
@ -423,7 +522,7 @@ hb_font_funcs_create (void)
|
|||
hb_font_funcs_t *
|
||||
hb_font_funcs_get_empty (void)
|
||||
{
|
||||
return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
|
||||
return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_default);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -562,9 +661,9 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
|
|||
ffuncs->user_data.name = user_data; \
|
||||
ffuncs->destroy.name = destroy; \
|
||||
} else { \
|
||||
ffuncs->get.f.name = hb_font_get_##name##_parent; \
|
||||
ffuncs->user_data.name = nullptr; \
|
||||
ffuncs->destroy.name = nullptr; \
|
||||
ffuncs->get.f.name = hb_font_get_##name##_default; \
|
||||
ffuncs->user_data.name = nullptr; \
|
||||
ffuncs->destroy.name = nullptr; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -574,9 +673,8 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
|||
bool
|
||||
hb_font_t::has_func (unsigned int i)
|
||||
{
|
||||
if (parent && parent != hb_font_get_empty () && parent->has_func (i))
|
||||
return true;
|
||||
return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
|
||||
return (this->klass->get.array[i] != _hb_font_funcs_default.get.array[i]) ||
|
||||
(parent && parent != &_hb_Null_hb_font_t && parent->has_func (i));
|
||||
}
|
||||
|
||||
/* Public getters */
|
||||
|
@ -1100,6 +1198,37 @@ hb_font_glyph_from_string (hb_font_t *font,
|
|||
* hb_font_t
|
||||
*/
|
||||
|
||||
DEFINE_NULL_INSTANCE (hb_font_t) =
|
||||
{
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
nullptr, /* parent */
|
||||
const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
|
||||
|
||||
1000, /* x_scale */
|
||||
1000, /* y_scale */
|
||||
|
||||
0, /* x_ppem */
|
||||
0, /* y_ppem */
|
||||
0, /* ptem */
|
||||
|
||||
0, /* num_coords */
|
||||
nullptr, /* coords */
|
||||
|
||||
const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t), /* klass */
|
||||
nullptr, /* user_data */
|
||||
nullptr, /* destroy */
|
||||
|
||||
{
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
|
||||
#include "hb-shaper-list.hh"
|
||||
#undef HB_SHAPER_IMPLEMENT
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* hb_font_create: (Xconstructor)
|
||||
* @face: a face.
|
||||
|
@ -1187,36 +1316,7 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||
hb_font_t *
|
||||
hb_font_get_empty (void)
|
||||
{
|
||||
static const hb_font_t _hb_font_nil = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
nullptr, /* parent */
|
||||
const_cast<hb_face_t *> (&_hb_face_nil),
|
||||
|
||||
1000, /* x_scale */
|
||||
1000, /* y_scale */
|
||||
|
||||
0, /* x_ppem */
|
||||
0, /* y_ppem */
|
||||
0, /* ptem */
|
||||
|
||||
0, /* num_coords */
|
||||
nullptr, /* coords */
|
||||
|
||||
const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
|
||||
nullptr, /* user_data */
|
||||
nullptr, /* destroy */
|
||||
|
||||
{
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
|
||||
#include "hb-shaper-list.hh"
|
||||
#undef HB_SHAPER_IMPLEMENT
|
||||
}
|
||||
};
|
||||
|
||||
return const_cast<hb_font_t *> (&_hb_font_nil);
|
||||
return const_cast<hb_font_t *> (&Null(hb_font_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -132,6 +132,16 @@ typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void
|
|||
typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
|
||||
typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
|
||||
|
||||
typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data,
|
||||
unsigned count,
|
||||
hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned advance_stride,
|
||||
void *user_data);
|
||||
typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t;
|
||||
typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
|
||||
|
||||
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y,
|
||||
|
@ -264,6 +274,38 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
|
|||
hb_font_get_glyph_v_advance_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_h_advances_func:
|
||||
* @ffuncs: font functions.
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified):
|
||||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_get_glyph_h_advances_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_v_advances_func:
|
||||
* @ffuncs: font functions.
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified):
|
||||
* @user_data:
|
||||
* @destroy:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_get_glyph_v_advances_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_h_origin_func:
|
||||
* @ffuncs: font functions.
|
||||
|
|
|
@ -594,7 +594,7 @@ template <unsigned int WheresFace,
|
|||
typename Subclass,
|
||||
typename Returned,
|
||||
typename Stored = Returned>
|
||||
struct hb_base_lazy_loader_t
|
||||
struct hb_lazy_loader_t
|
||||
{
|
||||
static_assert (WheresFace > 0, "");
|
||||
|
||||
|
@ -602,6 +602,7 @@ struct hb_base_lazy_loader_t
|
|||
inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); }
|
||||
inline Subclass* thiz (void) { return static_cast<Subclass *> (this); }
|
||||
|
||||
inline void init0 (void) {} /* Init, when memory is already set to 0. No-op for us. */
|
||||
inline void init (void)
|
||||
{
|
||||
instance = nullptr;
|
||||
|
@ -612,10 +613,8 @@ struct hb_base_lazy_loader_t
|
|||
thiz ()->destroy (instance);
|
||||
}
|
||||
|
||||
inline const Returned * operator-> (void) const
|
||||
{
|
||||
return thiz ()->get ();
|
||||
}
|
||||
inline const Returned * operator -> (void) const { return thiz ()->get (); }
|
||||
inline const Returned & operator * (void) const { return *thiz ()->get (); }
|
||||
|
||||
inline Stored * get_stored (void) const
|
||||
{
|
||||
|
@ -624,7 +623,11 @@ struct hb_base_lazy_loader_t
|
|||
if (unlikely (!p))
|
||||
{
|
||||
hb_face_t *face = *(((hb_face_t **) this) - WheresFace);
|
||||
p = thiz ()->create (face);
|
||||
if (likely (!p))
|
||||
p = thiz ()->create (face);
|
||||
if (unlikely (!p))
|
||||
p = thiz ()->create (nullptr); /* Produce nil object. */
|
||||
assert (p);
|
||||
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<Stored **>(&this->instance), nullptr, p)))
|
||||
{
|
||||
thiz ()->destroy (p);
|
||||
|
@ -634,6 +637,12 @@ struct hb_base_lazy_loader_t
|
|||
return p;
|
||||
}
|
||||
|
||||
inline void set_stored (Stored *instance_)
|
||||
{
|
||||
assert (instance == nullptr);
|
||||
instance = instance_;
|
||||
}
|
||||
|
||||
inline const Returned * get (void) const
|
||||
{
|
||||
return thiz ()->convert (get_stored ());
|
||||
|
@ -652,7 +661,7 @@ struct hb_base_lazy_loader_t
|
|||
/* Specializations. */
|
||||
|
||||
template <unsigned int WheresFace, typename T>
|
||||
struct hb_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_lazy_loader_t<WheresFace, T>, T>
|
||||
struct hb_object_lazy_loader_t : hb_lazy_loader_t<WheresFace, hb_object_lazy_loader_t<WheresFace, T>, T>
|
||||
{
|
||||
static inline T *create (hb_face_t *face)
|
||||
{
|
||||
|
@ -676,7 +685,7 @@ struct hb_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_lazy_loader_t<Whe
|
|||
};
|
||||
|
||||
template <unsigned int WheresFace, typename T>
|
||||
struct hb_table_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_table_lazy_loader_t<WheresFace, T>, T, hb_blob_t>
|
||||
struct hb_table_lazy_loader_t : hb_lazy_loader_t<WheresFace, hb_table_lazy_loader_t<WheresFace, T>, T, hb_blob_t>
|
||||
{
|
||||
static inline hb_blob_t *create (hb_face_t *face)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright © 2018 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_NULL_HH
|
||||
#define HB_NULL_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
|
||||
/*
|
||||
* Static pools
|
||||
*/
|
||||
|
||||
/* Global nul-content Null pool. Enlarge as necessary. */
|
||||
|
||||
#define HB_NULL_POOL_SIZE 800
|
||||
|
||||
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 <typename Type>
|
||||
static inline Type const & Null (void) {
|
||||
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
return *reinterpret_cast<Type const *> (_hb_NullPool);
|
||||
}
|
||||
#define Null(Type) Null<Type>()
|
||||
|
||||
/* Specializaitons 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]; \
|
||||
template <> \
|
||||
/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
|
||||
return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
|
||||
} \
|
||||
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]
|
||||
|
||||
/* Specializaitons for arbitrary-content Null objects expressed as struct initializer. */
|
||||
#define DECLARE_NULL_INSTANCE(Type) \
|
||||
extern HB_INTERNAL const Type _hb_Null_##Type; \
|
||||
template <> \
|
||||
/*static*/ inline const Type& Null<Type> (void) { \
|
||||
return _hb_Null_##Type; \
|
||||
} \
|
||||
static_assert (true, "Just so we take semicolon after.")
|
||||
#define DEFINE_NULL_INSTANCE(Type) \
|
||||
const Type _hb_Null_##Type
|
||||
|
||||
/* Global writable pool. Enlarge as necessary. */
|
||||
|
||||
/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
|
||||
* for correct operation. It only exist to catch and divert program logic bugs instead of
|
||||
* causing bad memory access. So, races there are not actually introducing incorrectness
|
||||
* in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
|
||||
extern HB_INTERNAL
|
||||
/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
|
||||
|
||||
/* CRAP pool: Common Region for Access Protection. */
|
||||
template <typename Type>
|
||||
static inline Type& Crap (void) {
|
||||
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
|
||||
*obj = Null(Type);
|
||||
return *obj;
|
||||
}
|
||||
#define Crap(Type) Crap<Type>()
|
||||
|
||||
template <typename Type>
|
||||
struct CrapOrNull {
|
||||
static inline Type & get (void) { return Crap(Type); }
|
||||
};
|
||||
template <typename Type>
|
||||
struct CrapOrNull<const Type> {
|
||||
static inline Type const & get (void) { return Null(Type); }
|
||||
};
|
||||
#define CrapOrNull(Type) CrapOrNull<Type>::get ()
|
||||
|
||||
|
||||
#endif /* HB_NULL_HH */
|
|
@ -35,9 +35,107 @@
|
|||
#include "hb-private.hh"
|
||||
#include "hb-atomic-private.hh"
|
||||
#include "hb-mutex-private.hh"
|
||||
#include "hb-vector-private.hh"
|
||||
|
||||
|
||||
/* reference_count */
|
||||
/*
|
||||
* Lockable set
|
||||
*/
|
||||
|
||||
template <typename item_t, typename lock_t>
|
||||
struct hb_lockable_set_t
|
||||
{
|
||||
hb_vector_t <item_t, 1> items;
|
||||
|
||||
inline void init (void) { items.init (); }
|
||||
|
||||
template <typename T>
|
||||
inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
|
||||
{
|
||||
l.lock ();
|
||||
item_t *item = items.find (v);
|
||||
if (item) {
|
||||
if (replace) {
|
||||
item_t old = *item;
|
||||
*item = v;
|
||||
l.unlock ();
|
||||
old.fini ();
|
||||
}
|
||||
else {
|
||||
item = nullptr;
|
||||
l.unlock ();
|
||||
}
|
||||
} else {
|
||||
item = items.push (v);
|
||||
l.unlock ();
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void remove (T v, lock_t &l)
|
||||
{
|
||||
l.lock ();
|
||||
item_t *item = items.find (v);
|
||||
if (item) {
|
||||
item_t old = *item;
|
||||
*item = items[items.len - 1];
|
||||
items.pop ();
|
||||
l.unlock ();
|
||||
old.fini ();
|
||||
} else {
|
||||
l.unlock ();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool find (T v, item_t *i, lock_t &l)
|
||||
{
|
||||
l.lock ();
|
||||
item_t *item = items.find (v);
|
||||
if (item)
|
||||
*i = *item;
|
||||
l.unlock ();
|
||||
return !!item;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline item_t *find_or_insert (T v, lock_t &l)
|
||||
{
|
||||
l.lock ();
|
||||
item_t *item = items.find (v);
|
||||
if (!item) {
|
||||
item = items.push (v);
|
||||
}
|
||||
l.unlock ();
|
||||
return item;
|
||||
}
|
||||
|
||||
inline void fini (lock_t &l)
|
||||
{
|
||||
if (!items.len) {
|
||||
/* No need for locking. */
|
||||
items.fini ();
|
||||
return;
|
||||
}
|
||||
l.lock ();
|
||||
while (items.len) {
|
||||
item_t old = items[items.len - 1];
|
||||
items.pop ();
|
||||
l.unlock ();
|
||||
old.fini ();
|
||||
l.lock ();
|
||||
}
|
||||
items.fini ();
|
||||
l.unlock ();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Reference-count.
|
||||
*/
|
||||
|
||||
#define HB_REFERENCE_COUNT_INERT_VALUE 0
|
||||
#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
|
||||
|
@ -89,7 +187,9 @@ struct hb_user_data_array_t
|
|||
};
|
||||
|
||||
|
||||
/* object_header */
|
||||
/*
|
||||
* Object header
|
||||
*/
|
||||
|
||||
struct hb_object_header_t
|
||||
{
|
||||
|
@ -103,7 +203,9 @@ struct hb_object_header_t
|
|||
};
|
||||
|
||||
|
||||
/* object */
|
||||
/*
|
||||
* Object
|
||||
*/
|
||||
|
||||
template <typename Type>
|
||||
static inline void hb_object_trace (const Type *obj, const char *function)
|
||||
|
|
|
@ -140,7 +140,6 @@ struct Tag : HBUINT32
|
|||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
DEFINE_NULL_DATA (OT, Tag, " ");
|
||||
|
||||
/* Glyph index number, same as uint16 (length = 16 bits) */
|
||||
typedef HBUINT16 GlyphID;
|
||||
|
@ -152,7 +151,7 @@ typedef HBUINT16 NameID;
|
|||
struct Index : HBUINT16 {
|
||||
static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
|
||||
};
|
||||
DEFINE_NULL_DATA (OT, Index, "\xff\xff");
|
||||
DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
|
||||
|
||||
/* Offset, Null offset = 0 */
|
||||
template <typename Type>
|
||||
|
|
|
@ -42,16 +42,39 @@
|
|||
|
||||
struct hb_ot_font_t
|
||||
{
|
||||
inline void init (hb_face_t *face)
|
||||
{
|
||||
cmap.init (face);
|
||||
h_metrics.init (face);
|
||||
v_metrics.init (face, h_metrics.ascender - h_metrics.descender); /* TODO Can we do this lazily? */
|
||||
|
||||
this->face = face;
|
||||
glyf.init ();
|
||||
cbdt.init ();
|
||||
post.init ();
|
||||
kern.init ();
|
||||
}
|
||||
inline void fini (void)
|
||||
{
|
||||
cmap.fini ();
|
||||
h_metrics.fini ();
|
||||
v_metrics.fini ();
|
||||
|
||||
glyf.fini ();
|
||||
cbdt.fini ();
|
||||
post.fini ();
|
||||
kern.fini ();
|
||||
}
|
||||
|
||||
OT::cmap::accelerator_t cmap;
|
||||
OT::hmtx::accelerator_t h_metrics;
|
||||
OT::vmtx::accelerator_t v_metrics;
|
||||
|
||||
hb_face_t *face; /* MUST be before the lazy loaders. */
|
||||
hb_lazy_loader_t<1, OT::glyf::accelerator_t> glyf;
|
||||
hb_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt;
|
||||
hb_lazy_loader_t<3, OT::post::accelerator_t> post;
|
||||
hb_lazy_loader_t<4, OT::kern::accelerator_t> kern;
|
||||
hb_lazy_loader_t<5, OT::kern::accelerator_t> cff2;
|
||||
hb_face_t *face; /* MUST be JUST before the lazy loaders. */
|
||||
hb_object_lazy_loader_t<1, OT::glyf::accelerator_t> glyf;
|
||||
hb_object_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt;
|
||||
hb_object_lazy_loader_t<3, OT::post::accelerator_t> post;
|
||||
hb_object_lazy_loader_t<4, OT::kern::accelerator_t> kern;
|
||||
};
|
||||
|
||||
|
||||
|
@ -63,14 +86,7 @@ _hb_ot_font_create (hb_face_t *face)
|
|||
if (unlikely (!ot_font))
|
||||
return nullptr;
|
||||
|
||||
ot_font->cmap.init (face);
|
||||
ot_font->h_metrics.init (face);
|
||||
ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
|
||||
ot_font->face = face;
|
||||
ot_font->glyf.init ();
|
||||
ot_font->cbdt.init ();
|
||||
ot_font->post.init ();
|
||||
ot_font->kern.init ();
|
||||
ot_font->init (face);
|
||||
|
||||
return ot_font;
|
||||
}
|
||||
|
@ -80,13 +96,7 @@ _hb_ot_font_destroy (void *data)
|
|||
{
|
||||
hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
|
||||
|
||||
ot_font->cmap.fini ();
|
||||
ot_font->h_metrics.fini ();
|
||||
ot_font->v_metrics.fini ();
|
||||
ot_font->glyf.fini ();
|
||||
ot_font->cbdt.fini ();
|
||||
ot_font->post.fini ();
|
||||
ot_font->kern.fini ();
|
||||
ot_font->fini ();
|
||||
|
||||
free (ot_font);
|
||||
}
|
||||
|
|
|
@ -238,9 +238,9 @@ struct glyf
|
|||
|
||||
hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (face);
|
||||
const head *head_table = head_blob->as<head> ();
|
||||
if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
|
||||
if (head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
|
||||
{
|
||||
/* head table is not present, or in an unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
||||
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
||||
hb_blob_destroy (head_blob);
|
||||
return;
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ struct glyf
|
|||
inline bool get_composite (hb_codepoint_t glyph,
|
||||
CompositeGlyphHeader::Iterator *composite /* OUT */) const
|
||||
{
|
||||
if (this->glyf_table == &Null(glyf) || !num_glyphs)
|
||||
if (unlikely (!num_glyphs))
|
||||
return false;
|
||||
|
||||
unsigned int start_offset, end_offset;
|
||||
|
|
|
@ -141,8 +141,8 @@ struct head
|
|||
* -1: Only strongly right to left;
|
||||
* -2: Like -1 but also contains neutrals. */
|
||||
public:
|
||||
HBINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */
|
||||
HBINT16 glyphDataFormat; /* 0 for current format. */
|
||||
HBUINT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */
|
||||
HBUINT16 glyphDataFormat; /* 0 for current format. */
|
||||
|
||||
DEFINE_SIZE_STATIC (54);
|
||||
};
|
||||
|
|
|
@ -33,13 +33,16 @@
|
|||
|
||||
namespace OT {
|
||||
|
||||
#define NOT_INDEXED ((unsigned int) -1)
|
||||
|
||||
/*
|
||||
* BASE -- Baseline
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/base
|
||||
*/
|
||||
|
||||
|
||||
/* XXX Review this. */
|
||||
#define NOT_INDEXED ((unsigned int) -1)
|
||||
|
||||
|
||||
struct BaseCoordFormat1
|
||||
{
|
||||
inline int get_coord (void) const { return coordinate; }
|
||||
|
@ -52,7 +55,7 @@ struct BaseCoordFormat1
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
HBINT16 coordinate; /* X or Y value, in design units */
|
||||
FWORD coordinate; /* X or Y value, in design units */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
@ -73,7 +76,7 @@ struct BaseCoordFormat2
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
HBINT16 coordinate; /* X or Y value, in design units */
|
||||
FWORD coordinate; /* X or Y value, in design units */
|
||||
GlyphID referenceGlyph; /* Glyph ID of control glyph */
|
||||
HBUINT16 coordPoint; /* Index of contour point on the
|
||||
* reference glyph */
|
||||
|
@ -97,7 +100,7 @@ struct BaseCoordFormat3
|
|||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 3 */
|
||||
HBINT16 coordinate; /* X or Y value, in design units */
|
||||
FWORD coordinate; /* X or Y value, in design units */
|
||||
OffsetTo<Device> deviceTable; /* Offset to Device table for X or
|
||||
* Y value, from beginning of
|
||||
* BaseCoord table (may be NULL). */
|
||||
|
@ -109,6 +112,7 @@ struct BaseCoord
|
|||
{
|
||||
inline int get_coord (void) const
|
||||
{
|
||||
/* XXX wire up direction and font. */
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.get_coord ();
|
||||
case 2: return u.format2.get_coord ();
|
||||
|
@ -142,14 +146,10 @@ struct BaseCoord
|
|||
|
||||
struct FeatMinMaxRecord
|
||||
{
|
||||
inline int get_min_value (void) const
|
||||
{ return (this+minCoord).get_coord(); }
|
||||
inline int get_min_value (void) const { return (this+minCoord).get_coord(); }
|
||||
inline int get_max_value (void) const { return (this+maxCoord).get_coord(); }
|
||||
|
||||
inline int get_max_value (void) const
|
||||
{ return (this+maxCoord).get_coord(); }
|
||||
|
||||
inline const Tag &get_tag () const
|
||||
{ return tag; }
|
||||
inline const Tag& get_tag () const { return tag; }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
|
@ -181,7 +181,7 @@ struct MinMax
|
|||
unsigned int count = featMinMaxRecords.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
Tag tag = featMinMaxRecords[i].get_tag();
|
||||
Tag tag = featMinMaxRecords[i].get_tag ();
|
||||
int cmp = tag.cmp(featureTableTag);
|
||||
if (cmp == 0) return i;
|
||||
if (cmp > 0) return NOT_INDEXED;
|
||||
|
@ -233,13 +233,13 @@ struct BaseLangSysRecord
|
|||
{ return baseLangSysTag; }
|
||||
|
||||
inline unsigned int get_feature_tag_index (Tag featureTableTag) const
|
||||
{ return (this+minMax).get_feature_tag_index(featureTableTag); }
|
||||
{ return (this+minMax).get_feature_tag_index( featureTableTag); }
|
||||
|
||||
inline int get_min_value (unsigned int featureTableTagIndex) const
|
||||
{ return (this+minMax).get_min_value(featureTableTagIndex); }
|
||||
{ return (this+minMax).get_min_value( featureTableTagIndex); }
|
||||
|
||||
inline int get_max_value (unsigned int featureTableTagIndex) const
|
||||
{ return (this+minMax).get_max_value(featureTableTagIndex); }
|
||||
{ return (this+minMax).get_max_value (featureTableTagIndex); }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
|
@ -263,34 +263,34 @@ struct BaseValues
|
|||
|
||||
inline int get_base_coord (unsigned int baselineTagIndex) const
|
||||
{
|
||||
return (this+baseCoords[baselineTagIndex]).get_coord();
|
||||
return (this+baseCoords[baselineTagIndex]).get_coord ();
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
defaultIndex <= baseCoordCount &&
|
||||
baseCoords.sanitize (c, this));
|
||||
baseCoords.sanitize (c, this));
|
||||
}
|
||||
|
||||
protected:
|
||||
Index defaultIndex;
|
||||
HBUINT16 baseCoordCount;
|
||||
OffsetArrayOf<BaseCoord> baseCoords;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, baseCoords);
|
||||
|
||||
DEFINE_SIZE_ARRAY (4, baseCoords);
|
||||
};
|
||||
|
||||
struct BaseScript {
|
||||
|
||||
inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
|
||||
{
|
||||
/* XXX bsearch */
|
||||
Tag tag;
|
||||
int cmp;
|
||||
for (unsigned int i = 0; i < baseLangSysCount; i++) {
|
||||
tag = baseLangSysRecords[i].get_tag();
|
||||
unsigned int count = baseLangSysRecords.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
tag = baseLangSysRecords[i].get_tag ();
|
||||
// taking advantage of alphabetical order
|
||||
cmp = tag.cmp(baseLangSysTag);
|
||||
if (cmp == 0) return i;
|
||||
|
@ -301,51 +301,50 @@ struct BaseScript {
|
|||
|
||||
inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
|
||||
{
|
||||
if (baseLangSysIndex == NOT_INDEXED) {
|
||||
if (baseLangSysIndex == NOT_INDEXED)
|
||||
{
|
||||
if (unlikely(defaultMinMax)) return NOT_INDEXED;
|
||||
return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
|
||||
return (this+defaultMinMax).get_feature_tag_index (featureTableTag);
|
||||
}
|
||||
if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
|
||||
return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
|
||||
return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index (featureTableTag);
|
||||
}
|
||||
|
||||
inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
{
|
||||
if (baseLangSysIndex == NOT_INDEXED)
|
||||
return (this+defaultMinMax).get_min_value(featureTableTagIndex);
|
||||
return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
|
||||
return (this+defaultMinMax).get_min_value (featureTableTagIndex);
|
||||
return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex);
|
||||
}
|
||||
|
||||
inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
{
|
||||
if (baseLangSysIndex == NOT_INDEXED)
|
||||
return (this+defaultMinMax).get_min_value(featureTableTagIndex);
|
||||
return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
|
||||
return (this+defaultMinMax).get_min_value (featureTableTagIndex);
|
||||
return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex);
|
||||
}
|
||||
|
||||
inline unsigned int get_default_base_tag_index (void) const
|
||||
{ return (this+baseValues).get_default_base_tag_index(); }
|
||||
{ return (this+baseValues).get_default_base_tag_index (); }
|
||||
|
||||
inline int get_base_coord (unsigned int baselineTagIndex) const
|
||||
{ return (this+baseValues).get_base_coord(baselineTagIndex); }
|
||||
{ return (this+baseValues).get_base_coord (baselineTagIndex); }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
baseValues.sanitize (c, this) &&
|
||||
defaultMinMax.sanitize (c, this) &&
|
||||
baseLangSysRecords.sanitize (c, this));
|
||||
baseValues.sanitize (c, this) &&
|
||||
defaultMinMax.sanitize (c, this) &&
|
||||
baseLangSysRecords.sanitize (c, this));
|
||||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<BaseValues> baseValues;
|
||||
OffsetTo<MinMax> defaultMinMax;
|
||||
HBUINT16 baseLangSysCount;
|
||||
ArrayOf<BaseLangSysRecord> baseLangSysRecords;
|
||||
OffsetTo<BaseValues> baseValues;
|
||||
OffsetTo<MinMax> defaultMinMax;
|
||||
ArrayOf<BaseLangSysRecord> baseLangSysRecords;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
|
||||
DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
|
||||
};
|
||||
|
||||
|
||||
|
@ -355,29 +354,28 @@ struct BaseScriptRecord {
|
|||
{ return baseScriptTag; }
|
||||
|
||||
inline unsigned int get_default_base_tag_index(void) const
|
||||
{ return (this+baseScript).get_default_base_tag_index(); }
|
||||
{ return (this+baseScript).get_default_base_tag_index (); }
|
||||
|
||||
inline int get_base_coord(unsigned int baselineTagIndex) const
|
||||
{ return (this+baseScript).get_base_coord(baselineTagIndex); }
|
||||
{ return (this+baseScript).get_base_coord (baselineTagIndex); }
|
||||
|
||||
inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
|
||||
{ return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
|
||||
{ return (this+baseScript).get_lang_tag_index (baseLangSysTag); }
|
||||
|
||||
inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
|
||||
{ return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
|
||||
{ return (this+baseScript).get_feature_tag_index (baseLangSysIndex, featureTableTag); }
|
||||
|
||||
inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
{ return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
|
||||
{ return (this+baseScript).get_max_value (baseLangSysIndex, featureTableTagIndex); }
|
||||
|
||||
inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
{ return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
|
||||
{ return (this+baseScript).get_min_value (baseLangSysIndex, featureTableTagIndex); }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
baseScript != Null(OffsetTo<BaseScript>) &&
|
||||
baseScript.sanitize (c, base));
|
||||
baseScript.sanitize (c, base));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -392,7 +390,9 @@ struct BaseScriptList {
|
|||
|
||||
inline unsigned int get_base_script_index (Tag baseScriptTag) const
|
||||
{
|
||||
for (unsigned int i = 0; i < baseScriptCount; i++)
|
||||
/* XXX bsearch? */
|
||||
unsigned int count = baseScriptRecords.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (baseScriptRecords[i].get_tag() == baseScriptTag)
|
||||
return i;
|
||||
return NOT_INDEXED;
|
||||
|
@ -400,7 +400,6 @@ struct BaseScriptList {
|
|||
|
||||
inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
|
||||
{
|
||||
if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
|
||||
return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
|
||||
}
|
||||
|
||||
|
@ -411,13 +410,11 @@ struct BaseScriptList {
|
|||
|
||||
inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
|
||||
{
|
||||
if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
|
||||
return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
|
||||
}
|
||||
|
||||
inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
|
||||
{
|
||||
if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
|
||||
return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
|
||||
}
|
||||
|
||||
|
@ -435,24 +432,23 @@ struct BaseScriptList {
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
baseScriptRecords.sanitize (c, this));
|
||||
baseScriptRecords.sanitize (c, this));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 baseScriptCount;
|
||||
ArrayOf<BaseScriptRecord> baseScriptRecords;
|
||||
ArrayOf<BaseScriptRecord> baseScriptRecords;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, baseScriptRecords);
|
||||
|
||||
DEFINE_SIZE_ARRAY (2, baseScriptRecords);
|
||||
};
|
||||
|
||||
struct BaseTagList
|
||||
{
|
||||
|
||||
inline unsigned int get_tag_index(Tag baselineTag) const
|
||||
inline unsigned int get_tag_index (Tag baselineTag) const
|
||||
{
|
||||
for (unsigned int i = 0; i < baseTagCount; i++)
|
||||
/* TODO bsearch? */
|
||||
unsigned int count = baselineTags.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (baselineTags[i] == baselineTag)
|
||||
return i;
|
||||
return NOT_INDEXED;
|
||||
|
@ -465,42 +461,37 @@ struct BaseTagList
|
|||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 baseTagCount;
|
||||
SortedArrayOf<Tag> baselineTags;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, baselineTags);
|
||||
DEFINE_SIZE_ARRAY (2, baselineTags);
|
||||
};
|
||||
|
||||
struct Axis
|
||||
{
|
||||
|
||||
inline unsigned int get_base_tag_index(Tag baselineTag) const
|
||||
inline unsigned int get_base_tag_index (Tag baselineTag) const
|
||||
{
|
||||
if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
|
||||
return (this+baseTagList).get_tag_index(baselineTag);
|
||||
}
|
||||
|
||||
inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
|
||||
{
|
||||
if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
|
||||
return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
|
||||
}
|
||||
|
||||
inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
|
||||
inline int get_base_coord (unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
|
||||
{
|
||||
return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
|
||||
}
|
||||
|
||||
inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
|
||||
{
|
||||
if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
|
||||
return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
|
||||
}
|
||||
|
||||
inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
|
||||
{
|
||||
if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
|
||||
return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
|
||||
}
|
||||
|
||||
|
@ -518,13 +509,13 @@ struct Axis
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
baseTagList.sanitize (c, this) &&
|
||||
baseScriptList.sanitize (c, this));
|
||||
baseTagList.sanitize (c, this) &&
|
||||
baseScriptList.sanitize (c, this));
|
||||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<BaseTagList> baseTagList;
|
||||
OffsetTo<BaseScriptList> baseScriptList;
|
||||
OffsetTo<BaseTagList> baseTagList;
|
||||
OffsetTo<BaseScriptList> baseScriptList;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
|
@ -534,96 +525,78 @@ struct BASE
|
|||
{
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_BASE;
|
||||
|
||||
inline bool has_vert_axis(void)
|
||||
{ return vertAxis != Null(OffsetTo<Axis>); }
|
||||
inline bool has_v_axis(void) { return vAxis != 0; }
|
||||
|
||||
inline bool has_horiz_axis(void)
|
||||
{ return horizAxis != Null(OffsetTo<Axis>); }
|
||||
inline bool has_h_axis(void) { return hAxis != 0; }
|
||||
|
||||
// horizontal axis base coords:
|
||||
|
||||
inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
|
||||
inline unsigned int get_h_base_tag_index (Tag baselineTag) const
|
||||
{
|
||||
if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
|
||||
return (this+horizAxis).get_base_tag_index(baselineTag);
|
||||
return (this+hAxis).get_base_tag_index(baselineTag);
|
||||
}
|
||||
|
||||
inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
|
||||
inline unsigned int get_h_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
|
||||
{
|
||||
if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
|
||||
return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
|
||||
return (this+hAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
|
||||
}
|
||||
|
||||
inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
|
||||
inline int get_h_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
|
||||
{
|
||||
return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
|
||||
return (this+hAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
|
||||
}
|
||||
|
||||
// vertical axis base coords:
|
||||
|
||||
inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
|
||||
inline unsigned int get_v_base_tag_index(Tag baselineTag) const
|
||||
{
|
||||
if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
|
||||
return (this+vertAxis).get_base_tag_index(baselineTag);
|
||||
return (this+vAxis).get_base_tag_index(baselineTag);
|
||||
}
|
||||
|
||||
inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
|
||||
inline unsigned int get_v_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
|
||||
{
|
||||
if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
|
||||
return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
|
||||
return (this+vAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
|
||||
}
|
||||
|
||||
inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
|
||||
inline int get_v_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
|
||||
{
|
||||
return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
|
||||
return (this+vAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
|
||||
}
|
||||
|
||||
// horizontal axis min/max coords:
|
||||
|
||||
inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
|
||||
inline unsigned int get_h_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
|
||||
{
|
||||
if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
|
||||
return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
|
||||
return (this+hAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
|
||||
}
|
||||
|
||||
inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
|
||||
inline unsigned int get_h_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
|
||||
{
|
||||
if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
|
||||
return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
|
||||
return (this+hAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
|
||||
}
|
||||
|
||||
inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
inline int get_h_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
{
|
||||
return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
|
||||
return (this+hAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
|
||||
}
|
||||
|
||||
inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
inline int get_h_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
{
|
||||
return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
|
||||
return (this+hAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
|
||||
}
|
||||
|
||||
// vertical axis min/max coords:
|
||||
|
||||
inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
|
||||
inline unsigned int get_v_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
|
||||
{
|
||||
if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
|
||||
return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
|
||||
return (this+vAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
|
||||
}
|
||||
|
||||
inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
|
||||
inline unsigned int get_v_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
|
||||
{
|
||||
if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
|
||||
return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
|
||||
return (this+vAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
|
||||
}
|
||||
|
||||
inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
inline int get_v_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
{
|
||||
return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
|
||||
return (this+vAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
|
||||
}
|
||||
|
||||
inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
inline int get_v_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
|
||||
{
|
||||
return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
|
||||
return (this+vAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -631,15 +604,15 @@ struct BASE
|
|||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
likely (version.major == 1) &&
|
||||
horizAxis.sanitize (c, this) &&
|
||||
vertAxis.sanitize (c, this) &&
|
||||
hAxis.sanitize (c, this) &&
|
||||
vAxis.sanitize (c, this) &&
|
||||
(version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
|
||||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<> version;
|
||||
OffsetTo<Axis> horizAxis;
|
||||
OffsetTo<Axis> vertAxis;
|
||||
OffsetTo<Axis> hAxis;
|
||||
OffsetTo<Axis> vAxis;
|
||||
LOffsetTo<VariationStore>
|
||||
varStore; /* Offset to the table of Item Variation
|
||||
* Store--from beginning of BASE
|
||||
|
|
|
@ -173,7 +173,7 @@ struct RangeRecord
|
|||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
DEFINE_NULL_DATA (OT, RangeRecord, "\000\001");
|
||||
DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
|
||||
|
||||
|
||||
struct IndexArray : ArrayOf<Index>
|
||||
|
@ -240,8 +240,7 @@ struct LangSys
|
|||
public:
|
||||
DEFINE_SIZE_ARRAY (6, featureIndex);
|
||||
};
|
||||
DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF");
|
||||
|
||||
DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
|
||||
|
||||
struct Script
|
||||
{
|
||||
|
|
|
@ -349,6 +349,7 @@ struct GDEF
|
|||
ComponentGlyph = 4
|
||||
};
|
||||
|
||||
inline bool has_data (void) const { return version.to_int () != 0; }
|
||||
inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
|
||||
inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
|
||||
{ return (this+glyphClassDef).get_class (glyph); }
|
||||
|
|
|
@ -1628,14 +1628,14 @@ GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
|||
template <typename context_t>
|
||||
/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
|
||||
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->table.GPOS);
|
||||
const PosLookup &l = gpos.get_lookup (lookup_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
|
||||
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->table.GPOS);
|
||||
const PosLookup &l = gpos.get_lookup (lookup_index);
|
||||
unsigned int saved_lookup_props = c->lookup_props;
|
||||
unsigned int saved_lookup_index = c->lookup_index;
|
||||
|
|
|
@ -1335,7 +1335,7 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
|
|||
{
|
||||
_hb_buffer_assert_gsubgpos_vars (buffer);
|
||||
|
||||
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
|
||||
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->table.GDEF;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
|
@ -1359,14 +1359,14 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
|
|||
template <typename context_t>
|
||||
/*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
|
||||
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->table.GSUB);
|
||||
const SubstLookup &l = gsub.get_lookup (lookup_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
/*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
|
||||
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->table.GSUB);
|
||||
const SubstLookup &l = gsub.get_lookup (lookup_index);
|
||||
unsigned int saved_lookup_props = c->lookup_props;
|
||||
unsigned int saved_lookup_index = c->lookup_index;
|
||||
|
|
|
@ -480,7 +480,7 @@ struct hb_ot_apply_context_t :
|
|||
iter_input (), iter_context (),
|
||||
font (font_), face (font->face), buffer (buffer_),
|
||||
recurse_func (nullptr),
|
||||
gdef (*hb_ot_layout_from_face (face)->gdef),
|
||||
gdef (*hb_ot_layout_from_face (face)->table.GDEF),
|
||||
var_store (gdef.get_var_store ()),
|
||||
direction (buffer_->props.direction),
|
||||
lookup_mask (1),
|
||||
|
@ -2320,6 +2320,7 @@ struct Extension
|
|||
|
||||
struct GSUBGPOS
|
||||
{
|
||||
inline bool has_data (void) const { return version.to_int () != 0; }
|
||||
inline unsigned int get_script_count (void) const
|
||||
{ return (this+scriptList).len; }
|
||||
inline const Tag& get_script_tag (unsigned int i) const
|
||||
|
|
|
@ -121,25 +121,6 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font,
|
|||
* hb_ot_layout_t
|
||||
*/
|
||||
|
||||
namespace OT {
|
||||
struct BASE;
|
||||
struct COLR;
|
||||
struct CPAL;
|
||||
struct GDEF;
|
||||
struct GSUB;
|
||||
struct GPOS;
|
||||
struct MATH;
|
||||
struct fvar;
|
||||
struct avar;
|
||||
}
|
||||
|
||||
namespace AAT {
|
||||
struct ankr;
|
||||
struct kerx;
|
||||
struct morx;
|
||||
struct trak;
|
||||
}
|
||||
|
||||
struct hb_ot_layout_lookup_accelerator_t
|
||||
{
|
||||
template <typename TLookup>
|
||||
|
@ -161,28 +142,73 @@ struct hb_ot_layout_lookup_accelerator_t
|
|||
hb_set_digest_t digest;
|
||||
};
|
||||
|
||||
/* Most of these tables are NOT needed for shaping. But we need to hook them *somewhere*.
|
||||
* This is as good as any place. */
|
||||
#define HB_OT_LAYOUT_TABLES \
|
||||
/* OpenType shaping. */ \
|
||||
HB_OT_LAYOUT_TABLE(OT, GDEF) \
|
||||
HB_OT_LAYOUT_TABLE(OT, GSUB) \
|
||||
HB_OT_LAYOUT_TABLE(OT, GPOS) \
|
||||
HB_OT_LAYOUT_TABLE(OT, JSTF) \
|
||||
HB_OT_LAYOUT_TABLE(OT, BASE) \
|
||||
/* AAT shaping. */ \
|
||||
HB_OT_LAYOUT_TABLE(AAT, morx) \
|
||||
HB_OT_LAYOUT_TABLE(AAT, kerx) \
|
||||
HB_OT_LAYOUT_TABLE(AAT, ankr) \
|
||||
HB_OT_LAYOUT_TABLE(AAT, trak) \
|
||||
/* OpenType variations. */ \
|
||||
HB_OT_LAYOUT_TABLE(OT, fvar) \
|
||||
HB_OT_LAYOUT_TABLE(OT, avar) \
|
||||
HB_OT_LAYOUT_TABLE(OT, MVAR) \
|
||||
/* OpenType color. */ \
|
||||
HB_OT_LAYOUT_TABLE(OT, COLR) \
|
||||
HB_OT_LAYOUT_TABLE(OT, CPAL) \
|
||||
HB_OT_LAYOUT_TABLE(OT, CBDT) \
|
||||
HB_OT_LAYOUT_TABLE(OT, CBLC) \
|
||||
HB_OT_LAYOUT_TABLE(OT, sbix) \
|
||||
HB_OT_LAYOUT_TABLE(OT, svg) \
|
||||
/* OpenType math. */ \
|
||||
HB_OT_LAYOUT_TABLE(OT, MATH) \
|
||||
/* OpenType fundamentals. */ \
|
||||
HB_OT_LAYOUT_TABLE(OT, post) \
|
||||
/* */
|
||||
|
||||
/* Declare tables. */
|
||||
#define HB_OT_LAYOUT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
|
||||
HB_OT_LAYOUT_TABLES
|
||||
#undef HB_OT_LAYOUT_TABLE
|
||||
|
||||
struct hb_ot_layout_t
|
||||
{
|
||||
hb_blob_t *gdef_blob;
|
||||
hb_blob_t *gsub_blob;
|
||||
hb_blob_t *gpos_blob;
|
||||
|
||||
const struct OT::GDEF *gdef;
|
||||
const struct OT::GSUB *gsub;
|
||||
const struct OT::GPOS *gpos;
|
||||
|
||||
unsigned int gsub_lookup_count;
|
||||
unsigned int gpos_lookup_count;
|
||||
|
||||
hb_ot_layout_lookup_accelerator_t *gsub_accels;
|
||||
hb_ot_layout_lookup_accelerator_t *gpos_accels;
|
||||
|
||||
/* TODO Move the following out of this struct. */
|
||||
hb_face_t *face; /* MUST be before the lazy loaders. */
|
||||
hb_table_lazy_loader_t<1, struct OT::MATH> math;
|
||||
hb_table_lazy_loader_t<2, struct OT::fvar> fvar;
|
||||
hb_table_lazy_loader_t<3, struct OT::avar> avar;
|
||||
hb_table_lazy_loader_t<4, struct AAT::morx> morx;
|
||||
/* Various non-shaping tables. */
|
||||
struct tables_t
|
||||
{
|
||||
HB_INTERNAL void init0 (hb_face_t *face);
|
||||
HB_INTERNAL void fini (void);
|
||||
|
||||
#define HB_OT_LAYOUT_TABLE_ORDER(Namespace, Type) \
|
||||
HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
|
||||
enum order_t
|
||||
{
|
||||
ORDER_ZERO,
|
||||
#define HB_OT_LAYOUT_TABLE(Namespace, Type) \
|
||||
HB_OT_LAYOUT_TABLE_ORDER (Namespace, Type),
|
||||
HB_OT_LAYOUT_TABLES
|
||||
#undef HB_OT_LAYOUT_TABLE
|
||||
};
|
||||
|
||||
hb_face_t *face; /* MUST be JUST before the lazy loaders. */
|
||||
#define HB_OT_LAYOUT_TABLE(Namespace, Type) \
|
||||
hb_table_lazy_loader_t<HB_OT_LAYOUT_TABLE_ORDER (Namespace, Type), struct Namespace::Type> Type;
|
||||
HB_OT_LAYOUT_TABLES
|
||||
#undef HB_OT_LAYOUT_TABLE
|
||||
} table;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "hb-open-type-private.hh"
|
||||
#include "hb-ot-layout-private.hh"
|
||||
#include "hb-ot-map-private.hh"
|
||||
#include "hb-map-private.hh"
|
||||
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
|
@ -44,9 +45,124 @@
|
|||
#include "hb-ot-color-sbix-table.hh"
|
||||
#include "hb-ot-color-svg-table.hh"
|
||||
#include "hb-ot-name-table.hh"
|
||||
#include "hb-map-private.hh"
|
||||
|
||||
|
||||
static bool
|
||||
_hb_ot_blacklist_gdef (unsigned int gdef_len,
|
||||
unsigned int gsub_len,
|
||||
unsigned int gpos_len)
|
||||
{
|
||||
/* The ugly business of blacklisting individual fonts' tables happen here!
|
||||
* See this thread for why we finally had to bend in and do this:
|
||||
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
|
||||
*
|
||||
* In certain versions of Times New Roman Italic and Bold Italic,
|
||||
* ASCII double quotation mark U+0022 has wrong glyph class 3 (mark)
|
||||
* in GDEF. Many versions of Tahoma have bad GDEF tables that
|
||||
* incorrectly classify some spacing marks such as certain IPA
|
||||
* symbols as glyph class 3. So do older versions of Microsoft
|
||||
* Himalaya, and the version of Cantarell shipped by Ubuntu 16.04.
|
||||
*
|
||||
* Nuke the GDEF tables of to avoid unwanted width-zeroing.
|
||||
*
|
||||
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
|
||||
*/
|
||||
#define ENCODE(x,y,z) ((int64_t) (x) << 32 | (int64_t) (y) << 16 | (z))
|
||||
switch ENCODE(gdef_len, gsub_len, gpos_len)
|
||||
{
|
||||
/* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
|
||||
case ENCODE (442, 2874, 42038):
|
||||
/* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
|
||||
case ENCODE (430, 2874, 40662):
|
||||
/* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
|
||||
case ENCODE (442, 2874, 39116):
|
||||
/* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
|
||||
case ENCODE (430, 2874, 39374):
|
||||
/* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
|
||||
case ENCODE (490, 3046, 41638):
|
||||
/* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
|
||||
case ENCODE (478, 3046, 41902):
|
||||
/* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */
|
||||
case ENCODE (898, 12554, 46470):
|
||||
/* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */
|
||||
case ENCODE (910, 12566, 47732):
|
||||
/* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */
|
||||
case ENCODE (928, 23298, 59332):
|
||||
/* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */
|
||||
case ENCODE (940, 23310, 60732):
|
||||
/* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
case ENCODE (964, 23836, 60072):
|
||||
/* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
case ENCODE (976, 23832, 61456):
|
||||
/* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */
|
||||
case ENCODE (994, 24474, 60336):
|
||||
/* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */
|
||||
case ENCODE (1006, 24470, 61740):
|
||||
/* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
case ENCODE (1006, 24576, 61346):
|
||||
/* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
case ENCODE (1018, 24572, 62828):
|
||||
/* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */
|
||||
case ENCODE (1006, 24576, 61352):
|
||||
/* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */
|
||||
case ENCODE (1018, 24572, 62834):
|
||||
/* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */
|
||||
case ENCODE (832, 7324, 47162):
|
||||
/* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */
|
||||
case ENCODE (844, 7302, 45474):
|
||||
/* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */
|
||||
case ENCODE (180, 13054, 7254):
|
||||
/* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */
|
||||
case ENCODE (192, 12638, 7254):
|
||||
/* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */
|
||||
case ENCODE (192, 12690, 7254):
|
||||
/* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
|
||||
/* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
|
||||
case ENCODE (188, 248, 3852):
|
||||
/* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
|
||||
/* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
|
||||
case ENCODE (188, 264, 3426):
|
||||
/* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
|
||||
case ENCODE (1058, 47032, 11818):
|
||||
/* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
|
||||
case ENCODE (1046, 47030, 12600):
|
||||
/* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
|
||||
case ENCODE (1058, 71796, 16770):
|
||||
/* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
|
||||
case ENCODE (1046, 71790, 17862):
|
||||
/* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
|
||||
case ENCODE (1046, 71788, 17112):
|
||||
/* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
|
||||
case ENCODE (1058, 71794, 17514):
|
||||
/* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
|
||||
case ENCODE (1330, 109904, 57938):
|
||||
/* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
|
||||
case ENCODE (1330, 109904, 58972):
|
||||
/* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf
|
||||
* "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
|
||||
case ENCODE (1004, 59092, 14836):
|
||||
return true;
|
||||
#undef ENCODE
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void hb_ot_layout_t::tables_t::init0 (hb_face_t *face)
|
||||
{
|
||||
this->face = face;
|
||||
#define HB_OT_LAYOUT_TABLE(Namespace, Type) Type.init0 ();
|
||||
HB_OT_LAYOUT_TABLES
|
||||
#undef HB_OT_LAYOUT_TABLE
|
||||
}
|
||||
void hb_ot_layout_t::tables_t::fini (void)
|
||||
{
|
||||
#define HB_OT_LAYOUT_TABLE(Namespace, Type) Type.fini ();
|
||||
HB_OT_LAYOUT_TABLES
|
||||
#undef HB_OT_LAYOUT_TABLE
|
||||
}
|
||||
|
||||
hb_ot_layout_t *
|
||||
_hb_ot_layout_create (hb_face_t *face)
|
||||
{
|
||||
|
@ -54,145 +170,33 @@ _hb_ot_layout_create (hb_face_t *face)
|
|||
if (unlikely (!layout))
|
||||
return nullptr;
|
||||
|
||||
layout->gdef_blob = hb_sanitize_context_t ().reference_table<OT::GDEF> (face);
|
||||
layout->gdef = layout->gdef_blob->as<OT::GDEF> ();
|
||||
layout->table.init0 (face);
|
||||
|
||||
layout->gsub_blob = hb_sanitize_context_t ().reference_table<OT::GSUB> (face);
|
||||
layout->gsub = layout->gsub_blob->as<OT::GSUB> ();
|
||||
const OT::GSUB &gsub = *layout->table.GSUB;
|
||||
const OT::GPOS &gpos = *layout->table.GPOS;
|
||||
|
||||
layout->gpos_blob = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
|
||||
layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
|
||||
if (unlikely (_hb_ot_blacklist_gdef (layout->table.GDEF.get_blob ()->length,
|
||||
layout->table.GSUB.get_blob ()->length,
|
||||
layout->table.GPOS.get_blob ()->length)))
|
||||
layout->table.GDEF.set_stored (hb_blob_get_empty ());
|
||||
|
||||
layout->face = face;
|
||||
layout->math.init ();
|
||||
layout->fvar.init ();
|
||||
layout->avar.init ();
|
||||
layout->morx.init ();
|
||||
unsigned int gsub_lookup_count = layout->gsub_lookup_count = gsub.get_lookup_count ();
|
||||
unsigned int gpos_lookup_count = layout->gpos_lookup_count = gpos.get_lookup_count ();
|
||||
|
||||
{
|
||||
/*
|
||||
* The ugly business of blacklisting individual fonts' tables happen here!
|
||||
* See this thread for why we finally had to bend in and do this:
|
||||
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
|
||||
*/
|
||||
unsigned int gdef_len = layout->gdef_blob->length;
|
||||
unsigned int gsub_len = layout->gsub_blob->length;
|
||||
unsigned int gpos_len = layout->gpos_blob->length;
|
||||
if (0
|
||||
/* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
|
||||
|| (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
|
||||
/* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
|
||||
|| (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len)
|
||||
/* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
|
||||
|| (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len)
|
||||
/* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
|
||||
|| (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len)
|
||||
/* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
|
||||
|| (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len)
|
||||
/* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
|
||||
|| (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len)
|
||||
)
|
||||
{
|
||||
/* In certain versions of Times New Roman Italic and Bold Italic,
|
||||
* ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
|
||||
* glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width
|
||||
* double-quote. See:
|
||||
* https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
|
||||
*/
|
||||
if (3 == layout->gdef->get_glyph_class (5))
|
||||
layout->gdef = &Null(OT::GDEF);
|
||||
}
|
||||
else if (0
|
||||
/* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */
|
||||
|| (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len)
|
||||
/* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */
|
||||
|| (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len)
|
||||
/* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */
|
||||
|| (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
|
||||
/* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */
|
||||
|| (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
|
||||
/* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
|| (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len)
|
||||
/* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
|| (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len)
|
||||
/* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */
|
||||
|| (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
|
||||
/* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */
|
||||
|| (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
|
||||
/* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
|| (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len)
|
||||
/* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
|
||||
|| (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len)
|
||||
/* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */
|
||||
|| (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len)
|
||||
/* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */
|
||||
|| (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len)
|
||||
/* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */
|
||||
|| (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len)
|
||||
/* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */
|
||||
|| (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len)
|
||||
/* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */
|
||||
|| (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len)
|
||||
/* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */
|
||||
|| (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len)
|
||||
/* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */
|
||||
|| (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
|
||||
/* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
|
||||
/* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
|
||||
|| (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
|
||||
/* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
|
||||
/* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
|
||||
|| (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
|
||||
/* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
|
||||
|| (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len)
|
||||
/* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
|
||||
|| (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len)
|
||||
/* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
|
||||
|| (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len)
|
||||
/* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
|
||||
|| (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len)
|
||||
/* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
|
||||
|| (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
|
||||
/* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
|
||||
|| (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
|
||||
/* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
|
||||
|| (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
|
||||
/* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
|
||||
|| (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
|
||||
/* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf
|
||||
* "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
|
||||
|| (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
|
||||
)
|
||||
{
|
||||
/* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
|
||||
* such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
|
||||
* and the version of Cantarell shipped by Ubuntu 16.04.
|
||||
* Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
|
||||
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
|
||||
*/
|
||||
layout->gdef = &Null(OT::GDEF);
|
||||
}
|
||||
}
|
||||
layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (gsub_lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
|
||||
layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (gpos_lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
|
||||
|
||||
layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
|
||||
layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
|
||||
|
||||
layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
|
||||
layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
|
||||
|
||||
if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
|
||||
(layout->gpos_lookup_count && !layout->gpos_accels)))
|
||||
if (unlikely ((gsub_lookup_count && !layout->gsub_accels) ||
|
||||
(gpos_lookup_count && !layout->gpos_accels)))
|
||||
{
|
||||
_hb_ot_layout_destroy (layout);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
|
||||
layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
|
||||
for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
|
||||
layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
|
||||
for (unsigned int i = 0; i < gsub_lookup_count; i++)
|
||||
layout->gsub_accels[i].init (gsub.get_lookup (i));
|
||||
for (unsigned int i = 0; i < gpos_lookup_count; i++)
|
||||
layout->gpos_accels[i].init (gpos.get_lookup (i));
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
@ -210,14 +214,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
|
|||
free (layout->gsub_accels);
|
||||
free (layout->gpos_accels);
|
||||
|
||||
hb_blob_destroy (layout->gdef_blob);
|
||||
hb_blob_destroy (layout->gsub_blob);
|
||||
hb_blob_destroy (layout->gpos_blob);
|
||||
|
||||
layout->math.fini ();
|
||||
layout->fvar.fini ();
|
||||
layout->avar.fini ();
|
||||
layout->morx.fini ();
|
||||
layout->table.fini ();
|
||||
|
||||
free (layout);
|
||||
}
|
||||
|
@ -234,19 +231,19 @@ static inline const OT::GDEF&
|
|||
_get_gdef (hb_face_t *face)
|
||||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
|
||||
return *hb_ot_layout_from_face (face)->gdef;
|
||||
return *hb_ot_layout_from_face (face)->table.GDEF;
|
||||
}
|
||||
static inline const OT::GSUB&
|
||||
_get_gsub (hb_face_t *face)
|
||||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB);
|
||||
return *hb_ot_layout_from_face (face)->gsub;
|
||||
return *hb_ot_layout_from_face (face)->table.GSUB;
|
||||
}
|
||||
static inline const OT::GPOS&
|
||||
_get_gpos (hb_face_t *face)
|
||||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS);
|
||||
return *hb_ot_layout_from_face (face)->gpos;
|
||||
return *hb_ot_layout_from_face (face)->table.GPOS;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -854,13 +851,13 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
|
|||
{
|
||||
case HB_OT_TAG_GSUB:
|
||||
{
|
||||
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
|
||||
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->table.GSUB->get_lookup (lookup_index);
|
||||
l.collect_glyphs (&c);
|
||||
return;
|
||||
}
|
||||
case HB_OT_TAG_GPOS:
|
||||
{
|
||||
const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
|
||||
const OT::PosLookup& l = hb_ot_layout_from_face (face)->table.GPOS->get_lookup (lookup_index);
|
||||
l.collect_glyphs (&c);
|
||||
return;
|
||||
}
|
||||
|
@ -907,7 +904,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
|
|||
hb_bool_t
|
||||
hb_ot_layout_has_substitution (hb_face_t *face)
|
||||
{
|
||||
return &_get_gsub (face) != &Null(OT::GSUB);
|
||||
return _get_gsub (face).has_data ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -936,7 +933,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
|
|||
if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
|
||||
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
|
||||
|
||||
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
|
||||
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->table.GSUB->get_lookup (lookup_index);
|
||||
|
||||
return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
|
||||
}
|
||||
|
@ -1009,7 +1006,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
|
|||
hb_bool_t
|
||||
hb_ot_layout_has_positioning (hb_face_t *face)
|
||||
{
|
||||
return &_get_gpos (face) != &Null(OT::GPOS);
|
||||
return _get_gpos (face).has_data ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1094,7 +1091,7 @@ struct GSUBProxy
|
|||
typedef OT::SubstLookup Lookup;
|
||||
|
||||
GSUBProxy (hb_face_t *face) :
|
||||
table (*hb_ot_layout_from_face (face)->gsub),
|
||||
table (*hb_ot_layout_from_face (face)->table.GSUB),
|
||||
accels (hb_ot_layout_from_face (face)->gsub_accels) {}
|
||||
|
||||
const OT::GSUB &table;
|
||||
|
@ -1108,7 +1105,7 @@ struct GPOSProxy
|
|||
typedef OT::PosLookup Lookup;
|
||||
|
||||
GPOSProxy (hb_face_t *face) :
|
||||
table (*hb_ot_layout_from_face (face)->gpos),
|
||||
table (*hb_ot_layout_from_face (face)->table.GPOS),
|
||||
accels (hb_ot_layout_from_face (face)->gpos_accels) {}
|
||||
|
||||
const OT::GPOS &table;
|
||||
|
@ -1344,5 +1341,5 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
|
|||
// hb_bool_t
|
||||
// hb_ot_base_has_data (hb_face_t *face)
|
||||
// {
|
||||
// return &_get_base (face) != &Null(OT::BASE);
|
||||
// return _get_base (face).has_data ();
|
||||
// }
|
||||
|
|
|
@ -686,6 +686,8 @@ struct MATH
|
|||
{
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_MATH;
|
||||
|
||||
inline bool has_data (void) const { return version.to_int () != 0; }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
|
@ -34,7 +34,7 @@ _get_math (hb_face_t *face)
|
|||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::MATH);
|
||||
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||
return *(layout->math.get ());
|
||||
return *(layout->table.MATH.get ());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -55,7 +55,7 @@ _get_math (hb_face_t *face)
|
|||
hb_bool_t
|
||||
hb_ot_math_has_data (hb_face_t *face)
|
||||
{
|
||||
return &_get_math (face) != &Null(OT::MATH);
|
||||
return _get_math (face).has_data ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -205,8 +205,6 @@ struct arabic_fallback_plan_t
|
|||
hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
|
||||
};
|
||||
|
||||
static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
|
||||
|
||||
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
|
||||
#define HB_WITH_WIN1256
|
||||
#endif
|
||||
|
@ -215,7 +213,8 @@ static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
|
|||
#include "hb-ot-shape-complex-arabic-win1256.hh"
|
||||
#endif
|
||||
|
||||
struct ManifestLookup {
|
||||
struct ManifestLookup
|
||||
{
|
||||
OT::Tag tag;
|
||||
OT::OffsetTo<OT::SubstLookup> lookupOffset;
|
||||
};
|
||||
|
@ -299,7 +298,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
|
|||
{
|
||||
arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
|
||||
if (unlikely (!fallback_plan))
|
||||
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
|
||||
return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
|
||||
|
||||
fallback_plan->num_lookups = 0;
|
||||
fallback_plan->free_lookups = false;
|
||||
|
@ -314,14 +313,15 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
|
|||
if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
|
||||
return fallback_plan;
|
||||
|
||||
assert (fallback_plan->num_lookups == 0);
|
||||
free (fallback_plan);
|
||||
return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
|
||||
return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
|
||||
}
|
||||
|
||||
static void
|
||||
arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
|
||||
{
|
||||
if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
|
||||
if (!fallback_plan || fallback_plan->num_lookups == 0)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
|
||||
|
|
|
@ -680,8 +680,8 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
|
|||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
|
||||
c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
|
||||
&pos[0].x_advance, sizeof(pos[0]));
|
||||
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
|
||||
if (c->font->has_glyph_h_origin_func ())
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
|
@ -691,9 +691,10 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
|
|||
}
|
||||
else
|
||||
{
|
||||
c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
|
||||
&pos[0].y_advance, sizeof(pos[0]));
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
|
||||
c->font->subtract_glyph_v_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
|
|
|
@ -87,6 +87,8 @@ struct fvar
|
|||
{
|
||||
static const hb_tag_t tableTag = HB_OT_TAG_fvar;
|
||||
|
||||
inline bool has_data (void) const { return version.to_int () != 0; }
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
|
@ -41,14 +41,14 @@ _get_fvar (hb_face_t *face)
|
|||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::fvar);
|
||||
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||
return *(layout->fvar.get ());
|
||||
return *(layout->table.fvar.get ());
|
||||
}
|
||||
static inline const OT::avar&
|
||||
_get_avar (hb_face_t *face)
|
||||
{
|
||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::avar);
|
||||
hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
|
||||
return *(layout->avar.get ());
|
||||
return *(layout->table.avar.get ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +65,7 @@ _get_avar (hb_face_t *face)
|
|||
hb_bool_t
|
||||
hb_ot_var_has_data (hb_face_t *face)
|
||||
{
|
||||
return &_get_fvar (face) != &Null(OT::fvar);
|
||||
return _get_fvar (face).has_data ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -86,7 +86,7 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
|
|||
|
||||
/*
|
||||
* Compiler attributes
|
||||
* */
|
||||
*/
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
|
||||
|
@ -98,7 +98,6 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
|
|||
#define constexpr const
|
||||
#endif
|
||||
|
||||
// Static assertions
|
||||
#ifndef static_assert
|
||||
#define static_assert(e, msg) \
|
||||
HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
|
||||
|
@ -124,7 +123,7 @@ struct _hb_alignof
|
|||
};
|
||||
#ifndef alignof
|
||||
#define alignof(x) (_hb_alignof<x>::value)
|
||||
#endif // alignof
|
||||
#endif
|
||||
|
||||
#endif // __cplusplus < 201103L
|
||||
|
||||
|
@ -286,13 +285,12 @@ static int errno = 0; /* Use something better? */
|
|||
#define HB_STMT_START do
|
||||
#define HB_STMT_END while (0)
|
||||
|
||||
/* Static-assert as expression. */
|
||||
template <unsigned int cond> class hb_assert_constant_t;
|
||||
template <> class hb_assert_constant_t<1> {};
|
||||
|
||||
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
|
||||
|
||||
/* Lets assert int types. Saves trouble down the road. */
|
||||
|
||||
static_assert ((sizeof (int8_t) == 1), "");
|
||||
static_assert ((sizeof (uint8_t) == 1), "");
|
||||
static_assert ((sizeof (int16_t) == 2), "");
|
||||
|
@ -301,7 +299,6 @@ static_assert ((sizeof (int32_t) == 4), "");
|
|||
static_assert ((sizeof (uint32_t) == 4), "");
|
||||
static_assert ((sizeof (int64_t) == 8), "");
|
||||
static_assert ((sizeof (uint64_t) == 8), "");
|
||||
|
||||
static_assert ((sizeof (hb_codepoint_t) == 4), "");
|
||||
static_assert ((sizeof (hb_position_t) == 4), "");
|
||||
static_assert ((sizeof (hb_mask_t) == 4), "");
|
||||
|
@ -371,82 +368,6 @@ typedef uint64_t hb_vector_size_impl_t;
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Static pools
|
||||
*/
|
||||
|
||||
/* Global nul-content Null pool. Enlarge as necessary. */
|
||||
|
||||
#define HB_NULL_POOL_SIZE 800
|
||||
|
||||
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 <typename Type>
|
||||
static inline Type const & Null (void) {
|
||||
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
return *reinterpret_cast<Type const *> (_hb_NullPool);
|
||||
}
|
||||
#define Null(Type) Null<Type>()
|
||||
|
||||
/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
|
||||
#define DEFINE_NULL_DATA(Namespace, Type, data) \
|
||||
} /* Close namespace. */ \
|
||||
static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \
|
||||
template <> \
|
||||
/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
|
||||
return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \
|
||||
} \
|
||||
namespace Namespace { \
|
||||
/* The following line really exists such that we end in a place needing semicolon */ \
|
||||
static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.")
|
||||
|
||||
|
||||
/* Global writable pool. Enlarge as necessary. */
|
||||
|
||||
/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
|
||||
* for correct operation. It only exist to catch and divert program logic bugs instead of
|
||||
* causing bad memory access. So, races there are not actually introducing incorrectness
|
||||
* in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
|
||||
extern HB_INTERNAL
|
||||
/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
|
||||
|
||||
/* CRAP pool: Common Region for Access Protection. */
|
||||
template <typename Type>
|
||||
static inline Type& Crap (void) {
|
||||
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
|
||||
*obj = Null(Type);
|
||||
return *obj;
|
||||
}
|
||||
#define Crap(Type) Crap<Type>()
|
||||
|
||||
template <typename Type>
|
||||
struct CrapOrNull {
|
||||
static inline Type & get (void) { return Crap(Type); }
|
||||
};
|
||||
template <typename Type>
|
||||
struct CrapOrNull<const Type> {
|
||||
static inline Type const & get (void) { return Null(Type); }
|
||||
};
|
||||
#define CrapOrNull(Type) CrapOrNull<Type>::get ()
|
||||
|
||||
|
||||
/* ASCII tag/character handling */
|
||||
|
||||
static inline bool ISALPHA (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
|
||||
static inline bool ISALNUM (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
|
||||
static inline bool ISSPACE (unsigned char c)
|
||||
{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
|
||||
static inline unsigned char TOUPPER (unsigned char c)
|
||||
{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
|
||||
static inline unsigned char TOLOWER (unsigned char c)
|
||||
{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
|
||||
|
||||
|
||||
/* HB_NDEBUG disables some sanity checks that are very safe to disable and
|
||||
* should be disabled in production systems. If NDEBUG is defined, enable
|
||||
* HB_NDEBUG; but if it's desirable that normal assert()s (which are very
|
||||
|
@ -457,41 +378,7 @@ static inline unsigned char TOLOWER (unsigned char c)
|
|||
#endif
|
||||
|
||||
|
||||
/* Misc */
|
||||
|
||||
template <typename T> class hb_assert_unsigned_t;
|
||||
template <> class hb_assert_unsigned_t<unsigned char> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned short> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned int> {};
|
||||
template <> class hb_assert_unsigned_t<unsigned long> {};
|
||||
|
||||
template <typename T> static inline bool
|
||||
hb_in_range (T u, T lo, T hi)
|
||||
{
|
||||
/* The sizeof() is here to force template instantiation.
|
||||
* I'm sure there are better ways to do this but can't think of
|
||||
* one right now. Declaring a variable won't work as HB_UNUSED
|
||||
* is unusable on some platforms and unused types are less likely
|
||||
* to generate a warning than unused variables. */
|
||||
static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
|
||||
|
||||
/* The casts below are important as if T is smaller than int,
|
||||
* the subtract results will become a signed int! */
|
||||
return (T)(u - lo) <= (T)(hi - lo);
|
||||
}
|
||||
|
||||
template <typename T> static inline bool
|
||||
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
|
||||
{
|
||||
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
|
||||
}
|
||||
|
||||
template <typename T> static inline bool
|
||||
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
|
||||
{
|
||||
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
|
||||
}
|
||||
|
||||
/* Flags */
|
||||
|
||||
/* Enable bitwise ops on enums marked as flags_t */
|
||||
/* To my surprise, looks like the function resolver is happy to silently cast
|
||||
|
@ -515,7 +402,6 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
|
|||
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
|
||||
}
|
||||
|
||||
|
||||
/* Useful for set-operations on small enums.
|
||||
* For example, for testing "x ∈ {x1, x2, x3}" use:
|
||||
* (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
|
||||
|
@ -575,6 +461,7 @@ _hb_memalign(void **memptr, size_t alignment, size_t size)
|
|||
#include "hb-debug.hh"
|
||||
#include "hb-dsalgs.hh"
|
||||
#include "hb-mutex-private.hh"
|
||||
#include "hb-null.hh"
|
||||
#include "hb-object-private.hh"
|
||||
|
||||
#endif /* HB_PRIVATE_HH */
|
||||
|
|
|
@ -51,6 +51,7 @@ struct hb_shape_plan_t
|
|||
|
||||
struct hb_shaper_data_t shaper_data;
|
||||
};
|
||||
DECLARE_NULL_INSTANCE (hb_shape_plan_t);
|
||||
|
||||
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
|
||||
, const hb_feature_t *user_features \
|
||||
|
|
|
@ -88,6 +88,31 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
|
|||
* hb_shape_plan_t
|
||||
*/
|
||||
|
||||
DEFINE_NULL_INSTANCE (hb_shape_plan_t) =
|
||||
{
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* default_shaper_list */
|
||||
nullptr, /* face */
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
|
||||
|
||||
nullptr, /* shaper_func */
|
||||
nullptr, /* shaper_name */
|
||||
|
||||
nullptr, /* user_features */
|
||||
0, /* num_user_featurs */
|
||||
|
||||
nullptr, /* coords */
|
||||
0, /* num_coords */
|
||||
|
||||
{
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
|
||||
#include "hb-shaper-list.hh"
|
||||
#undef HB_SHAPER_IMPLEMENT
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* hb_shape_plan_create: (Xconstructor)
|
||||
* @face:
|
||||
|
@ -188,30 +213,7 @@ hb_shape_plan_create2 (hb_face_t *face,
|
|||
hb_shape_plan_t *
|
||||
hb_shape_plan_get_empty (void)
|
||||
{
|
||||
static const hb_shape_plan_t _hb_shape_plan_nil = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
true, /* default_shaper_list */
|
||||
nullptr, /* face */
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
|
||||
|
||||
nullptr, /* shaper_func */
|
||||
nullptr, /* shaper_name */
|
||||
|
||||
nullptr, /* user_features */
|
||||
0, /* num_user_featurs */
|
||||
|
||||
nullptr, /* coords */
|
||||
0, /* num_coords */
|
||||
|
||||
{
|
||||
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
|
||||
#include "hb-shaper-list.hh"
|
||||
#undef HB_SHAPER_IMPLEMENT
|
||||
}
|
||||
};
|
||||
|
||||
return const_cast<hb_shape_plan_t *> (&_hb_shape_plan_nil);
|
||||
return const_cast<hb_shape_plan_t *> (&Null(hb_shape_plan_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,8 +25,11 @@
|
|||
*/
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-face-private.hh"
|
||||
|
||||
#include "hb-open-type-private.hh"
|
||||
#include "hb-ot-layout-common-private.hh"
|
||||
|
||||
#include "hb-face-private.hh"
|
||||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-maxp-table.hh"
|
||||
|
||||
|
@ -35,6 +38,11 @@
|
|||
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)] = {};
|
||||
/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
|
||||
|
||||
DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF};
|
||||
DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
|
||||
DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
|
||||
|
||||
|
||||
void
|
||||
hb_face_t::load_num_glyphs (void) const
|
||||
{
|
||||
|
|
|
@ -84,7 +84,7 @@ _subset (hb_subset_plan_t *plan)
|
|||
|
||||
hb_tag_t tag = TableType::tableTag;
|
||||
hb_bool_t result = false;
|
||||
if (table != &Null(TableType))
|
||||
if (source_blob->data)
|
||||
{
|
||||
result = table->subset(plan);
|
||||
} else {
|
||||
|
|
|
@ -60,7 +60,8 @@ extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
|
|||
HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
|
||||
/* ^--- Add new simple callbacks here */
|
||||
|
||||
struct hb_unicode_funcs_t {
|
||||
struct hb_unicode_funcs_t
|
||||
{
|
||||
hb_object_header_t header;
|
||||
ASSERT_POD ();
|
||||
|
||||
|
@ -263,9 +264,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
|||
#undef HB_UNICODE_FUNC_IMPLEMENT
|
||||
} destroy;
|
||||
};
|
||||
|
||||
|
||||
extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
|
||||
DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
|
||||
|
||||
|
||||
/* Modified combining marks */
|
||||
|
|
|
@ -185,7 +185,8 @@ hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
|
|||
}
|
||||
|
||||
|
||||
const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
|
||||
DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) =
|
||||
{
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
nullptr, /* parent */
|
||||
|
@ -209,7 +210,7 @@ const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
|
|||
hb_unicode_funcs_t *
|
||||
hb_unicode_funcs_get_empty (void)
|
||||
{
|
||||
return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
|
||||
return const_cast<hb_unicode_funcs_t *> (&Null(hb_unicode_funcs_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright © 2017,2018 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_VECTOR_PRIVATE_HH
|
||||
#define HB_VECTOR_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
|
||||
template <typename Type, unsigned int StaticSize=8>
|
||||
struct hb_vector_t
|
||||
{
|
||||
unsigned int len;
|
||||
unsigned int allocated; /* == 0 means allocation failed. */
|
||||
Type *arrayZ;
|
||||
Type static_array[StaticSize];
|
||||
|
||||
void init (void)
|
||||
{
|
||||
len = 0;
|
||||
allocated = ARRAY_LENGTH (static_array);
|
||||
arrayZ = static_array;
|
||||
}
|
||||
|
||||
inline Type& operator [] (unsigned int i)
|
||||
{
|
||||
if (unlikely (i >= len))
|
||||
return Crap (Type);
|
||||
return arrayZ[i];
|
||||
}
|
||||
inline const Type& operator [] (unsigned int i) const
|
||||
{
|
||||
if (unlikely (i >= len))
|
||||
return Null(Type);
|
||||
return arrayZ[i];
|
||||
}
|
||||
|
||||
inline Type *push (void)
|
||||
{
|
||||
if (unlikely (!resize (len + 1)))
|
||||
return &Crap(Type);
|
||||
return &arrayZ[len - 1];
|
||||
}
|
||||
inline Type *push (const Type& v)
|
||||
{
|
||||
Type *p = push ();
|
||||
*p = v;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Allocate for size but don't adjust len. */
|
||||
inline bool alloc (unsigned int size)
|
||||
{
|
||||
if (unlikely (!allocated))
|
||||
return false;
|
||||
|
||||
if (likely (size <= allocated))
|
||||
return true;
|
||||
|
||||
/* Reallocate */
|
||||
|
||||
unsigned int new_allocated = allocated;
|
||||
while (size >= new_allocated)
|
||||
new_allocated += (new_allocated >> 1) + 8;
|
||||
|
||||
Type *new_array = nullptr;
|
||||
|
||||
if (arrayZ == static_array)
|
||||
{
|
||||
new_array = (Type *) calloc (new_allocated, sizeof (Type));
|
||||
if (new_array)
|
||||
memcpy (new_array, arrayZ, len * sizeof (Type));
|
||||
}
|
||||
else
|
||||
{
|
||||
bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
|
||||
if (likely (!overflows))
|
||||
new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
|
||||
}
|
||||
|
||||
if (unlikely (!new_array))
|
||||
{
|
||||
allocated = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
arrayZ = new_array;
|
||||
allocated = new_allocated;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool resize (int size_)
|
||||
{
|
||||
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
|
||||
if (!alloc (size))
|
||||
return false;
|
||||
|
||||
if (size > len)
|
||||
memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
|
||||
|
||||
len = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void pop (void)
|
||||
{
|
||||
if (!len) return;
|
||||
len--;
|
||||
}
|
||||
|
||||
inline void remove (unsigned int i)
|
||||
{
|
||||
if (unlikely (i >= len))
|
||||
return;
|
||||
memmove (static_cast<void *> (&arrayZ[i]),
|
||||
static_cast<void *> (&arrayZ[i + 1]),
|
||||
(len - i - 1) * sizeof (Type));
|
||||
len--;
|
||||
}
|
||||
|
||||
inline void shrink (int size_)
|
||||
{
|
||||
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
|
||||
if (size < len)
|
||||
len = size;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Type *find (T v) {
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (arrayZ[i] == v)
|
||||
return &arrayZ[i];
|
||||
return nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
inline const Type *find (T v) const {
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (arrayZ[i] == v)
|
||||
return &arrayZ[i];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Type *lsearch (const T &x)
|
||||
{
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (0 == this->arrayZ[i].cmp (&x))
|
||||
return &arrayZ[i];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Type *bsearch (const T &x)
|
||||
{
|
||||
unsigned int i;
|
||||
return bfind (x, &i) ? &arrayZ[i] : nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
inline const Type *bsearch (const T &x) const
|
||||
{
|
||||
unsigned int i;
|
||||
return bfind (x, &i) ? &arrayZ[i] : nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
inline bool bfind (const T &x, unsigned int *i) const
|
||||
{
|
||||
int min = 0, max = (int) this->len - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int c = this->arrayZ[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 && this->arrayZ[max].cmp (&x) > 0))
|
||||
max++;
|
||||
*i = max;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
if (arrayZ != static_array)
|
||||
free (arrayZ);
|
||||
arrayZ = nullptr;
|
||||
allocated = len = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_VECTOR_PRIVATE_HH */
|
|
@ -53,7 +53,7 @@ main (int argc, char **argv)
|
|||
|
||||
hb_blob_t *font_blob = hb_sanitize_context_t().sanitize_blob<OpenTypeFontFile> (blob);
|
||||
const OpenTypeFontFile* sanitized = font_blob->as<OpenTypeFontFile> ();
|
||||
if (sanitized == &Null(OpenTypeFontFile))
|
||||
if (!font_blob->data)
|
||||
{
|
||||
printf ("Sanitization of the file wasn't successful. Exit");
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue