HarfBuzz: Update to version 3.3.1

This commit is contained in:
bruvzg 2022-02-02 16:04:28 +02:00
parent ca42bfb2a5
commit 5676b3c022
No known key found for this signature in database
GPG key ID: 7960FCF39844EC38
79 changed files with 1708 additions and 1121 deletions

View file

@ -62,7 +62,6 @@ if env["builtin_harfbuzz"]:
#'src/hb-gobject-structs.cc',
"src/hb-icu.cc",
"src/hb-map.cc",
"src/hb-ms-feature-ranges.cc",
"src/hb-number.cc",
"src/hb-ot-cff1-table.cc",
"src/hb-ot-cff2-table.cc",

View file

@ -206,7 +206,7 @@ Files extracted from upstream source:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
- Version: 3.2.0 (be91d2917d9860326cb5fd1d03ffe1042a72f6d3, 2021)
- Version: 3.3.1 (45df259538c204540819d74456d30ffb40df488a, 2022)
- License: MIT
Files extracted from upstream source:

View file

@ -839,7 +839,7 @@ struct StateTableDriver
}
if (!c->in_place)
buffer->swap_buffers ();
buffer->sync ();
}
public:

View file

@ -146,7 +146,7 @@ struct DuctileGlyphAction
HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
* This would normally be 0x64756374 ('duct'),
* but you may use any axis the font contains. */
HBFixed minimumLimit; /* The lowest value for the ductility axis tha
HBFixed minimumLimit; /* The lowest value for the ductility axis that
* still yields an acceptable appearance. Normally
* this will be 1.0. */
HBFixed noStretchValue; /* This is the default value that corresponds to

View file

@ -36,6 +36,7 @@
#include <algorithm>
#include <initializer_list>
#include <functional>
#include <new>
/*
@ -210,12 +211,23 @@ struct
}
HB_FUNCOBJ (hb_bool);
template <typename T>
static inline
T hb_coerce (const T v) { return v; }
template <typename T, typename V,
hb_enable_if (!hb_is_same (hb_decay<T>, hb_decay<V>) && std::is_pointer<V>::value)>
static inline
T hb_coerce (const V v) { return *v; }
struct
{
private:
template <typename T> constexpr auto
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
template <typename T> constexpr auto
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
template <typename T,
hb_enable_if (std::is_integral<T>::value)> constexpr auto
@ -435,23 +447,29 @@ struct
private:
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
impl (T1&& v1, T2 &&v2, hb_priority<3>) const HB_AUTO_RETURN
(
std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0
)
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
(
std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0
)
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
(
std::forward<T1> (v1) == std::forward<T2> (v2)
)
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
(
std::forward<T2> (v2) == std::forward<T1> (v1)
)
public:
template <typename T1, typename T2> auto
@ -472,6 +490,10 @@ struct hb_pair_t
typedef T2 second_t;
typedef hb_pair_t<T1, T2> pair_t;
template <typename U1 = T1, typename U2 = T2,
hb_enable_if (std::is_default_constructible<U1>::value &&
std::is_default_constructible<U2>::value)>
hb_pair_t () : first (), second () {}
hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
template <typename Q1, typename Q2,
@ -870,7 +892,7 @@ hb_bsearch_impl (unsigned *pos, /* Out */
#pragma GCC diagnostic ignored "-Wcast-align"
V* p = (V*) (((const char *) base) + (mid * stride));
#pragma GCC diagnostic pop
int c = compar ((const void *) hb_addressof (key), (const void *) p, ds...);
int c = compar ((const void *) std::addressof (key), (const void *) p, ds...);
if (c < 0)
max = mid - 1;
else if (c > 0)

View file

@ -412,7 +412,7 @@ bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
return true;
}
/* TODO Specialize opeator== for hb_bytes_t and hb_ubytes_t. */
/* TODO Specialize operator== for hb_bytes_t and hb_ubytes_t. */
template <>
inline uint32_t hb_array_t<const char>::hash () const {

View file

@ -33,20 +33,6 @@
/* Bi-directional map */
struct hb_bimap_t
{
/* XXX(remove) */
void init ()
{
forw_map.init ();
back_map.init ();
}
/* XXX(remove) */
void fini ()
{
forw_map.fini ();
back_map.fini ();
}
void reset ()
{
forw_map.reset ();

View file

@ -86,7 +86,46 @@ hb_segment_properties_hash (const hb_segment_properties_t *p)
(intptr_t) (p->language);
}
/**
* hb_segment_properties_overlay:
* @p: #hb_segment_properties_t to fill in.
* @src: #hb_segment_properties_t to fill in from.
*
* Fills in missing fields of @p from @src in a considered manner.
*
* First, if @p does not have direction set, direction is copied from @src.
*
* Next, if @p and @src have the same direction (which can be unset), if @p
* does not have script set, script is copied from @src.
*
* Finally, if @p and @src have the same direction and script (which either
* can be unset), if @p does not have language set, language is copied from
* @src.
*
* Since: 3.3.0
**/
void
hb_segment_properties_overlay (hb_segment_properties_t *p,
const hb_segment_properties_t *src)
{
if (unlikely (!p || !src))
return;
if (!p->direction)
p->direction = src->direction;
if (p->direction != src->direction)
return;
if (!p->script)
p->script = src->script;
if (p->script != src->script)
return;
if (!p->language)
p->language = src->language;
}
/* Here is how the buffer works internally:
*
@ -96,14 +135,14 @@ hb_segment_properties_hash (const hb_segment_properties_t *p)
* As an optimization, both info and out_info may point to the
* same piece of memory, which is owned by info. This remains the
* case as long as out_len doesn't exceed i at any time.
* In that case, swap_buffers() is mostly no-op and the glyph operations
* In that case, sync() is mostly no-op and the glyph operations
* operate mostly in-place.
*
* As soon as out_info gets longer than info, out_info is moved over
* to an alternate buffer (which we reuse the pos buffer for), and its
* current contents (out_len entries) are copied to the new place.
*
* This should all remain transparent to the user. swap_buffers() then
* This should all remain transparent to the user. sync() then
* switches info over to out_info and does housekeeping.
*/
@ -216,12 +255,25 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size)
/* HarfBuzz-Internal API */
void
hb_buffer_t::similar (const hb_buffer_t &src)
{
hb_unicode_funcs_destroy (unicode);
unicode = hb_unicode_funcs_reference (src.unicode);
flags = src.flags;
cluster_level = src.cluster_level;
replacement = src.invisible;
invisible = src.invisible;
not_found = src.not_found;
}
void
hb_buffer_t::reset ()
{
hb_unicode_funcs_destroy (unicode);
unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
flags = HB_BUFFER_FLAG_DEFAULT;
cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
invisible = 0;
not_found = 0;
@ -232,11 +284,10 @@ hb_buffer_t::reset ()
void
hb_buffer_t::clear ()
{
content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
props = default_props;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
successful = true;
have_output = false;
have_positions = false;
@ -244,16 +295,44 @@ hb_buffer_t::clear ()
idx = 0;
len = 0;
out_len = 0;
out_info = info;
serial = 0;
out_info = info;
memset (context, 0, sizeof context);
memset (context_len, 0, sizeof context_len);
deallocate_var_all ();
serial = 0;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
}
void
hb_buffer_t::enter ()
{
deallocate_var_all ();
serial = 0;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
{
max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR,
(unsigned) HB_BUFFER_MAX_LEN_MIN);
}
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR)))
{
max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR,
(unsigned) HB_BUFFER_MAX_OPS_MIN);
}
}
void
hb_buffer_t::leave ()
{
max_len = HB_BUFFER_MAX_LEN_DEFAULT;
max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
deallocate_var_all ();
serial = 0;
}
void
hb_buffer_t::add (hb_codepoint_t codepoint,
unsigned int cluster)
@ -307,7 +386,7 @@ hb_buffer_t::clear_positions ()
}
void
hb_buffer_t::swap_buffers ()
hb_buffer_t::sync ()
{
assert (have_output);
@ -493,33 +572,6 @@ done:
skip_glyph ();
}
void
hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
{
unsigned int cluster = UINT_MAX;
cluster = _infos_find_min_cluster (info, start, end, cluster);
_unsafe_to_break_set_mask (info, start, end, cluster);
}
void
hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end)
{
if (!have_output)
{
unsafe_to_break_impl (start, end);
return;
}
assert (start <= out_len);
assert (idx <= end);
unsigned int cluster = UINT_MAX;
cluster = _infos_find_min_cluster (out_info, start, out_len, cluster);
cluster = _infos_find_min_cluster (info, idx, end, cluster);
_unsafe_to_break_set_mask (out_info, start, out_len, cluster);
_unsafe_to_break_set_mask (info, idx, end, cluster);
}
void
hb_buffer_t::guess_segment_properties ()
{
@ -565,12 +617,11 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
0, /* invisible */
0, /* not_found */
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 */
false, /* have_output */
true /* have_positions */
@ -609,6 +660,46 @@ hb_buffer_create ()
return buffer;
}
/**
* hb_buffer_create_similar:
* @src: An #hb_buffer_t
*
* Creates a new #hb_buffer_t, similar to hb_buffer_create(). The only
* difference is that the buffer is configured similarly to @src.
*
* Return value: (transfer full):
* A newly allocated #hb_buffer_t, similar to hb_buffer_create().
*
* Since: 3.3.0
**/
hb_buffer_t *
hb_buffer_create_similar (const hb_buffer_t *src)
{
hb_buffer_t *buffer = hb_buffer_create ();
buffer->similar (*src);
return buffer;
}
/**
* hb_buffer_reset:
* @buffer: An #hb_buffer_t
*
* Resets the buffer to its initial status, as if it was just newly created
* with hb_buffer_create().
*
* Since: 0.9.2
**/
void
hb_buffer_reset (hb_buffer_t *buffer)
{
if (unlikely (hb_object_is_immutable (buffer)))
return;
buffer->reset ();
}
/**
* hb_buffer_get_empty:
*
@ -1156,24 +1247,6 @@ hb_buffer_get_not_found_glyph (hb_buffer_t *buffer)
}
/**
* hb_buffer_reset:
* @buffer: An #hb_buffer_t
*
* Resets the buffer to its initial status, as if it was just newly created
* with hb_buffer_create().
*
* Since: 0.9.2
**/
void
hb_buffer_reset (hb_buffer_t *buffer)
{
if (unlikely (hb_object_is_immutable (buffer)))
return;
buffer->reset ();
}
/**
* hb_buffer_clear_contents:
* @buffer: An #hb_buffer_t
@ -1749,6 +1822,8 @@ hb_buffer_append (hb_buffer_t *buffer,
if (!buffer->have_positions && source->have_positions)
buffer->clear_positions ();
hb_segment_properties_overlay (&buffer->props, &source->props);
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
if (buffer->have_positions)
memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));

View file

@ -76,18 +76,68 @@ typedef struct hb_glyph_info_t {
* @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the
* beginning of the cluster this glyph is part of,
* then both sides need to be re-shaped, as the
* result might be different. On the flip side,
* it means that when this flag is not present,
* then it's safe to break the glyph-run at the
* beginning of this cluster, and the two sides
* represent the exact same result one would get
* if breaking input text at the beginning of
* this cluster and shaping the two sides
* separately. This can be used to optimize
* paragraph layout, by avoiding re-shaping
* of each line after line-breaking, or limiting
* the reshaping to a small piece around the
* breaking point only.
* result might be different.
* On the flip side, it means that when this
* flag is not present, then it is safe to break
* the glyph-run at the beginning of this
* cluster, and the two sides will represent the
* exact same result one would get if breaking
* input text at the beginning of this cluster
* and shaping the two sides separately.
* This can be used to optimize paragraph
* layout, by avoiding re-shaping of each line
* after line-breaking.
* @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT: Indicates that if input text is changed on one
* side of the beginning of the cluster this glyph
* is part of, then the shaping results for the
* other side might change.
* Note that the absence of this flag will NOT by
* itself mean that it IS safe to concat text.
* Only two pieces of text both of which clear of
* this flag can be concatenated safely.
* This can be used to optimize paragraph
* layout, by avoiding re-shaping of each line
* after line-breaking, by limiting the
* reshaping to a small piece around the
* breaking positin only, even if the breaking
* position carries the
* #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when
* hyphenation or other text transformation
* happens at line-break position, in the following
* way:
* 1. Iterate back from the line-break position
* until the first cluster start position that is
* NOT unsafe-to-concat, 2. shape the segment from
* there till the end of line, 3. check whether the
* resulting glyph-run also is clear of the
* unsafe-to-concat at its start-of-text position;
* if it is, just splice it into place and the line
* is shaped; If not, move on to a position further
* back that is clear of unsafe-to-concat and retry
* from there, and repeat.
* At the start of next line a similar algorithm can
* be implemented. That is: 1. Iterate forward from
* the line-break position untill the first cluster
* start position that is NOT unsafe-to-concat, 2.
* shape the segment from beginning of the line to
* that position, 3. check whether the resulting
* glyph-run also is clear of the unsafe-to-concat
* at its end-of-text position; if it is, just splice
* it into place and the beginning is shaped; If not,
* move on to a position further forward that is clear
* of unsafe-to-concat and retry up to there, and repeat.
* A slight complication will arise in the
* implementation of the algorithm above,
* because while our buffer API has a way to
* return flags for position corresponding to
* start-of-text, there is currently no position
* corresponding to end-of-text. This limitation
* can be alleviated by shaping more text than needed
* and looking for unsafe-to-concat flag within text
* clusters.
* The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will
* always imply this flag.
* Since: 3.3.0
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
* Flags for #hb_glyph_info_t.
@ -96,8 +146,9 @@ typedef struct hb_glyph_info_t {
*/
typedef enum { /*< flags >*/
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */
HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */
} hb_glyph_flags_t;
HB_EXTERN hb_glyph_flags_t
@ -170,6 +221,9 @@ hb_segment_properties_equal (const hb_segment_properties_t *a,
HB_EXTERN unsigned int
hb_segment_properties_hash (const hb_segment_properties_t *p);
HB_EXTERN void
hb_segment_properties_overlay (hb_segment_properties_t *p,
const hb_segment_properties_t *src);
/**
@ -184,6 +238,13 @@ typedef struct hb_buffer_t hb_buffer_t;
HB_EXTERN hb_buffer_t *
hb_buffer_create (void);
HB_EXTERN hb_buffer_t *
hb_buffer_create_similar (const hb_buffer_t *src);
HB_EXTERN void
hb_buffer_reset (hb_buffer_t *buffer);
HB_EXTERN hb_buffer_t *
hb_buffer_get_empty (void);
@ -391,8 +452,9 @@ HB_EXTERN hb_codepoint_t
hb_buffer_get_not_found_glyph (hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_reset (hb_buffer_t *buffer);
/*
* Content API.
*/
HB_EXTERN void
hb_buffer_clear_contents (hb_buffer_t *buffer);

View file

@ -67,8 +67,8 @@ enum hb_buffer_scratch_flags_t {
HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u,
HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u,
HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u,
HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u,
/* Reserved for complex shapers' internal use. */
HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
@ -87,18 +87,21 @@ struct hb_buffer_t
{
hb_object_header_t header;
/* Information about how the text in the buffer should be treated */
/*
* Information about how the text in the buffer should be treated.
*/
hb_unicode_funcs_t *unicode; /* Unicode functions */
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
hb_buffer_cluster_level_t cluster_level;
hb_codepoint_t replacement; /* U+FFFD or something else. */
hb_codepoint_t invisible; /* 0 or something else. */
hb_codepoint_t not_found; /* 0 or something else. */
hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
unsigned int max_len; /* Maximum allowed len. */
int max_ops; /* Maximum allowed operations. */
/* Buffer contents */
/*
* Buffer contents
*/
hb_buffer_content_type_t content_type;
hb_segment_properties_t props; /* Script, language, direction */
@ -115,8 +118,6 @@ struct hb_buffer_t
hb_glyph_info_t *out_info;
hb_glyph_position_t *pos;
unsigned int serial;
/* Text before / after the main buffer contents.
* Always in Unicode, and ordered outward.
* Index 0 is for "pre-context", 1 for "post-context". */
@ -124,7 +125,25 @@ struct hb_buffer_t
hb_codepoint_t context[2][CONTEXT_LENGTH];
unsigned int context_len[2];
/* Debugging API */
/*
* Managed by enter / leave
*/
#ifndef HB_NDEBUG
uint8_t allocated_var_bits;
#endif
uint8_t serial;
hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
unsigned int max_len; /* Maximum allowed len. */
int max_ops; /* Maximum allowed operations. */
/* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
/*
* Messaging callback
*/
#ifndef HB_NO_BUFFER_MESSAGE
hb_buffer_message_func_t message_func;
void *message_data;
@ -134,11 +153,6 @@ struct hb_buffer_t
static constexpr unsigned message_depth = 0u;
#endif
/* Internal debugging. */
/* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
#ifndef HB_NDEBUG
uint8_t allocated_var_bits;
#endif
/* Methods */
@ -190,12 +204,17 @@ struct hb_buffer_t
hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; }
hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
HB_INTERNAL void similar (const hb_buffer_t &src);
HB_INTERNAL void reset ();
HB_INTERNAL void clear ();
/* Called around shape() */
HB_INTERNAL void enter ();
HB_INTERNAL void leave ();
unsigned int backtrack_len () const { return have_output ? out_len : idx; }
unsigned int lookahead_len () const { return len - idx; }
unsigned int next_serial () { return serial++; }
uint8_t next_serial () { return ++serial ? serial : ++serial; }
HB_INTERNAL void add (hb_codepoint_t codepoint,
unsigned int cluster);
@ -252,7 +271,7 @@ struct hb_buffer_t
HB_INTERNAL void guess_segment_properties ();
HB_INTERNAL void swap_buffers ();
HB_INTERNAL void sync ();
HB_INTERNAL void clear_output ();
HB_INTERNAL void clear_positions ();
@ -366,15 +385,80 @@ struct hb_buffer_t
/* Merge clusters for deleting current glyph, and skip it. */
HB_INTERNAL void delete_glyph ();
void unsafe_to_break (unsigned int start,
unsigned int end)
void set_glyph_flags (hb_mask_t mask,
unsigned start = 0,
unsigned end = (unsigned) -1,
bool interior = false,
bool from_out_buffer = false)
{
if (end - start < 2)
end = hb_min (end, len);
if (interior && !from_out_buffer && end - start < 2)
return;
unsafe_to_break_impl (start, end);
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
if (!from_out_buffer || !have_output)
{
if (!interior)
{
for (unsigned i = start; i < end; i++)
info[i].mask |= mask;
}
else
{
unsigned cluster = _infos_find_min_cluster (info, start, end);
_infos_set_glyph_flags (info, start, end, cluster, mask);
}
}
else
{
assert (start <= out_len);
assert (idx <= end);
if (!interior)
{
for (unsigned i = start; i < out_len; i++)
out_info[i].mask |= mask;
for (unsigned i = idx; i < end; i++)
info[i].mask |= mask;
}
else
{
unsigned cluster = _infos_find_min_cluster (info, idx, end);
cluster = _infos_find_min_cluster (out_info, start, out_len, cluster);
_infos_set_glyph_flags (out_info, start, out_len, cluster, mask);
_infos_set_glyph_flags (info, idx, end, cluster, mask);
}
}
}
void unsafe_to_break (unsigned int start = 0, unsigned int end = -1)
{
set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
true);
}
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
{
set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
true);
}
void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
{
set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
true, true);
}
void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
{
set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
false, true);
}
HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
/* Internal methods */
@ -465,36 +549,31 @@ struct hb_buffer_t
set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
{
if (inf.cluster != cluster)
{
if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
else
inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
}
inf.mask = (inf.mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED);
inf.cluster = cluster;
}
static unsigned
_infos_find_min_cluster (const hb_glyph_info_t *infos,
unsigned start, unsigned end,
unsigned cluster)
{
for (unsigned int i = start; i < end; i++)
cluster = hb_min (cluster, infos[i].cluster);
return cluster;
}
void
_unsafe_to_break_set_mask (hb_glyph_info_t *infos,
unsigned int start, unsigned int end,
unsigned int cluster)
_infos_set_glyph_flags (hb_glyph_info_t *infos,
unsigned int start, unsigned int end,
unsigned int cluster,
hb_mask_t mask)
{
for (unsigned int i = start; i < end; i++)
if (cluster != infos[i].cluster)
{
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
infos[i].mask |= mask;
}
}
static unsigned
_infos_find_min_cluster (const hb_glyph_info_t *infos,
unsigned start, unsigned end,
unsigned cluster = UINT_MAX)
{
for (unsigned int i = start; i < end; i++)
cluster = hb_min (cluster, infos[i].cluster);
return cluster;
}
void clear_glyph_flags (hb_mask_t mask = 0)
{

View file

@ -217,9 +217,6 @@ inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2:
struct number_t
{
void init () { set_real (0.0); }
void fini () {}
void set_int (int v) { value = v; }
int to_int () const { return value; }
@ -245,7 +242,7 @@ struct number_t
}
protected:
double value;
double value = 0.;
};
/* byte string */
@ -380,10 +377,8 @@ struct cff_stack_t
count = 0;
elements.init ();
elements.resize (kSizeLimit);
for (unsigned int i = 0; i < elements.length; i++)
elements[i].init ();
}
void fini () { elements.fini_deep (); }
void fini () { elements.fini (); }
ELEM& operator [] (unsigned int i)
{
@ -523,9 +518,6 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
/* an operator prefixed by its operands in a byte string */
struct op_str_t
{
void init () {}
void fini () {}
op_code_t op;
byte_str_t str;
};
@ -553,7 +545,7 @@ struct parsed_values_t
opStart = 0;
values.init ();
}
void fini () { values.fini_deep (); }
void fini () { values.fini (); }
void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
{

View file

@ -94,12 +94,6 @@ struct biased_subrs_t
struct point_t
{
void init ()
{
x.init ();
y.init ();
}
void set_int (int _x, int _y)
{
x.set_int (_x);
@ -128,7 +122,7 @@ struct cs_interp_env_t : interp_env_t<ARG>
hstem_count = 0;
vstem_count = 0;
hintmask_size = 0;
pt.init ();
pt.set_int (0, 0);
callStack.init ();
globalSubrs.init (globalSubrs_);
localSubrs.init (localSubrs_);
@ -841,7 +835,6 @@ struct path_procs_t
if (likely (env.argStack.get_count () == 11))
{
point_t d;
d.init ();
for (unsigned int i = 0; i < 10; i += 2)
d.move (env.eval_arg (i), env.eval_arg (i+1));

View file

@ -35,18 +35,6 @@ using namespace OT;
struct blend_arg_t : number_t
{
void init ()
{
number_t::init ();
deltas.init ();
}
void fini ()
{
number_t::fini ();
deltas.fini_deep ();
}
void set_int (int v) { reset_blends (); number_t::set_int (v); }
void set_fixed (int32_t v) { reset_blends (); number_t::set_fixed (v); }
void set_real (double v) { reset_blends (); number_t::set_real (v); }
@ -202,7 +190,7 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
switch (op) {
case OpCode_callsubr:
case OpCode_callgsubr:
/* a subroutine number shoudln't be a blended value */
/* a subroutine number shouldn't be a blended value */
if (unlikely (env.argStack.peek ().blending ()))
{
env.set_error ();

View file

@ -29,10 +29,31 @@
#include "hb.hh"
#include "hb-machinery.hh"
#include <locale.h>
#if !defined(HB_NO_SETLOCALE) && (!defined(HAVE_NEWLOCALE) || !defined(HAVE_USELOCALE))
#define HB_NO_SETLOCALE 1
#endif
#ifndef HB_NO_SETLOCALE
#include <locale.h>
#ifdef HAVE_XLOCALE_H
#include <xlocale.h> // Needed on BSD/OS X for uselocale
#endif
#ifdef WIN32
#define hb_locale_t _locale_t
#else
#define hb_locale_t locale_t
#endif
#define hb_setlocale setlocale
#define hb_uselocale uselocale
#else
#define hb_locale_t void *
#define hb_setlocale(Category, Locale) "C"
#define hb_uselocale(Locale) ((hb_locale_t) 0)
#ifdef HB_NO_SETLOCALE
#define setlocale(Category, Locale) "C"
#endif
/**
@ -122,7 +143,7 @@ hb_tag_from_string (const char *str, int len)
* @tag: #hb_tag_t to convert
* @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t): Converted string
*
* Converts an #hb_tag_t to a string and returns it in @buf.
* Converts an #hb_tag_t to a string and returns it in @buf.
* Strings will be four characters long.
*
* Since: 0.9.5
@ -151,13 +172,13 @@ const char direction_strings[][4] = {
* @str: (array length=len) (element-type uint8_t): String to convert
* @len: Length of @str, or -1 if it is %NULL-terminated
*
* Converts a string to an #hb_direction_t.
* Converts a string to an #hb_direction_t.
*
* Matching is loose and applies only to the first letter. For
* examples, "LTR" and "left-to-right" will both return #HB_DIRECTION_LTR.
*
* Unmatched strings will return #HB_DIRECTION_INVALID.
*
*
* Return value: The #hb_direction_t matching @str
*
* Since: 0.9.2
@ -413,7 +434,7 @@ hb_language_get_default ()
hb_language_t language = default_language;
if (unlikely (language == HB_LANGUAGE_INVALID))
{
language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1);
language = hb_language_from_string (hb_setlocale (LC_CTYPE, nullptr), -1);
(void) default_language.cmpexch (HB_LANGUAGE_INVALID, language);
}
@ -1039,6 +1060,47 @@ hb_variation_from_string (const char *str, int len,
return false;
}
#ifndef HB_NO_SETLOCALE
static inline void free_static_C_locale ();
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<hb_locale_t>,
hb_C_locale_lazy_loader_t>
{
static hb_locale_t create ()
{
hb_locale_t l = newlocale (LC_ALL_MASK, "C", NULL);
if (!l)
return l;
hb_atexit (free_static_C_locale);
return l;
}
static void destroy (hb_locale_t l)
{
freelocale (l);
}
static hb_locale_t get_null ()
{
return (hb_locale_t) 0;
}
} static_C_locale;
static inline
void free_static_C_locale ()
{
static_C_locale.free_instance ();
}
static hb_locale_t
get_C_locale ()
{
return static_C_locale.get_unconst ();
}
#endif
/**
* hb_variation_to_string:
* @variation: an #hb_variation_t to convert
@ -1064,7 +1126,11 @@ hb_variation_to_string (hb_variation_t *variation,
while (len && s[len - 1] == ' ')
len--;
s[len++] = '=';
hb_locale_t oldlocale HB_UNUSED;
oldlocale = hb_uselocale (get_C_locale ());
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
(void) hb_uselocale (oldlocale);
assert (len < ARRAY_LENGTH (s));
len = hb_min (len, size - 1);

View file

@ -481,8 +481,8 @@ struct active_feature_t {
a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 :
0;
}
bool operator== (const active_feature_t *f) {
return cmp (this, f) == 0;
bool operator== (const active_feature_t& f) const {
return cmp (this, &f) == 0;
}
};
@ -677,7 +677,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
{
active_features.push (event->feature);
} else {
active_feature_t *feature = active_features.find (&event->feature);
active_feature_t *feature = active_features.lsearch (event->feature);
if (feature)
active_features.remove (feature - active_features.arrayZ);
}
@ -1213,7 +1213,8 @@ resize_and_retry:
}
}
buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK);
buffer->clear_glyph_flags ();
buffer->unsafe_to_break ();
#undef FAIL

View file

@ -762,7 +762,8 @@ retry_getglyphs:
if (isRightToLeft) hb_buffer_reverse (buffer);
buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK);
buffer->clear_glyph_flags ();
buffer->unsafe_to_break ();
delete [] clusterMap;
delete [] glyphIndices;

View file

@ -50,7 +50,7 @@ typedef void (*hb_draw_close_path_func_t) (void *user_data);
*
* Glyph draw callbacks.
*
* _move_to, _line_to and _cubic_to calls are nessecary to be defined but we
* _move_to, _line_to and _cubic_to calls are necessary to be defined but we
* translate _quadratic_to calls to _cubic_to if the callback isn't defined.
*
* Since: EXPERIMENTAL

View file

@ -143,7 +143,7 @@ hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
typedef struct hb_face_for_data_closure_t {
hb_blob_t *blob;
unsigned int index;
uint16_t index;
} hb_face_for_data_closure_t;
static hb_face_for_data_closure_t *
@ -156,7 +156,7 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
return nullptr;
closure->blob = blob;
closure->index = index;
closure->index = (uint16_t) (index & 0xFFFFu);
return closure;
}
@ -195,9 +195,19 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
* @index: The index of the face within @blob
*
* Constructs a new face object from the specified blob and
* a face index into that blob. This is used for blobs of
* file formats such as Dfont and TTC that can contain more
* than one face.
* a face index into that blob.
*
* The face index is used for blobs of file formats such as TTC and
* and DFont that can contain more than one face. Face indices within
* such collections are zero-based.
*
* <note>Note: If the blob font format is not a collection, @index
* is ignored. Otherwise, only the lower 16-bits of @index are used.
* The unmodified @index can be accessed via hb_face_get_index().</note>
*
* <note>Note: The high 16-bits of @index, if non-zero, are used by
* hb_font_create() to load named-instances in variable fonts. See
* hb_font_create() for details.</note>
*
* Return value: (transfer full): The new face object
*
@ -420,7 +430,8 @@ hb_face_reference_blob (hb_face_t *face)
* Assigns the specified face-index to @face. Fails if the
* face is immutable.
*
* <note>Note: face indices within a collection are zero-based.</note>
* <note>Note: changing the index has no effect on the face itself
* This only changes the value returned by hb_face_get_index().</note>
*
* Since: 0.9.2
**/

View file

@ -631,7 +631,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
* @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified font-functions structure.
* Attaches a user-data key/data pair to the specified font-functions structure.
*
* Return value: %true if success, %false otherwise
*
@ -821,7 +821,7 @@ hb_font_get_glyph (hb_font_t *font,
* @glyph: (out): The glyph ID retrieved
*
* Fetches the nominal glyph ID for a Unicode code point in the
* specified font.
* specified font.
*
* This version of the function should not be used to fetch glyph IDs
* for code points modified by variation selectors. For variation-selector
@ -940,7 +940,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
* @advance_stride: The stride between successive advances
*
* Fetches the advances for a sequence of glyph IDs in the specified
* font, for horizontal text segments.
* font, for horizontal text segments.
*
* Since: 1.8.6
**/
@ -964,7 +964,7 @@ hb_font_get_glyph_h_advances (hb_font_t* font,
* @advance_stride: (out): The stride between successive advances
*
* Fetches the advances for a sequence of glyph IDs in the specified
* font, for vertical text segments.
* font, for vertical text segments.
*
* Since: 1.8.6
**/
@ -1278,7 +1278,7 @@ hb_font_get_glyph_origin_for_direction (hb_font_t *font,
* @font: #hb_font_t to work upon
* @glyph: The glyph ID to query
* @direction: The direction of the text segment
* @x: (inout): Input = The original X coordinate
* @x: (inout): Input = The original X coordinate
* Output = The X coordinate plus the X-coordinate of the origin
* @y: (inout): Input = The original Y coordinate
* Output = The Y coordinate plus the Y-coordinate of the origin
@ -1306,7 +1306,7 @@ hb_font_add_glyph_origin_for_direction (hb_font_t *font,
* @font: #hb_font_t to work upon
* @glyph: The glyph ID to query
* @direction: The direction of the text segment
* @x: (inout): Input = The original X coordinate
* @x: (inout): Input = The original X coordinate
* Output = The X coordinate minus the X-coordinate of the origin
* @y: (inout): Input = The original Y coordinate
* Output = The Y coordinate minus the Y-coordinate of the origin
@ -1477,6 +1477,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
1000, /* x_scale */
1000, /* y_scale */
0., /* slant */
0., /* slant_xy; */
1<<16, /* x_mult */
1<<16, /* y_mult */
@ -1521,6 +1523,13 @@ _hb_font_create (hb_face_t *face)
*
* Constructs a new font object from the specified face.
*
* <note>Note: If @face's index value (as passed to hb_face_create()
* has non-zero top 16-bits, those bits minus one are passed to
* hb_font_set_var_named_instance(), effectively loading a named-instance
* of a variable font, instead of the default-instance. This allows
* specifying which named-instance to load by default when creating the
* face.</note>
*
* Return value: (transfer full): The new font object
*
* Since: 0.9.2
@ -1535,6 +1544,11 @@ hb_font_create (hb_face_t *face)
hb_ot_font_set_funcs (font);
#endif
#ifndef HB_NO_VAR
if (face && face->index >> 16)
hb_font_set_var_named_instance (font, (face->index >> 16) - 1);
#endif
return font;
}
@ -1578,6 +1592,7 @@ hb_font_create_sub_font (hb_font_t *parent)
font->x_scale = parent->x_scale;
font->y_scale = parent->y_scale;
font->slant = parent->slant;
font->mults_changed ();
font->x_ppem = parent->x_ppem;
font->y_ppem = parent->y_ppem;
@ -1668,12 +1683,12 @@ hb_font_destroy (hb_font_t *font)
/**
* hb_font_set_user_data: (skip)
* @font: #hb_font_t to work upon
* @key: The user-data key
* @key: The user-data key
* @data: A pointer to the user data
* @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the specified font object.
* Attaches a user-data key/data pair to the specified font object.
*
* Return value: %true if success, %false otherwise
*
@ -1875,7 +1890,7 @@ hb_font_set_funcs (hb_font_t *font,
* @font_data: (destroy destroy) (scope notified): Data to attach to @font
* @destroy: (nullable): The function to call when @font_data is not needed anymore
*
* Replaces the user data attached to a font, updating the font's
* Replaces the user data attached to a font, updating the font's
* @destroy callback.
*
* Since: 0.9.2
@ -1949,7 +1964,7 @@ hb_font_get_scale (hb_font_t *font,
* @x_ppem: Horizontal ppem value to assign
* @y_ppem: Vertical ppem value to assign
*
* Sets the horizontal and vertical pixels-per-em (ppem) of a font.
* Sets the horizontal and vertical pixels-per-em (ppem) of a font.
*
* Since: 0.9.2
**/
@ -1971,7 +1986,7 @@ hb_font_set_ppem (hb_font_t *font,
* @x_ppem: (out): Horizontal ppem value
* @y_ppem: (out): Vertical ppem value
*
* Fetches the horizontal and vertical points-per-em (ppem) of a font.
* Fetches the horizontal and vertical points-per-em (ppem) of a font.
*
* Since: 0.9.2
**/
@ -2015,7 +2030,7 @@ hb_font_set_ptem (hb_font_t *font,
*
* Return value: Point size. A value of zero means "not set."
*
* Since: 0.9.2
* Since: 1.6.0
**/
float
hb_font_get_ptem (hb_font_t *font)
@ -2023,6 +2038,49 @@ hb_font_get_ptem (hb_font_t *font)
return font->ptem;
}
/**
* hb_font_set_synthetic_slant:
* @font: #hb_font_t to work upon
* @slant: synthetic slant value.
*
* Sets the "synthetic slant" of a font. By default is zero.
* Synthetic slant is the graphical skew that the renderer
* applies to the font at rendering time.
*
* HarfBuzz needs to know this value to adjust shaping results,
* metrics, and style values to match the slanted rendering.
*
* <note>Note: The slant value is a ratio. For example, a
* 20% slant would be represented as a 0.2 value.</note>
*
* Since: 3.3.0
**/
HB_EXTERN void
hb_font_set_synthetic_slant (hb_font_t *font, float slant)
{
if (hb_object_is_immutable (font))
return;
font->slant = slant;
font->mults_changed ();
}
/**
* hb_font_get_synthetic_slant:
* @font: #hb_font_t to work upon
*
* Fetches the "synthetic slant" of a font.
*
* Return value: Synthetic slant. By default is zero.
*
* Since: 3.3.0
**/
HB_EXTERN float
hb_font_get_synthetic_slant (hb_font_t *font)
{
return font->slant;
}
#ifndef HB_NO_VAR
/*
* Variations
@ -2036,6 +2094,10 @@ hb_font_get_ptem (hb_font_t *font)
*
* Applies a list of font-variation settings to a font.
*
* Note that this overrides all existing variations set on @font.
* Axes not included in @variations will be effectively set to their
* default values.
*
* Since: 1.4.2
*/
void
@ -2091,6 +2153,10 @@ hb_font_set_variations (hb_font_t *font,
* Applies a list of variation coordinates (in design-space units)
* to a font.
*
* Note that this overrides all existing variations set on @font.
* Axes not included in @coords will be effectively set to their
* default values.
*
* Since: 1.4.2
*/
void
@ -2154,6 +2220,10 @@ hb_font_set_var_named_instance (hb_font_t *font,
* Applies a list of variation coordinates (in normalized units)
* to a font.
*
* Note that this overrides all existing variations set on @font.
* Axes not included in @coords will be effectively set to their
* default values.
*
* <note>Note: Coordinates should be normalized to 2.14.</note>
*
* Since: 1.4.2
@ -2196,14 +2266,19 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
/**
* hb_font_get_var_coords_normalized:
* @font: #hb_font_t to work upon
* @length: Number of coordinates retrieved
* @length: (out): Number of coordinates retrieved
*
* Fetches the list of normalized variation coordinates currently
* set on a font.
*
* Note that this returned array may only contain values for some
* (or none) of the axes; omitted axes effectively have zero values.
*
* Return value is valid as long as variation coordinates of the font
* are not modified.
*
* Return value: coordinates array
*
* Since: 1.4.2
*/
const int *
@ -2216,18 +2291,24 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
return font->coords;
}
#ifdef HB_EXPERIMENTAL_API
/**
* hb_font_get_var_coords_design:
* @font: #hb_font_t to work upon
* @length: (out): number of coordinates
* @length: (out): Number of coordinates retrieved
*
* Fetches the list of variation coordinates (in design-space units) currently
* set on a font.
*
* Note that this returned array may only contain values for some
* (or none) of the axes; omitted axes effectively have their default
* values.
*
* Return value is valid as long as variation coordinates of the font
* are not modified.
*
* Return value: coordinates array
*
* Since: EXPERIMENTAL
* Since: 3.3.0
*/
const float *
hb_font_get_var_coords_design (hb_font_t *font,
@ -2239,7 +2320,6 @@ hb_font_get_var_coords_design (hb_font_t *font,
return font->design_coords;
}
#endif
#endif
#ifndef HB_DISABLE_DEPRECATED
/*

View file

@ -1023,6 +1023,12 @@ hb_font_set_ptem (hb_font_t *font, float ptem);
HB_EXTERN float
hb_font_get_ptem (hb_font_t *font);
HB_EXTERN void
hb_font_set_synthetic_slant (hb_font_t *font, float slant);
HB_EXTERN float
hb_font_get_synthetic_slant (hb_font_t *font);
HB_EXTERN void
hb_font_set_variations (hb_font_t *font,
const hb_variation_t *variations,
@ -1033,11 +1039,9 @@ hb_font_set_var_coords_design (hb_font_t *font,
const float *coords,
unsigned int coords_length);
#ifdef HB_EXPERIMENTAL_API
HB_EXTERN const float *
hb_font_get_var_coords_design (hb_font_t *font,
unsigned int *length);
#endif
HB_EXTERN void
hb_font_set_var_coords_normalized (hb_font_t *font,

View file

@ -109,6 +109,8 @@ struct hb_font_t
int32_t x_scale;
int32_t y_scale;
float slant;
float slant_xy;
int64_t x_mult;
int64_t y_mult;
@ -617,6 +619,7 @@ struct hb_font_t
signed upem = face->get_upem ();
x_mult = ((int64_t) x_scale << 16) / upem;
y_mult = ((int64_t) y_scale << 16) / upem;
slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
}
hb_position_t em_mult (int16_t v, int64_t mult)

View file

@ -439,7 +439,8 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
if (feats) gr_featureval_destroy (feats);
gr_seg_destroy (seg);
buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK);
buffer->clear_glyph_flags ();
buffer->unsafe_to_break ();
return true;
}

View file

@ -90,8 +90,8 @@ struct hb_iter_t
* it will be returning pointer to temporary rvalue.
* TODO Use a wrapper return type to fix for non-reference type. */
template <typename T = item_t,
hb_enable_if (hb_is_reference (T))>
hb_remove_reference<item_t>* operator -> () const { return hb_addressof (**thiz()); }
hb_enable_if (std::is_reference<T>::value)>
hb_remove_reference<item_t>* operator -> () const { return std::addressof (**thiz()); }
item_t operator * () const { return thiz()->__item__ (); }
item_t operator * () { return thiz()->__item__ (); }
item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); }
@ -289,7 +289,7 @@ struct hb_is_source_of
{
private:
template <typename Iter2 = Iter,
hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<hb_add_const<Item>>))>
hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<const Item>))>
static hb_true_type impl (hb_priority<2>);
template <typename Iter2 = Iter>
static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ());

View file

@ -49,6 +49,10 @@ struct hb_kern_machine_t
hb_mask_t kern_mask,
bool scale = true) const
{
if (!buffer->message (font, "start kern"))
return;
buffer->unsafe_to_concat ();
OT::hb_ot_apply_context_t c (1, font, buffer);
c.set_lookup_mask (kern_mask);
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
@ -67,7 +71,8 @@ struct hb_kern_machine_t
}
skippy_iter.reset (idx, 1);
if (!skippy_iter.next ())
unsigned unsafe_to;
if (!skippy_iter.next (&unsafe_to))
{
idx++;
continue;
@ -125,6 +130,8 @@ struct hb_kern_machine_t
skip:
idx = skippy_iter.idx;
}
(void) buffer->message (font, "end kern");
}
const Driver &driver;

View file

@ -244,19 +244,19 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
{
Stored *p = (Stored *) hb_calloc (1, sizeof (Stored));
if (likely (p))
p->init (data);
p = new (p) Stored (data);
return p;
}
static Stored *create ()
{
Stored *p = (Stored *) hb_calloc (1, sizeof (Stored));
if (likely (p))
p->init ();
p = new (p) Stored ();
return p;
}
static void destroy (Stored *p)
{
p->fini ();
p->~Stored ();
hb_free (p);
}

View file

@ -37,13 +37,10 @@
template <typename K, typename V,
typename k_invalid_t = K,
typename v_invalid_t = V,
k_invalid_t kINVALID = hb_is_pointer (K) ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1,
v_invalid_t vINVALID = hb_is_pointer (V) ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1>
k_invalid_t kINVALID = std::is_pointer<K>::value ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1,
v_invalid_t vINVALID = std::is_pointer<V>::value ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1>
struct hb_hashmap_t
{
static constexpr K INVALID_KEY = kINVALID;
static constexpr V INVALID_VALUE = vINVALID;
hb_hashmap_t () { init (); }
~hb_hashmap_t () { fini (); }
@ -64,24 +61,40 @@ struct hb_hashmap_t
hb_copy (o, *this);
}
static_assert (std::is_trivially_copyable<K>::value, "");
static_assert (std::is_trivially_copyable<V>::value, "");
static_assert (std::is_trivially_destructible<K>::value, "");
static_assert (std::is_trivially_destructible<V>::value, "");
struct item_t
{
K key;
V value;
uint32_t hash;
void clear () { key = kINVALID; value = vINVALID; hash = 0; }
void clear ()
{
new (std::addressof (key)) K ();
key = hb_coerce<K> (kINVALID);
new (std::addressof (value)) V ();
value = hb_coerce<V> (vINVALID);
hash = 0;
}
bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); }
bool operator == (const item_t &o) { return *this == o.key; }
bool is_unused () const { return key == kINVALID; }
bool is_tombstone () const { return key != kINVALID && value == vINVALID; }
bool is_real () const { return key != kINVALID && value != vINVALID; }
bool is_unused () const
{
const K inv = hb_coerce<K> (kINVALID);
return key == inv;
}
bool is_tombstone () const
{
const K kinv = hb_coerce<K> (kINVALID);
const V vinv = hb_coerce<V> (vINVALID);
return key != kinv && value == vinv;
}
bool is_real () const
{
const K kinv = hb_coerce<K> (kINVALID);
const V vinv = hb_coerce<V> (vINVALID);
return key != kinv && value != vinv;
}
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
};
@ -118,8 +131,13 @@ struct hb_hashmap_t
}
void fini_shallow ()
{
hb_free (items);
items = nullptr;
if (likely (items)) {
unsigned size = mask + 1;
for (unsigned i = 0; i < size; i++)
items[i].~item_t ();
hb_free (items);
items = nullptr;
}
population = occupancy = 0;
}
void fini ()
@ -163,10 +181,15 @@ struct hb_hashmap_t
/* Insert back old items. */
if (old_items)
for (unsigned int i = 0; i < old_size; i++)
{
if (old_items[i].is_real ())
{
set_with_hash (old_items[i].key,
old_items[i].hash,
std::move (old_items[i].value));
}
old_items[i].~item_t ();
}
hb_free (old_items);
@ -178,22 +201,22 @@ struct hb_hashmap_t
V get (K key) const
{
if (unlikely (!items)) return vINVALID;
if (unlikely (!items)) return hb_coerce<V> (vINVALID);
unsigned int i = bucket_for (key);
return items[i].is_real () && items[i] == key ? items[i].value : vINVALID;
return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID);
}
void del (K key) { set (key, vINVALID); }
void del (K key) { set (key, hb_coerce<V> (vINVALID)); }
/* Has interface. */
static constexpr V SENTINEL = vINVALID;
typedef V value_t;
value_t operator [] (K k) const { return get (k); }
bool has (K k, V *vp = nullptr) const
{
V v = (*this)[k];
if (vp) *vp = v;
return v != SENTINEL;
const V vinv = hb_coerce<V> (vINVALID);
return v != vinv;
}
/* Projection. */
V operator () (K k) const { return get (k); }
@ -248,11 +271,13 @@ struct hb_hashmap_t
bool set_with_hash (K key, uint32_t hash, VV&& value)
{
if (unlikely (!successful)) return false;
if (unlikely (key == kINVALID)) return true;
const K kinv = hb_coerce<K> (kINVALID);
if (unlikely (key == kinv)) return true;
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
unsigned int i = bucket_for_hash (key, hash);
if (value == vINVALID && items[i].key != key)
const V vinv = hb_coerce<V> (vINVALID);
if (value == vinv && items[i].key != key)
return true; /* Trying to delete non-existent key. */
if (!items[i].is_unused ())

View file

@ -29,6 +29,7 @@
#include "hb.hh"
#include <memory>
#include <type_traits>
#include <utility>
@ -85,30 +86,13 @@ template <> struct hb_priority<0> {};
template <typename T> struct hb_type_identity_t { typedef T type; };
template <typename T> using hb_type_identity = typename hb_type_identity_t<T>::type;
struct
{
template <typename T> constexpr T*
operator () (T& arg) const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
/* https://en.cppreference.com/w/cpp/memory/addressof */
return reinterpret_cast<T*> (
&const_cast<char&> (
reinterpret_cast<const volatile char&> (arg)));
#pragma GCC diagnostic pop
}
}
HB_FUNCOBJ (hb_addressof);
template <typename T> static inline T hb_declval ();
#define hb_declval(T) (hb_declval<T> ())
template <typename T> struct hb_match_const : hb_type_identity_t<T>, hb_false_type {};
template <typename T> struct hb_match_const<const T> : hb_type_identity_t<T>, hb_true_type {};
template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
template <typename T> using hb_add_const = const T;
#define hb_is_const(T) hb_match_const<T>::value
template <typename T> struct hb_match_reference : hb_type_identity_t<T>, hb_false_type {};
template <typename T> struct hb_match_reference<T &> : hb_type_identity_t<T>, hb_true_type {};
template <typename T> struct hb_match_reference<T &&> : hb_type_identity_t<T>, hb_true_type {};
@ -119,14 +103,13 @@ template <typename T> using hb_add_lvalue_reference = decltype (_hb_try_add_lval
template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_type_identity<T&&>;
template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize));
#define hb_is_reference(T) hb_match_reference<T>::value
template <typename T> struct hb_match_pointer : hb_type_identity_t<T>, hb_false_type {};
template <typename T> struct hb_match_pointer<T *> : hb_type_identity_t<T>, hb_true_type {};
template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>;
template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>;
template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize));
#define hb_is_pointer(T) hb_match_pointer<T>::value
/* TODO Add feature-parity to std::decay. */
@ -137,8 +120,8 @@ template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
template <typename From, typename To>
using hb_is_cr_convertible = hb_bool_constant<
hb_is_same (hb_decay<From>, hb_decay<To>) &&
(!hb_is_const (From) || hb_is_const (To)) &&
(!hb_is_reference (To) || hb_is_const (To) || hb_is_reference (To))
(!std::is_const<From>::value || std::is_const<To>::value) &&
(!std::is_reference<To>::value || std::is_const<To>::value || std::is_reference<To>::value)
>;
#define hb_is_cr_convertible(From,To) hb_is_cr_convertible<From, To>::value
@ -153,16 +136,6 @@ struct
}
HB_FUNCOBJ (hb_deref);
struct
{
template <typename T> constexpr auto
operator () (T&& v) const HB_AUTO_RETURN (std::forward<T> (v))
template <typename T> constexpr auto
operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v))
}
HB_FUNCOBJ (hb_ref);
template <typename T>
struct hb_reference_wrapper
{
@ -176,7 +149,7 @@ struct hb_reference_wrapper
template <typename T>
struct hb_reference_wrapper<T&>
{
hb_reference_wrapper (T& v) : v (hb_addressof (v)) {}
hb_reference_wrapper (T& v) : v (std::addressof (v)) {}
bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
operator T& () const { return *v; }

View file

@ -1,177 +0,0 @@
/*
* Copyright © 2011,2012,2013 Google, Inc.
* Copyright © 2021 Khaled Hosny
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#include "hb-ms-feature-ranges.hh"
bool
hb_ms_setup_features (const hb_feature_t *features,
unsigned int num_features,
hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */
hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */)
{
feature_records.shrink(0);
range_records.shrink(0);
/* Sort features by start/end events. */
hb_vector_t<hb_ms_feature_event_t> feature_events;
for (unsigned int i = 0; i < num_features; i++)
{
hb_ms_active_feature_t feature;
feature.fea.tag_le = hb_uint32_swap (features[i].tag);
feature.fea.value = features[i].value;
feature.order = i;
hb_ms_feature_event_t *event;
event = feature_events.push ();
event->index = features[i].start;
event->start = true;
event->feature = feature;
event = feature_events.push ();
event->index = features[i].end;
event->start = false;
event->feature = feature;
}
feature_events.qsort ();
/* Add a strategic final event. */
{
hb_ms_active_feature_t feature;
feature.fea.tag_le = 0;
feature.fea.value = 0;
feature.order = num_features + 1;
auto *event = feature_events.push ();
event->index = 0; /* This value does magic. */
event->start = false;
event->feature = feature;
}
/* Scan events and save features for each range. */
hb_vector_t<hb_ms_active_feature_t> active_features;
unsigned int last_index = 0;
for (unsigned int i = 0; i < feature_events.length; i++)
{
auto *event = &feature_events[i];
if (event->index != last_index)
{
/* Save a snapshot of active features and the range. */
auto *range = range_records.push ();
auto offset = feature_records.length;
active_features.qsort ();
for (unsigned int j = 0; j < active_features.length; j++)
{
if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le)
{
feature_records.push (active_features[j].fea);
}
else
{
/* Overrides value for existing feature. */
feature_records[feature_records.length - 1].value = active_features[j].fea.value;
}
}
/* Will convert to pointer after all is ready, since feature_records.array
* may move as we grow it. */
range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset);
range->features.num_features = feature_records.length - offset;
range->index_first = last_index;
range->index_last = event->index - 1;
last_index = event->index;
}
if (event->start)
{
active_features.push (event->feature);
}
else
{
auto *feature = active_features.find (&event->feature);
if (feature)
active_features.remove (feature - active_features.arrayZ);
}
}
if (!range_records.length) /* No active feature found. */
num_features = 0;
/* Fixup the pointers. */
for (unsigned int i = 0; i < range_records.length; i++)
{
auto *range = &range_records[i];
range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features);
}
return !!num_features;
}
void
hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records,
hb_vector_t<hb_ms_range_record_t> &range_records,
unsigned int chars_offset,
unsigned int chars_len,
uint16_t *log_clusters,
hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */
hb_vector_t<uint32_t> &range_counts /* OUT */)
{
range_features.shrink (0);
range_counts.shrink (0);
auto *last_range = &range_records[0];
for (unsigned int i = chars_offset; i < chars_len; i++)
{
auto *range = last_range;
while (log_clusters[i] < range->index_first)
range--;
while (log_clusters[i] > range->index_last)
range++;
if (!range_features.length ||
&range->features != range_features[range_features.length - 1])
{
auto **features = range_features.push ();
auto *c = range_counts.push ();
if (unlikely (!features || !c))
{
range_features.shrink (0);
range_counts.shrink (0);
break;
}
*features = &range->features;
*c = 1;
}
else
{
range_counts[range_counts.length - 1]++;
}
last_range = range;
}
}

View file

@ -52,8 +52,8 @@ struct hb_ms_active_feature_t {
a->fea.value < b->fea.value ? -1 : a->fea.value > b->fea.value ? 1 :
0;
}
bool operator== (const hb_ms_active_feature_t *f)
{ return cmp (this, f) == 0; }
bool operator== (const hb_ms_active_feature_t& f) const
{ return cmp (this, &f) == 0; }
};
struct hb_ms_feature_event_t {
@ -77,20 +77,153 @@ struct hb_ms_range_record_t {
unsigned int index_last; /* == end - 1 */
};
HB_INTERNAL bool
static inline bool
hb_ms_setup_features (const hb_feature_t *features,
unsigned int num_features,
hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */
hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */);
hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */)
{
feature_records.shrink(0);
range_records.shrink(0);
/* Sort features by start/end events. */
hb_vector_t<hb_ms_feature_event_t> feature_events;
for (unsigned int i = 0; i < num_features; i++)
{
hb_ms_active_feature_t feature;
feature.fea.tag_le = hb_uint32_swap (features[i].tag);
feature.fea.value = features[i].value;
feature.order = i;
HB_INTERNAL void
hb_ms_feature_event_t *event;
event = feature_events.push ();
event->index = features[i].start;
event->start = true;
event->feature = feature;
event = feature_events.push ();
event->index = features[i].end;
event->start = false;
event->feature = feature;
}
feature_events.qsort ();
/* Add a strategic final event. */
{
hb_ms_active_feature_t feature;
feature.fea.tag_le = 0;
feature.fea.value = 0;
feature.order = num_features + 1;
auto *event = feature_events.push ();
event->index = 0; /* This value does magic. */
event->start = false;
event->feature = feature;
}
/* Scan events and save features for each range. */
hb_vector_t<hb_ms_active_feature_t> active_features;
unsigned int last_index = 0;
for (unsigned int i = 0; i < feature_events.length; i++)
{
auto *event = &feature_events[i];
if (event->index != last_index)
{
/* Save a snapshot of active features and the range. */
auto *range = range_records.push ();
auto offset = feature_records.length;
active_features.qsort ();
for (unsigned int j = 0; j < active_features.length; j++)
{
if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le)
{
feature_records.push (active_features[j].fea);
}
else
{
/* Overrides value for existing feature. */
feature_records[feature_records.length - 1].value = active_features[j].fea.value;
}
}
/* Will convert to pointer after all is ready, since feature_records.array
* may move as we grow it. */
range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset);
range->features.num_features = feature_records.length - offset;
range->index_first = last_index;
range->index_last = event->index - 1;
last_index = event->index;
}
if (event->start)
{
active_features.push (event->feature);
}
else
{
auto *feature = active_features.lsearch (event->feature);
if (feature)
active_features.remove (feature - active_features.arrayZ);
}
}
if (!range_records.length) /* No active feature found. */
num_features = 0;
/* Fixup the pointers. */
for (unsigned int i = 0; i < range_records.length; i++)
{
auto *range = &range_records[i];
range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features);
}
return !!num_features;
}
static inline void
hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records,
hb_vector_t<hb_ms_range_record_t> &range_records,
unsigned int chars_offset,
unsigned int chars_len,
uint16_t *log_clusters,
hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */
hb_vector_t<uint32_t> &range_counts /* OUT */);
hb_vector_t<uint32_t> &range_counts /* OUT */)
{
range_features.shrink (0);
range_counts.shrink (0);
auto *last_range = &range_records[0];
for (unsigned int i = chars_offset; i < chars_len; i++)
{
auto *range = last_range;
while (log_clusters[i] < range->index_first)
range--;
while (log_clusters[i] > range->index_last)
range++;
if (!range_features.length ||
&range->features != range_features[range_features.length - 1])
{
auto **features = range_features.push ();
auto *c = range_counts.push ();
if (unlikely (!features || !c))
{
range_features.shrink (0);
range_counts.shrink (0);
break;
}
*features = &range->features;
*c = 1;
}
else
{
range_counts[range_counts.length - 1]++;
}
last_range = range;
}
}
#endif /* HB_MS_FEATURE_RANGES_HH */

View file

@ -53,7 +53,7 @@ struct hb_lockable_set_t
item_t *replace_or_insert (T v, lock_t &l, bool replace)
{
l.lock ();
item_t *item = items.find (v);
item_t *item = items.lsearch (v);
if (item) {
if (replace) {
item_t old = *item;
@ -76,7 +76,7 @@ struct hb_lockable_set_t
void remove (T v, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
item_t *item = items.lsearch (v);
if (item)
{
item_t old = *item;
@ -93,7 +93,7 @@ struct hb_lockable_set_t
bool find (T v, item_t *i, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
item_t *item = items.lsearch (v);
if (item)
*i = *item;
l.unlock ();

View file

@ -68,8 +68,6 @@ struct code_pair_t
typedef hb_vector_t<unsigned char> str_buff_t;
struct str_buff_vec_t : hb_vector_t<str_buff_t>
{
void fini () { SUPER::fini_deep (); }
unsigned int total_size () const
{
unsigned int size = 0;

View file

@ -1144,8 +1144,8 @@ struct cff1
{
sc.end_processing ();
topDict.fini ();
fontDicts.fini_deep ();
privateDicts.fini_deep ();
fontDicts.fini ();
privateDicts.fini ();
hb_blob_destroy (blob);
blob = nullptr;
}
@ -1245,32 +1245,32 @@ struct cff1
}
protected:
hb_blob_t *blob;
hb_blob_t *blob = nullptr;
hb_sanitize_context_t sc;
public:
const Encoding *encoding;
const Charset *charset;
const CFF1NameIndex *nameIndex;
const CFF1TopDictIndex *topDictIndex;
const CFF1StringIndex *stringIndex;
const CFF1Subrs *globalSubrs;
const CFF1CharStrings *charStrings;
const CFF1FDArray *fdArray;
const CFF1FDSelect *fdSelect;
unsigned int fdCount;
const Encoding *encoding = nullptr;
const Charset *charset = nullptr;
const CFF1NameIndex *nameIndex = nullptr;
const CFF1TopDictIndex *topDictIndex = nullptr;
const CFF1StringIndex *stringIndex = nullptr;
const CFF1Subrs *globalSubrs = nullptr;
const CFF1CharStrings *charStrings = nullptr;
const CFF1FDArray *fdArray = nullptr;
const CFF1FDSelect *fdSelect = nullptr;
unsigned int fdCount = 0;
cff1_top_dict_values_t topDict;
hb_vector_t<cff1_font_dict_values_t>
fontDicts;
hb_vector_t<PRIVDICTVAL> privateDicts;
unsigned int num_glyphs;
unsigned int num_glyphs = 0;
};
struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{
SUPER::init (face);
@ -1295,8 +1295,7 @@ struct cff1
}
glyph_names.qsort ();
}
void fini ()
~accelerator_t ()
{
glyph_names.fini ();
@ -1398,7 +1397,10 @@ struct cff1
DEFINE_SIZE_STATIC (4);
};
struct cff1_accelerator_t : cff1::accelerator_t {};
struct cff1_accelerator_t : cff1::accelerator_t {
cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
};
} /* namespace OT */
#endif /* HB_OT_CFF1_TABLE_HH */

View file

@ -397,7 +397,7 @@ struct cff2
template <typename PRIVOPSET, typename PRIVDICTVAL>
struct accelerator_templ_t
{
void init (hb_face_t *face)
accelerator_templ_t (hb_face_t *face)
{
topDict.init ();
fontDicts.init ();
@ -412,15 +412,15 @@ struct cff2
const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
if (cff2 == &Null (OT::cff2))
{ fini (); return; }
goto fail;
{ /* parse top dict */
byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
cff2_top_dict_interpreter_t top_interp;
top_interp.env.init (topDictStr);
topDict.init ();
if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
if (unlikely (!top_interp.interpret (topDict))) goto fail;
}
globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize);
@ -434,49 +434,55 @@ struct cff2
(globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
(fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
(((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
{ fini (); return; }
goto fail;
num_glyphs = charStrings->count;
if (num_glyphs != sc.get_num_glyphs ())
{ fini (); return; }
goto fail;
fdCount = fdArray->count;
if (!privateDicts.resize (fdCount))
{ fini (); return; }
goto fail;
/* parse font dicts and gather private dicts */
for (unsigned int i = 0; i < fdCount; i++)
{
const byte_str_t fontDictStr = (*fdArray)[i];
if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
cff2_font_dict_values_t *font;
cff2_font_dict_interpreter_t font_interp;
font_interp.env.init (fontDictStr);
font = fontDicts.push ();
if (unlikely (font == &Crap (cff2_font_dict_values_t))) { fini (); return; }
if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
font->init ();
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
if (unlikely (!font_interp.interpret (*font))) goto fail;
const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp;
priv_interp.env.init(privDictStr);
privateDicts[i].init ();
if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; }
if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
if (privateDicts[i].localSubrs != &Null (CFF2Subrs) &&
unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
{ fini (); return; }
goto fail;
}
}
void fini ()
return;
fail:
_fini ();
}
~accelerator_templ_t () { _fini (); }
void _fini ()
{
sc.end_processing ();
topDict.fini ();
fontDicts.fini_deep ();
privateDicts.fini_deep ();
fontDicts.fini ();
privateDicts.fini ();
hb_blob_destroy (blob);
blob = nullptr;
}
@ -484,26 +490,28 @@ struct cff2
bool is_valid () const { return blob; }
protected:
hb_blob_t *blob;
hb_blob_t *blob = nullptr;
hb_sanitize_context_t sc;
public:
cff2_top_dict_values_t topDict;
const CFF2Subrs *globalSubrs;
const CFF2VariationStore *varStore;
const CFF2CharStrings *charStrings;
const CFF2FDArray *fdArray;
const CFF2FDSelect *fdSelect;
unsigned int fdCount;
const CFF2Subrs *globalSubrs = nullptr;
const CFF2VariationStore *varStore = nullptr;
const CFF2CharStrings *charStrings = nullptr;
const CFF2FDArray *fdArray = nullptr;
const CFF2FDSelect *fdSelect = nullptr;
unsigned int fdCount = 0;
hb_vector_t<cff2_font_dict_values_t> fontDicts;
hb_vector_t<PRIVDICTVAL> privateDicts;
unsigned int num_glyphs;
unsigned int num_glyphs = 0;
};
struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t>
{
accelerator_t (hb_face_t *face) : accelerator_templ_t (face) {}
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
@ -525,7 +533,10 @@ struct cff2
DEFINE_SIZE_STATIC (5);
};
struct cff2_accelerator_t : cff2::accelerator_t {};
struct cff2_accelerator_t : cff2::accelerator_t {
cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {}
};
} /* namespace OT */
#endif /* HB_OT_CFF2_TABLE_HH */

View file

@ -369,7 +369,6 @@ struct CmapSubtableFormat4
{
accelerator_t () {}
accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); }
~accelerator_t () { fini (); }
void init (const CmapSubtableFormat4 *subtable)
{
@ -381,7 +380,6 @@ struct CmapSubtableFormat4
glyphIdArray = idRangeOffset + segCount;
glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
}
void fini () {}
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
@ -1607,7 +1605,7 @@ struct cmap
unsigned format = (this + _.subtable).u.format;
if (format == 12) has_format12 = true;
const EncodingRecord *table = hb_addressof (_);
const EncodingRecord *table = std::addressof (_);
if (_.platformID == 0 && _.encodingID == 3) unicode_bmp = table;
else if (_.platformID == 0 && _.encodingID == 4) unicode_ucs4 = table;
else if (_.platformID == 3 && _.encodingID == 1) ms_bmp = table;
@ -1665,7 +1663,7 @@ struct cmap
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{
this->table = hb_sanitize_context_t ().reference_table<cmap> (face);
bool symbol;
@ -1700,8 +1698,7 @@ struct cmap
}
}
}
void fini () { this->table.destroy (); }
~accelerator_t () { this->table.destroy (); }
bool get_nominal_glyph (hb_codepoint_t unicode,
hb_codepoint_t *glyph) const
@ -1863,7 +1860,9 @@ struct cmap
DEFINE_SIZE_ARRAY (4, encodingRecord);
};
struct cmap_accelerator_t : cmap::accelerator_t {};
struct cmap_accelerator_t : cmap::accelerator_t {
cmap_accelerator_t (hb_face_t *face) : cmap::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -360,6 +360,16 @@ struct IndexSubtable
struct IndexSubtableRecord
{
/* XXX Remove this and fix by not inserting it into vector. */
IndexSubtableRecord& operator = (const IndexSubtableRecord &o)
{
firstGlyphIndex = o.firstGlyphIndex;
lastGlyphIndex = o.lastGlyphIndex;
offsetToSubtable = (unsigned) o.offsetToSubtable;
assert (offsetToSubtable.is_null ());
return *this;
}
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@ -809,15 +819,14 @@ struct CBDT
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{
cblc = hb_sanitize_context_t ().reference_table<CBLC> (face);
cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face);
this->cblc = hb_sanitize_context_t ().reference_table<CBLC> (face);
this->cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face);
upem = hb_face_get_upem (face);
}
void fini ()
~accelerator_t ()
{
this->cblc.destroy ();
this->cbdt.destroy ();
@ -978,7 +987,10 @@ CBLC::subset (hb_subset_context_t *c) const
return_trace (CBLC::sink_cbdt (c, &cbdt_prime));
}
struct CBDT_accelerator_t : CBDT::accelerator_t {};
struct CBDT_accelerator_t : CBDT::accelerator_t {
CBDT_accelerator_t (hb_face_t *face) : CBDT::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -71,7 +71,7 @@ struct hb_colrv1_closure_context_t :
bool paint_visited (const void *paint)
{
hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) paint - (uintptr_t) base);
if (visited_paint.has (delta))
if (visited_paint.in_error() || visited_paint.has (delta))
return true;
visited_paint.add (delta);
@ -1270,13 +1270,9 @@ struct COLR
struct accelerator_t
{
accelerator_t () {}
~accelerator_t () { fini (); }
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{ colr = hb_sanitize_context_t ().reference_table<COLR> (face); }
void fini () { this->colr.destroy (); }
~accelerator_t () { this->colr.destroy (); }
bool is_valid () { return colr.get_blob ()->length; }
@ -1535,6 +1531,10 @@ struct COLR
DEFINE_SIZE_MIN (14);
};
struct COLR_accelerator_t : COLR::accelerator_t {
COLR_accelerator_t (hb_face_t *face) : COLR::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -43,7 +43,7 @@ HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) con
const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
{
const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i];
const Paint &paint = std::addressof (paint_offset_lists) + paint_offset_lists[i];
paint.dispatch (c);
}
}

View file

@ -202,12 +202,12 @@ struct sbix
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{
table = hb_sanitize_context_t ().reference_table<sbix> (face);
num_glyphs = face->get_num_glyphs ();
}
void fini () { table.destroy (); }
~accelerator_t () { table.destroy (); }
bool has_data () const { return table->has_data (); }
@ -407,7 +407,10 @@ struct sbix
DEFINE_SIZE_ARRAY (8, strikes);
};
struct sbix_accelerator_t : sbix::accelerator_t {};
struct sbix_accelerator_t : sbix::accelerator_t {
sbix_accelerator_t (hb_face_t *face) : sbix::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -79,9 +79,9 @@ struct SVG
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<SVG> (face); }
void fini () { table.destroy (); }
~accelerator_t () { table.destroy (); }
hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
{
@ -116,7 +116,9 @@ struct SVG
DEFINE_SIZE_STATIC (10);
};
struct SVG_accelerator_t : SVG::accelerator_t {};
struct SVG_accelerator_t : SVG::accelerator_t {
SVG_accelerator_t (hb_face_t *face) : SVG::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -90,15 +90,15 @@ hb_ot_color_palette_get_count (hb_face_t *face)
/**
* hb_ot_color_palette_get_name_id:
* @face: #hb_face_t to work upon
* @palette_index: The index of the color palette
* @palette_index: The index of the color palette
*
* Fetches the `name` table Name ID that provides display names for
* a `CPAL` color palette.
* a `CPAL` color palette.
*
* Palette display names can be generic (e.g., "Default") or provide
* specific, themed names (e.g., "Spring", "Summer", "Fall", and "Winter").
*
* Return value: the Named ID found for the palette.
* Return value: the Named ID found for the palette.
* If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
*
* Since: 2.1.0
@ -116,7 +116,7 @@ hb_ot_color_palette_get_name_id (hb_face_t *face,
* @color_index: The index of the color
*
* Fetches the `name` table Name ID that provides display names for
* the specificed color in a face's `CPAL` color palette.
* the specified color in a face's `CPAL` color palette.
*
* Display names can be generic (e.g., "Background") or specific
* (e.g., "Eye color").
@ -256,6 +256,8 @@ hb_ot_color_has_svg (hb_face_t *face)
*
* Fetches the SVG document for a glyph. The blob may be either plain text or gzip-encoded.
*
* If the glyph has no SVG document, the singleton empty blob is returned.
*
* Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available
*
* Since: 2.1.0
@ -296,6 +298,8 @@ hb_ot_color_has_png (hb_face_t *face)
* as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font
* object. If UPEM is unset, the blob returned will be the largest PNG available.
*
* If the glyph has no PNG image, the singleton empty blob is returned.
*
* Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available
*
* Since: 2.1.0

View file

@ -207,8 +207,7 @@ struct glyf
_populate_subset_glyphs (const hb_subset_plan_t *plan,
hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const
{
OT::glyf::accelerator_t glyf;
glyf.init (plan->source);
OT::glyf::accelerator_t glyf (plan->source);
+ hb_range (plan->num_output_glyphs ())
| hb_map ([&] (hb_codepoint_t new_gid)
@ -233,8 +232,6 @@ struct glyf
})
| hb_sink (glyphs)
;
glyf.fini ();
}
static bool
@ -595,7 +592,7 @@ struct glyf
if (unlikely (!header.numberOfContours)) return;
unsigned flags_offset = length (instructions_length ());
if (unlikely (length (flags_offset + 1) > bytes.length)) return;
if (unlikely (flags_offset + 1 > bytes.length)) return;
HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
@ -920,7 +917,7 @@ struct glyf
struct accelerator_t
{
void init (hb_face_t *face_)
accelerator_t (hb_face_t *face_)
{
short_offset = false;
num_glyphs = 0;
@ -953,8 +950,7 @@ struct glyf
num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
}
void fini ()
~accelerator_t ()
{
loca_table.destroy ();
glyf_table.destroy ();
@ -1358,7 +1354,10 @@ struct glyf
* defining it _MIN instead. */
};
struct glyf_accelerator_t : glyf::accelerator_t {};
struct glyf_accelerator_t : glyf::accelerator_t {
glyf_accelerator_t (hb_face_t *face) : glyf::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -127,8 +127,7 @@ struct hmtxvmtx
T *table_prime = c->serializer->start_embed <T> ();
if (unlikely (!table_prime)) return_trace (false);
accelerator_t _mtx;
_mtx.init (c->plan->source);
accelerator_t _mtx (c->plan->source);
unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
auto it =
@ -144,8 +143,6 @@ struct hmtxvmtx
table_prime->serialize (c->serializer, it, num_advances);
_mtx.fini ();
if (unlikely (c->serializer->in_error ()))
return_trace (false);
@ -160,8 +157,8 @@ struct hmtxvmtx
{
friend struct hmtxvmtx;
void init (hb_face_t *face,
unsigned int default_advance_ = 0)
accelerator_t (hb_face_t *face,
unsigned int default_advance_ = 0)
{
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
@ -193,8 +190,7 @@ struct hmtxvmtx
var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
}
void fini ()
~accelerator_t ()
{
table.destroy ();
var_table.destroy ();
@ -338,8 +334,12 @@ struct vmtx : hmtxvmtx<vmtx, vhea> {
static constexpr bool is_horizontal = false;
};
struct hmtx_accelerator_t : hmtx::accelerator_t {};
struct vmtx_accelerator_t : vmtx::accelerator_t {};
struct hmtx_accelerator_t : hmtx::accelerator_t {
hmtx_accelerator_t (hb_face_t *face) : hmtx::accelerator_t (face) {}
};
struct vmtx_accelerator_t : vmtx::accelerator_t {
vmtx_accelerator_t (hb_face_t *face) : vmtx::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -128,7 +128,7 @@ struct hb_prune_langsys_context_t
bool visited (const T *p, hb_set_t &visited_set)
{
hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table);
if (visited_set.has (delta))
if (visited_set.in_error () || visited_set.has (delta))
return true;
visited_set.add (delta);
@ -655,7 +655,6 @@ struct LangSys
void collect_features (hb_prune_langsys_context_t *c) const
{
if (!has_required_feature () && !get_feature_count ()) return;
if (c->visitedLangsys (this)) return;
if (has_required_feature () &&
c->duplicate_feature_map->has (reqFeatureIndex))
c->new_feature_indexes->add (get_required_feature_index ());
@ -750,11 +749,15 @@ struct Script
{
//only collect features from non-redundant langsys
const LangSys& d = get_default_lang_sys ();
d.collect_features (c);
if (!c->visitedLangsys (&d)) {
d.collect_features (c);
}
for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
{
const LangSys& l = this+_.first.offset;
if (c->visitedLangsys (&l)) continue;
if (l.compare (d, c->duplicate_feature_map)) continue;
l.collect_features (c);
@ -766,6 +769,7 @@ struct Script
for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
{
const LangSys& l = this+_.first.offset;
if (c->visitedLangsys (&l)) continue;
l.collect_features (c);
c->script_langsys_map->get (script_index)->add (_.second);
}
@ -845,7 +849,7 @@ struct FeatureParamsSize
if (unlikely (!c->check_struct (this))) return_trace (false);
/* This subtable has some "history", if you will. Some earlier versions of
* Adobe tools calculated the offset of the FeatureParams sutable from the
* Adobe tools calculated the offset of the FeatureParams subtable from the
* beginning of the FeatureList table! Now, that is dealt with in the
* Feature implementation. But we still need to be able to tell junk from
* real data. Note: We don't check that the nameID actually exists.
@ -2926,8 +2930,6 @@ struct VariationStore
hb_vector_t<hb_inc_bimap_t> inner_maps;
inner_maps.resize ((unsigned) dataSets.len);
for (unsigned i = 0; i < inner_maps.length; i++)
inner_maps[i].init ();
for (unsigned idx : c->plan->layout_variation_indices->iter ())
{
@ -2935,18 +2937,11 @@ struct VariationStore
uint16_t minor = idx & 0xFFFF;
if (major >= inner_maps.length)
{
for (unsigned i = 0; i < inner_maps.length; i++)
inner_maps[i].fini ();
return_trace (false);
}
inner_maps[major].add (minor);
}
varstore_prime->serialize (c->serializer, this, inner_maps.as_array ());
for (unsigned i = 0; i < inner_maps.length; i++)
inner_maps[i].fini ();
return_trace (
!c->serializer->in_error()
&& varstore_prime->dataSets);

View file

@ -585,17 +585,16 @@ struct GDEF
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{
this->table = hb_sanitize_context_t ().reference_table<GDEF> (face);
if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
table = hb_sanitize_context_t ().reference_table<GDEF> (face);
if (unlikely (table->is_blocklisted (table.get_blob (), face)))
{
hb_blob_destroy (this->table.get_blob ());
this->table = hb_blob_get_empty ();
hb_blob_destroy (table.get_blob ());
table = hb_blob_get_empty ();
}
}
void fini () { this->table.destroy (); }
~accelerator_t () { table.destroy (); }
hb_blob_ptr_t<GDEF> table;
};
@ -715,7 +714,9 @@ struct GDEF
DEFINE_SIZE_MIN (12);
};
struct GDEF_accelerator_t : GDEF::accelerator_t {};
struct GDEF_accelerator_t : GDEF::accelerator_t {
GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -706,7 +706,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage or
float mark_x, mark_y, base_x, base_y;
buffer->unsafe_to_break (glyph_pos, buffer->idx);
buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
@ -1235,6 +1235,7 @@ struct PairSet
buffer->idx = pos;
return_trace (true);
}
buffer->unsafe_to_concat (buffer->idx, pos + 1);
return_trace (false);
}
@ -1362,7 +1363,12 @@ struct PairPosFormat1
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.next ()) return_trace (false);
unsigned unsafe_to;
if (!skippy_iter.next (&unsafe_to))
{
buffer->unsafe_to_concat (buffer->idx, unsafe_to);
return_trace (false);
}
return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
}
@ -1555,7 +1561,12 @@ struct PairPosFormat2
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.next ()) return_trace (false);
unsigned unsafe_to;
if (!skippy_iter.next (&unsafe_to))
{
buffer->unsafe_to_concat (buffer->idx, unsafe_to);
return_trace (false);
}
unsigned int len1 = valueFormat1.get_len ();
unsigned int len2 = valueFormat2.get_len ();
@ -1563,13 +1574,81 @@ struct PairPosFormat2
unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
{
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
return_trace (false);
}
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
bool applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
bool applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
bool applied_first = false, applied_second = false;
/* Isolate simple kerning and apply it half to each side.
* Results in better cursor positinoing / underline drawing. */
{
if (!len2)
{
const hb_direction_t dir = buffer->props.direction;
const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
if (backward)
mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
/* Add Devices. */
mask |= mask << 4;
if (valueFormat1 & ~mask)
goto bail;
/* Is simple kern. Apply value on an empty position slot,
* then split it between sides. */
hb_glyph_position_t pos{};
if (valueFormat1.apply_value (c, this, v, pos))
{
hb_position_t *src = &pos.x_advance;
hb_position_t *dst1 = &buffer->cur_pos().x_advance;
hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
unsigned i = horizontal ? 0 : 1;
hb_position_t kern = src[i];
hb_position_t kern1 = kern >> 1;
hb_position_t kern2 = kern - kern1;
if (!backward)
{
dst1[i] += kern1;
dst2[i] += kern2;
dst2[i + 2] += kern2;
}
else
{
dst1[i] += kern1;
dst1[i + 2] += src[i + 2] - kern2;
dst2[i] += kern2;
}
applied_first = applied_second = kern != 0;
goto success;
}
goto boring;
}
}
bail:
applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
success:
if (applied_first || applied_second)
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
else
boring:
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
buffer->idx = skippy_iter.idx;
if (len2)
@ -1799,10 +1878,19 @@ struct CursivePosFormat1
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
if (!skippy_iter.prev ()) return_trace (false);
unsigned unsafe_from;
if (!skippy_iter.prev (&unsafe_from))
{
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
return_trace (false);
}
const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
if (!prev_record.exitAnchor) return_trace (false);
if (!prev_record.exitAnchor)
{
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
}
unsigned int i = skippy_iter.idx;
unsigned int j = buffer->idx;
@ -2066,7 +2154,13 @@ struct MarkBasePosFormat1
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
do {
if (!skippy_iter.prev ()) return_trace (false);
unsigned unsafe_from;
if (!skippy_iter.prev (&unsafe_from))
{
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
return_trace (false);
}
/* We only want to attach to the first of a MultipleSubst sequence.
* https://github.com/harfbuzz/harfbuzz/issues/740
* Reject others...
@ -2089,7 +2183,11 @@ struct MarkBasePosFormat1
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
if (base_index == NOT_COVERED) return_trace (false);
if (base_index == NOT_COVERED)
{
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
}
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
}
@ -2320,21 +2418,34 @@ struct MarkLigPosFormat1
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
if (!skippy_iter.prev ()) return_trace (false);
unsigned unsafe_from;
if (!skippy_iter.prev (&unsafe_from))
{
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
return_trace (false);
}
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
//if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
unsigned int j = skippy_iter.idx;
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
if (lig_index == NOT_COVERED) return_trace (false);
if (lig_index == NOT_COVERED)
{
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
}
const LigatureArray& lig_array = this+ligatureArray;
const LigatureAttach& lig_attach = lig_array[lig_index];
/* Find component to attach to */
unsigned int comp_count = lig_attach.rows;
if (unlikely (!comp_count)) return_trace (false);
if (unlikely (!comp_count))
{
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
}
/* We must now check whether the ligature ID of the current mark glyph
* is identical to the ligature ID of the found ligature. If yes, we
@ -2517,9 +2628,18 @@ struct MarkMarkPosFormat1
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
if (!skippy_iter.prev ()) return_trace (false);
unsigned unsafe_from;
if (!skippy_iter.prev (&unsafe_from))
{
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
return_trace (false);
}
if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); }
if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))
{
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
}
unsigned int j = skippy_iter.idx;
@ -2544,11 +2664,16 @@ struct MarkMarkPosFormat1
}
/* Didn't match. */
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
good:
unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
if (mark2_index == NOT_COVERED) return_trace (false);
if (mark2_index == NOT_COVERED)
{
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
return_trace (false);
}
return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
}
@ -2951,7 +3076,7 @@ GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer H
}
void
GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
{
_hb_buffer_assert_gsubgpos_vars (buffer);
@ -2961,12 +3086,21 @@ GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
/* Handle attachments */
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
for (unsigned int i = 0; i < len; i++)
for (unsigned i = 0; i < len; i++)
propagate_attachment_offsets (pos, len, i, direction);
if (unlikely (font->slant))
{
for (unsigned i = 0; i < len; i++)
if (unlikely (pos[i].y_offset))
pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
}
}
struct GPOS_accelerator_t : GPOS::accelerator_t {};
struct GPOS_accelerator_t : GPOS::accelerator_t {
GPOS_accelerator_t (hb_face_t *face) : GPOS::accelerator_t (face) {}
};
/* Out-of-class implementation for methods recursing */

View file

@ -826,22 +826,25 @@ struct Ligature
unsigned int total_component_count = 0;
unsigned int match_length = 0;
unsigned int match_end = 0;
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
if (likely (!match_input (c, count,
&component[1],
match_glyph,
nullptr,
&match_length,
&match_end,
match_positions,
&total_component_count)))
{
c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
return_trace (false);
}
ligate_input (c,
count,
match_positions,
match_length,
match_end,
ligGlyph,
total_component_count);
@ -1296,7 +1299,7 @@ struct ReverseChainSingleSubstFormat1
match_lookahead (c,
lookahead.len, (HBUINT16 *) lookahead.arrayZ,
match_coverage, this,
1, &end_index))
c->buffer->idx + 1, &end_index))
{
c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
c->replace_glyph_inplace (substitute[index]);
@ -1305,8 +1308,11 @@ struct ReverseChainSingleSubstFormat1
* calls us through a Context lookup. */
return_trace (true);
}
return_trace (false);
else
{
c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
return_trace (false);
}
}
template<typename Iterator,
@ -1739,7 +1745,9 @@ struct GSUB : GSUBGPOS
};
struct GSUB_accelerator_t : GSUB::accelerator_t {};
struct GSUB_accelerator_t : GSUB::accelerator_t {
GSUB_accelerator_t (hb_face_t *face) : GSUB::accelerator_t (face) {}
};
/* Out-of-class implementation for methods recursing */

View file

@ -125,24 +125,31 @@ struct hb_closure_context_t :
hb_set_t *covered_glyph_set = done_lookups_glyph_set->get (lookup_index);
if (unlikely (covered_glyph_set->in_error ()))
return true;
if (parent_active_glyphs ()->is_subset (*covered_glyph_set))
if (parent_active_glyphs ().is_subset (*covered_glyph_set))
return true;
hb_set_union (covered_glyph_set, parent_active_glyphs ());
covered_glyph_set->union_ (parent_active_glyphs ());
return false;
}
hb_set_t* parent_active_glyphs ()
const hb_set_t& previous_parent_active_glyphs () {
if (active_glyphs_stack.length <= 1)
return *glyphs;
return active_glyphs_stack[active_glyphs_stack.length - 2];
}
const hb_set_t& parent_active_glyphs ()
{
if (active_glyphs_stack.length < 1)
return glyphs;
if (!active_glyphs_stack)
return *glyphs;
return active_glyphs_stack.tail ();
}
void push_cur_active_glyphs (hb_set_t* cur_active_glyph_set)
hb_set_t& push_cur_active_glyphs ()
{
active_glyphs_stack.push (cur_active_glyph_set);
return *active_glyphs_stack.push ();
}
bool pop_cur_done_glyphs ()
@ -156,29 +163,24 @@ struct hb_closure_context_t :
hb_face_t *face;
hb_set_t *glyphs;
hb_set_t *cur_intersected_glyphs;
hb_set_t output[1];
hb_vector_t<hb_set_t *> active_glyphs_stack;
hb_vector_t<hb_set_t> active_glyphs_stack;
recurse_func_t recurse_func;
unsigned int nesting_level_left;
hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_,
hb_set_t *cur_intersected_glyphs_,
hb_map_t *done_lookups_glyph_count_,
hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set_,
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
face (face_),
glyphs (glyphs_),
cur_intersected_glyphs (cur_intersected_glyphs_),
recurse_func (nullptr),
nesting_level_left (nesting_level_left_),
done_lookups_glyph_count (done_lookups_glyph_count_),
done_lookups_glyph_set (done_lookups_glyph_set_),
lookup_count (0)
{
push_cur_active_glyphs (glyphs_);
}
{}
~hb_closure_context_t () { flush (); }
@ -186,11 +188,11 @@ struct hb_closure_context_t :
void flush ()
{
hb_set_del_range (output, face->get_num_glyphs (), HB_SET_VALUE_INVALID); /* Remove invalid glyphs. */
hb_set_union (glyphs, output);
hb_set_clear (output);
output->del_range (face->get_num_glyphs (), HB_SET_VALUE_INVALID); /* Remove invalid glyphs. */
glyphs->union_ (*output);
output->clear ();
active_glyphs_stack.pop ();
active_glyphs_stack.fini ();
active_glyphs_stack.reset ();
}
private:
@ -520,7 +522,7 @@ struct hb_ot_apply_context_t :
may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
bool next ()
bool next (unsigned *unsafe_to = nullptr)
{
assert (num_items > 0);
while (idx + num_items < end)
@ -543,11 +545,17 @@ struct hb_ot_apply_context_t :
}
if (skip == matcher_t::SKIP_NO)
{
if (unsafe_to)
*unsafe_to = idx + 1;
return false;
}
}
if (unsafe_to)
*unsafe_to = end;
return false;
}
bool prev ()
bool prev (unsigned *unsafe_from = nullptr)
{
assert (num_items > 0);
while (idx > num_items - 1)
@ -570,8 +578,14 @@ struct hb_ot_apply_context_t :
}
if (skip == matcher_t::SKIP_NO)
{
if (unsafe_from)
*unsafe_from = hb_max (1u, idx) - 1u;
return false;
}
}
if (unsafe_from)
*unsafe_from = 0;
return false;
}
@ -712,53 +726,60 @@ struct hb_ot_apply_context_t :
return true;
}
void _set_glyph_props (hb_codepoint_t glyph_index,
void _set_glyph_class (hb_codepoint_t glyph_index,
unsigned int class_guess = 0,
bool ligature = false,
bool component = false) const
{
unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur());
props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
if (ligature)
{
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
props |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
/* In the only place that the MULTIPLIED bit is used, Uniscribe
* seems to only care about the "last" transformation between
* Ligature and Multiple substitutions. Ie. if you ligate, expand,
* and ligate again, it forgives the multiplication and acts as
* if only ligation happened. As such, clear MULTIPLIED bit.
*/
add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
props &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
}
if (component)
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
props |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
if (likely (has_glyph_classes))
_hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
{
props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
_hb_glyph_info_set_glyph_props (&buffer->cur(), props | gdef.get_glyph_props (glyph_index));
}
else if (class_guess)
_hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
{
props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
_hb_glyph_info_set_glyph_props (&buffer->cur(), props | class_guess);
}
else
_hb_glyph_info_set_glyph_props (&buffer->cur(), props);
}
void replace_glyph (hb_codepoint_t glyph_index) const
{
_set_glyph_props (glyph_index);
_set_glyph_class (glyph_index);
(void) buffer->replace_glyph (glyph_index);
}
void replace_glyph_inplace (hb_codepoint_t glyph_index) const
{
_set_glyph_props (glyph_index);
_set_glyph_class (glyph_index);
buffer->cur().codepoint = glyph_index;
}
void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
unsigned int class_guess) const
{
_set_glyph_props (glyph_index, class_guess, true);
_set_glyph_class (glyph_index, class_guess, true);
(void) buffer->replace_glyph (glyph_index);
}
void output_glyph_for_component (hb_codepoint_t glyph_index,
unsigned int class_guess) const
{
_set_glyph_props (glyph_index, class_guess, false, true);
_set_glyph_class (glyph_index, class_guess, false, true);
(void) buffer->output_glyph (glyph_index);
}
};
@ -948,7 +969,7 @@ static inline bool match_input (hb_ot_apply_context_t *c,
const HBUINT16 input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data,
unsigned int *end_offset,
unsigned int *end_position,
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
unsigned int *p_total_component_count = nullptr)
{
@ -1001,7 +1022,12 @@ static inline bool match_input (hb_ot_apply_context_t *c,
match_positions[0] = buffer->idx;
for (unsigned int i = 1; i < count; i++)
{
if (!skippy_iter.next ()) return_trace (false);
unsigned unsafe_to;
if (!skippy_iter.next (&unsafe_to))
{
*end_position = unsafe_to;
return_trace (false);
}
match_positions[i] = skippy_iter.idx;
@ -1055,7 +1081,7 @@ static inline bool match_input (hb_ot_apply_context_t *c,
total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
}
*end_offset = skippy_iter.idx - buffer->idx + 1;
*end_position = skippy_iter.idx + 1;
if (p_total_component_count)
*p_total_component_count = total_component_count;
@ -1065,7 +1091,7 @@ static inline bool match_input (hb_ot_apply_context_t *c,
static inline bool ligate_input (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph */
const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
unsigned int match_length,
unsigned int match_end,
hb_codepoint_t lig_glyph,
unsigned int total_component_count)
{
@ -1073,7 +1099,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
hb_buffer_t *buffer = c->buffer;
buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
buffer->merge_clusters (buffer->idx, match_end);
/* - If a base and one or more marks ligate, consider that as a base, NOT
* ligature, such that all following marks can still attach to it.
@ -1190,11 +1216,16 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
skippy_iter.set_match_func (match_func, match_data, backtrack);
for (unsigned int i = 0; i < count; i++)
if (!skippy_iter.prev ())
{
unsigned unsafe_from;
if (!skippy_iter.prev (&unsafe_from))
{
*match_start = unsafe_from;
return_trace (false);
}
}
*match_start = skippy_iter.idx;
return_trace (true);
}
@ -1203,21 +1234,26 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
const HBUINT16 lookahead[],
match_func_t match_func,
const void *match_data,
unsigned int offset,
unsigned int start_index,
unsigned int *end_index)
{
TRACE_APPLY (nullptr);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->idx + offset - 1, count);
skippy_iter.reset (start_index - 1, count);
skippy_iter.set_match_func (match_func, match_data, lookahead);
for (unsigned int i = 0; i < count; i++)
if (!skippy_iter.next ())
{
unsigned unsafe_to;
if (!skippy_iter.next (&unsafe_to))
{
*end_index = unsafe_to;
return_trace (false);
}
}
*end_index = skippy_iter.idx + 1;
return_trace (true);
}
@ -1284,22 +1320,23 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
unsigned seqIndex = lookupRecord[i].sequenceIndex;
if (seqIndex >= inputCount) continue;
hb_set_t *pos_glyphs = nullptr;
bool has_pos_glyphs = false;
hb_set_t pos_glyphs;
if (hb_set_is_empty (covered_seq_indicies) || !hb_set_has (covered_seq_indicies, seqIndex))
{
pos_glyphs = hb_set_create ();
has_pos_glyphs = true;
if (seqIndex == 0)
{
switch (context_format) {
case ContextFormat::SimpleContext:
pos_glyphs->add (value);
pos_glyphs.add (value);
break;
case ContextFormat::ClassBasedContext:
intersected_glyphs_func (c->cur_intersected_glyphs, data, value, pos_glyphs);
intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs);
break;
case ContextFormat::CoverageBasedContext:
hb_set_set (pos_glyphs, c->cur_intersected_glyphs);
pos_glyphs.set (c->parent_active_glyphs ());
break;
}
}
@ -1313,12 +1350,16 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
input_value = input[seqIndex - 1];
}
intersected_glyphs_func (c->glyphs, input_data, input_value, pos_glyphs);
intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs);
}
}
hb_set_add (covered_seq_indicies, seqIndex);
c->push_cur_active_glyphs (pos_glyphs ? pos_glyphs : c->glyphs);
covered_seq_indicies->add (seqIndex);
if (has_pos_glyphs) {
c->push_cur_active_glyphs () = pos_glyphs;
} else {
c->push_cur_active_glyphs ().set (*c->glyphs);
}
unsigned endIndex = inputCount;
if (context_format == ContextFormat::CoverageBasedContext)
@ -1327,8 +1368,6 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
c->recurse (lookupRecord[i].lookupListIndex, covered_seq_indicies, seqIndex, endIndex);
c->pop_cur_done_glyphs ();
if (pos_glyphs)
hb_set_destroy (pos_glyphs);
}
hb_set_destroy (covered_seq_indicies);
@ -1343,15 +1382,13 @@ static inline void recurse_lookups (context_t *c,
c->recurse (lookupRecord[i].lookupListIndex);
}
static inline bool apply_lookup (hb_ot_apply_context_t *c,
static inline void apply_lookup (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph */
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
unsigned int match_length)
unsigned int match_end)
{
TRACE_APPLY (nullptr);
hb_buffer_t *buffer = c->buffer;
int end;
@ -1359,7 +1396,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
* Adjust. */
{
unsigned int bl = buffer->backtrack_len ();
end = bl + match_length;
end = bl + match_end - buffer->idx;
int delta = bl - buffer->idx;
/* Convert positions to new indexing. */
@ -1461,8 +1498,6 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
}
(void) buffer->move_to (end);
return_trace (true);
}
@ -1550,17 +1585,25 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
const LookupRecord lookupRecord[],
ContextApplyLookupContext &lookup_context)
{
unsigned int match_length = 0;
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
return match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data,
&match_length, match_positions)
&& (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
apply_lookup (c,
inputCount, match_positions,
lookupCount, lookupRecord,
match_length));
unsigned match_end = 0;
unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
if (match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data,
&match_end, match_positions))
{
c->buffer->unsafe_to_break (c->buffer->idx, match_end);
apply_lookup (c,
inputCount, match_positions,
lookupCount, lookupRecord,
match_end);
return true;
}
else
{
c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
return false;
}
}
struct Rule
@ -1828,8 +1871,9 @@ struct ContextFormat1
void closure (hb_closure_context_t *c) const
{
c->cur_intersected_glyphs->clear ();
get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
cur_active_glyphs);
struct ContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@ -1838,10 +1882,14 @@ struct ContextFormat1
};
+ hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
| hb_filter (c->parent_active_glyphs (), hb_first)
| hb_filter ([&] (hb_codepoint_t _) {
return c->previous_parent_active_glyphs ().has (_);
}, hb_first)
| hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const RuleSet&> (_.first, this+ruleSet[_.second]); })
| hb_apply ([&] (const hb_pair_t<unsigned, const RuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
;
c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@ -1989,8 +2037,9 @@ struct ContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
c->cur_intersected_glyphs->clear ();
get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
cur_active_glyphs);
const ClassDef &class_def = this+classDef;
@ -2000,10 +2049,9 @@ struct ContextFormat2
&class_def
};
return
+ hb_enumerate (ruleSet)
| hb_filter ([&] (unsigned _)
{ return class_def.intersects_class (c->cur_intersected_glyphs, _); },
{ return class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
| hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _)
{
@ -2011,6 +2059,8 @@ struct ContextFormat2
rule_set.closure (c, _.first, lookup_context);
})
;
c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@ -2183,8 +2233,10 @@ struct ContextFormat3
if (!(this+coverageZ[0]).intersects (c->glyphs))
return;
c->cur_intersected_glyphs->clear ();
get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
cur_active_glyphs);
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
struct ContextClosureLookupContext lookup_context = {
@ -2196,6 +2248,8 @@ struct ContextFormat3
glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
lookupCount, lookupRecord,
0, lookup_context);
c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@ -2452,25 +2506,38 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
const LookupRecord lookupRecord[],
ChainContextApplyLookupContext &lookup_context)
{
unsigned int start_index = 0, match_length = 0, end_index = 0;
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
return match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data[1],
&match_length, match_positions)
&& match_backtrack (c,
backtrackCount, backtrack,
lookup_context.funcs.match, lookup_context.match_data[0],
&start_index)
&& match_lookahead (c,
lookaheadCount, lookahead,
lookup_context.funcs.match, lookup_context.match_data[2],
match_length, &end_index)
&& (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
apply_lookup (c,
inputCount, match_positions,
lookupCount, lookupRecord,
match_length));
unsigned end_index = c->buffer->idx;
unsigned match_end = 0;
unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
if (!(match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data[1],
&match_end, match_positions) && (end_index = match_end)
&& match_lookahead (c,
lookaheadCount, lookahead,
lookup_context.funcs.match, lookup_context.match_data[2],
match_end, &end_index)))
{
c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
return false;
}
unsigned start_index = c->buffer->out_len;
if (!match_backtrack (c,
backtrackCount, backtrack,
lookup_context.funcs.match, lookup_context.match_data[0],
&start_index))
{
c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
return false;
}
c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
apply_lookup (c,
inputCount, match_positions,
lookupCount, lookupRecord,
match_end);
return true;
}
struct ChainRule
@ -2802,8 +2869,9 @@ struct ChainContextFormat1
void closure (hb_closure_context_t *c) const
{
c->cur_intersected_glyphs->clear ();
get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
cur_active_glyphs);
struct ChainContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@ -2812,10 +2880,14 @@ struct ChainContextFormat1
};
+ hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
| hb_filter (c->parent_active_glyphs (), hb_first)
| hb_filter ([&] (hb_codepoint_t _) {
return c->previous_parent_active_glyphs ().has (_);
}, hb_first)
| hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const ChainRuleSet&> (_.first, this+ruleSet[_.second]); })
| hb_apply ([&] (const hb_pair_t<unsigned, const ChainRuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
;
c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@ -2964,8 +3036,10 @@ struct ChainContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
c->cur_intersected_glyphs->clear ();
get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
cur_active_glyphs);
const ClassDef &backtrack_class_def = this+backtrackClassDef;
const ClassDef &input_class_def = this+inputClassDef;
@ -2979,10 +3053,9 @@ struct ChainContextFormat2
&lookahead_class_def}
};
return
+ hb_enumerate (ruleSet)
| hb_filter ([&] (unsigned _)
{ return input_class_def.intersects_class (c->cur_intersected_glyphs, _); },
{ return input_class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
| hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _)
{
@ -2990,6 +3063,8 @@ struct ChainContextFormat2
chainrule_set.closure (c, _.first, lookup_context);
})
;
c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@ -3216,8 +3291,10 @@ struct ChainContextFormat3
if (!(this+input[0]).intersects (c->glyphs))
return;
c->cur_intersected_glyphs->clear ();
get_coverage ().intersected_coverage_glyphs (c->parent_active_glyphs (), c->cur_intersected_glyphs);
hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
cur_active_glyphs);
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
@ -3232,6 +3309,8 @@ struct ChainContextFormat3
lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
lookup.len, lookup.arrayZ,
0, lookup_context);
c->pop_cur_done_glyphs ();
}
void closure_lookups (hb_closure_lookups_context_t *c) const
@ -3706,7 +3785,7 @@ struct GSUBGPOS
for (unsigned i : feature_indices->iter ())
{
hb_tag_t t = get_feature_tag (i);
if (t == unique_features.INVALID_KEY) continue;
if (t == HB_MAP_VALUE_INVALID) continue;
if (!unique_features.has (t))
{
hb_set_t* indices = hb_set_create ();
@ -3839,7 +3918,7 @@ struct GSUBGPOS
template <typename T>
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{
this->table = hb_sanitize_context_t ().reference_table<T> (face);
if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
@ -3861,8 +3940,7 @@ struct GSUBGPOS
for (unsigned int i = 0; i < this->lookup_count; i++)
this->accels[i].init (table->get_lookup (i));
}
void fini ()
~accelerator_t ()
{
for (unsigned int i = 0; i < this->lookup_count; i++)
this->accels[i].fini ();

View file

@ -1491,10 +1491,9 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
unsigned int lookup_index,
hb_set_t *glyphs /* OUT */)
{
hb_set_t cur_intersected_glyphs;
hb_map_t done_lookups_glyph_count;
hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
@ -1520,10 +1519,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
const hb_set_t *lookups,
hb_set_t *glyphs /* OUT */)
{
hb_set_t cur_intersected_glyphs;
hb_map_t done_lookups_glyph_count;
hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const OT::GSUB& gsub = *face->table.GSUB->table;
unsigned int iteration_count = 0;
@ -1890,7 +1888,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
apply_forward (c, accel);
if (!Proxy::inplace)
buffer->swap_buffers ();
buffer->sync ();
}
else
{

View file

@ -482,10 +482,9 @@ _hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
}
static inline uint8_t
_hb_allocate_lig_id (hb_buffer_t *buffer) {
_hb_allocate_lig_id (hb_buffer_t *buffer)
{
uint8_t lig_id = buffer->next_serial () & 0x07;
if (unlikely (!lig_id))
lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
return lig_id;
}

View file

@ -71,9 +71,9 @@ struct meta
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<meta> (face); }
void fini () { table.destroy (); }
~accelerator_t () { table.destroy (); }
hb_blob_t *reference_entry (hb_tag_t tag) const
{ return table->dataMaps.lsearch (tag).reference_entry (table.get_blob ()); }
@ -119,7 +119,9 @@ struct meta
DEFINE_SIZE_ARRAY (16, dataMaps);
};
struct meta_accelerator_t : meta::accelerator_t {};
struct meta_accelerator_t : meta::accelerator_t {
meta_accelerator_t (hb_face_t *face) : meta::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -160,9 +160,50 @@ hb_ot_metrics_get_position (hb_font_t *font,
(position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true))
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent);
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent);
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: return GET_METRIC_Y (hhea, caretSlopeRise);
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: return GET_METRIC_X (hhea, caretSlopeRun);
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE:
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN:
{
unsigned mult = 1u;
if (font->slant)
{
unsigned rise = face->table.hhea->caretSlopeRise;
unsigned upem = face->get_upem ();
mult = (rise && rise < upem) ? hb_min (upem / rise, 256u) : 1u;
}
if (metrics_tag == HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE)
{
bool ret = GET_METRIC_Y (hhea, caretSlopeRise);
if (position)
*position *= mult;
return ret;
}
else
{
hb_position_t rise = 0;
if (font->slant && position && GET_METRIC_Y (hhea, caretSlopeRise))
rise = *position;
bool ret = GET_METRIC_X (hhea, caretSlopeRun);
if (position)
{
*position *= mult;
if (font->slant)
*position += _hb_roundf (mult * font->slant_xy * rise);
}
return ret;
}
}
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: return GET_METRIC_X (hhea, caretOffset);
#ifndef HB_NO_VERTICAL
case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: return GET_METRIC_X (vhea, caretSlopeRise);
case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: return GET_METRIC_Y (vhea, caretSlopeRun);

View file

@ -256,7 +256,7 @@ struct name
})
;
name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
name_prime->serialize (c->serializer, it, std::addressof (this + stringOffset));
return_trace (name_prime->count);
}
@ -279,7 +279,7 @@ struct name
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{
this->table = hb_sanitize_context_t ().reference_table<name> (face);
assert (this->table.get_length () >= this->table->stringOffset);
@ -288,7 +288,6 @@ struct name
const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
this->table->count);
this->names.init ();
this->names.alloc (all_names.length);
for (unsigned int i = 0; i < all_names.length; i++)
@ -318,10 +317,8 @@ struct name
}
this->names.resize (j);
}
void fini ()
~accelerator_t ()
{
this->names.fini ();
this->table.destroy ();
}
@ -373,7 +370,9 @@ struct name
#undef entry_index
#undef entry_score
struct name_accelerator_t : name::accelerator_t {};
struct name_accelerator_t : name::accelerator_t {
name_accelerator_t (hb_face_t *face) : name::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -76,8 +76,7 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
hb_map_t old_new_index_map, old_gid_new_index_map;
unsigned i = 0;
post::accelerator_t _post;
_post.init (c->plan->source);
post::accelerator_t _post (c->plan->source);
hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index;
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
@ -128,9 +127,7 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
})
;
bool ret = serialize (c->serializer, index_iter, &_post);
_post.fini ();
return_trace (ret);
return_trace (serialize (c->serializer, index_iter, &_post));
}
} /* namespace OT */

View file

@ -111,10 +111,9 @@ struct post
struct accelerator_t
{
friend struct postV2Tail;
void init (hb_face_t *face)
{
index_to_offset.init ();
accelerator_t (hb_face_t *face)
{
table = hb_sanitize_context_t ().reference_table<post> (face);
unsigned int table_length = table.get_length ();
@ -132,9 +131,8 @@ struct post
data += 1 + *data)
index_to_offset.push (data - pool);
}
void fini ()
~accelerator_t ()
{
index_to_offset.fini ();
hb_free (gids_sorted_by_name.get ());
table.destroy ();
}
@ -254,9 +252,9 @@ struct post
private:
uint32_t version;
const Array16Of<HBUINT16> *glyphNameIndex;
const Array16Of<HBUINT16> *glyphNameIndex = nullptr;
hb_vector_t<uint32_t> index_to_offset;
const uint8_t *pool;
const uint8_t *pool = nullptr;
hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
};
@ -307,7 +305,10 @@ struct post
DEFINE_SIZE_MIN (32);
};
struct post_accelerator_t : post::accelerator_t {};
struct post_accelerator_t : post::accelerator_t {
post_accelerator_t (hb_face_t *face) : post::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -87,6 +87,8 @@
#define OT_GLYPHID /* GlyphID */ \
OT_UINT16
/* Shorthand. */
#define G OT_GLYPHID
#define OT_UARRAY(Name, Items) \
OT_LABEL_START(Name) \
@ -183,8 +185,6 @@
Tag \
OT_OFFSET(manifest, Name)
/* Shorthand. */
#define G OT_GLYPHID
/*
* Table Start
@ -300,14 +300,40 @@ OT_TABLE_END
/*
* Clean up
*/
#undef MANIFEST
#undef MANIFEST_LOOKUP
#undef OT_TABLE_START
#undef OT_TABLE_END
#undef OT_LABEL_START
#undef OT_LABEL_END
#undef OT_UINT8
#undef OT_UINT16
#undef OT_DISTANCE
#undef OT_COUNT
#undef OT_DISTANCE
#undef OT_LABEL
#undef OT_LIST
#undef OT_TAG
#undef OT_OFFSET
#undef OT_GLYPHID
#undef G
#undef OT_UARRAY
#undef OT_UHEADLESSARRAY
#undef OT_LOOKUP_FLAG_IGNORE_MARKS
#undef OT_LOOKUP
#undef OT_SUBLOOKUP
#undef OT_COVERAGE1
#undef OT_LOOKUP_TYPE_SUBST_SINGLE
#undef OT_LOOKUP_TYPE_SUBST_LIGATURE
#undef OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2
#undef OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1
#undef OT_LIGATURE_SET
#undef OT_LIGATURE
/*
* Include a second time to get the table data...

View file

@ -321,6 +321,20 @@ arabic_joining (hb_buffer_t *buffer)
info[prev].arabic_shaping_action() = entry->prev_action;
buffer->unsafe_to_break (prev, i + 1);
}
else
{
if (prev == UINT_MAX)
{
if (this_type >= JOINING_TYPE_R)
buffer->unsafe_to_concat_from_outbuffer (0, i + 1);
}
else
{
if (this_type >= JOINING_TYPE_R ||
(2 <= state && state <= 5) /* States that have a possible prev_action. */)
buffer->unsafe_to_concat (prev, i + 1);
}
}
info[i].arabic_shaping_action() = entry->curr_action;
@ -337,7 +351,14 @@ arabic_joining (hb_buffer_t *buffer)
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
if (entry->prev_action != NONE && prev != UINT_MAX)
{
info[prev].arabic_shaping_action() = entry->prev_action;
buffer->unsafe_to_break (prev, buffer->len);
}
else if (2 <= state && state <= 5) /* States that have a possible prev_action. */
{
buffer->unsafe_to_concat (prev, buffer->len);
}
break;
}
}

View file

@ -140,7 +140,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
*
* - LV can be precomposed, or decomposed. Lets call those
* <LV> and <L,V>,
* - LVT can be fully precomposed, partically precomposed, or
* - LVT can be fully precomposed, partially precomposed, or
* fully decomposed. Ie. <LVT>, <LV,T>, or <L,V,T>.
*
* The composition / decomposition is mechanical. However, not
@ -392,7 +392,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
*/
(void) buffer->next_glyph ();
}
buffer->swap_buffers ();
buffer->sync ();
}
static void

View file

@ -96,7 +96,7 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
else
(void) buffer->next_glyph ();
}
buffer->swap_buffers ();
buffer->sync ();
}

View file

@ -364,7 +364,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
buffer->merge_out_clusters (start - 1, end);
}
}
buffer->swap_buffers ();
buffer->sync ();
/* If font has Thai GSUB, we are done. */
if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0])

View file

@ -435,7 +435,7 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
default:
break;
}
buffer->swap_buffers ();
buffer->sync ();
}

View file

@ -446,6 +446,9 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
return;
#endif
if (!buffer->message (font, "start fallback mark"))
return;
_hb_buffer_assert_gsubgpos_vars (buffer);
unsigned int start = 0;
@ -457,6 +460,8 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
start = i;
}
position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
(void) buffer->message (font, "end fallback mark");
}
@ -492,6 +497,9 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
#endif
#ifndef HB_DISABLE_DEPRECATED
if (!buffer->message (font, "start fallback kern"))
return;
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
!font->has_glyph_h_kerning_func () :
!font->has_glyph_v_kerning_func ())
@ -508,6 +516,8 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
if (reverse)
buffer->reverse ();
(void) buffer->message (font, "end fallback kern");
#endif
}
@ -525,6 +535,15 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
for (unsigned int i = 0; i < count; i++)
if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
{
/* If font had no ASCII space and we used the invisible glyph, give it a 1/4 EM default advance. */
if (buffer->invisible && info[i].codepoint == buffer->invisible)
{
if (horizontal)
pos[i].x_advance = +font->x_scale / 4;
else
pos[i].y_advance = -font->y_scale / 4;
}
hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
hb_codepoint_t glyph;
typedef hb_unicode_funcs_t t;

View file

@ -193,7 +193,8 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
{
hb_codepoint_t space_glyph;
hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u);
if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_nominal_glyph (0x0020u, &space_glyph))
if (space_type != hb_unicode_funcs_t::NOT_SPACE &&
(c->font->get_nominal_glyph (0x0020, &space_glyph) || (space_glyph = buffer->invisible)))
{
_hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type);
next_char (buffer, space_glyph);
@ -374,7 +375,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
decompose_multi_char_cluster (&c, end, always_short_circuit);
}
while (buffer->idx < count && buffer->successful);
buffer->swap_buffers ();
buffer->sync ();
}
@ -477,7 +478,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
if (info_cc (buffer->prev()) == 0)
starter = buffer->out_len - 1;
}
buffer->swap_buffers ();
buffer->sync ();
}
}

View file

@ -566,7 +566,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
info.mask = buffer->cur().mask;
(void) buffer->output_info (info);
buffer->swap_buffers ();
buffer->sync ();
}
static void
@ -1034,7 +1034,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
* hanging over the next glyph after the final reordering.
*
* Note: If fallback positinoing happens, we don't care about
* this as it will be overriden.
* this as it will be overridden.
*/
bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
@ -1120,7 +1120,7 @@ hb_propagate_flags (hb_buffer_t *buffer)
/* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
* Simplifies using them. */
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK))
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
return;
hb_glyph_info_t *info = buffer->info;
@ -1129,11 +1129,7 @@ hb_propagate_flags (hb_buffer_t *buffer)
{
unsigned int mask = 0;
for (unsigned int i = start; i < end; i++)
if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
{
mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
break;
}
mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
if (mask)
for (unsigned int i = start; i < end; i++)
info[i].mask |= mask;
@ -1145,18 +1141,7 @@ hb_propagate_flags (hb_buffer_t *buffer)
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
c->buffer->deallocate_var_all ();
c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
{
c->buffer->max_len = hb_max (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
(unsigned) HB_BUFFER_MAX_LEN_MIN);
}
if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
{
c->buffer->max_ops = hb_max (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
(unsigned) HB_BUFFER_MAX_OPS_MIN);
}
c->buffer->enter ();
/* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
@ -1188,9 +1173,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
c->buffer->props.direction = c->target_direction;
c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
c->buffer->deallocate_var_all ();
c->buffer->leave ();
}

View file

@ -6,8 +6,8 @@
*
* on files with these headers:
*
* <meta name="updated_at" content="2021-12-09 12:01 AM" />
* File-Date: 2021-08-06
* <meta name="updated_at" content="2022-01-28 10:00 PM" />
* File-Date: 2021-12-29
*/
#ifndef HB_OT_TAG_TABLE_HH
@ -66,7 +66,7 @@ static const LangTag ot_languages[] = {
{"an", HB_TAG('A','R','G',' ')}, /* Aragonese */
/*{"ang", HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */
{"aoa", HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */
{"apa", HB_TAG('A','T','H',' ')}, /* Apache [family] -> Athapaskan */
{"apa", HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */
{"apc", HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */
{"apd", HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */
{"apj", HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */
@ -86,7 +86,7 @@ static const LangTag ot_languages[] = {
{"arz", HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */
{"as", HB_TAG('A','S','M',' ')}, /* Assamese */
/*{"ast", HB_TAG('A','S','T',' ')},*/ /* Asturian */
/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [family] -> Athapaskan */
/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */
{"atj", HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */
{"atv", HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */
{"auj", HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */
@ -110,10 +110,10 @@ static const LangTag ot_languages[] = {
{"azn", HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */
{"azz", HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */
{"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */
{"bad", HB_TAG('B','A','D','0')}, /* Banda [family] */
{"bad", HB_TAG('B','A','D','0')}, /* Banda [collection] */
{"bag", HB_TAG_NONE }, /* Tuki != Baghelkhandi */
{"bah", HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */
{"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [family] */
{"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */
{"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */
/*{"ban", HB_TAG('B','A','N',' ')},*/ /* Balinese */
/*{"bar", HB_TAG('B','A','R',' ')},*/ /* Bavarian */
@ -135,7 +135,7 @@ static const LangTag ot_languages[] = {
{"bea", HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */
{"beb", HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */
/*{"bem", HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */
{"ber", HB_TAG('B','B','R',' ')}, /* Berber [family] */
{"ber", HB_TAG('B','B','R',' ')}, /* Berber [collection] */
{"bew", HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */
{"bfl", HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */
{"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */
@ -203,7 +203,7 @@ static const LangTag ot_languages[] = {
{"btd", HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */
{"bti", HB_TAG_NONE }, /* Burate != Beti */
{"btj", HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */
/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [family] */
/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */
{"btm", HB_TAG('B','T','M',' ')}, /* Batak Mandailing */
{"btm", HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */
{"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */
@ -256,6 +256,8 @@ static const LangTag ot_languages[] = {
{"chh", HB_TAG_NONE }, /* Chinook != Chattisgarhi */
{"chj", HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */
{"chk", HB_TAG('C','H','K','0')}, /* Chuukese */
{"chm", HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */
{"chm", HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */
{"chn", HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */
/*{"cho", HB_TAG('C','H','O',' ')},*/ /* Choctaw */
{"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */
@ -297,10 +299,10 @@ static const LangTag ot_languages[] = {
/*{"cop", HB_TAG('C','O','P',' ')},*/ /* Coptic */
{"coq", HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */
{"cpa", HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */
{"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [family] -> Creoles */
{"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [family] -> Creoles */
{"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */
{"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */
{"cpi", HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */
/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [family] -> Creoles */
/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */
{"cpx", HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */
{"cqd", HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */
{"cqu", HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
@ -320,7 +322,7 @@ static const LangTag ot_languages[] = {
{"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */
{"crm", HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */
{"crm", HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */
{"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [family] -> Creoles */
{"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */
{"crr", HB_TAG_NONE }, /* Carolina Algonquian != Carrier */
{"crs", HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */
{"crt", HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */
@ -431,7 +433,7 @@ static const LangTag ot_languages[] = {
{"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
{"eto", HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */
{"eu", HB_TAG('E','U','Q',' ')}, /* Basque */
{"euq", HB_TAG_NONE }, /* Basque [family] != Basque */
{"euq", HB_TAG_NONE }, /* Basque [collection] != Basque */
{"eve", HB_TAG('E','V','N',' ')}, /* Even */
{"evn", HB_TAG('E','V','K',' ')}, /* Evenki */
{"ewo", HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */
@ -620,10 +622,11 @@ static const LangTag ot_languages[] = {
{"ijc", HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */
{"ije", HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */
{"ijn", HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */
/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [family] */
/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */
{"ijs", HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */
{"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */
{"ike", HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */
{"ike", HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */
{"ikt", HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */
/*{"ilo", HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */
{"in", HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */
@ -638,6 +641,7 @@ static const LangTag ot_languages[] = {
{"it", HB_TAG('I','T','A',' ')}, /* Italian */
{"itz", HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */
{"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */
{"iu", HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */
{"iw", HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */
{"ixl", HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */
{"ja", HB_TAG('J','A','N',' ')}, /* Japanese */
@ -667,7 +671,7 @@ static const LangTag ot_languages[] = {
{"kab", HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */
{"kac", HB_TAG_NONE }, /* Kachin != Kachchi */
{"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
{"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */
{"kar", HB_TAG('K','R','N',' ')}, /* Karen [collection] */
/*{"kaw", HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
{"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */
{"kby", HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
@ -876,7 +880,7 @@ static const LangTag ot_languages[] = {
{"mam", HB_TAG('M','A','M',' ')}, /* Mam */
{"mam", HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */
{"man", HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */
{"map", HB_TAG_NONE }, /* Austronesian [family] != Mapudungun */
{"map", HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */
{"maw", HB_TAG_NONE }, /* Mampruli != Marwari */
{"max", HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */
{"max", HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */
@ -936,6 +940,7 @@ static const LangTag ot_languages[] = {
{"mnw", HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */
{"mnx", HB_TAG_NONE }, /* Manikion != Manx */
{"mo", HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */
{"mo", HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */
{"mod", HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */
/*{"moh", HB_TAG('M','O','H',' ')},*/ /* Mohawk */
{"mok", HB_TAG_NONE }, /* Morori != Moksha */
@ -958,7 +963,7 @@ static const LangTag ot_languages[] = {
{"mts", HB_TAG_NONE }, /* Yora != Maltese */
{"mud", HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */
{"mui", HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */
{"mun", HB_TAG_NONE }, /* Munda [family] != Mundari */
{"mun", HB_TAG_NONE }, /* Munda [collection] != Mundari */
{"mup", HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */
{"muq", HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */
/*{"mus", HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */
@ -973,7 +978,7 @@ static const LangTag ot_languages[] = {
{"mww", HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */
{"my", HB_TAG('B','R','M',' ')}, /* Burmese */
{"mym", HB_TAG('M','E','N',' ')}, /* Meen */
/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [family] */
/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */
{"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */
{"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */
{"mzb", HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */
@ -982,7 +987,7 @@ static const LangTag ot_languages[] = {
{"na", HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */
{"nag", HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */
{"nag", HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */
/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [family] */
/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */
{"nan", HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */
/*{"nap", HB_TAG('N','A','P',' ')},*/ /* Neapolitan */
{"nas", HB_TAG_NONE }, /* Naasioi != Naskapi */
@ -1039,7 +1044,6 @@ static const LangTag ot_languages[] = {
{"nln", HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */
{"nlv", HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */
{"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */
{"nn", HB_TAG('N','O','R',' ')}, /* Norwegian Nynorsk -> Norwegian */
{"nnh", HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */
{"nnz", HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */
{"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */
@ -1093,7 +1097,7 @@ static const LangTag ot_languages[] = {
{"otw", HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */
{"oua", HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */
{"pa", HB_TAG('P','A','N',' ')}, /* Punjabi */
{"paa", HB_TAG_NONE }, /* Papuan [family] != Palestinian Aramaic */
{"paa", HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */
/*{"pag", HB_TAG('P','A','G',' ')},*/ /* Pangasinan */
{"pal", HB_TAG_NONE }, /* Pahlavi != Pali */
/*{"pam", HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */
@ -1308,6 +1312,9 @@ static const LangTag ot_languages[] = {
{"sgo", HB_TAG_NONE }, /* Songa (retired code) != Sango */
/*{"sgs", HB_TAG('S','G','S',' ')},*/ /* Samogitian */
{"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */
{"sh", HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */
{"sh", HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */
{"sh", HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */
{"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */
{"shi", HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */
{"shl", HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */
@ -1329,7 +1336,7 @@ static const LangTag ot_languages[] = {
{"skw", HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */
{"sky", HB_TAG_NONE }, /* Sikaiana != Slovak */
{"sl", HB_TAG('S','L','V',' ')}, /* Slovenian */
{"sla", HB_TAG_NONE }, /* Slavic [family] != Slavey */
{"sla", HB_TAG_NONE }, /* Slavic [collection] != Slavey */
{"sm", HB_TAG('S','M','O',' ')}, /* Samoan */
{"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */
{"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */
@ -1451,7 +1458,7 @@ static const LangTag ot_languages[] = {
{"tpi", HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */
{"tr", HB_TAG('T','R','K',' ')}, /* Turkish */
{"trf", HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */
{"trk", HB_TAG_NONE }, /* Turkic [family] != Turkish */
{"trk", HB_TAG_NONE }, /* Turkic [collection] != Turkish */
{"tru", HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */
{"tru", HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */
{"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */
@ -1593,7 +1600,7 @@ static const LangTag ot_languages[] = {
{"zlq", HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */
{"zmi", HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */
{"zmz", HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */
{"znd", HB_TAG_NONE }, /* Zande [family] != Zande */
{"znd", HB_TAG_NONE }, /* Zande [collection] != Zande */
{"zne", HB_TAG('Z','N','D',' ')}, /* Zande */
{"zom", HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */
{"zqe", HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */
@ -2607,14 +2614,8 @@ hb_ot_tags_from_complex_language (const char *lang_str,
if (0 == strcmp (&lang_str[1], "o-nyn"))
{
/* Norwegian Nynorsk (retired code) */
unsigned int i;
hb_tag_t possible_tags[] = {
HB_TAG('N','Y','N',' '), /* Norwegian Nynorsk (Nynorsk, Norwegian) */
HB_TAG('N','O','R',' '), /* Norwegian */
};
for (i = 0; i < 2 && i < *count; i++)
tags[i] = possible_tags[i];
*count = i;
tags[0] = HB_TAG('N','Y','N',' '); /* Norwegian Nynorsk (Nynorsk, Norwegian) */
*count = 1;
return true;
}
break;
@ -2623,8 +2624,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
&& subtag_matches (lang_str, limit, "-md"))
{
/* Romanian; Moldova */
tags[0] = HB_TAG('M','O','L',' '); /* Moldavian */
*count = 1;
unsigned int i;
hb_tag_t possible_tags[] = {
HB_TAG('M','O','L',' '), /* Moldavian */
HB_TAG('R','O','M',' '), /* Romanian */
};
for (i = 0; i < 2 && i < *count; i++)
tags[i] = possible_tags[i];
*count = i;
return true;
}
break;
@ -2813,15 +2820,15 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
case HB_TAG('A','R','K',' '): /* Rakhine */
return hb_language_from_string ("rki", -1); /* Rakhine */
case HB_TAG('A','T','H',' '): /* Athapaskan */
return hb_language_from_string ("ath", -1); /* Athapascan [family] */
return hb_language_from_string ("ath", -1); /* Athapascan [collection] */
case HB_TAG('B','B','R',' '): /* Berber */
return hb_language_from_string ("ber", -1); /* Berber [family] */
return hb_language_from_string ("ber", -1); /* Berber [collection] */
case HB_TAG('B','I','K',' '): /* Bikol */
return hb_language_from_string ("bik", -1); /* Bikol [macrolanguage] */
case HB_TAG('B','T','K',' '): /* Batak */
return hb_language_from_string ("btk", -1); /* Batak [family] */
return hb_language_from_string ("btk", -1); /* Batak [collection] */
case HB_TAG('C','P','P',' '): /* Creoles */
return hb_language_from_string ("crp", -1); /* Creoles and pidgins [family] */
return hb_language_from_string ("crp", -1); /* Creoles and pidgins [collection] */
case HB_TAG('C','R','R',' '): /* Carrier */
return hb_language_from_string ("crx", -1); /* Carrier */
case HB_TAG('D','G','R',' '): /* Dogri (macrolanguage) */
@ -2838,6 +2845,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("fa", -1); /* Persian [macrolanguage] */
case HB_TAG('G','O','N',' '): /* Gondi */
return hb_language_from_string ("gon", -1); /* Gondi [macrolanguage] */
case HB_TAG('H','M','A',' '): /* High Mari */
return hb_language_from_string ("mrj", -1); /* Western Mari */
case HB_TAG('H','M','N',' '): /* Hmong */
return hb_language_from_string ("hmn", -1); /* Hmong [macrolanguage] */
case HB_TAG('H','N','D',' '): /* Hindko */
@ -2847,7 +2856,7 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
case HB_TAG('I','B','A',' '): /* Iban */
return hb_language_from_string ("iba", -1); /* Iban */
case HB_TAG('I','J','O',' '): /* Ijo */
return hb_language_from_string ("ijo", -1); /* Ijo [family] */
return hb_language_from_string ("ijo", -1); /* Ijo [collection] */
case HB_TAG('I','N','U',' '): /* Inuktitut */
return hb_language_from_string ("iu", -1); /* Inuktitut [macrolanguage] */
case HB_TAG('I','P','K',' '): /* Inupiat */
@ -2873,11 +2882,13 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
case HB_TAG('K','P','L',' '): /* Kpelle */
return hb_language_from_string ("kpe", -1); /* Kpelle [macrolanguage] */
case HB_TAG('K','R','N',' '): /* Karen */
return hb_language_from_string ("kar", -1); /* Karen [family] */
return hb_language_from_string ("kar", -1); /* Karen [collection] */
case HB_TAG('K','U','I',' '): /* Kui */
return hb_language_from_string ("uki", -1); /* Kui (India) */
case HB_TAG('K','U','R',' '): /* Kurdish */
return hb_language_from_string ("ku", -1); /* Kurdish [macrolanguage] */
case HB_TAG('L','M','A',' '): /* Low Mari */
return hb_language_from_string ("mhr", -1); /* Eastern Mari */
case HB_TAG('L','U','H',' '): /* Luyia */
return hb_language_from_string ("luy", -1); /* Luyia [macrolanguage] */
case HB_TAG('L','V','I',' '): /* Latvian */
@ -2897,9 +2908,9 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
case HB_TAG('M','O','N','T'): /* Thailand Mon */
return hb_language_from_string ("mnw-TH", -1); /* Mon; Thailand */
case HB_TAG('M','Y','N',' '): /* Mayan */
return hb_language_from_string ("myn", -1); /* Mayan [family] */
return hb_language_from_string ("myn", -1); /* Mayan [collection] */
case HB_TAG('N','A','H',' '): /* Nahuatl */
return hb_language_from_string ("nah", -1); /* Nahuatl [family] */
return hb_language_from_string ("nah", -1); /* Nahuatl [collection] */
case HB_TAG('N','E','P',' '): /* Nepali */
return hb_language_from_string ("ne", -1); /* Nepali [macrolanguage] */
case HB_TAG('N','I','S',' '): /* Nisi */
@ -2926,6 +2937,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("qwh", -1); /* Huaylas Ancash Quechua */
case HB_TAG('R','A','J',' '): /* Rajasthani */
return hb_language_from_string ("raj", -1); /* Rajasthani [macrolanguage] */
case HB_TAG('R','O','M',' '): /* Romanian */
return hb_language_from_string ("ro", -1); /* Romanian */
case HB_TAG('R','O','Y',' '): /* Romany */
return hb_language_from_string ("rom", -1); /* Romany [macrolanguage] */
case HB_TAG('S','Q','I',' '): /* Albanian */

View file

@ -263,7 +263,7 @@ struct fvar
if (coords_length && *coords_length)
{
hb_array_t<const HBFixed> instanceCoords = instance->get_coordinates (axisCount)
.sub_array (0, *coords_length);
.sub_array (0, coords_length);
for (unsigned int i = 0; i < instanceCoords.length; i++)
coords[i] = instanceCoords.arrayZ[i].to_float ();
}

View file

@ -399,7 +399,7 @@ struct gvar
get_offset (glyphCount) - get_offset (0)));
}
/* GlyphVariationData not sanitized here; must be checked while accessing each glyph varation data */
/* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
bool sanitize (hb_sanitize_context_t *c) const
{ return sanitize_shallow (c); }
@ -498,9 +498,9 @@ struct gvar
public:
struct accelerator_t
{
void init (hb_face_t *face)
accelerator_t (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<gvar> (face); }
void fini () { table.destroy (); }
~accelerator_t () { table.destroy (); }
private:
struct x_getter { static float get (const contour_point_t &p) { return p.x; } };
@ -698,7 +698,9 @@ no_more_gaps:
DEFINE_SIZE_MIN (20);
};
struct gvar_accelerator_t : gvar::accelerator_t {};
struct gvar_accelerator_t : gvar::accelerator_t {
gvar_accelerator_t (hb_face_t *face) : gvar::accelerator_t (face) {}
};
} /* namespace OT */

View file

@ -177,9 +177,6 @@ struct hvarvvar_subset_plan_t
inner_maps.resize (var_store->get_sub_table_count ());
for (unsigned int i = 0; i < inner_maps.length; i++)
inner_maps[i].init ();
if (unlikely (!index_map_plans.length || !inner_sets.length || !inner_maps.length)) return;
bool retain_adv_map = false;
@ -229,8 +226,8 @@ struct hvarvvar_subset_plan_t
for (unsigned int i = 0; i < inner_sets.length; i++)
hb_set_destroy (inner_sets[i]);
hb_set_destroy (adv_set);
inner_maps.fini_deep ();
index_map_plans.fini_deep ();
inner_maps.fini ();
index_map_plans.fini ();
}
hb_inc_bimap_t outer_map;

View file

@ -303,6 +303,9 @@ hb_ot_var_normalize_variations (hb_face_t *face,
* values for the axis are mapped to the interval [-1,1], with the default
* axis value mapped to 0.
*
* The normalized values have 14 bits of fixed-point sub-integer precision as per
* OpenType specification.
*
* Any additional scaling defined in the face's `avar` table is also
* applied, as described at https://docs.microsoft.com/en-us/typography/opentype/spec/avar
*

View file

@ -109,7 +109,7 @@ typedef enum { /*< flags >*/
* @tag: The #hb_tag_t tag identifying the design variation of the axis
* @name_id: The `name` table Name ID that provides display names for the axis
* @flags: The #hb_ot_var_axis_flags_t flags for the axis
* @min_value: The mininum value on the variation axis that the font covers
* @min_value: The minimum value on the variation axis that the font covers
* @default_value: The position on the variation axis corresponding to the font's defaults
* @max_value: The maximum value on the variation axis that the font covers
*

View file

@ -42,26 +42,13 @@ struct graph_t
{
struct vertex_t
{
vertex_t () :
distance (0),
space (0),
parents (),
start (0),
end (0),
priority(0) {}
void fini () {
obj.fini ();
parents.fini ();
}
hb_serialize_context_t::object_t obj;
int64_t distance;
int64_t space;
int64_t distance = 0 ;
int64_t space = 0 ;
hb_vector_t<unsigned> parents;
unsigned start;
unsigned end;
unsigned priority;
unsigned start = 0;
unsigned end = 0;
unsigned priority = 0;
bool is_shared () const
{
@ -186,7 +173,7 @@ struct graph_t
~graph_t ()
{
vertices_.fini_deep ();
vertices_.fini ();
}
bool in_error () const
@ -309,7 +296,7 @@ struct graph_t
remap_all_obj_indices (id_map, &sorted_graph);
hb_swap (vertices_, sorted_graph);
sorted_graph.fini_deep ();
sorted_graph.fini ();
}
/*
@ -369,7 +356,7 @@ struct graph_t
remap_all_obj_indices (id_map, &sorted_graph);
hb_swap (vertices_, sorted_graph);
sorted_graph.fini_deep ();
sorted_graph.fini ();
}
/*
@ -402,11 +389,15 @@ struct graph_t
while (roots)
{
unsigned next = HB_SET_VALUE_INVALID;
if (unlikely (!check_success (!roots.in_error ()))) break;
if (!roots.next (&next)) break;
hb_set_t connected_roots;
find_connected_nodes (next, roots, visited, connected_roots);
if (unlikely (!check_success (!connected_roots.in_error ()))) break;
isolate_subgraph (connected_roots);
if (unlikely (!check_success (!connected_roots.in_error ()))) break;
unsigned next_space = this->next_space ();
num_roots_for_space_.push (0);
@ -423,6 +414,8 @@ struct graph_t
// into the 32 bit space as needed, instead of using isolation.
}
return true;
}
@ -865,7 +858,7 @@ struct graph_t
// Redundant ones are filtered out later on by the visited set.
// According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
// for practical performance this is faster then using a more advanced queue
// (such as a fibonaacci queue) with a fast decrease priority.
// (such as a fibonacci queue) with a fast decrease priority.
for (unsigned i = 0; i < vertices_.length; i++)
{
if (i == vertices_.length - 1)
@ -1074,6 +1067,7 @@ struct graph_t
hb_set_t& visited,
hb_set_t& connected)
{
if (unlikely (!check_success (!visited.in_error ()))) return;
if (visited.has (start_idx)) return;
visited.add (start_idx);

View file

@ -279,7 +279,7 @@ struct hb_serialize_context_t
object_pool.release (obj);
}
/* Set share to false when an object is unlikely sharable with others
/* Set share to false when an object is unlikely shareable with others
* so not worth an attempt, or a contiguous table is serialized as
* multiple consecutive objects in the reverse order so can't be shared.
*/
@ -381,7 +381,7 @@ struct hb_serialize_context_t
// Adding a virtual link from object a to object b will ensure that object b is always packed after
// object a in the final serialized order.
//
// This is useful in certain situtations where there needs to be a specific ordering in the
// This is useful in certain situations where there needs to be a specific ordering in the
// final serialization. Such as when platform bugs require certain orderings, or to provide
// guidance to the repacker for better offset overflow resolution.
void add_virtual_link (objidx_t objidx)
@ -510,7 +510,7 @@ struct hb_serialize_context_t
{ return reinterpret_cast<Type *> (this->head); }
template <typename Type>
Type *start_embed (const Type &obj) const
{ return start_embed (hb_addressof (obj)); }
{ return start_embed (std::addressof (obj)); }
bool err (hb_serialize_error_t err_type)
{
@ -548,7 +548,7 @@ struct hb_serialize_context_t
}
template <typename Type>
Type *embed (const Type &obj)
{ return embed (hb_addressof (obj)); }
{ return embed (std::addressof (obj)); }
template <typename Type, typename ...Ts> auto
_copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN
@ -595,19 +595,19 @@ struct hb_serialize_context_t
}
template <typename Type>
Type *extend_size (Type &obj, size_t size)
{ return extend_size (hb_addressof (obj), size); }
{ return extend_size (std::addressof (obj), size); }
template <typename Type>
Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); }
template <typename Type>
Type *extend_min (Type &obj) { return extend_min (hb_addressof (obj)); }
Type *extend_min (Type &obj) { return extend_min (std::addressof (obj)); }
template <typename Type, typename ...Ts>
Type *extend (Type *obj, Ts&&... ds)
{ return extend_size (obj, obj->get_size (std::forward<Ts> (ds)...)); }
template <typename Type, typename ...Ts>
Type *extend (Type &obj, Ts&&... ds)
{ return extend (hb_addressof (obj), std::forward<Ts> (ds)...); }
{ return extend (std::addressof (obj), std::forward<Ts> (ds)...); }
/* Output routines. */
hb_bytes_t copy_bytes () const

View file

@ -48,13 +48,12 @@ _hb_angle_to_ratio (float a)
{
return tanf (a * float (M_PI / 180.));
}
#if 0
static inline float
_hb_ratio_to_angle (float r)
{
return atanf (r) * float (180. / M_PI);
}
#endif
/**
* hb_style_get_value:
@ -73,7 +72,8 @@ float
hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag)
{
if (unlikely (style_tag == HB_STYLE_TAG_SLANT_RATIO))
return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE));
return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE))
+ font->slant;
hb_face_t *face = font->face;
@ -109,7 +109,14 @@ hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag)
: 12.f;
}
case HB_STYLE_TAG_SLANT_ANGLE:
return face->table.post->table->italicAngle.to_float ();
{
float angle = face->table.post->table->italicAngle.to_float ();
if (font->slant)
angle = _hb_ratio_to_angle (font->slant + _hb_angle_to_ratio (angle));
return angle;
}
case HB_STYLE_TAG_WIDTH:
return face->table.OS2->has_data ()
? face->table.OS2->get_width ()

View file

@ -275,60 +275,36 @@ struct subr_flattener_t
struct subr_closures_t
{
subr_closures_t () : valid (false), global_closure (nullptr)
{ local_closures.init (); }
void init (unsigned int fd_count)
subr_closures_t (unsigned int fd_count) : valid (false), global_closure (), local_closures ()
{
valid = true;
global_closure = hb_set_create ();
if (global_closure == hb_set_get_empty ())
valid = false;
if (!local_closures.resize (fd_count))
valid = false;
for (unsigned int i = 0; i < local_closures.length; i++)
{
local_closures[i] = hb_set_create ();
if (local_closures[i] == hb_set_get_empty ())
valid = false;
}
}
void fini ()
{
hb_set_destroy (global_closure);
for (unsigned int i = 0; i < local_closures.length; i++)
hb_set_destroy (local_closures[i]);
local_closures.fini ();
}
void reset ()
{
hb_set_clear (global_closure);
global_closure.clear();
for (unsigned int i = 0; i < local_closures.length; i++)
hb_set_clear (local_closures[i]);
local_closures[i].clear();
}
bool is_valid () const { return valid; }
bool valid;
hb_set_t *global_closure;
hb_vector_t<hb_set_t *> local_closures;
hb_set_t global_closure;
hb_vector_t<hb_set_t> local_closures;
};
struct parsed_cs_op_t : op_str_t
{
void init (unsigned int subr_num_ = 0)
{
op_str_t::init ();
subr_num = subr_num_;
drop_flag = false;
keep_flag = false;
skip_flag = false;
}
void fini () { op_str_t::fini (); }
bool for_drop () const { return drop_flag; }
void set_drop () { if (!for_keep ()) drop_flag = true; }
@ -416,16 +392,6 @@ struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
{
void init (unsigned int len_ = 0)
{
SUPER::init ();
if (unlikely (!resize (len_)))
return;
for (unsigned int i = 0; i < length; i++)
(*this)[i].init ();
}
void fini () { SUPER::fini_deep (); }
private:
typedef hb_vector_t<parsed_cs_str_t> SUPER;
};
@ -496,7 +462,7 @@ struct subr_subset_param_t
struct subr_remap_t : hb_inc_bimap_t
{
void create (hb_set_t *closure)
void create (const hb_set_t *closure)
{
/* create a remapping of subroutine numbers from old to new.
* no optimization based on usage counts. fonttools doesn't appear doing that either.
@ -526,19 +492,9 @@ struct subr_remap_t : hb_inc_bimap_t
struct subr_remaps_t
{
subr_remaps_t ()
subr_remaps_t (unsigned int fdCount)
{
global_remap.init ();
local_remaps.init ();
}
~subr_remaps_t () { fini (); }
void init (unsigned int fdCount)
{
if (unlikely (!local_remaps.resize (fdCount))) return;
for (unsigned int i = 0; i < fdCount; i++)
local_remaps[i].init ();
local_remaps.resize (fdCount);
}
bool in_error()
@ -548,15 +504,9 @@ struct subr_remaps_t
void create (subr_closures_t& closures)
{
global_remap.create (closures.global_closure);
global_remap.create (&closures.global_closure);
for (unsigned int i = 0; i < local_remaps.length; i++)
local_remaps[i].create (closures.local_closures[i]);
}
void fini ()
{
global_remap.fini ();
local_remaps.fini_deep ();
local_remaps[i].create (&closures.local_closures[i]);
}
subr_remap_t global_remap;
@ -567,21 +517,8 @@ template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typena
struct subr_subsetter_t
{
subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_)
: acc (acc_), plan (plan_)
{
parsed_charstrings.init ();
parsed_global_subrs.init ();
parsed_local_subrs.init ();
}
~subr_subsetter_t ()
{
closures.fini ();
remaps.fini ();
parsed_charstrings.fini_deep ();
parsed_global_subrs.fini_deep ();
parsed_local_subrs.fini_deep ();
}
: acc (acc_), plan (plan_), closures(acc_.fdCount), remaps(acc_.fdCount)
{}
/* Subroutine subsetting with --no-desubroutinize runs in phases:
*
@ -599,11 +536,8 @@ struct subr_subsetter_t
*/
bool subset (void)
{
closures.init (acc.fdCount);
remaps.init (acc.fdCount);
parsed_charstrings.init (plan->num_output_glyphs ());
parsed_global_subrs.init (acc.globalSubrs->count);
parsed_charstrings.resize (plan->num_output_glyphs ());
parsed_global_subrs.resize (acc.globalSubrs->count);
if (unlikely (remaps.in_error()
|| parsed_charstrings.in_error ()
@ -615,7 +549,7 @@ struct subr_subsetter_t
for (unsigned int i = 0; i < acc.fdCount; i++)
{
parsed_local_subrs[i].init (acc.privateDicts[i].localSubrs->count);
parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count);
if (unlikely (parsed_local_subrs[i].in_error ())) return false;
}
if (unlikely (!closures.valid))
@ -638,7 +572,7 @@ struct subr_subsetter_t
subr_subset_param_t param;
param.init (&parsed_charstrings[i],
&parsed_global_subrs, &parsed_local_subrs[fd],
closures.global_closure, closures.local_closures[fd],
&closures.global_closure, &closures.local_closures[fd],
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
if (unlikely (!interp.interpret (param)))
@ -662,7 +596,7 @@ struct subr_subsetter_t
subr_subset_param_t param;
param.init (&parsed_charstrings[i],
&parsed_global_subrs, &parsed_local_subrs[fd],
closures.global_closure, closures.local_closures[fd],
&closures.global_closure, &closures.local_closures[fd],
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
drop_hints_param_t drop;
@ -687,7 +621,7 @@ struct subr_subsetter_t
subr_subset_param_t param;
param.init (&parsed_charstrings[i],
&parsed_global_subrs, &parsed_local_subrs[fd],
closures.global_closure, closures.local_closures[fd],
&closures.global_closure, &closures.local_closures[fd],
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
collect_subr_refs_in_str (parsed_charstrings[i], param);
}

View file

@ -362,43 +362,11 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs
struct cff_subset_plan {
cff_subset_plan ()
: info (),
orig_fdcount (0),
subset_fdcount (1),
subset_fdselect_format (0),
drop_hints (false),
desubroutinize(false)
{
topdict_mod.init ();
subset_fdselect_ranges.init ();
fdmap.init ();
subset_charstrings.init ();
subset_globalsubrs.init ();
subset_localsubrs.init ();
fontdicts_mod.init ();
subset_enc_code_ranges.init ();
subset_enc_supp_codes.init ();
subset_charset_ranges.init ();
sidmap.init ();
for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
topDictModSIDs[i] = CFF_UNDEF_SID;
}
~cff_subset_plan ()
{
topdict_mod.fini ();
subset_fdselect_ranges.fini ();
fdmap.fini ();
subset_charstrings.fini_deep ();
subset_globalsubrs.fini_deep ();
subset_localsubrs.fini_deep ();
fontdicts_mod.fini ();
subset_enc_code_ranges.fini ();
subset_enc_supp_codes.fini ();
subset_charset_ranges.fini ();
sidmap.fini ();
}
void plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
{
const Encoding *encoding = acc.encoding;
@ -672,9 +640,9 @@ struct cff_subset_plan {
cff1_sub_table_info_t info;
unsigned int num_glyphs;
unsigned int orig_fdcount;
unsigned int subset_fdcount;
unsigned int subset_fdselect_format;
unsigned int orig_fdcount = 0;
unsigned int subset_fdcount = 1;
unsigned int subset_fdselect_format = 0;
hb_vector_t<code_pair_t> subset_fdselect_ranges;
/* font dict index remap table from fullset FDArray to subset FDArray.
@ -686,7 +654,7 @@ struct cff_subset_plan {
hb_vector_t<str_buff_vec_t> subset_localsubrs;
hb_vector_t<cff1_font_dict_values_mod_t> fontdicts_mod;
bool drop_hints;
bool drop_hints = false;
bool gid_renum;
bool subset_encoding;
@ -702,7 +670,7 @@ struct cff_subset_plan {
remap_sid_t sidmap;
unsigned int topDictModSIDs[name_dict_values_t::ValCount];
bool desubroutinize;
bool desubroutinize = false;
};
static bool _serialize_cff1 (hb_serialize_context_t *c,

View file

@ -233,29 +233,6 @@ struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs
};
struct cff2_subset_plan {
cff2_subset_plan ()
: orig_fdcount (0),
subset_fdcount(1),
subset_fdselect_size (0),
subset_fdselect_format (0),
drop_hints (false),
desubroutinize (false)
{
subset_fdselect_ranges.init ();
fdmap.init ();
subset_charstrings.init ();
subset_globalsubrs.init ();
subset_localsubrs.init ();
}
~cff2_subset_plan ()
{
subset_fdselect_ranges.fini ();
fdmap.fini ();
subset_charstrings.fini_deep ();
subset_globalsubrs.fini_deep ();
subset_localsubrs.fini_deep ();
}
bool create (const OT::cff2::accelerator_subset_t &acc,
hb_subset_plan_t *plan)
@ -320,10 +297,10 @@ struct cff2_subset_plan {
cff2_sub_table_info_t info;
unsigned int orig_fdcount;
unsigned int subset_fdcount;
unsigned int subset_fdselect_size;
unsigned int subset_fdselect_format;
unsigned int orig_fdcount = 0;
unsigned int subset_fdcount = 1;
unsigned int subset_fdselect_size = 0;
unsigned int subset_fdselect_format = 0;
hb_vector_t<code_pair_t> subset_fdselect_ranges;
hb_inc_bimap_t fdmap;
@ -332,8 +309,8 @@ struct cff2_subset_plan {
str_buff_vec_t subset_globalsubrs;
hb_vector_t<str_buff_vec_t> subset_localsubrs;
bool drop_hints;
bool desubroutinize;
bool drop_hints = false;
bool desubroutinize = false;
};
static bool _serialize_cff2 (hb_serialize_context_t *c,
@ -473,12 +450,8 @@ _hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
bool
hb_subset_cff2 (hb_subset_context_t *c)
{
OT::cff2::accelerator_subset_t acc;
acc.init (c->plan->source);
bool result = likely (acc.is_valid ()) && _hb_subset_cff2 (acc, c);
acc.fini ();
return result;
OT::cff2::accelerator_subset_t acc (c->plan->source);
return acc.is_valid () && _hb_subset_cff2 (acc, c);
}
#endif

View file

@ -228,10 +228,8 @@ _cmap_closure (hb_face_t *face,
const hb_set_t *unicodes,
hb_set_t *glyphset)
{
OT::cmap::accelerator_t cmap;
cmap.init (face);
OT::cmap::accelerator_t cmap (face);
cmap.table->closure_glyphs (unicodes, glyphset);
cmap.fini ();
}
static void _colr_closure (hb_face_t *face,
@ -239,8 +237,7 @@ static void _colr_closure (hb_face_t *face,
hb_map_t *palettes_map,
hb_set_t *glyphs_colred)
{
OT::COLR::accelerator_t colr;
colr.init (face);
OT::COLR::accelerator_t colr (face);
if (!colr.is_valid ()) return;
unsigned iteration_count = 0;
@ -263,7 +260,6 @@ static void _colr_closure (hb_face_t *face,
colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
_remap_indexes (&layer_indices, layers_map);
_remap_palette_indexes (&palette_indices, palettes_map);
colr.fini ();
}
static inline void
@ -294,8 +290,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
const hb_set_t *glyphs,
hb_subset_plan_t *plan)
{
OT::cmap::accelerator_t cmap;
cmap.init (plan->source);
OT::cmap::accelerator_t cmap (plan->source);
constexpr static const int size_threshold = 4096;
@ -343,8 +338,6 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
+ plan->codepoint_to_glyph->keys () | hb_sink (plan->unicodes);
+ plan->codepoint_to_glyph->values () | hb_sink (plan->_glyphset_gsub);
cmap.fini ();
}
static void
@ -353,13 +346,9 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
bool close_over_gpos,
bool close_over_gdef)
{
OT::glyf::accelerator_t glyf;
OT::glyf::accelerator_t glyf (plan->source);
#ifndef HB_NO_SUBSET_CFF
OT::cff1::accelerator_t cff;
#endif
glyf.init (plan->source);
#ifndef HB_NO_SUBSET_CFF
cff.init (plan->source);
OT::cff1::accelerator_t cff (plan->source);
#endif
plan->_glyphset_gsub->add (0); // Not-def
@ -419,11 +408,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
plan->layout_variation_indices,
plan->layout_variation_idx_map);
#endif
#ifndef HB_NO_SUBSET_CFF
cff.fini ();
#endif
glyf.fini ();
}
static void

View file

@ -878,7 +878,8 @@ retry:
if (backward)
hb_buffer_reverse (buffer);
buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK);
buffer->clear_glyph_flags ();
buffer->unsafe_to_break ();
/* Wow, done! */
return true;

View file

@ -32,11 +32,14 @@
#include "hb-null.hh"
template <typename Type>
struct hb_vector_t
template <typename Type,
bool sorted=false>
struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty_t>::type
{
typedef Type item_t;
static constexpr unsigned item_size = hb_static_size (Type);
using array_t = typename std::conditional<sorted, hb_sorted_array_t<Type>, hb_array_t<Type>>::type;
using c_array_t = typename std::conditional<sorted, hb_sorted_array_t<const Type>, hb_array_t<const Type>>::type;
hb_vector_t () = default;
hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t ()
@ -82,16 +85,10 @@ struct hb_vector_t
void fini ()
{
shrink_vector (0);
hb_free (arrayZ);
init ();
}
void fini_deep ()
{
unsigned int count = length;
for (unsigned int i = 0; i < count; i++)
arrayZ[i].fini ();
fini ();
}
void reset ()
{
@ -152,24 +149,24 @@ struct hb_vector_t
template <typename T>
hb_vector_t& operator << (T&& v) { push (std::forward<T> (v)); return *this; }
hb_array_t< Type> as_array () { return hb_array (arrayZ, length); }
hb_array_t<const Type> as_array () const { return hb_array (arrayZ, length); }
array_t as_array () { return hb_array (arrayZ, length); }
c_array_t as_array () const { return hb_array (arrayZ, length); }
/* Iterator. */
typedef hb_array_t<const Type> iter_t;
typedef hb_array_t< Type> writer_t;
typedef c_array_t iter_t;
typedef array_t writer_t;
iter_t iter () const { return as_array (); }
writer_t writer () { return as_array (); }
operator iter_t () const { return iter (); }
operator writer_t () { return writer (); }
hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
c_array_t sub_array (unsigned int start_offset, unsigned int count) const
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
c_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
array_t sub_array (unsigned int start_offset, unsigned int count)
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
{ return as_array ().sub_array (start_offset, count); }
hb_sorted_array_t<Type> as_sorted_array ()
@ -192,6 +189,7 @@ struct hb_vector_t
template <typename T>
Type *push (T&& v)
{
/* TODO Emplace? */
Type *p = push ();
if (p == &Crap (Type))
// If push failed to allocate then don't copy v, since this may cause
@ -204,6 +202,92 @@ struct hb_vector_t
bool in_error () const { return allocated < 0; }
template <typename T = Type,
hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
Type *
realloc_vector (unsigned new_allocated)
{
return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
}
template <typename T = Type,
hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
Type *
realloc_vector (unsigned new_allocated)
{
Type *new_array = (Type *) hb_malloc (new_allocated * sizeof (Type));
if (likely (new_array))
{
for (unsigned i = 0; i < length; i++)
new (std::addressof (new_array[i])) Type ();
for (unsigned i = 0; i < (unsigned) length; i++)
new_array[i] = std::move (arrayZ[i]);
unsigned old_length = length;
shrink_vector (0);
length = old_length;
hb_free (arrayZ);
}
return new_array;
}
template <typename T = Type,
hb_enable_if (std::is_trivially_constructible<T>::value ||
!std::is_default_constructible<T>::value)>
void
grow_vector (unsigned size)
{
memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
length = size;
}
template <typename T = Type,
hb_enable_if (!std::is_trivially_constructible<T>::value &&
std::is_default_constructible<T>::value)>
void
grow_vector (unsigned size)
{
while (length < size)
{
length++;
new (std::addressof (arrayZ[length - 1])) Type ();
}
}
template <typename T = Type,
hb_enable_if (std::is_trivially_destructible<T>::value)>
void
shrink_vector (unsigned size)
{
length = size;
}
template <typename T = Type,
hb_enable_if (!std::is_trivially_destructible<T>::value)>
void
shrink_vector (unsigned size)
{
while ((unsigned) length > size)
{
arrayZ[(unsigned) length - 1].~Type ();
length--;
}
}
template <typename T = Type,
hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
void
shift_down_vector (unsigned i)
{
memmove (static_cast<void *> (&arrayZ[i - 1]),
static_cast<void *> (&arrayZ[i]),
(length - i) * sizeof (Type));
}
template <typename T = Type,
hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
void
shift_down_vector (unsigned i)
{
for (; i < length; i++)
arrayZ[i - 1] = std::move (arrayZ[i]);
}
/* Allocate for size but don't adjust length. */
bool alloc (unsigned int size)
{
@ -225,7 +309,7 @@ struct hb_vector_t
(new_allocated < (unsigned) allocated) ||
hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
if (likely (!overflows))
new_array = (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
new_array = realloc_vector (new_allocated);
if (unlikely (!new_array))
{
@ -246,7 +330,9 @@ struct hb_vector_t
return false;
if (size > length)
memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
grow_vector (size);
else if (size < length)
shrink_vector (size);
length = size;
return true;
@ -255,48 +341,38 @@ struct hb_vector_t
Type pop ()
{
if (!length) return Null (Type);
return std::move (arrayZ[--length]); /* Does this move actually work? */
Type v = std::move (arrayZ[length - 1]);
arrayZ[length - 1].~Type ();
length--;
return v;
}
void remove (unsigned int i)
{
if (unlikely (i >= length))
return;
memmove (static_cast<void *> (&arrayZ[i]),
static_cast<void *> (&arrayZ[i + 1]),
(length - i - 1) * sizeof (Type));
arrayZ[i].~Type ();
shift_down_vector (i + 1);
length--;
}
void shrink (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (size < length)
length = size;
if (size >= length)
return;
shrink_vector (size);
}
template <typename T>
Type *find (T v)
{
for (unsigned int i = 0; i < length; i++)
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
template <typename T>
const Type *find (T v) const
{
for (unsigned int i = 0; i < length; i++)
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
/* Sorting API. */
void qsort (int (*cmp)(const void*, const void*))
{ as_array ().qsort (cmp); }
void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
{ as_array ().qsort (start, end); }
/* Unsorted search API. */
template <typename T>
Type *lsearch (const T &x, Type *not_found = nullptr)
{ return as_array ().lsearch (x, not_found); }
@ -306,47 +382,25 @@ struct hb_vector_t
template <typename T>
bool lfind (const T &x, unsigned *pos = nullptr) const
{ return as_array ().lfind (x, pos); }
};
template <typename Type>
struct hb_sorted_vector_t : hb_vector_t<Type>
{
hb_sorted_vector_t () = default;
~hb_sorted_vector_t () = default;
hb_sorted_vector_t (hb_sorted_vector_t& o) = default;
hb_sorted_vector_t (hb_sorted_vector_t &&o) = default;
hb_sorted_vector_t (std::initializer_list<Type> lst) : hb_vector_t<Type> (lst) {}
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
hb_sorted_vector_t (const Iterable &o) : hb_vector_t<Type> (o) {}
hb_sorted_vector_t& operator = (const hb_sorted_vector_t &o) = default;
hb_sorted_vector_t& operator = (hb_sorted_vector_t &&o) = default;
friend void swap (hb_sorted_vector_t& a, hb_sorted_vector_t& b)
{ hb_swap ((hb_vector_t<Type>&) (a), (hb_vector_t<Type>&) (b)); }
hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->length); }
hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ, this->length); }
/* Iterator. */
typedef hb_sorted_array_t<const Type> const_iter_t;
typedef hb_sorted_array_t< Type> iter_t;
const_iter_t iter () const { return as_array (); }
const_iter_t citer () const { return as_array (); }
iter_t iter () { return as_array (); }
operator iter_t () { return iter (); }
operator const_iter_t () const { return iter (); }
template <typename T>
/* Sorted search API. */
template <typename T,
bool Sorted=sorted, hb_enable_if (Sorted)>
Type *bsearch (const T &x, Type *not_found = nullptr)
{ return as_array ().bsearch (x, not_found); }
template <typename T>
template <typename T,
bool Sorted=sorted, hb_enable_if (Sorted)>
const Type *bsearch (const T &x, const Type *not_found = nullptr) const
{ return as_array ().bsearch (x, not_found); }
template <typename T>
template <typename T,
bool Sorted=sorted, hb_enable_if (Sorted)>
bool bfind (const T &x, unsigned int *i = nullptr,
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
unsigned int to_store = (unsigned int) -1) const
{ return as_array ().bfind (x, i, not_found, to_store); }
};
template <typename Type>
using hb_sorted_vector_t = hb_vector_t<Type, true>;
#endif /* HB_VECTOR_HH */

View file

@ -47,20 +47,20 @@ HB_BEGIN_DECLS
*
* The minor component of the library version available at compile-time.
*/
#define HB_VERSION_MINOR 2
#define HB_VERSION_MINOR 3
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
#define HB_VERSION_MICRO 0
#define HB_VERSION_MICRO 1
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
#define HB_VERSION_STRING "3.2.0"
#define HB_VERSION_STRING "3.3.1"
/**
* HB_VERSION_ATLEAST: