HarfBuzz: Update to version 2.8.0

This commit is contained in:
bruvzg 2021-03-16 19:56:39 +02:00
parent 4c56fcd6cd
commit b79e8c22f0
No known key found for this signature in database
GPG Key ID: 009E1BFE42239B95
121 changed files with 3844 additions and 3151 deletions

View File

@ -83,8 +83,8 @@ if env["builtin_harfbuzz"]:
"src/hb-ot-shape-complex-indic.cc", "src/hb-ot-shape-complex-indic.cc",
"src/hb-ot-shape-complex-khmer.cc", "src/hb-ot-shape-complex-khmer.cc",
"src/hb-ot-shape-complex-myanmar.cc", "src/hb-ot-shape-complex-myanmar.cc",
"src/hb-ot-shape-complex-syllabic.cc",
"src/hb-ot-shape-complex-thai.cc", "src/hb-ot-shape-complex-thai.cc",
"src/hb-ot-shape-complex-use-table.cc",
"src/hb-ot-shape-complex-use.cc", "src/hb-ot-shape-complex-use.cc",
"src/hb-ot-shape-complex-vowel-constraints.cc", "src/hb-ot-shape-complex-vowel-constraints.cc",
"src/hb-ot-shape-fallback.cc", "src/hb-ot-shape-fallback.cc",

View File

@ -174,7 +174,7 @@ Files extracted from upstream source:
## harfbuzz ## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz
- Version: 2.7.4 (7236c7e29cef1c2d76c7a284c5081ff4d3aa1127, 2020) - Version: 2.8.0 (03538e872a0610a65fad692b33d3646f387cf578, 2021)
- License: MIT - License: MIT
Files extracted from upstream source: Files extracted from upstream source:

View File

@ -1,3 +1,18 @@
Overview of changes leading to 2.8.0
Tuesday, March 16, 2021
====================================
- Shape joining scripts other than Arabic/Syriac using the Universal Shaping Engine.
Previously these were shaped using the generalized Arabic shaper. (David Corbett)
- Fix regression in shaping of U+0B55 ORIYA SIGN OVERLINE. (David Corbett)
- Update language tags. (David Corbett)
- Variations: reduce error: do not round each interpolated delta. (Just van Rossum)
- Documentation improvements. (Khaled Hosny, Nathan Willis)
- Subsetter improvements: subsets most, if not all, lookup types now. (Garret Rieger, Qunxin Liu)
- Fuzzer-found fixes and other improvements when memory failures happen. (Behdad)
- Removed most atomic implementations now that we have C++11 atomic impl. (Behdad)
- General codebase upkeep; using more C++11 features: constexpr constructors, etc. (Behdad)
Overview of changes leading to 2.7.4 Overview of changes leading to 2.7.4
Sunday, December 27, 2020 Sunday, December 27, 2020
==================================== ====================================

View File

@ -510,7 +510,7 @@ struct StateTable
const Entry<Extra> &get_entry (int state, unsigned int klass) const const Entry<Extra> &get_entry (int state, unsigned int klass) const
{ {
if (unlikely (klass >= nClasses)) if (unlikely (klass >= nClasses))
klass = StateTable<Types, Entry<Extra>>::CLASS_OUT_OF_BOUNDS; klass = StateTable::CLASS_OUT_OF_BOUNDS;
const HBUSHORT *states = (this+stateArrayTable).arrayZ; const HBUSHORT *states = (this+stateArrayTable).arrayZ;
const Entry<Extra> *entries = (this+entryTable).arrayZ; const Entry<Extra> *entries = (this+entryTable).arrayZ;
@ -576,7 +576,7 @@ struct StateTable
if (unlikely (stop > states)) if (unlikely (stop > states))
return_trace (false); return_trace (false);
for (const HBUSHORT *p = states; stop < p; p--) for (const HBUSHORT *p = states; stop < p; p--)
num_entries = hb_max (num_entries, *(p - 1) + 1); num_entries = hb_max (num_entries, *(p - 1) + 1u);
state_neg = min_state; state_neg = min_state;
} }
} }
@ -597,7 +597,7 @@ struct StateTable
if (unlikely (stop < states)) if (unlikely (stop < states))
return_trace (false); return_trace (false);
for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++) for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
num_entries = hb_max (num_entries, *p + 1); num_entries = hb_max (num_entries, *p + 1u);
state_pos = max_state + 1; state_pos = max_state + 1;
} }
} }
@ -729,7 +729,10 @@ struct ExtendedTypes
template <typename Types, typename EntryData> template <typename Types, typename EntryData>
struct StateTableDriver struct StateTableDriver
{ {
StateTableDriver (const StateTable<Types, EntryData> &machine_, using StateTableT = StateTable<Types, EntryData>;
using EntryT = Entry<EntryData>;
StateTableDriver (const StateTableT &machine_,
hb_buffer_t *buffer_, hb_buffer_t *buffer_,
hb_face_t *face_) : hb_face_t *face_) :
machine (machine_), machine (machine_),
@ -742,59 +745,101 @@ struct StateTableDriver
if (!c->in_place) if (!c->in_place)
buffer->clear_output (); buffer->clear_output ();
int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT; int state = StateTableT::STATE_START_OF_TEXT;
for (buffer->idx = 0; buffer->successful;) for (buffer->idx = 0; buffer->successful;)
{ {
unsigned int klass = buffer->idx < buffer->len ? unsigned int klass = buffer->idx < buffer->len ?
machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) : machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
(unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT; (unsigned) StateTableT::CLASS_END_OF_TEXT;
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx); DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
const Entry<EntryData> &entry = machine.get_entry (state, klass); const EntryT &entry = machine.get_entry (state, klass);
const int next_state = machine.new_state (entry.newState);
/* Unsafe-to-break before this if not in state 0, as things might /* Conditions under which it's guaranteed safe-to-break before current glyph:
* go differently if we start from state 0 here.
* *
* Ugh. The indexing here is ugly... */ * 1. There was no action in this transition; and
if (state && buffer->backtrack_len () && buffer->idx < buffer->len) *
{ * 2. If we break before current glyph, the results will be the same. That
/* If there's no action and we're just epsilon-transitioning to state 0, * is guaranteed if:
* safe to break. */ *
if (c->is_actionable (this, entry) || * 2a. We were already in start-of-text state; or
!(entry.newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT && *
entry.flags == context_t::DontAdvance)) * 2b. We are epsilon-transitioning to start-of-text state; or
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1); *
} * 2c. Starting from start-of-text state seeing current glyph:
*
* 2c'. There won't be any actions; and
*
* 2c". We would end up in the same state that we were going to end up
* in now, including whether epsilon-transitioning.
*
* and
*
* 3. If we break before current glyph, there won't be any end-of-text action
* after previous glyph.
*
* This triples the transitions we need to look up, but is worth returning
* granular unsafe-to-break results. See eg.:
*
* https://github.com/harfbuzz/harfbuzz/issues/2860
*/
const EntryT *wouldbe_entry;
bool safe_to_break =
/* 1. */
!c->is_actionable (this, entry)
&&
/* 2. */
(
/* 2a. */
state == StateTableT::STATE_START_OF_TEXT
||
/* 2b. */
(
(entry.flags & context_t::DontAdvance) &&
next_state == StateTableT::STATE_START_OF_TEXT
)
||
/* 2c. */
(
wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
,
/* 2c'. */
!c->is_actionable (this, *wouldbe_entry)
&&
/* 2c". */
(
next_state == machine.new_state (wouldbe_entry->newState)
&&
(entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
)
)
)
&&
/* 3. */
!c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
;
/* Unsafe-to-break if end-of-text would kick in here. */ if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
if (buffer->idx + 2 <= buffer->len) buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
{
const Entry<EntryData> &end_entry = machine.get_entry (state, StateTable<Types, EntryData>::CLASS_END_OF_TEXT);
if (c->is_actionable (this, end_entry))
buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
}
c->transition (this, entry); c->transition (this, entry);
state = machine.new_state (entry.newState); state = next_state;
DEBUG_MSG (APPLY, nullptr, "s%d", state); DEBUG_MSG (APPLY, nullptr, "s%d", state);
if (buffer->idx == buffer->len) if (buffer->idx == buffer->len || unlikely (!buffer->successful))
break; break;
if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0) if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
if (!c->in_place) if (!c->in_place)
{
for (; buffer->successful && buffer->idx < buffer->len;)
buffer->next_glyph ();
buffer->swap_buffers (); buffer->swap_buffers ();
}
} }
public: public:
const StateTable<Types, EntryData> &machine; const StateTableT &machine;
hb_buffer_t *buffer; hb_buffer_t *buffer;
unsigned int num_glyphs; unsigned int num_glyphs;
}; };

View File

@ -337,9 +337,9 @@ struct ContextualSubtable
const EntryData &data = entries[i].data; const EntryData &data = entries[i].data;
if (data.markIndex != 0xFFFF) if (data.markIndex != 0xFFFF)
num_lookups = hb_max (num_lookups, 1 + data.markIndex); num_lookups = hb_max (num_lookups, 1u + data.markIndex);
if (data.currentIndex != 0xFFFF) if (data.currentIndex != 0xFFFF)
num_lookups = hb_max (num_lookups, 1 + data.currentIndex); num_lookups = hb_max (num_lookups, 1u + data.currentIndex);
} }
return_trace (substitutionTables.sanitize (c, this, num_lookups)); return_trace (substitutionTables.sanitize (c, this, num_lookups));
@ -499,7 +499,7 @@ struct LigatureSubtable
} }
DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1); DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]); if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return;
if (unlikely (!actionData->sanitize (&c->sanitizer))) break; if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
action = *actionData; action = *actionData;
@ -525,25 +525,25 @@ struct LigatureSubtable
hb_codepoint_t lig = ligatureData; hb_codepoint_t lig = ligatureData;
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig); DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
buffer->replace_glyph (lig); if (unlikely (!buffer->replace_glyph (lig))) return;
unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u; unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
/* Now go and delete all subsequent components. */ /* Now go and delete all subsequent components. */
while (match_length - 1u > cursor) while (match_length - 1u > cursor)
{ {
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]); if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
buffer->replace_glyph (DELETED_GLYPH); if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
} }
buffer->move_to (lig_end); if (unlikely (!buffer->move_to (lig_end))) return;
buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len); buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len);
} }
actionData++; actionData++;
} }
while (!(action & LigActionLast)); while (!(action & LigActionLast));
buffer->move_to (end); if (unlikely (!buffer->move_to (end))) return;
} }
} }
@ -733,17 +733,16 @@ struct InsertionSubtable
bool before = flags & MarkedInsertBefore; bool before = flags & MarkedInsertBefore;
unsigned int end = buffer->out_len; unsigned int end = buffer->out_len;
buffer->move_to (mark); if (unlikely (!buffer->move_to (mark))) return;
if (buffer->idx < buffer->len && !before) if (buffer->idx < buffer->len && !before)
buffer->copy_glyph (); if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */ /* TODO We ignore KashidaLike setting. */
for (unsigned int i = 0; i < count; i++) if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
buffer->output_glyph (glyphs[i]);
if (buffer->idx < buffer->len && !before) if (buffer->idx < buffer->len && !before)
buffer->skip_glyph (); buffer->skip_glyph ();
buffer->move_to (end + count); if (unlikely (!buffer->move_to (end + count))) return;
buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len)); buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len));
} }
@ -764,10 +763,9 @@ struct InsertionSubtable
unsigned int end = buffer->out_len; unsigned int end = buffer->out_len;
if (buffer->idx < buffer->len && !before) if (buffer->idx < buffer->len && !before)
buffer->copy_glyph (); if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */ /* TODO We ignore KashidaLike setting. */
for (unsigned int i = 0; i < count; i++) if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
buffer->output_glyph (glyphs[i]);
if (buffer->idx < buffer->len && !before) if (buffer->idx < buffer->len && !before)
buffer->skip_glyph (); buffer->skip_glyph ();
@ -786,7 +784,7 @@ struct InsertionSubtable
* *
* https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417 * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417
*/ */
buffer->move_to ((flags & DontAdvance) ? end : end + count); if (unlikely (!buffer->move_to ((flags & DontAdvance) ? end : end + count))) return;
} }
} }

View File

@ -227,7 +227,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
* *
* <note>Note: does not examine the `GSUB` table.</note> * <note>Note: does not examine the `GSUB` table.</note>
* *
* Return value: true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 2.3.0 * Since: 2.3.0
*/ */
@ -294,7 +294,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
* *
* <note>Note: does not examine the `GPOS` table.</note> * <note>Note: does not examine the `GPOS` table.</note>
* *
* Return value: true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 2.3.0 * Since: 2.3.0
*/ */
@ -325,7 +325,7 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
* Tests whether the specified face includes any tracking information * Tests whether the specified face includes any tracking information
* in the `trak` table. * in the `trak` table.
* *
* Return value: true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 2.3.0 * Since: 2.3.0
*/ */
@ -350,7 +350,7 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
* hb_aat_layout_get_feature_types: * hb_aat_layout_get_feature_types:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @start_offset: offset of the first feature type to retrieve * @start_offset: offset of the first feature type to retrieve
* @feature_count: (inout) (allow-none): Input = the maximum number of feature types to return; * @feature_count: (inout) (optional): Input = the maximum number of feature types to return;
* Output = the actual number of feature types returned (may be zero) * Output = the actual number of feature types returned (may be zero)
* @features: (out caller-allocates) (array length=feature_count): Array of feature types found * @features: (out caller-allocates) (array length=feature_count): Array of feature types found
* *
@ -374,9 +374,9 @@ hb_aat_layout_get_feature_types (hb_face_t *face,
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type * @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type
* *
* Fetches the name ID of the specified feature type in the face's `name` table. * Fetches the name identifier of the specified feature type in the face's `name` table.
* *
* Return value: Name ID of the requested feature type * Return value: Name identifier of the requested feature type
* *
* Since: 2.2.0 * Since: 2.2.0
*/ */
@ -388,15 +388,15 @@ hb_aat_layout_feature_type_get_name_id (hb_face_t *face,
} }
/** /**
* hb_aat_layout_feature_type_get_selectors: * hb_aat_layout_feature_type_get_selector_infos:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type * @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type
* @start_offset: offset of the first feature type to retrieve * @start_offset: offset of the first feature type to retrieve
* @selector_count: (inout) (allow-none): Input = the maximum number of selectors to return; * @selector_count: (inout) (optional): Input = the maximum number of selectors to return;
* Output = the actual number of selectors returned (may be zero) * Output = the actual number of selectors returned (may be zero)
* @selectors: (out caller-allocates) (array length=selector_count): A buffer pointer. * @selectors: (out caller-allocates) (array length=selector_count) (optional):
* The selectors available for the feature type queries. * A buffer pointer. The selectors available for the feature type queries.
* @default_index: (out) (allow-none): The index of the feature's default selector, if any * @default_index: (out) (optional): The index of the feature's default selector, if any
* *
* Fetches a list of the selectors available for the specified feature in the given face. * Fetches a list of the selectors available for the specified feature in the given face.
* *

View File

@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/ */
#ifndef HB_AAT_H_IN #if !defined(HB_AAT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-aat.h> instead." #error "Include <hb-aat.h> instead."
#endif #endif
@ -38,47 +38,47 @@ HB_BEGIN_DECLS
/** /**
* hb_aat_layout_feature_type_t: * hb_aat_layout_feature_type_t:
* @HB_AAT_LAYOUT_FEATURE_TYPE_INVALID: Initial, unset feature type * @HB_AAT_LAYOUT_FEATURE_TYPE_INVALID: Initial, unset feature type
* @HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC: * @HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC: [All Typographic Features](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type0)
* @HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES: * @HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES: [Ligatures](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type1)
* @HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION: * @HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION: [Cursive Connection](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type2)
* @HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE: * @HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE: [Letter Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type3)
* @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION: * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION: [Vertical Substitution](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type4)
* @HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT: * @HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT: [Linguistic Rearrangement](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type5)
* @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING: * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING: [Number Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type6)
* @HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE: [Smart Swash](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type8)
* @HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE: [Diacritics](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type9)
* @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION: * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION: [Vertical Position](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type10)
* @HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS: * @HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS: [Fractions](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type11)
* @HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE: [Overlapping Characters](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type13)
* @HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS: * @HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS: [Typographic Extras](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type14)
* @HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS: * @HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS: [Mathematical Extras](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type15)
* @HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE: [Ornament Sets](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type16)
* @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES: * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES: [Character Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type17)
* @HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE: [Design Complexity](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type18)
* @HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS: * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS: [Style Options](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type19)
* @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE: [Character Shape](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type20)
* @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE: * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE: [Number Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type21)
* @HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING: * @HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING: [Text Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type22)
* @HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION: * @HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION: [Transliteration](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type23)
* @HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE: [Annotation](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type24)
* @HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE: [Kana Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type25)
* @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE: [Ideographic Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type26)
* @HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE: [Unicode Decomposition](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type27)
* @HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA: * @HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA: [Ruby Kana](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type28)
* @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE: [CJK Symbol Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type29)
* @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE: [Ideographic Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type30)
* @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE: [CJK Vertical Roman Placement](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type31)
* @HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN: * @HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN: [Italic CJK Roman](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type32)
* @HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT: * @HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT: [Case Sensitive Layout](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type33)
* @HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA: * @HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA: [Alternate Kana](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type34)
* @HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES: * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES: [Stylistic Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type35)
* @HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES: * @HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES: [Contextual Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type36)
* @HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE: * @HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE: [Lower Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type37)
* @HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE: * @HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE: [Upper Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type38)
* @HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE: [Language Tag](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type39)
* @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE: * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE: [CJK Roman Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type103)
* *
* The possible feature types defined for AAT shaping. * The possible feature types defined for AAT shaping, from Apple [Font Feature Registry](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html).
* *
* Since: 2.2.0 * Since: 2.2.0
*/ */
@ -732,6 +732,14 @@ HB_EXTERN hb_ot_name_id_t
hb_aat_layout_feature_type_get_name_id (hb_face_t *face, hb_aat_layout_feature_type_get_name_id (hb_face_t *face,
hb_aat_layout_feature_type_t feature_type); hb_aat_layout_feature_type_t feature_type);
/**
* hb_aat_layout_feature_selector_info_t:
* @name_id: The selector's name identifier
* @enable: The value to turn the selector on
* @disable: The value to turn the selector off
*
* Structure representing a setting for an #hb_aat_layout_feature_type_t.
*/
typedef struct hb_aat_layout_feature_selector_info_t { typedef struct hb_aat_layout_feature_selector_info_t {
hb_ot_name_id_t name_id; hb_ot_name_id_t name_id;
hb_aat_layout_feature_selector_t enable; hb_aat_layout_feature_selector_t enable;

View File

@ -35,6 +35,132 @@
#include "hb-number.hh" #include "hb-number.hh"
/*
* Flags
*/
/* Enable bitwise ops on enums marked as flags_t */
/* To my surprise, looks like the function resolver is happy to silently cast
* one enum to another... So this doesn't provide the type-checking that I
* originally had in mind... :(.
*
* For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
*/
#ifdef _MSC_VER
# pragma warning(disable:4200)
# pragma warning(disable:4800)
#endif
#define HB_MARK_AS_FLAG_T(T) \
extern "C++" { \
static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \
static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
} \
static_assert (true, "")
/* Useful for set-operations on small enums.
* For example, for testing "x ∈ {x1, x2, x3}" use:
* (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
*/
#define FLAG(x) (static_assert_expr ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
#define FLAG_RANGE(x,y) (static_assert_expr ((x) < (y)) + FLAG(y+1) - FLAG(x))
#define FLAG64(x) (static_assert_expr ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
/*
* Big-endian integers.
*/
/* Endian swap, used in Windows related backends */
static inline constexpr uint16_t hb_uint16_swap (uint16_t v)
{ return (v >> 8) | (v << 8); }
static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
template <typename Type, int Bytes = sizeof (Type)>
struct BEInt;
template <typename Type>
struct BEInt<Type, 1>
{
public:
BEInt () = default;
constexpr BEInt (Type V) : v {uint8_t (V)} {}
constexpr operator Type () const { return v; }
private: uint8_t v;
};
template <typename Type>
struct BEInt<Type, 2>
{
public:
BEInt () = default;
constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF),
uint8_t ((V ) & 0xFF)} {}
struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
constexpr operator Type () const
{
#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
defined(__BYTE_ORDER) && \
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
/* Spoon-feed the compiler a big-endian integer with alignment 1.
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
return __builtin_bswap16 (((packed_uint16_t *) this)->v);
#else /* __BYTE_ORDER == __BIG_ENDIAN */
return ((packed_uint16_t *) this)->v;
#endif
#else
return (v[0] << 8)
+ (v[1] );
#endif
}
private: uint8_t v[2];
};
template <typename Type>
struct BEInt<Type, 3>
{
static_assert (!hb_is_signed (Type), "");
public:
BEInt () = default;
constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
uint8_t ((V >> 8) & 0xFF),
uint8_t ((V ) & 0xFF)} {}
constexpr operator Type () const { return (v[0] << 16)
+ (v[1] << 8)
+ (v[2] ); }
private: uint8_t v[3];
};
template <typename Type>
struct BEInt<Type, 4>
{
public:
BEInt () = default;
constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF),
uint8_t ((V >> 16) & 0xFF),
uint8_t ((V >> 8) & 0xFF),
uint8_t ((V ) & 0xFF)} {}
constexpr operator Type () const { return (v[0] << 24)
+ (v[1] << 16)
+ (v[2] << 8)
+ (v[3] ); }
private: uint8_t v[4];
};
/* Floats. */
/* We want our rounding towards +infinity. */
static inline float
_hb_roundf (float x) { return floorf (x + .5f); }
#define roundf(x) _hb_roundf(x)
/* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits, /* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
* values will be truncated / overlap, and might not decode exactly. */ * values will be truncated / overlap, and might not decode exactly. */
#define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z)) #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
@ -48,6 +174,7 @@
#define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300) #define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
#define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu) #define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
struct struct
{ {
/* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */ /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
@ -215,7 +342,9 @@ struct
template <typename Pred, typename Val> auto template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v))) (
hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v))
)
template <typename Pred, typename Val> auto template <typename Pred, typename Val> auto
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
@ -269,7 +398,9 @@ struct
template <typename Proj, typename Val> auto template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
(hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v))) (
hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v))
)
template <typename Proj, typename Val> auto template <typename Proj, typename Val> auto
impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
@ -296,6 +427,40 @@ struct
} }
HB_FUNCOBJ (hb_get); HB_FUNCOBJ (hb_get);
struct
{
private:
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
(
hb_forward<T2> (v2).cmp (hb_forward<T1> (v1)) == 0
)
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
(
hb_forward<T1> (v1).cmp (hb_forward<T2> (v2)) == 0
)
template <typename T1, typename T2> auto
impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
(
hb_forward<T1> (v1) == hb_forward<T2> (v2)
)
public:
template <typename T1, typename T2> auto
operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
(
impl (hb_forward<T1> (v1),
hb_forward<T2> (v2),
hb_prioritize)
)
}
HB_FUNCOBJ (hb_equal);
template <typename T1, typename T2> template <typename T1, typename T2>
struct hb_pair_t struct hb_pair_t
@ -375,7 +540,7 @@ HB_FUNCOBJ (hb_clamp);
/* Return the number of 1 bits in v. */ /* Return the number of 1 bits in v. */
template <typename T> template <typename T>
static inline HB_CONST_FUNC unsigned int static inline unsigned int
hb_popcount (T v) hb_popcount (T v)
{ {
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
@ -416,7 +581,7 @@ hb_popcount (T v)
/* Returns the number of bits needed to store number */ /* Returns the number of bits needed to store number */
template <typename T> template <typename T>
static inline HB_CONST_FUNC unsigned int static inline unsigned int
hb_bit_storage (T v) hb_bit_storage (T v)
{ {
if (unlikely (!v)) return 0; if (unlikely (!v)) return 0;
@ -490,7 +655,7 @@ hb_bit_storage (T v)
/* Returns the number of zero bits in the least significant side of v */ /* Returns the number of zero bits in the least significant side of v */
template <typename T> template <typename T>
static inline HB_CONST_FUNC unsigned int static inline unsigned int
hb_ctz (T v) hb_ctz (T v)
{ {
if (unlikely (!v)) return 8 * sizeof (T); if (unlikely (!v)) return 8 * sizeof (T);
@ -988,32 +1153,24 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
struct hb_bitwise_and struct hb_bitwise_and
{ HB_PARTIALIZE(2); { HB_PARTIALIZE(2);
static constexpr bool passthru_left = false;
static constexpr bool passthru_right = false;
template <typename T> constexpr auto template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b) operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
} }
HB_FUNCOBJ (hb_bitwise_and); HB_FUNCOBJ (hb_bitwise_and);
struct hb_bitwise_or struct hb_bitwise_or
{ HB_PARTIALIZE(2); { HB_PARTIALIZE(2);
static constexpr bool passthru_left = true;
static constexpr bool passthru_right = true;
template <typename T> constexpr auto template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b) operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
} }
HB_FUNCOBJ (hb_bitwise_or); HB_FUNCOBJ (hb_bitwise_or);
struct hb_bitwise_xor struct hb_bitwise_xor
{ HB_PARTIALIZE(2); { HB_PARTIALIZE(2);
static constexpr bool passthru_left = true;
static constexpr bool passthru_right = true;
template <typename T> constexpr auto template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b) operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
} }
HB_FUNCOBJ (hb_bitwise_xor); HB_FUNCOBJ (hb_bitwise_xor);
struct hb_bitwise_sub struct hb_bitwise_sub
{ HB_PARTIALIZE(2); { HB_PARTIALIZE(2);
static constexpr bool passthru_left = true;
static constexpr bool passthru_right = false;
template <typename T> constexpr auto template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
} }

View File

@ -142,7 +142,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
bool lfind (const T &x, unsigned *pos = nullptr) const bool lfind (const T &x, unsigned *pos = nullptr) const
{ {
for (unsigned i = 0; i < length; ++i) for (unsigned i = 0; i < length; ++i)
if (!this->arrayZ[i].cmp (x)) if (hb_equal (x, this->arrayZ[i]))
{ {
if (pos) if (pos)
*pos = i; *pos = i;

View File

@ -52,7 +52,7 @@
#elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE) #elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE)
/* C++11-style GCC primitives. */ /* C++11-style GCC primitives. We prefer these as they don't require linking to libstdc++ / libc++. */
#define _hb_memory_barrier() __sync_synchronize () #define _hb_memory_barrier() __sync_synchronize ()
@ -73,7 +73,8 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
} }
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) #define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
#elif !defined(HB_NO_MT)
/* C++11 atomics. */ /* C++11 atomics. */
@ -101,117 +102,6 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) #define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
#elif !defined(HB_NO_MT) && defined(_WIN32)
#include <windows.h>
static inline void _hb_memory_barrier ()
{
#if !defined(MemoryBarrier) && !defined(__MINGW32_VERSION)
/* MinGW has a convoluted history of supporting MemoryBarrier. */
LONG dummy = 0;
InterlockedExchange (&dummy, 1);
#else
MemoryBarrier ();
#endif
}
#define _hb_memory_barrier() _hb_memory_barrier ()
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((LONG *) (AI), (V))
static_assert ((sizeof (LONG) == sizeof (int)), "");
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((P), (N), (O)) == (O))
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
#define _hb_memory_barrier() __sync_synchronize ()
#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
#include <atomic.h>
#include <mbarrier.h>
#define _hb_memory_r_barrier() __machine_r_barrier ()
#define _hb_memory_w_barrier() __machine_w_barrier ()
#define _hb_memory_barrier() __machine_rw_barrier ()
static inline int _hb_fetch_and_add (int *AI, int V)
{
_hb_memory_w_barrier ();
int result = atomic_add_int_nv ((uint_t *) AI, V) - V;
_hb_memory_r_barrier ();
return result;
}
static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N)
{
_hb_memory_w_barrier ();
bool result = atomic_cas_ptr (P, O, N) == O;
_hb_memory_r_barrier ();
return result;
}
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swap_ptr ((P), (O), (N))
#elif !defined(HB_NO_MT) && defined(__APPLE__)
#include <libkern/OSAtomic.h>
#ifdef __MAC_OS_X_MIN_REQUIRED
#include <AvailabilityMacros.h>
#elif defined(__IPHONE_OS_MIN_REQUIRED)
#include <Availability.h>
#endif
#define _hb_memory_barrier() OSMemoryBarrier ()
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), (AI)) - (V))
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((O), (N), (P))
#else
#if __ppc64__ || __x86_64__ || __aarch64__
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
#else
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
#endif
#endif
#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))
#include <builtins.h>
#define _hb_memory_barrier() __lwsync ()
static inline int _hb_fetch_and_add (int *AI, int V)
{
_hb_memory_barrier ();
int result = __fetch_and_add (AI, V);
_hb_memory_barrier ();
return result;
}
static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
{
_hb_memory_barrier ();
bool result = __compare_and_swaplp (P, &O, N);
_hb_memory_barrier ();
return result;
}
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
static_assert ((sizeof (long) == sizeof (void *)), "");
#elif defined(HB_NO_MT) #elif defined(HB_NO_MT)
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) #define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
@ -259,9 +149,11 @@ inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory
#endif #endif
#define HB_ATOMIC_INT_INIT(V) {V}
struct hb_atomic_int_t struct hb_atomic_int_t
{ {
hb_atomic_int_t () = default;
constexpr hb_atomic_int_t (int v) : v (v) {}
void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
void set (int v_) { hb_atomic_int_impl_set (&v, v_); } void set (int v_) { hb_atomic_int_impl_set (&v, v_); }
int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
@ -269,16 +161,17 @@ struct hb_atomic_int_t
int inc () { return hb_atomic_int_impl_add (&v, 1); } int inc () { return hb_atomic_int_impl_add (&v, 1); }
int dec () { return hb_atomic_int_impl_add (&v, -1); } int dec () { return hb_atomic_int_impl_add (&v, -1); }
int v; int v = 0;
}; };
#define HB_ATOMIC_PTR_INIT(V) {V}
template <typename P> template <typename P>
struct hb_atomic_ptr_t struct hb_atomic_ptr_t
{ {
typedef hb_remove_pointer<P> T; typedef hb_remove_pointer<P> T;
hb_atomic_ptr_t () = default;
constexpr hb_atomic_ptr_t (T* v) : v (v) {}
void init (T* v_ = nullptr) { set_relaxed (v_); } void init (T* v_ = nullptr) { set_relaxed (v_); }
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); } T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
@ -288,7 +181,7 @@ struct hb_atomic_ptr_t
T * operator -> () const { return get (); } T * operator -> () const { return get (); }
template <typename C> operator C * () const { return get (); } template <typename C> operator C * () const { return get (); }
T *v; T *v = nullptr;
}; };

View File

@ -35,9 +35,6 @@
#include <sys/mman.h> #include <sys/mman.h>
#endif /* HAVE_SYS_MMAN_H */ #endif /* HAVE_SYS_MMAN_H */
#include <stdio.h>
#include <stdlib.h>
/** /**
* SECTION: hb-blob * SECTION: hb-blob
@ -58,7 +55,7 @@
* @length: Length of @data in bytes. * @length: Length of @data in bytes.
* @mode: Memory mode for @data. * @mode: Memory mode for @data.
* @user_data: Data parameter to pass to @destroy. * @user_data: Data parameter to pass to @destroy.
* @destroy: (optional): Callback to call when @data is not needed anymore. * @destroy: (nullable): Callback to call when @data is not needed anymore.
* *
* Creates a new "blob" object wrapping @data. The @mode parameter is used * Creates a new "blob" object wrapping @data. The @mode parameter is used
* to negotiate ownership and lifecycle of @data. * to negotiate ownership and lifecycle of @data.
@ -116,7 +113,7 @@ _hb_blob_destroy (void *data)
* @length: Length of sub-blob. * @length: Length of sub-blob.
* *
* Returns a blob that represents a range of bytes in @parent. The new * Returns a blob that represents a range of bytes in @parent. The new
* blob is always created with %HB_MEMORY_MODE_READONLY, meaning that it * blob is always created with #HB_MEMORY_MODE_READONLY, meaning that it
* will never modify data in the parent blob. The parent data is not * will never modify data in the parent blob. The parent data is not
* expected to be modified, and will result in undefined behavior if it * expected to be modified, and will result in undefined behavior if it
* is. * is.
@ -237,7 +234,7 @@ hb_blob_destroy (hb_blob_t *blob)
* @blob: An #hb_blob_t * @blob: An #hb_blob_t
* @key: The user-data key to set * @key: The user-data key to set
* @data: A pointer to the user data to set * @data: A pointer to the user data to set
* @destroy: (optional): A callback to call when @data is not needed anymore * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key * @replace: Whether to replace an existing data with the same key
* *
* Attaches a user-data key/data pair to the specified blob. * Attaches a user-data key/data pair to the specified blob.
@ -299,7 +296,7 @@ hb_blob_make_immutable (hb_blob_t *blob)
* *
* Tests whether a blob is immutable. * Tests whether a blob is immutable.
* *
* Return value: %true if @blob is immutable, false otherwise * Return value: %true if @blob is immutable, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -365,16 +362,14 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
char * char *
hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
{ {
if (!blob->try_make_writable ()) { if (hb_object_is_immutable (blob) ||
if (length) !blob->try_make_writable ())
*length = 0; {
if (length) *length = 0;
return nullptr; return nullptr;
} }
if (length) if (length) *length = blob->length;
*length = blob->length;
return const_cast<char *> (blob->data); return const_cast<char *> (blob->data);
} }
@ -440,8 +435,8 @@ hb_blob_t::try_make_writable_inplace ()
bool bool
hb_blob_t::try_make_writable () hb_blob_t::try_make_writable ()
{ {
if (hb_object_is_immutable (this)) if (unlikely (!length))
return false; mode = HB_MEMORY_MODE_WRITABLE;
if (this->mode == HB_MEMORY_MODE_WRITABLE) if (this->mode == HB_MEMORY_MODE_WRITABLE)
return true; return true;

View File

@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
*/ */
#ifndef HB_H_IN #if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead." #error "Include <hb.h> instead."
#endif #endif
@ -38,10 +38,12 @@ HB_BEGIN_DECLS
/** /**
* hb_memory_mode_t: * hb_memory_mode_t:
* @HB_MEMORY_MODE_DUPLICATE * @HB_MEMORY_MODE_DUPLICATE: HarfBuzz immediately makes a copy of the data.
* @HB_MEMORY_MODE_READONLY * @HB_MEMORY_MODE_READONLY: HarfBuzz client will never modify the data,
* @HB_MEMORY_MODE_WRITABLE * and HarfBuzz will never modify the data.
* @HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE * @HB_MEMORY_MODE_WRITABLE: HarfBuzz client made a copy of the data solely
* for HarfBuzz, so HarfBuzz may modify the data.
* @HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE: See above
* *
* Data type holding the memory modes available to * Data type holding the memory modes available to
* client programs. * client programs.

View File

@ -400,8 +400,8 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into. * write serialized buffer into.
* @buf_size: the size of @buf. * @buf_size: the size of @buf.
* @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
* @font: (allow-none): the #hb_font_t used to shape this buffer, needed to * @font: (nullable): the #hb_font_t used to shape this buffer, needed to
* read glyph names and extents. If %NULL, and empty font will be used. * read glyph names and extents. If %NULL, and empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
@ -514,8 +514,10 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into. * write serialized buffer into.
* @buf_size: the size of @buf. * @buf_size: the size of @buf.
* @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
* *
* Serializes @buffer into a textual representation of its content, * Serializes @buffer into a textual representation of its content,
* when the buffer contains Unicode codepoints (i.e., before shaping). This is * when the buffer contains Unicode codepoints (i.e., before shaping). This is
@ -635,8 +637,8 @@ _hb_buffer_serialize_invalid (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into. * write serialized buffer into.
* @buf_size: the size of @buf. * @buf_size: the size of @buf.
* @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
* @font: (allow-none): the #hb_font_t used to shape this buffer, needed to * @font: (nullable): the #hb_font_t used to shape this buffer, needed to
* read glyph names and extents. If %NULL, and empty font will be used. * read glyph names and extents. If %NULL, and empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
@ -724,15 +726,17 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
/** /**
* hb_buffer_deserialize_glyphs: * hb_buffer_deserialize_glyphs:
* @buffer: an #hb_buffer_t buffer. * @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len): * @buf: (array length=buf_len): string to deserialize
* @buf_len: * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
* @end_ptr: (out): * @end_ptr: (out) (optional): output pointer to the character after last
* @font: * consumed one.
* @format: * @font: (nullable): font for getting glyph IDs
* @format: the #hb_buffer_serialize_format_t of the input @buf
* *
* Deserializes glyphs @buffer from textual representation in the format
* produced by hb_buffer_serialize_glyphs().
* *
* * Return value: %true if @buf is not fully consumed, %false otherwise.
* Return value:
* *
* Since: 0.9.7 * Since: 0.9.7
**/ **/
@ -795,14 +799,16 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
/** /**
* hb_buffer_deserialize_unicode: * hb_buffer_deserialize_unicode:
* @buffer: an #hb_buffer_t buffer. * @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len): * @buf: (array length=buf_len): string to deserialize
* @buf_len: * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
* @end_ptr: (out): * @end_ptr: (out) (optional): output pointer to the character after last
* @format: * consumed one.
* @format: the #hb_buffer_serialize_format_t of the input @buf
* *
* Deserializes Unicode @buffer from textual representation in the format
* produced by hb_buffer_serialize_unicode().
* *
* * Return value: %true if @buf is not fully consumed, %false otherwise.
* Return value:
* *
* Since: 2.7.3 * Since: 2.7.3
**/ **/

View File

@ -218,9 +218,6 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size)
void void
hb_buffer_t::reset () hb_buffer_t::reset ()
{ {
if (unlikely (hb_object_is_immutable (this)))
return;
hb_unicode_funcs_destroy (unicode); hb_unicode_funcs_destroy (unicode);
unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ()); unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
flags = HB_BUFFER_FLAG_DEFAULT; flags = HB_BUFFER_FLAG_DEFAULT;
@ -233,9 +230,6 @@ hb_buffer_t::reset ()
void void
hb_buffer_t::clear () hb_buffer_t::clear ()
{ {
if (unlikely (hb_object_is_immutable (this)))
return;
hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
props = default_props; props = default_props;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
@ -290,9 +284,6 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
void void
hb_buffer_t::remove_output () hb_buffer_t::remove_output ()
{ {
if (unlikely (hb_object_is_immutable (this)))
return;
have_output = false; have_output = false;
have_positions = false; have_positions = false;
@ -303,9 +294,6 @@ hb_buffer_t::remove_output ()
void void
hb_buffer_t::clear_output () hb_buffer_t::clear_output ()
{ {
if (unlikely (hb_object_is_immutable (this)))
return;
have_output = true; have_output = true;
have_positions = false; have_positions = false;
@ -316,9 +304,6 @@ hb_buffer_t::clear_output ()
void void
hb_buffer_t::clear_positions () hb_buffer_t::clear_positions ()
{ {
if (unlikely (hb_object_is_immutable (this)))
return;
have_output = false; have_output = false;
have_positions = true; have_positions = true;
@ -333,15 +318,19 @@ hb_buffer_t::swap_buffers ()
{ {
if (unlikely (!successful)) return; if (unlikely (!successful)) return;
assert (idx <= len);
if (unlikely (!next_glyphs (len - idx))) return;
assert (have_output); assert (have_output);
have_output = false; have_output = false;
if (out_info != info) if (out_info != info)
{ {
hb_glyph_info_t *tmp_string; hb_glyph_info_t *tmp;
tmp_string = info; tmp = info;
info = out_info; info = out_info;
out_info = tmp_string; out_info = tmp;
pos = (hb_glyph_position_t *) out_info; pos = (hb_glyph_position_t *) out_info;
} }
@ -353,31 +342,6 @@ hb_buffer_t::swap_buffers ()
idx = 0; idx = 0;
} }
void
hb_buffer_t::replace_glyphs (unsigned int num_in,
unsigned int num_out,
const uint32_t *glyph_data)
{
if (unlikely (!make_room_for (num_in, num_out))) return;
assert (idx + num_in <= len);
merge_clusters (idx, idx + num_in);
hb_glyph_info_t orig_info = info[idx];
hb_glyph_info_t *pinfo = &out_info[out_len];
for (unsigned int i = 0; i < num_out; i++)
{
*pinfo = orig_info;
pinfo->codepoint = glyph_data[i];
pinfo++;
}
idx += num_in;
out_len += num_out;
}
bool bool
hb_buffer_t::move_to (unsigned int i) hb_buffer_t::move_to (unsigned int i)
{ {
@ -768,7 +732,7 @@ hb_buffer_destroy (hb_buffer_t *buffer)
* @buffer: An #hb_buffer_t * @buffer: An #hb_buffer_t
* @key: The user-data key * @key: The user-data key
* @data: A pointer to the user data * @data: A pointer to the user data
* @destroy: (optional): A callback to call when @data is not needed anymore * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key * @replace: Whether to replace an existing data with the same key
* *
* Attaches a user-data key/data pair to the specified buffer. * Attaches a user-data key/data pair to the specified buffer.
@ -795,7 +759,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
* Fetches the user data associated with the specified key, * Fetches the user data associated with the specified key,
* attached to the specified buffer. * attached to the specified buffer.
* *
* Return value: (transfer-none): A pointer to the user data * Return value: (transfer none): A pointer to the user data
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1137,7 +1101,7 @@ hb_buffer_get_cluster_level (hb_buffer_t *buffer)
* Sets the #hb_codepoint_t that replaces invalid entries for a given encoding * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding
* when adding text to @buffer. * when adding text to @buffer.
* *
* Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT. * Default is #HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
* *
* Since: 0.9.31 * Since: 0.9.31
**/ **/
@ -1222,6 +1186,9 @@ hb_buffer_get_invisible_glyph (hb_buffer_t *buffer)
void void
hb_buffer_reset (hb_buffer_t *buffer) hb_buffer_reset (hb_buffer_t *buffer)
{ {
if (unlikely (hb_object_is_immutable (buffer)))
return;
buffer->reset (); buffer->reset ();
} }
@ -1237,6 +1204,9 @@ hb_buffer_reset (hb_buffer_t *buffer)
void void
hb_buffer_clear_contents (hb_buffer_t *buffer) hb_buffer_clear_contents (hb_buffer_t *buffer)
{ {
if (unlikely (hb_object_is_immutable (buffer)))
return;
buffer->clear (); buffer->clear ();
} }
@ -1321,7 +1291,7 @@ hb_buffer_set_length (hb_buffer_t *buffer,
if (unlikely (hb_object_is_immutable (buffer))) if (unlikely (hb_object_is_immutable (buffer)))
return length == 0; return length == 0;
if (!buffer->ensure (length)) if (unlikely (!buffer->ensure (length)))
return false; return false;
/* Wipe the new space */ /* Wipe the new space */
@ -1501,20 +1471,20 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer)
* *
* Sets unset buffer segment properties based on buffer Unicode * Sets unset buffer segment properties based on buffer Unicode
* contents. If buffer is not empty, it must have content type * contents. If buffer is not empty, it must have content type
* %HB_BUFFER_CONTENT_TYPE_UNICODE. * #HB_BUFFER_CONTENT_TYPE_UNICODE.
* *
* If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it * If buffer script is not set (ie. is #HB_SCRIPT_INVALID), it
* will be set to the Unicode script of the first character in * will be set to the Unicode script of the first character in
* the buffer that has a script other than %HB_SCRIPT_COMMON, * the buffer that has a script other than #HB_SCRIPT_COMMON,
* %HB_SCRIPT_INHERITED, and %HB_SCRIPT_UNKNOWN. * #HB_SCRIPT_INHERITED, and #HB_SCRIPT_UNKNOWN.
* *
* Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID), * Next, if buffer direction is not set (ie. is #HB_DIRECTION_INVALID),
* it will be set to the natural horizontal direction of the * it will be set to the natural horizontal direction of the
* buffer script as returned by hb_script_get_horizontal_direction(). * buffer script as returned by hb_script_get_horizontal_direction().
* If hb_script_get_horizontal_direction() returns %HB_DIRECTION_INVALID, * If hb_script_get_horizontal_direction() returns #HB_DIRECTION_INVALID,
* then %HB_DIRECTION_LTR is used. * then #HB_DIRECTION_LTR is used.
* *
* Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID), * Finally, if buffer language is not set (ie. is #HB_LANGUAGE_INVALID),
* it will be set to the process's default language as returned by * it will be set to the process's default language as returned by
* hb_language_get_default(). This may change in the future by * hb_language_get_default(). This may change in the future by
* taking buffer script into consideration when choosing a language. * taking buffer script into consideration when choosing a language.
@ -1551,7 +1521,10 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
if (item_length == -1) if (item_length == -1)
item_length = text_length - item_offset; item_length = text_length - item_offset;
buffer->ensure (buffer->len + item_length * sizeof (T) / 4); if (unlikely (item_length < 0 ||
item_length > INT_MAX / 8 ||
!buffer->ensure (buffer->len + item_length * sizeof (T) / 4)))
return;
/* If buffer is empty and pre-context provided, install it. /* If buffer is empty and pre-context provided, install it.
* This check is written this way, to make sure people can * This check is written this way, to make sure people can
@ -1768,11 +1741,6 @@ hb_buffer_append (hb_buffer_t *buffer,
if (start == end) if (start == end)
return; return;
if (!buffer->len)
buffer->content_type = source->content_type;
if (!buffer->have_positions && source->have_positions)
buffer->clear_positions ();
if (buffer->len + (end - start) < buffer->len) /* Overflows. */ if (buffer->len + (end - start) < buffer->len) /* Overflows. */
{ {
buffer->successful = false; buffer->successful = false;
@ -1784,6 +1752,11 @@ hb_buffer_append (hb_buffer_t *buffer,
if (unlikely (!buffer->successful)) if (unlikely (!buffer->successful))
return; return;
if (!orig_len)
buffer->content_type = source->content_type;
if (!buffer->have_positions && source->have_positions)
buffer->clear_positions ();
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
if (buffer->have_positions) if (buffer->have_positions)
memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
@ -1902,8 +1875,8 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g
* @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1. * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1.
* @position_fuzz: allowed absolute difference in position values. * @position_fuzz: allowed absolute difference in position values.
* *
* If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT * If dottedcircle_glyph is (hb_codepoint_t) -1 then #HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
* and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most * and #HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most
* callers if just comparing two buffers is needed. * callers if just comparing two buffers is needed.
* *
* Since: 1.5.0 * Since: 1.5.0
@ -1994,11 +1967,11 @@ hb_buffer_diff (hb_buffer_t *buffer,
/** /**
* hb_buffer_set_message_func: * hb_buffer_set_message_func:
* @buffer: An #hb_buffer_t * @buffer: An #hb_buffer_t
* @func: (closure user_data) (destroy destroy) (scope notified): * @func: (closure user_data) (destroy destroy) (scope notified): Callback function
* @user_data: * @user_data: (nullable): Data to pass to @func
* @destroy: * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* *
* Sets the implementation function for #hb_buffer_message_func_t.
* *
* Since: 1.1.3 * Since: 1.1.3
**/ **/

View File

@ -27,7 +27,7 @@
* Google Author(s): Behdad Esfahbod * Google Author(s): Behdad Esfahbod
*/ */
#ifndef HB_H_IN #if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead." #error "Include <hb.h> instead."
#endif #endif
@ -90,6 +90,8 @@ typedef struct hb_glyph_info_t {
* breaking point only. * breaking point only.
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
* *
* Flags for #hb_glyph_info_t.
*
* Since: 1.5.0 * Since: 1.5.0
*/ */
typedef enum { /*< flags >*/ typedef enum { /*< flags >*/
@ -150,6 +152,11 @@ typedef struct hb_segment_properties_t {
void *reserved2; void *reserved2;
} hb_segment_properties_t; } hb_segment_properties_t;
/**
* HB_SEGMENT_PROPERTIES_DEFAULT:
*
* The default #hb_segment_properties_t of of freshly created #hb_buffer_t.
*/
#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \ #define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \
HB_SCRIPT_INVALID, \ HB_SCRIPT_INVALID, \
HB_LANGUAGE_INVALID, \ HB_LANGUAGE_INVALID, \
@ -203,6 +210,8 @@ hb_buffer_get_user_data (hb_buffer_t *buffer,
* @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer. * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
* @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping). * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping).
* @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping). * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping).
*
* The type of #hb_buffer_t contents.
*/ */
typedef enum { typedef enum {
HB_BUFFER_CONTENT_TYPE_INVALID = 0, HB_BUFFER_CONTENT_TYPE_INVALID = 0,
@ -288,6 +297,8 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* not be inserted in the rendering of incorrect * not be inserted in the rendering of incorrect
* character sequences (such at <0905 093E>). Since: 2.4 * character sequences (such at <0905 093E>). Since: 2.4
* *
* Flags for #hb_buffer_t.
*
* Since: 0.9.20 * Since: 0.9.20
*/ */
typedef enum { /*< flags >*/ typedef enum { /*< flags >*/
@ -579,6 +590,35 @@ hb_buffer_deserialize_unicode (hb_buffer_t *buffer,
* Compare buffers * Compare buffers
*/ */
/**
* hb_buffer_diff_flags_t:
* @HB_BUFFER_DIFF_FLAG_EQUAL: equal buffers.
* @HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH: buffers with different
* #hb_buffer_content_type_t.
* @HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH: buffers with differing length.
* @HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT: `.notdef` glyph is present in the
* reference buffer.
* @HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT: dotted circle glyph is present
* in the reference buffer.
* @HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH: difference in #hb_glyph_info_t.codepoint
* @HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH: difference in #hb_glyph_info_t.cluster
* @HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH: difference in #hb_glyph_flags_t.
* @HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH: difference in #hb_glyph_position_t.
*
* Flags from comparing two #hb_buffer_t's.
*
* Buffer with different #hb_buffer_content_type_t cannot be meaningfully
* compared in any further detail.
*
* For buffers with differing length, the per-glyph comparison is not
* attempted, though we do still scan reference buffer for dotted circle and
* `.notdef` glyphs.
*
* If the buffers have the same length, we compare them glyph-by-glyph and
* report which aspect(s) of the glyph info/position are different.
*
* Since: 1.5.0
*/
typedef enum { /*< flags >*/ typedef enum { /*< flags >*/
HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000, HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000,
@ -618,6 +658,23 @@ hb_buffer_diff (hb_buffer_t *buffer,
* Debugging. * Debugging.
*/ */
/**
* hb_buffer_message_func_t:
* @buffer: An #hb_buffer_t to work upon
* @font: The #hb_font_t the @buffer is shaped with
* @message: %NULL-terminated message passed to the function
* @user_data: User data pointer passed by the caller
*
* A callback method for #hb_buffer_t. The method gets called with the
* #hb_buffer_t it was set on, the #hb_font_t the buffer is shaped with and a
* message describing what step of the shaping process will be performed.
* Returning %false from this method will skip this shaping step and move to
* the next one.
*
* Return value: %true to perform the shaping step, %false to skip it.
*
* Since: 1.1.3
*/
typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer, typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer,
hb_font_t *font, hb_font_t *font,
const char *message, const char *message,

View File

@ -139,7 +139,7 @@ struct hb_buffer_t
/* Methods */ /* Methods */
bool in_error () const { return !successful; } HB_NODISCARD bool in_error () const { return !successful; }
void allocate_var (unsigned int start, unsigned int count) void allocate_var (unsigned int start, unsigned int count)
{ {
@ -186,7 +186,7 @@ struct hb_buffer_t
hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; } 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_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
bool has_separate_output () const { return info != out_info; } HB_NODISCARD bool has_separate_output () const { return info != out_info; }
HB_INTERNAL void reset (); HB_INTERNAL void reset ();
@ -210,86 +210,89 @@ struct hb_buffer_t
HB_INTERNAL void clear_output (); HB_INTERNAL void clear_output ();
HB_INTERNAL void clear_positions (); HB_INTERNAL void clear_positions ();
HB_INTERNAL void replace_glyphs (unsigned int num_in, template <typename T>
unsigned int num_out, HB_NODISCARD bool replace_glyphs (unsigned int num_in,
const hb_codepoint_t *glyph_data); unsigned int num_out,
const T *glyph_data)
void replace_glyph (hb_codepoint_t glyph_index)
{ {
if (unlikely (out_info != info || out_len != idx)) { if (unlikely (!make_room_for (num_in, num_out))) return false;
if (unlikely (!make_room_for (1, 1))) return;
out_info[out_len] = info[idx]; assert (idx + num_in <= len);
merge_clusters (idx, idx + num_in);
hb_glyph_info_t &orig_info = idx < len ? cur() : prev();
hb_glyph_info_t *pinfo = &out_info[out_len];
for (unsigned int i = 0; i < num_out; i++)
{
*pinfo = orig_info;
pinfo->codepoint = glyph_data[i];
pinfo++;
} }
out_info[out_len].codepoint = glyph_index;
idx++; idx += num_in;
out_len++; out_len += num_out;
return true;
} }
HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph_index)
{ return replace_glyphs (1, 1, &glyph_index); }
/* Makes a copy of the glyph at idx to output and replace glyph_index */ /* Makes a copy of the glyph at idx to output and replace glyph_index */
hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index) HB_NODISCARD bool output_glyph (hb_codepoint_t glyph_index)
{ return replace_glyphs (0, 1, &glyph_index); }
HB_NODISCARD bool output_info (const hb_glyph_info_t &glyph_info)
{ {
if (unlikely (!make_room_for (0, 1))) return Crap (hb_glyph_info_t); if (unlikely (!make_room_for (0, 1))) return false;
if (unlikely (idx == len && !out_len))
return Crap (hb_glyph_info_t);
out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
out_info[out_len].codepoint = glyph_index;
out_len++;
return out_info[out_len - 1];
}
void output_info (const hb_glyph_info_t &glyph_info)
{
if (unlikely (!make_room_for (0, 1))) return;
out_info[out_len] = glyph_info; out_info[out_len] = glyph_info;
out_len++; out_len++;
return true;
} }
/* Copies glyph at idx to output but doesn't advance idx */ /* Copies glyph at idx to output but doesn't advance idx */
void copy_glyph () HB_NODISCARD bool copy_glyph ()
{ {
if (unlikely (!make_room_for (0, 1))) return; /* Extra copy because cur()'s return can be freed within
* output_info() call if buffer reallocates. */
out_info[out_len] = info[idx]; return output_info (hb_glyph_info_t (cur()));
out_len++;
} }
/* Copies glyph at idx to output and advance idx. /* Copies glyph at idx to output and advance idx.
* If there's no output, just advance idx. */ * If there's no output, just advance idx. */
void HB_NODISCARD bool next_glyph ()
next_glyph ()
{ {
if (have_output) if (have_output)
{ {
if (out_info != info || out_len != idx) if (out_info != info || out_len != idx)
{ {
if (unlikely (!make_room_for (1, 1))) return; if (unlikely (!make_room_for (1, 1))) return false;
out_info[out_len] = info[idx]; out_info[out_len] = info[idx];
} }
out_len++; out_len++;
} }
idx++; idx++;
return true;
} }
/* Copies n glyphs at idx to output and advance idx. /* Copies n glyphs at idx to output and advance idx.
* If there's no output, just advance idx. */ * If there's no output, just advance idx. */
void HB_NODISCARD bool next_glyphs (unsigned int n)
next_glyphs (unsigned int n)
{ {
if (have_output) if (have_output)
{ {
if (out_info != info || out_len != idx) if (out_info != info || out_len != idx)
{ {
if (unlikely (!make_room_for (n, n))) return; if (unlikely (!make_room_for (n, n))) return false;
memmove (out_info + out_len, info + idx, n * sizeof (out_info[0])); memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
} }
out_len += n; out_len += n;
} }
idx += n; idx += n;
return true;
} }
/* Advance idx without copying to output. */ /* Advance idx without copying to output. */
void skip_glyph () { idx++; } void skip_glyph () { idx++; }
@ -329,14 +332,14 @@ struct hb_buffer_t
/* Internal methods */ /* Internal methods */
HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */ HB_NODISCARD HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
HB_INTERNAL bool enlarge (unsigned int size); HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size);
bool ensure (unsigned int size) HB_NODISCARD bool ensure (unsigned int size)
{ return likely (!size || size < allocated) ? true : enlarge (size); } { return likely (!size || size < allocated) ? true : enlarge (size); }
bool ensure_inplace (unsigned int size) HB_NODISCARD bool ensure_inplace (unsigned int size)
{ return likely (!size || size < allocated); } { return likely (!size || size < allocated); }
void assert_glyphs () void assert_glyphs ()
@ -349,7 +352,7 @@ struct hb_buffer_t
assert ((content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) || assert ((content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) ||
(!len && (content_type == HB_BUFFER_CONTENT_TYPE_INVALID))); (!len && (content_type == HB_BUFFER_CONTENT_TYPE_INVALID)));
} }
bool ensure_glyphs () HB_NODISCARD bool ensure_glyphs ()
{ {
if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS))
{ {
@ -360,7 +363,7 @@ struct hb_buffer_t
} }
return true; return true;
} }
bool ensure_unicode () HB_NODISCARD bool ensure_unicode ()
{ {
if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_UNICODE)) if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_UNICODE))
{ {
@ -372,8 +375,8 @@ struct hb_buffer_t
return true; return true;
} }
HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); HB_NODISCARD HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
HB_INTERNAL bool shift_forward (unsigned int count); HB_NODISCARD HB_INTERNAL bool shift_forward (unsigned int count);
typedef long scratch_buffer_t; typedef long scratch_buffer_t;
HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size); HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);

View File

@ -675,8 +675,8 @@ hb_version_string ()
* Tests the library version against a minimum value, * Tests the library version against a minimum value,
* as three integer components. * as three integer components.
* *
* Return value: True if the library is equal to or greater than * Return value: %true if the library is equal to or greater than
* the test value, false otherwise * the test value, %false otherwise
* *
* Since: 0.9.30 * Since: 0.9.30
**/ **/
@ -1003,6 +1003,21 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation
/** /**
* hb_variation_from_string: * hb_variation_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
* @len: length of @str, or -1 if string is %NULL terminated
* @variation: (out): the #hb_variation_t to initialize with the parsed values
*
* Parses a string into a #hb_variation_t.
*
* The format for specifying variation settings follows. All valid CSS
* font-variation-settings values other than 'normal' and 'inherited' are also
* accepted, though, not documented below.
*
* The format is a tag, optionally followed by an equals sign, followed by a
* number. For example `wght=500`, or `slnt=-7.5`.
*
* Return value:
* %true if @str is successfully parsed, %false otherwise
* *
* Since: 1.4.2 * Since: 1.4.2
*/ */
@ -1029,6 +1044,13 @@ hb_variation_from_string (const char *str, int len,
/** /**
* hb_variation_to_string: * hb_variation_to_string:
* @variation: an #hb_variation_t to convert
* @buf: (array length=size) (out): output string
* @size: the allocated size of @buf
*
* Converts an #hb_variation_t into a %NULL-terminated string in the format
* understood by hb_variation_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
* *
* Since: 1.4.2 * Since: 1.4.2
*/ */
@ -1055,9 +1077,11 @@ hb_variation_to_string (hb_variation_t *variation,
/** /**
* hb_color_get_alpha: * hb_color_get_alpha:
* color: a #hb_color_t we are interested in its channels. * @color: an #hb_color_t we are interested in its channels.
* *
* Return value: Alpha channel value of the given color * Fetches the alpha channel of the given @color.
*
* Return value: Alpha channel value
* *
* Since: 2.1.0 * Since: 2.1.0
*/ */
@ -1069,9 +1093,11 @@ uint8_t
/** /**
* hb_color_get_red: * hb_color_get_red:
* color: a #hb_color_t we are interested in its channels. * @color: an #hb_color_t we are interested in its channels.
* *
* Return value: Red channel value of the given color * Fetches the red channel of the given @color.
*
* Return value: Red channel value
* *
* Since: 2.1.0 * Since: 2.1.0
*/ */
@ -1083,9 +1109,11 @@ uint8_t
/** /**
* hb_color_get_green: * hb_color_get_green:
* color: a #hb_color_t we are interested in its channels. * @color: an #hb_color_t we are interested in its channels.
* *
* Return value: Green channel value of the given color * Fetches the green channel of the given @color.
*
* Return value: Green channel value
* *
* Since: 2.1.0 * Since: 2.1.0
*/ */
@ -1097,9 +1125,11 @@ uint8_t
/** /**
* hb_color_get_blue: * hb_color_get_blue:
* color: a #hb_color_t we are interested in its channels. * @color: an #hb_color_t we are interested in its channels.
* *
* Return value: Blue channel value of the given color * Fetches the blue channel of the given @color.
*
* Return value: Blue channel value
* *
* Since: 2.1.0 * Since: 2.1.0
*/ */

View File

@ -26,7 +26,7 @@
* Google Author(s): Behdad Esfahbod * Google Author(s): Behdad Esfahbod
*/ */
#ifndef HB_H_IN #if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead." #error "Include <hb.h> instead."
#endif #endif
@ -135,7 +135,7 @@ typedef union _hb_var_int_t {
/** /**
* hb_tag_t: * hb_tag_t:
* *
* Data type for tag identifiers. Tags are four * Data type for tag identifiers. Tags are four
* byte integers, each byte representing a character. * byte integers, each byte representing a character.
* *
@ -148,22 +148,48 @@ typedef uint32_t hb_tag_t;
/** /**
* HB_TAG: * HB_TAG:
* @c1: 1st character of the tag
* @c2: 2nd character of the tag
* @c3: 3rd character of the tag
* @c4: 4th character of the tag
* *
* Constructs an #hb_tag_t from four characters. * Constructs an #hb_tag_t from four character literals.
* *
**/ **/
#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF))) #define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF)))
/** /**
* HB_UNTAG: * HB_UNTAG:
* @tag: an #hb_tag_t
* *
* Extracts the characters from an #hb_tag_t. * Extracts four character literals from an #hb_tag_t.
*
* Since: 0.6.0
* *
**/ **/
#define HB_UNTAG(tag) (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF) #define HB_UNTAG(tag) (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF)
/**
* HB_TAG_NONE:
*
* Unset #hb_tag_t.
*/
#define HB_TAG_NONE HB_TAG(0,0,0,0) #define HB_TAG_NONE HB_TAG(0,0,0,0)
/**
* HB_TAG_MAX:
*
* Maximum possible unsigned #hb_tag_t.
*
* Since: 0.9.26
*/
#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff) #define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
/**
* HB_TAG_MAX_SIGNED:
*
* Maximum possible signed #hb_tag_t.
*
* Since: 0.9.33
*/
#define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff) #define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff)
/* len=-1 means str is NUL-terminated. */ /* len=-1 means str is NUL-terminated. */
@ -263,6 +289,13 @@ hb_direction_to_string (hb_direction_t direction);
/* hb_language_t */ /* hb_language_t */
/**
* hb_language_t:
*
* Data type for languages. Each #hb_language_t corresponds to a BCP 47
* language tag.
*
*/
typedef const struct hb_language_impl_t *hb_language_t; typedef const struct hb_language_impl_t *hb_language_t;
HB_EXTERN hb_language_t HB_EXTERN hb_language_t
@ -271,6 +304,13 @@ hb_language_from_string (const char *str, int len);
HB_EXTERN const char * HB_EXTERN const char *
hb_language_to_string (hb_language_t language); hb_language_to_string (hb_language_t language);
/**
* HB_LANGUAGE_INVALID:
*
* An unset #hb_language_t.
*
* Since: 0.6.0
*/
#define HB_LANGUAGE_INVALID ((hb_language_t) 0) #define HB_LANGUAGE_INVALID ((hb_language_t) 0)
HB_EXTERN hb_language_t HB_EXTERN hb_language_t
@ -279,160 +319,164 @@ hb_language_get_default (void);
/** /**
* hb_script_t: * hb_script_t:
* @HB_SCRIPT_COMMON: HB_TAG ('Z','y','y','y') * @HB_SCRIPT_COMMON: `Zyyy`
* @HB_SCRIPT_INHERITED: HB_TAG ('Z','i','n','h') * @HB_SCRIPT_INHERITED: `Zinh`
* @HB_SCRIPT_UNKNOWN: HB_TAG ('Z','z','z','z') * @HB_SCRIPT_UNKNOWN: `Zzzz`
* @HB_SCRIPT_ARABIC * @HB_SCRIPT_ARABIC: `Arab`
* @HB_SCRIPT_ARMENIAN * @HB_SCRIPT_ARMENIAN: `Armn`
* @HB_SCRIPT_BENGALI * @HB_SCRIPT_BENGALI: `Beng`
* @HB_SCRIPT_CYRILLIC * @HB_SCRIPT_CYRILLIC: `Cyrl`
* @HB_SCRIPT_DEVANAGARI * @HB_SCRIPT_DEVANAGARI: `Deva`
* @HB_SCRIPT_GEORGIAN * @HB_SCRIPT_GEORGIAN: `Geor`
* @HB_SCRIPT_GREEK * @HB_SCRIPT_GREEK: `Grek`
* @HB_SCRIPT_GUJARATI * @HB_SCRIPT_GUJARATI: `Gujr`
* @HB_SCRIPT_GURMUKHI * @HB_SCRIPT_GURMUKHI: `Guru`
* @HB_SCRIPT_HANGUL * @HB_SCRIPT_HANGUL: `Hang`
* @HB_SCRIPT_HAN * @HB_SCRIPT_HAN: `Hani`
* @HB_SCRIPT_HEBREW * @HB_SCRIPT_HEBREW: `Hebr`
* @HB_SCRIPT_HIRAGANA * @HB_SCRIPT_HIRAGANA: `Hira`
* @HB_SCRIPT_KANNADA * @HB_SCRIPT_KANNADA: `Knda`
* @HB_SCRIPT_KATAKANA * @HB_SCRIPT_KATAKANA: `Kana`
* @HB_SCRIPT_LAO * @HB_SCRIPT_LAO: `Laoo`
* @HB_SCRIPT_LATIN * @HB_SCRIPT_LATIN: `Latn`
* @HB_SCRIPT_MALAYALAM * @HB_SCRIPT_MALAYALAM: `Mlym`
* @HB_SCRIPT_ORIYA * @HB_SCRIPT_ORIYA: `Orya`
* @HB_SCRIPT_TAMIL * @HB_SCRIPT_TAMIL: `Taml`
* @HB_SCRIPT_TELUGU * @HB_SCRIPT_TELUGU: `Telu`
* @HB_SCRIPT_THAI * @HB_SCRIPT_THAI: `Thai`
* @HB_SCRIPT_TIBETAN * @HB_SCRIPT_TIBETAN: `Tibt`
* @HB_SCRIPT_BOPOMOFO * @HB_SCRIPT_BOPOMOFO: `Bopo`
* @HB_SCRIPT_BRAILLE * @HB_SCRIPT_BRAILLE: `Brai`
* @HB_SCRIPT_CANADIAN_SYLLABICS * @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans`
* @HB_SCRIPT_CHEROKEE * @HB_SCRIPT_CHEROKEE: `Cher`
* @HB_SCRIPT_ETHIOPIC * @HB_SCRIPT_ETHIOPIC: `Ethi`
* @HB_SCRIPT_KHMER * @HB_SCRIPT_KHMER: `Khmr`
* @HB_SCRIPT_MONGOLIAN * @HB_SCRIPT_MONGOLIAN: `Mong`
* @HB_SCRIPT_MYANMAR * @HB_SCRIPT_MYANMAR: `Mymr`
* @HB_SCRIPT_OGHAM * @HB_SCRIPT_OGHAM: `Ogam`
* @HB_SCRIPT_RUNIC * @HB_SCRIPT_RUNIC: `Runr`
* @HB_SCRIPT_SINHALA * @HB_SCRIPT_SINHALA: `Sinh`
* @HB_SCRIPT_SYRIAC * @HB_SCRIPT_SYRIAC: `Syrc`
* @HB_SCRIPT_THAANA * @HB_SCRIPT_THAANA: `Thaa`
* @HB_SCRIPT_YI * @HB_SCRIPT_YI: `Yiii`
* @HB_SCRIPT_DESERET * @HB_SCRIPT_DESERET: `Dsrt`
* @HB_SCRIPT_GOTHIC * @HB_SCRIPT_GOTHIC: `Goth`
* @HB_SCRIPT_OLD_ITALIC * @HB_SCRIPT_OLD_ITALIC: `Ital`
* @HB_SCRIPT_BUHID * @HB_SCRIPT_BUHID: `Buhd`
* @HB_SCRIPT_HANUNOO * @HB_SCRIPT_HANUNOO: `Hano`
* @HB_SCRIPT_TAGALOG * @HB_SCRIPT_TAGALOG: `Tglg`
* @HB_SCRIPT_TAGBANWA * @HB_SCRIPT_TAGBANWA: `Tagb`
* @HB_SCRIPT_CYPRIOT * @HB_SCRIPT_CYPRIOT: `Cprt`
* @HB_SCRIPT_LIMBU * @HB_SCRIPT_LIMBU: `Limb`
* @HB_SCRIPT_LINEAR_B * @HB_SCRIPT_LINEAR_B: `Linb`
* @HB_SCRIPT_OSMANYA * @HB_SCRIPT_OSMANYA: `Osma`
* @HB_SCRIPT_SHAVIAN * @HB_SCRIPT_SHAVIAN: `Shaw`
* @HB_SCRIPT_TAI_LE * @HB_SCRIPT_TAI_LE: `Tale`
* @HB_SCRIPT_UGARITIC * @HB_SCRIPT_UGARITIC: `Ugar`
* @HB_SCRIPT_BUGINESE * @HB_SCRIPT_BUGINESE: `Bugi`
* @HB_SCRIPT_COPTIC * @HB_SCRIPT_COPTIC: `Copt`
* @HB_SCRIPT_GLAGOLITIC * @HB_SCRIPT_GLAGOLITIC: `Glag`
* @HB_SCRIPT_KHAROSHTHI * @HB_SCRIPT_KHAROSHTHI: `Khar`
* @HB_SCRIPT_NEW_TAI_LUE * @HB_SCRIPT_NEW_TAI_LUE: `Talu`
* @HB_SCRIPT_OLD_PERSIAN * @HB_SCRIPT_OLD_PERSIAN: `Xpeo`
* @HB_SCRIPT_SYLOTI_NAGRI * @HB_SCRIPT_SYLOTI_NAGRI: `Sylo`
* @HB_SCRIPT_TIFINAGH * @HB_SCRIPT_TIFINAGH: `Tfng`
* @HB_SCRIPT_BALINESE * @HB_SCRIPT_BALINESE: `Bali`
* @HB_SCRIPT_CUNEIFORM * @HB_SCRIPT_CUNEIFORM: `Xsux`
* @HB_SCRIPT_NKO * @HB_SCRIPT_NKO: `Nkoo`
* @HB_SCRIPT_PHAGS_PA * @HB_SCRIPT_PHAGS_PA: `Phag`
* @HB_SCRIPT_PHOENICIAN * @HB_SCRIPT_PHOENICIAN: `Phnx`
* @HB_SCRIPT_CARIAN * @HB_SCRIPT_CARIAN: `Cari`
* @HB_SCRIPT_CHAM * @HB_SCRIPT_CHAM: `Cham`
* @HB_SCRIPT_KAYAH_LI * @HB_SCRIPT_KAYAH_LI: `Kali`
* @HB_SCRIPT_LEPCHA * @HB_SCRIPT_LEPCHA: `Lepc`
* @HB_SCRIPT_LYCIAN * @HB_SCRIPT_LYCIAN: `Lyci`
* @HB_SCRIPT_LYDIAN * @HB_SCRIPT_LYDIAN: `Lydi`
* @HB_SCRIPT_OL_CHIKI * @HB_SCRIPT_OL_CHIKI: `Olck`
* @HB_SCRIPT_REJANG * @HB_SCRIPT_REJANG: `Rjng`
* @HB_SCRIPT_SAURASHTRA * @HB_SCRIPT_SAURASHTRA: `Saur`
* @HB_SCRIPT_SUNDANESE * @HB_SCRIPT_SUNDANESE: `Sund`
* @HB_SCRIPT_VAI * @HB_SCRIPT_VAI: `Vaii`
* @HB_SCRIPT_AVESTAN * @HB_SCRIPT_AVESTAN: `Avst`
* @HB_SCRIPT_BAMUM * @HB_SCRIPT_BAMUM: `Bamu`
* @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp`
* @HB_SCRIPT_IMPERIAL_ARAMAIC * @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi`
* @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli`
* @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti`
* @HB_SCRIPT_JAVANESE * @HB_SCRIPT_JAVANESE: `Java`
* @HB_SCRIPT_KAITHI * @HB_SCRIPT_KAITHI: `Kthi`
* @HB_SCRIPT_LISU * @HB_SCRIPT_LISU: `Lisu`
* @HB_SCRIPT_MEETEI_MAYEK * @HB_SCRIPT_MEETEI_MAYEK: `Mtei`
* @HB_SCRIPT_OLD_SOUTH_ARABIAN * @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb`
* @HB_SCRIPT_OLD_TURKIC * @HB_SCRIPT_OLD_TURKIC: `Orkh`
* @HB_SCRIPT_SAMARITAN * @HB_SCRIPT_SAMARITAN: `Samr`
* @HB_SCRIPT_TAI_THAM * @HB_SCRIPT_TAI_THAM: `Lana`
* @HB_SCRIPT_TAI_VIET * @HB_SCRIPT_TAI_VIET: `Tavt`
* @HB_SCRIPT_BATAK * @HB_SCRIPT_BATAK: `Batk`
* @HB_SCRIPT_BRAHMI * @HB_SCRIPT_BRAHMI: `Brah`
* @HB_SCRIPT_MANDAIC * @HB_SCRIPT_MANDAIC: `Mand`
* @HB_SCRIPT_CHAKMA * @HB_SCRIPT_CHAKMA: `Cakm`
* @HB_SCRIPT_MEROITIC_CURSIVE * @HB_SCRIPT_MEROITIC_CURSIVE: `Merc`
* @HB_SCRIPT_MEROITIC_HIEROGLYPHS * @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero`
* @HB_SCRIPT_MIAO * @HB_SCRIPT_MIAO: `Plrd`
* @HB_SCRIPT_SHARADA * @HB_SCRIPT_SHARADA: `Shrd`
* @HB_SCRIPT_SORA_SOMPENG * @HB_SCRIPT_SORA_SOMPENG: `Sora`
* @HB_SCRIPT_TAKRI * @HB_SCRIPT_TAKRI: `Takr`
* @HB_SCRIPT_BASSA_VAH * @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30
* @HB_SCRIPT_CAUCASIAN_ALBANIAN * @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30
* @HB_SCRIPT_DUPLOYAN * @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30
* @HB_SCRIPT_ELBASAN * @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30
* @HB_SCRIPT_GRANTHA * @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30
* @HB_SCRIPT_KHOJKI * @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30
* @HB_SCRIPT_KHUDAWADI * @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30
* @HB_SCRIPT_LINEAR_A * @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30
* @HB_SCRIPT_MAHAJANI * @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30
* @HB_SCRIPT_MANICHAEAN * @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30
* @HB_SCRIPT_MENDE_KIKAKUI * @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30
* @HB_SCRIPT_MODI * @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30
* @HB_SCRIPT_MRO * @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30
* @HB_SCRIPT_NABATAEAN * @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30
* @HB_SCRIPT_OLD_NORTH_ARABIAN * @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30
* @HB_SCRIPT_OLD_PERMIC * @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30
* @HB_SCRIPT_PAHAWH_HMONG * @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30
* @HB_SCRIPT_PALMYRENE * @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30
* @HB_SCRIPT_PAU_CIN_HAU * @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30
* @HB_SCRIPT_PSALTER_PAHLAVI * @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30
* @HB_SCRIPT_SIDDHAM * @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30
* @HB_SCRIPT_TIRHUTA * @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30
* @HB_SCRIPT_WARANG_CITI * @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30
* @HB_SCRIPT_AHOM * @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30
* @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30
* @HB_SCRIPT_HATRAN * @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30
* @HB_SCRIPT_MULTANI * @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30
* @HB_SCRIPT_OLD_HUNGARIAN * @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30
* @HB_SCRIPT_SIGNWRITING * @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30
* @HB_SCRIPT_ADLAM * @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0
* @HB_SCRIPT_BHAIKSUKI * @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0
* @HB_SCRIPT_MARCHEN * @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0
* @HB_SCRIPT_OSAGE * @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0
* @HB_SCRIPT_TANGUT * @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0
* @HB_SCRIPT_NEWA * @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0
* @HB_SCRIPT_MASARAM_GONDI * @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0
* @HB_SCRIPT_NUSHU * @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0
* @HB_SCRIPT_SOYOMBO * @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0
* @HB_SCRIPT_ZANABAZAR_SQUARE * @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0
* @HB_SCRIPT_DOGRA * @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0
* @HB_SCRIPT_GUNJALA_GONDI * @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0
* @HB_SCRIPT_HANIFI_ROHINGYA * @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0
* @HB_SCRIPT_MAKASAR * @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0
* @HB_SCRIPT_MEDEFAIDRIN * @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0
* @HB_SCRIPT_OLD_SOGDIAN * @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0
* @HB_SCRIPT_SOGDIAN * @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0
* @HB_SCRIPT_ELYMAIC * @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0
* @HB_SCRIPT_NANDINAGARI * @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0
* @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0
* @HB_SCRIPT_WANCHO * @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0
* @HB_SCRIPT_INVALID: #HB_TAG_NONE * @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7
* @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
* @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
* @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
* @HB_SCRIPT_INVALID: No script set
* *
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
* to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/). * to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/).
@ -441,208 +485,208 @@ hb_language_get_default (void);
* *
**/ **/
/* https://unicode.org/iso15924/ */
/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */ /* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */
/* Unicode Character Database property: Script (sc) */
typedef enum typedef enum
{ {
/*1.1*/ HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/
/*1.1*/ HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/
/*5.0*/ HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/
/*1.1*/ HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/
/*1.1*/ HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/
/*1.1*/ HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/
/*1.1*/ HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/
/*1.1*/ HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/
/*1.1*/ HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/
/*1.1*/ HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/
/*1.1*/ HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/
/*1.1*/ HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/
/*1.1*/ HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/
/*1.1*/ HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/
/*1.1*/ HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/
/*1.1*/ HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/
/*1.1*/ HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/
/*1.1*/ HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/
/*1.1*/ HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/
/*1.1*/ HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/
/*1.1*/ HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/
/*1.1*/ HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/
/*1.1*/ HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/
/*1.1*/ HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/
/*1.1*/ HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/
/*2.0*/ HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/
/*3.0*/ HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/
/*3.0*/ HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/
/*3.0*/ HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/
/*3.0*/ HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/
/*3.0*/ HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/
/*3.0*/ HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/
/*3.0*/ HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/
/*3.0*/ HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/
/*3.0*/ HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/
/*3.0*/ HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/
/*3.0*/ HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/
/*3.0*/ HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/
/*3.0*/ HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/
/*3.0*/ HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/
/*3.1*/ HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/
/*3.1*/ HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/
/*3.1*/ HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/
/*3.2*/ HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/
/*3.2*/ HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/
/*3.2*/ HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/
/*3.2*/ HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/
/*4.0*/ HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/
/*4.0*/ HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/
/*4.0*/ HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/
/*4.0*/ HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/
/*4.0*/ HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/
/*4.0*/ HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/
/*4.0*/ HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/
/*4.1*/ HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/
/*4.1*/ HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/
/*4.1*/ HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/
/*4.1*/ HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/
/*4.1*/ HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/
/*4.1*/ HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/
/*4.1*/ HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/
/*4.1*/ HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/
/*5.0*/ HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/
/*5.0*/ HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/
/*5.0*/ HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/
/*5.0*/ HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/
/*5.0*/ HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/
/*5.1*/ HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/
/*5.1*/ HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/
/*5.1*/ HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/
/*5.1*/ HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/
/*5.1*/ HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/
/*5.1*/ HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/
/*5.1*/ HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/
/*5.1*/ HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/
/*5.1*/ HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/
/*5.1*/ HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/
/*5.1*/ HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/
/*5.2*/ HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/
/*5.2*/ HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/
/*5.2*/ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/
/*5.2*/ HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/
/*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/
/*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/
/*5.2*/ HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/
/*5.2*/ HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/
/*5.2*/ HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/
/*5.2*/ HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/
/*5.2*/ HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/
/*5.2*/ HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/
/*5.2*/ HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/
/*5.2*/ HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/
/*5.2*/ HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/
/*6.0*/ HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/
/*6.0*/ HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/
/*6.0*/ HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/
/*6.1*/ HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/
/*6.1*/ HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/
/*6.1*/ HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/
/*6.1*/ HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/
/*6.1*/ HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/
/*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/
/*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/
/* /*
* Since: 0.9.30 * Since: 0.9.30
*/ */
/*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/
/*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/
/*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/
/*7.0*/ HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/
/*7.0*/ HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/
/*7.0*/ HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/
/*7.0*/ HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/
/*7.0*/ HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/
/*7.0*/ HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/
/*7.0*/ HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/
/*7.0*/ HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/
/*7.0*/ HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/
/*7.0*/ HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/
/*7.0*/ HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/
/*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/
/*7.0*/ HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/
/*7.0*/ HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/
/*7.0*/ HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/
/*7.0*/ HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/
/*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/
/*7.0*/ HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/
/*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/
/*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/
/*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/
/*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/
/*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/
/*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/
/*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/
/*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/
/* /*
* Since 1.3.0 * Since 1.3.0
*/ */
/*9.0*/ HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/
/*9.0*/ HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/
/*9.0*/ HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/
/*9.0*/ HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/
/*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/
/*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/
/* /*
* Since 1.6.0 * Since 1.6.0
*/ */
/*10.0*/HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/
/*10.0*/HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/
/*10.0*/HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/
/*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/
/* /*
* Since 1.8.0 * Since 1.8.0
*/ */
/*11.0*/HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/
/*11.0*/HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/
/*11.0*/HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/
/*11.0*/HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/
/*11.0*/HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/
/*11.0*/HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/
/*11.0*/HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/
/* /*
* Since 2.4.0 * Since 2.4.0
*/ */
/*12.0*/HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/
/*12.0*/HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/
/*12.0*/HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/
/*12.0*/HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/
/* /*
* Since 2.6.7 * Since 2.6.7
*/ */
/*13.0*/HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/
/*13.0*/HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/
/*13.0*/HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/
/*13.0*/HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/
/* No script set. */ /* No script set. */
HB_SCRIPT_INVALID = HB_TAG_NONE, HB_SCRIPT_INVALID = HB_TAG_NONE,
/*< private >*/
/* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
* without risking undefined behavior. We have two, for historical reasons. * without risking undefined behavior. We have two, for historical reasons.
@ -687,19 +731,33 @@ typedef struct hb_user_data_key_t {
char unused; char unused;
} hb_user_data_key_t; } hb_user_data_key_t;
/**
* hb_destroy_func_t:
* @user_data: the data to be destroyed
*
* A virtual method for destroy user-data callbacks.
*
*/
typedef void (*hb_destroy_func_t) (void *user_data); typedef void (*hb_destroy_func_t) (void *user_data);
/* Font features and variations. */ /* Font features and variations. */
/** /**
* HB_FEATURE_GLOBAL_START * HB_FEATURE_GLOBAL_START:
*
* Special setting for #hb_feature_t.start to apply the feature from the start
* of the buffer.
* *
* Since: 2.0.0 * Since: 2.0.0
*/ */
#define HB_FEATURE_GLOBAL_START 0 #define HB_FEATURE_GLOBAL_START 0
/** /**
* HB_FEATURE_GLOBAL_END * HB_FEATURE_GLOBAL_END:
*
* Special setting for #hb_feature_t.end to apply the feature from to the end
* of the buffer.
* *
* Since: 2.0.0 * Since: 2.0.0
*/ */
@ -717,7 +775,7 @@ typedef void (*hb_destroy_func_t) (void *user_data);
* The #hb_feature_t is the structure that holds information about requested * The #hb_feature_t is the structure that holds information about requested
* feature application. The feature will be applied with the given value to all * feature application. The feature will be applied with the given value to all
* glyphs which are in clusters between @start (inclusive) and @end (exclusive). * glyphs which are in clusters between @start (inclusive) and @end (exclusive).
* Setting start to @HB_FEATURE_GLOBAL_START and end to @HB_FEATURE_GLOBAL_END * Setting start to #HB_FEATURE_GLOBAL_START and end to #HB_FEATURE_GLOBAL_END
* specifies that the feature always applies to the entire buffer. * specifies that the feature always applies to the entire buffer.
*/ */
typedef struct hb_feature_t { typedef struct hb_feature_t {
@ -741,8 +799,8 @@ hb_feature_to_string (hb_feature_t *feature,
* @value: The value of the variation axis * @value: The value of the variation axis
* *
* Data type for holding variation data. Registered OpenType * Data type for holding variation data. Registered OpenType
* variation-axis tags are listed at * variation-axis tags are listed in
* https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg * [OpenType Axis Tag Registry](https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg).
* *
* Since: 1.4.2 * Since: 1.4.2
*/ */
@ -769,6 +827,17 @@ hb_variation_to_string (hb_variation_t *variation,
*/ */
typedef uint32_t hb_color_t; typedef uint32_t hb_color_t;
/**
* HB_COLOR:
* @b: blue channel value
* @g: green channel value
* @r: red channel value
* @a: alpha channel value
*
* Constructs an #hb_color_t from four integers.
*
* Since: 2.1.0
*/
#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a))) #define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
HB_EXTERN uint8_t HB_EXTERN uint8_t

View File

@ -34,7 +34,6 @@
#include "hb-coretext.h" #include "hb-coretext.h"
#include "hb-aat-layout.hh" #include "hb-aat-layout.hh"
#include <math.h>
/** /**
@ -190,7 +189,10 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
* reconfiguring the cascade list causes CoreText crashes. For details, see * reconfiguring the cascade list causes CoreText crashes. For details, see
* crbug.com/549610 */ * crbug.com/549610 */
// 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) { if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) {
#pragma GCC diagnostic pop
CFStringRef fontName = CTFontCopyPostScriptName (ct_font); CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo; bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
CFRelease (fontName); CFRelease (fontName);
@ -346,7 +348,7 @@ retry:
const hb_coretext_font_data_t *data = font->data.coretext; const hb_coretext_font_data_t *data = font->data.coretext;
if (unlikely (!data)) return nullptr; if (unlikely (!data)) return nullptr;
if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > .5) if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > (CGFloat) .5)
{ {
/* XXX-MT-bug /* XXX-MT-bug
* Note that evaluating condition above can be dangerous if another thread * Note that evaluating condition above can be dangerous if another thread
@ -402,7 +404,7 @@ hb_coretext_font_create (CTFontRef ct_font)
} }
/** /**
* hb_coretext_face_get_ct_font: * hb_coretext_font_get_ct_font:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* *
* Fetches the CTFontRef associated with the specified * Fetches the CTFontRef associated with the specified
@ -858,7 +860,7 @@ resize_and_retry:
buffer->len = 0; buffer->len = 0;
uint32_t status_and = ~0, status_or = 0; uint32_t status_and = ~0, status_or = 0;
double advances_so_far = 0; CGFloat advances_so_far = 0;
/* For right-to-left runs, CoreText returns the glyphs positioned such that /* For right-to-left runs, CoreText returns the glyphs positioned such that
* any trailing whitespace is to the left of (0,0). Adjust coordinate system * any trailing whitespace is to the left of (0,0). Adjust coordinate system
* to fix for that. Test with any RTL string with trailing spaces. * to fix for that. Test with any RTL string with trailing spaces.
@ -880,10 +882,10 @@ resize_and_retry:
status_or |= run_status; status_or |= run_status;
status_and &= run_status; status_and &= run_status;
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
double run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr); CGFloat run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
run_advance = -run_advance; run_advance = -run_advance;
DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); DEBUG_MSG (CORETEXT, run, "Run advance: %g", (double) run_advance);
/* CoreText does automatic font fallback (AKA "cascading") for characters /* CoreText does automatic font fallback (AKA "cascading") for characters
* not supported by the requested font, and provides no way to turn it off, * not supported by the requested font, and provides no way to turn it off,
@ -1062,7 +1064,7 @@ resize_and_retry:
hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult; hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
for (unsigned int j = 0; j < num_glyphs; j++) for (unsigned int j = 0; j < num_glyphs; j++)
{ {
double advance; CGFloat advance;
if (likely (j + 1 < num_glyphs)) if (likely (j + 1 < num_glyphs))
advance = positions[j + 1].x - positions[j].x; advance = positions[j + 1].x - positions[j].x;
else /* last glyph */ else /* last glyph */
@ -1078,7 +1080,7 @@ resize_and_retry:
hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult; hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult;
for (unsigned int j = 0; j < num_glyphs; j++) for (unsigned int j = 0; j < num_glyphs; j++)
{ {
double advance; CGFloat advance;
if (likely (j + 1 < num_glyphs)) if (likely (j + 1 < num_glyphs))
advance = positions[j + 1].y - positions[j].y; advance = positions[j + 1].y - positions[j].y;
else /* last glyph */ else /* last glyph */

View File

@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod * Google Author(s): Behdad Esfahbod
*/ */
#ifndef HB_H_IN #if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead." #error "Include <hb.h> instead."
#endif #endif
@ -53,11 +53,50 @@ HB_BEGIN_DECLS
#ifndef HB_DISABLE_DEPRECATED #ifndef HB_DISABLE_DEPRECATED
/**
* HB_SCRIPT_CANADIAN_ABORIGINAL:
*
* Use #HB_SCRIPT_CANADIAN_SYLLABICS instead:
*
* Deprecated: 0.9.20
*/
#define HB_SCRIPT_CANADIAN_ABORIGINAL HB_SCRIPT_CANADIAN_SYLLABICS #define HB_SCRIPT_CANADIAN_ABORIGINAL HB_SCRIPT_CANADIAN_SYLLABICS
/**
* HB_BUFFER_FLAGS_DEFAULT:
*
* Use #HB_BUFFER_FLAG_DEFAULT instead.
*
* Deprecated: 0.9.20
*/
#define HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_FLAG_DEFAULT #define HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_FLAG_DEFAULT
/**
* HB_BUFFER_SERIALIZE_FLAGS_DEFAULT:
*
* Use #HB_BUFFER_SERIALIZE_FLAG_DEFAULT instead.
*
* Deprecated: 0.9.20
*/
#define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAG_DEFAULT #define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAG_DEFAULT
/**
* hb_font_get_glyph_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @unicode: The Unicode code point to query
* @variation_selector: The variation-selector code point to query
* @glyph: (out): The glyph ID retrieved
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the glyph ID for a specified Unicode code point
* font, with an optional variation selector.
*
* Return value: %true if data found, %false otherwise
* Deprecated: 1.2.3
*
**/
typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph, hb_codepoint_t *glyph,
@ -73,6 +112,11 @@ hb_set_invert (hb_set_t *set);
/** /**
* hb_unicode_eastasian_width_func_t: * hb_unicode_eastasian_width_func_t:
* @ufuncs: A Unicode-functions structure
* @unicode: The code point to query
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_unicode_funcs_t structure.
* *
* Deprecated: 2.0.0 * Deprecated: 2.0.0
*/ */
@ -82,12 +126,12 @@ typedef unsigned int (*hb_unicode_eastasian_width_func_t) (hb_unicode_funcs_t
/** /**
* hb_unicode_funcs_set_eastasian_width_func: * hb_unicode_funcs_set_eastasian_width_func:
* @ufuncs: a Unicode function structure * @ufuncs: a Unicode-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: * @user_data: Data to pass to @func
* @destroy: * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* * Sets the implementation function for #hb_unicode_eastasian_width_func_t.
* *
* Since: 0.9.2 * Since: 0.9.2
* Deprecated: 2.0.0 * Deprecated: 2.0.0
@ -99,6 +143,10 @@ hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
/** /**
* hb_unicode_eastasian_width: * hb_unicode_eastasian_width:
* @ufuncs: a Unicode-function structure
* @unicode: The code point to query
*
* Don't use. Not used by HarfBuzz.
* *
* Since: 0.9.2 * Since: 0.9.2
* Deprecated: 2.0.0 * Deprecated: 2.0.0
@ -112,7 +160,7 @@ hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
* hb_unicode_decompose_compatibility_func_t: * hb_unicode_decompose_compatibility_func_t:
* @ufuncs: a Unicode function structure * @ufuncs: a Unicode function structure
* @u: codepoint to decompose * @u: codepoint to decompose
* @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into * @decomposed: address of codepoint array (of length #HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
* @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func() * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
* *
* Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed. * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
@ -120,7 +168,7 @@ hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
* *
* If @u has no compatibility decomposition, zero should be returned. * If @u has no compatibility decomposition, zero should be returned.
* *
* The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any * The Unicode standard guarantees that a buffer of length #HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
* compatibility decomposition plus an terminating value of 0. Consequently, @decompose must be allocated by the caller to be at least this length. Implementations * compatibility decomposition plus an terminating value of 0. Consequently, @decompose must be allocated by the caller to be at least this length. Implementations
* of this function type must ensure that they do not write past the provided array. * of this function type must ensure that they do not write past the provided array.
* *
@ -144,10 +192,12 @@ typedef unsigned int (*hb_unicode_decompose_compatibility_func_t) (hb_unicode_
/** /**
* hb_unicode_funcs_set_decompose_compatibility_func: * hb_unicode_funcs_set_decompose_compatibility_func:
* @ufuncs: a Unicode function structure * @ufuncs: A Unicode-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: * @user_data: Data to pass to @func
* @destroy: * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_unicode_decompose_compatibility_func_t.
* *
* *
* *
@ -165,16 +215,25 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t *decomposed); hb_codepoint_t *decomposed);
/**
* hb_font_get_glyph_v_kerning_func_t:
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the kerning-adjustment value for a glyph-pair in
* the specified font, for vertical text segments.
*
**/
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t; typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
/** /**
* hb_font_funcs_set_glyph_v_kerning_func: * hb_font_funcs_set_glyph_v_kerning_func:
* @ffuncs: font functions. * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: * @user_data: Data to pass to @func
* @destroy: * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* * Sets the implementation function for #hb_font_get_glyph_v_kerning_func_t.
* *
* Since: 0.9.2 * Since: 0.9.2
* Deprecated: 2.0.0 * Deprecated: 2.0.0

View File

@ -957,6 +957,8 @@ _hb_directwrite_font_release (void *data)
* hb_directwrite_face_create: * hb_directwrite_face_create:
* @font_face: a DirectWrite IDWriteFontFace object. * @font_face: a DirectWrite IDWriteFontFace object.
* *
* Constructs a new face object from the specified DirectWrite IDWriteFontFace.
*
* Return value: #hb_face_t object corresponding to the given input * Return value: #hb_face_t object corresponding to the given input
* *
* Since: 2.4.0 * Since: 2.4.0
@ -974,6 +976,8 @@ hb_directwrite_face_create (IDWriteFontFace *font_face)
* hb_directwrite_face_get_font_face: * hb_directwrite_face_get_font_face:
* @face: a #hb_face_t object * @face: a #hb_face_t object
* *
* Gets the DirectWrite IDWriteFontFace associated with @face.
*
* Return value: DirectWrite IDWriteFontFace object corresponding to the given input * Return value: DirectWrite IDWriteFontFace object corresponding to the given input
* *
* Since: 2.5.0 * Since: 2.5.0

View File

@ -38,7 +38,6 @@
template <typename Context, typename Return=hb_empty_t, unsigned int MaxDebugDepth=0> template <typename Context, typename Return=hb_empty_t, unsigned int MaxDebugDepth=0>
struct hb_dispatch_context_t struct hb_dispatch_context_t
{ {
hb_dispatch_context_t () : debug_depth (0) {}
private: private:
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
const Context* thiz () const { return static_cast<const Context *> (this); } const Context* thiz () const { return static_cast<const Context *> (this); }
@ -54,7 +53,7 @@ struct hb_dispatch_context_t
{ return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); } { return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); }
static return_t no_dispatch_return_value () { return Context::default_return_value (); } static return_t no_dispatch_return_value () { return Context::default_return_value (); }
static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; } static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
unsigned debug_depth; unsigned debug_depth = 0;
}; };

View File

@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/ */
#ifndef HB_H_IN #if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead." #error "Include <hb.h> instead."
#endif #endif

View File

@ -89,8 +89,8 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
nullptr, /* destroy */ nullptr, /* destroy */
0, /* index */ 0, /* index */
HB_ATOMIC_INT_INIT (1000), /* upem */ 1000, /* upem */
HB_ATOMIC_INT_INIT (0), /* num_glyphs */ 0, /* num_glyphs */
/* Zero for the rest is fine. */ /* Zero for the rest is fine. */
}; };
@ -100,7 +100,7 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
* hb_face_create_for_tables: * hb_face_create_for_tables:
* @reference_table_func: (closure user_data) (destroy destroy) (scope notified): Table-referencing function * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): Table-referencing function
* @user_data: A pointer to the user data * @user_data: A pointer to the user data
* @destroy: (optional): A callback to call when @data is not needed anymore * @destroy: (nullable): A callback to call when @data is not needed anymore
* *
* Variant of hb_face_create(), built for those cases where it is more * Variant of hb_face_create(), built for those cases where it is more
* convenient to provide data for individual tables instead of the whole font * convenient to provide data for individual tables instead of the whole font
@ -235,7 +235,7 @@ hb_face_create (hb_blob_t *blob,
* *
* Fetches the singleton empty face object. * Fetches the singleton empty face object.
* *
* Return value: (transfer full) The empty face object * Return value: (transfer full): The empty face object
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -299,7 +299,7 @@ hb_face_destroy (hb_face_t *face)
* @face: A face object * @face: A face object
* @key: The user-data key to set * @key: The user-data key to set
* @data: A pointer to the user data * @data: A pointer to the user data
* @destroy: (optional): A callback to call when @data is not needed anymore * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key * @replace: Whether to replace an existing data with the same key
* *
* Attaches a user-data key/data pair to the given face object. * Attaches a user-data key/data pair to the given face object.
@ -360,7 +360,7 @@ hb_face_make_immutable (hb_face_t *face)
* *
* Tests whether the given face object is immutable. * Tests whether the given face object is immutable.
* *
* Return value: True is @face is immutable, false otherwise * Return value: %true is @face is immutable, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -756,7 +756,7 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data; hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
hb_face_builder_data_t::table_entry_t *entry = data->tables.push (); hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
if (data->tables.in_error()) if (unlikely (data->tables.in_error()))
return false; return false;
entry->tag = tag; entry->tag = tag;

View File

@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
*/ */
#ifndef HB_H_IN #if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead." #error "Include <hb.h> instead."
#endif #endif
@ -58,6 +58,19 @@ HB_EXTERN hb_face_t *
hb_face_create (hb_blob_t *blob, hb_face_create (hb_blob_t *blob,
unsigned int index); unsigned int index);
/**
* hb_reference_table_func_t:
* @face: an #hb_face_t to reference table for
* @tag: the tag of the table to reference
* @user_data: User data pointer passed by the caller
*
* Callback function for hb_face_create_for_tables().
*
* Return value: (transfer full): A pointer to the @tag table within @face
*
* Since: 0.9.2
*/
typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data); typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data);
/* calls destroy() when not needing user_data anymore */ /* calls destroy() when not needing user_data anymore */

View File

@ -81,7 +81,7 @@ struct hb_face_t
return blob; return blob;
} }
HB_PURE_FUNC unsigned int get_upem () const unsigned int get_upem () const
{ {
unsigned int ret = upem.get_relaxed (); unsigned int ret = upem.get_relaxed ();
if (unlikely (!ret)) if (unlikely (!ret))

View File

@ -628,7 +628,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
* @ffuncs: The font-functions structure * @ffuncs: The font-functions structure
* @key: The user-data key to set * @key: The user-data key to set
* @data: A pointer to the user data set * @data: A pointer to the user data set
* @destroy: (optional): A callback to call when @data is not needed anymore * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key * @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.
@ -690,7 +690,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
* *
* Tests whether a font-functions structure is immutable. * Tests whether a font-functions structure is immutable.
* *
* Return value: %true if @ffuncs is immutable, false otherwise * Return value: %true if @ffuncs is immutable, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -753,10 +753,10 @@ hb_font_t::has_func (unsigned int i)
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @extents: (out): The font extents retrieved * @extents: (out): The font extents retrieved
* *
* Fetches the extents for a specified font, in horizontal * Fetches the extents for a specified font, for horizontal
* text segments. * text segments.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 1.1.3 * Since: 1.1.3
**/ **/
@ -772,10 +772,10 @@ hb_font_get_h_extents (hb_font_t *font,
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @extents: (out): The font extents retrieved * @extents: (out): The font extents retrieved
* *
* Fetches the extents for a specified font, in vertical * Fetches the extents for a specified font, for vertical
* text segments. * text segments.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 1.1.3 * Since: 1.1.3
**/ **/
@ -790,7 +790,7 @@ hb_font_get_v_extents (hb_font_t *font,
* hb_font_get_glyph: * hb_font_get_glyph:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @unicode: The Unicode code point to query * @unicode: The Unicode code point to query
* @variation_selector: (optional): A variation-selector code point * @variation_selector: A variation-selector code point
* @glyph: (out): The glyph ID retrieved * @glyph: (out): The glyph ID retrieved
* *
* Fetches the glyph ID for a Unicode code point in the specified * Fetches the glyph ID for a Unicode code point in the specified
@ -799,7 +799,7 @@ hb_font_get_v_extents (hb_font_t *font,
* If @variation_selector is 0, calls hb_font_get_nominal_glyph(); * If @variation_selector is 0, calls hb_font_get_nominal_glyph();
* otherwise calls hb_font_get_variation_glyph(). * otherwise calls hb_font_get_variation_glyph().
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -827,7 +827,7 @@ hb_font_get_glyph (hb_font_t *font,
* for code points modified by variation selectors. For variation-selector * for code points modified by variation selectors. For variation-selector
* support, user hb_font_get_variation_glyph() or use hb_font_get_glyph(). * support, user hb_font_get_variation_glyph() or use hb_font_get_glyph().
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 1.2.3 * Since: 1.2.3
**/ **/
@ -841,11 +841,17 @@ hb_font_get_nominal_glyph (hb_font_t *font,
/** /**
* hb_font_get_nominal_glyphs: * hb_font_get_nominal_glyphs:
* @font: a font. * @font: #hb_font_t to work upon
* @count: number of code points to query
* @first_unicode: The first Unicode code point to query
* @unicode_stride: The stride between successive code points
* @first_glyph: (out): The first glyph ID retrieved
* @glyph_stride: The stride between successive glyph IDs
* *
* Fetches the nominal glyph IDs for a sequence of Unicode code points. Glyph
* IDs must be returned in a #hb_codepoint_t output parameter.
* *
* * Return value: the number of code points processed
* Return value:
* *
* Since: 2.6.3 * Since: 2.6.3
**/ **/
@ -873,7 +879,7 @@ hb_font_get_nominal_glyphs (hb_font_t *font,
* by the specified variation-selector code point, in the specified * by the specified variation-selector code point, in the specified
* font. * font.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 1.2.3 * Since: 1.2.3
**/ **/
@ -931,7 +937,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
* @first_glyph: The first glyph ID to query * @first_glyph: The first glyph ID to query
* @glyph_stride: The stride between successive glyph IDs * @glyph_stride: The stride between successive glyph IDs
* @first_advance: (out): The first advance retrieved * @first_advance: (out): The first advance retrieved
* @advance_stride: (out): The stride between successive advances * @advance_stride: The stride between successive advances
* *
* Fetches the advances for a sequence of glyph IDs in the specified * Fetches the advances for a sequence of glyph IDs in the specified
* font, for horizontal text segments. * font, for horizontal text segments.
@ -983,7 +989,7 @@ hb_font_get_glyph_v_advances (hb_font_t* font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID * Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for horizontal text segments. * in the specified font, for horizontal text segments.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1006,7 +1012,7 @@ hb_font_get_glyph_h_origin (hb_font_t *font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID * Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for vertical text segments. * in the specified font, for vertical text segments.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1026,7 +1032,7 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
* @right_glyph: The glyph ID of the right glyph in the glyph pair * @right_glyph: The glyph ID of the right glyph in the glyph pair
* *
* Fetches the kerning-adjustment value for a glyph-pair in * Fetches the kerning-adjustment value for a glyph-pair in
* the specified font, in horizontal text segments. * the specified font, for horizontal text segments.
* *
* <note>It handles legacy kerning only (as returned by the corresponding * <note>It handles legacy kerning only (as returned by the corresponding
* #hb_font_funcs_t function).</note> * #hb_font_funcs_t function).</note>
@ -1051,7 +1057,7 @@ hb_font_get_glyph_h_kerning (hb_font_t *font,
* @bottom_glyph: The glyph ID of the bottom glyph in the glyph pair * @bottom_glyph: The glyph ID of the bottom glyph in the glyph pair
* *
* Fetches the kerning-adjustment value for a glyph-pair in * Fetches the kerning-adjustment value for a glyph-pair in
* the specified font, in vertical text segments. * the specified font, for vertical text segments.
* *
* <note>It handles legacy kerning only (as returned by the corresponding * <note>It handles legacy kerning only (as returned by the corresponding
* #hb_font_funcs_t function).</note> * #hb_font_funcs_t function).</note>
@ -1079,7 +1085,7 @@ hb_font_get_glyph_v_kerning (hb_font_t *font,
* Fetches the #hb_glyph_extents_t data for a glyph ID * Fetches the #hb_glyph_extents_t data for a glyph ID
* in the specified font. * in the specified font.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1102,7 +1108,7 @@ hb_font_get_glyph_extents (hb_font_t *font,
* Fetches the (x,y) coordinates of a specified contour-point index * Fetches the (x,y) coordinates of a specified contour-point index
* in the specified glyph, within the specified font. * in the specified glyph, within the specified font.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1125,7 +1131,7 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
* *
* Fetches the glyph-name string for a glyph ID in the specified @font. * Fetches the glyph-name string for a glyph ID in the specified @font.
* *
* Return value: %true if data found, zero otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1149,7 +1155,7 @@ hb_font_get_glyph_name (hb_font_t *font,
* *
* <note>Note: @len == -1 means the name string is null-terminated.</note> * <note>Note: @len == -1 means the name string is null-terminated.</note>
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1169,7 +1175,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
* hb_font_get_extents_for_direction: * hb_font_get_extents_for_direction:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @direction: The direction of the text segment * @direction: The direction of the text segment
* @extents: (out): The #hb_glyph_extents_t retrieved * @extents: (out): The #hb_font_extents_t retrieved
* *
* Fetches the extents for a font in a text segment of the * Fetches the extents for a font in a text segment of the
* specified direction. * specified direction.
@ -1364,7 +1370,7 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal * Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction. * or vertical) depending on the value of @direction.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1393,7 +1399,7 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal * Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction. * or vertical) depending on the value of @direction.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1444,7 +1450,7 @@ hb_font_glyph_to_string (hb_font_t *font,
* *
* <note>Note: @len == -1 means the string is null-terminated.</note> * <note>Note: @len == -1 means the string is null-terminated.</note>
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1664,12 +1670,12 @@ hb_font_destroy (hb_font_t *font)
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @key: The user-data key * @key: The user-data key
* @data: A pointer to the user data * @data: A pointer to the user data
* @destroy: (optional): A callback to call when @data is not needed anymore * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key * @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: * Return value: %true if success, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1728,7 +1734,7 @@ hb_font_make_immutable (hb_font_t *font)
* *
* Tests whether a font object is immutable. * Tests whether a font object is immutable.
* *
* Return value: %true if @font is immutable, false otherwise * Return value: %true if @font is immutable, %false otherwise
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -1828,9 +1834,9 @@ hb_font_get_face (hb_font_t *font)
/** /**
* hb_font_set_funcs: * hb_font_set_funcs:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @klass: (closure font_data) (destroy destroy) (scope notified): * @klass: (closure font_data) (destroy destroy) (scope notified): The font-functions structure.
* @font_data: Data to attach to @font * @font_data: Data to attach to @font
* @destroy: (optional): The function to call when @font_data is not needed anymore * @destroy: (nullable): The function to call when @font_data is not needed anymore
* *
* Replaces the font-functions structure attached to a font, updating * Replaces the font-functions structure attached to a font, updating
* the font's user-data with @font-data and the @destroy callback. * the font's user-data with @font-data and the @destroy callback.
@ -1867,7 +1873,7 @@ hb_font_set_funcs (hb_font_t *font,
* hb_font_set_funcs_data: * hb_font_set_funcs_data:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* @font_data: (destroy destroy) (scope notified): Data to attach to @font * @font_data: (destroy destroy) (scope notified): Data to attach to @font
* @destroy: (optional): The function to call when @font_data is not needed anymore * @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. * @destroy callback.
@ -2212,10 +2218,14 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
#ifdef HB_EXPERIMENTAL_API #ifdef HB_EXPERIMENTAL_API
/** /**
* hb_font_get_var_coords_design: * hb_font_get_var_coords_design:
* @font: #hb_font_t to work upon
* @length: (out): number of coordinates
* *
* Return value is valid as long as variation coordinates of the font * Return value is valid as long as variation coordinates of the font
* are not modified. * are not modified.
* *
* Return value: coordinates array
*
* Since: EXPERIMENTAL * Since: EXPERIMENTAL
*/ */
const float * const float *
@ -2319,7 +2329,7 @@ hb_font_get_variation_glyph_trampoline (hb_font_t *font,
* @ffuncs: The font-functions structure * @ffuncs: The font-functions structure
* @func: (closure user_data) (destroy destroy) (scope notified): callback function * @func: (closure user_data) (destroy destroy) (scope notified): callback function
* @user_data: data to pass to @func * @user_data: data to pass to @func
* @destroy: (optional): function to call when @user_data is not needed anymore * @destroy: (nullable): function to call when @user_data is not needed anymore
* *
* Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and * Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and
* hb_font_funcs_set_variation_glyph_func() instead. * hb_font_funcs_set_variation_glyph_func() instead.

View File

@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
*/ */
#ifndef HB_H_IN #if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead." #error "Include <hb.h> instead."
#endif #endif
@ -37,7 +37,12 @@
HB_BEGIN_DECLS HB_BEGIN_DECLS
/**
* hb_font_t:
*
* Data type for holding fonts.
*
*/
typedef struct hb_font_t hb_font_t; typedef struct hb_font_t hb_font_t;
@ -141,6 +146,16 @@ typedef struct hb_glyph_extents_t {
/* func types */ /* func types */
/**
* hb_font_get_font_extents_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @extents: (out): The font extents retrieved
* @user_data: User data pointer passed by the caller
*
* This method should retrieve the extents for a font.
*
**/
typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
hb_font_extents_t *extents, hb_font_extents_t *extents,
void *user_data); void *user_data);
@ -150,7 +165,7 @@ typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *fon
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the extents for a font, in horizontal-direction * This method should retrieve the extents for a font, for horizontal-direction
* text segments. Extents must be returned in an #hb_glyph_extents output * text segments. Extents must be returned in an #hb_glyph_extents output
* parameter. * parameter.
* *
@ -162,7 +177,7 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the extents for a font, in vertical-direction * This method should retrieve the extents for a font, for vertical-direction
* text segments. Extents must be returned in an #hb_glyph_extents output * text segments. Extents must be returned in an #hb_glyph_extents output
* parameter. * parameter.
* *
@ -172,12 +187,19 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
/** /**
* hb_font_get_nominal_glyph_func_t: * hb_font_get_nominal_glyph_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @unicode: The Unicode code point to query
* @glyph: (out): The glyph ID retrieved
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the nominal glyph ID for a specified Unicode code * This method should retrieve the nominal glyph ID for a specified Unicode code
* point. Glyph IDs must be returned in a #hb_codepoint_t output parameter. * point. Glyph IDs must be returned in a #hb_codepoint_t output parameter.
* *
* Return value: %true if data found, %false otherwise
*
**/ **/
typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t unicode,
@ -186,6 +208,12 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo
/** /**
* hb_font_get_variation_glyph_func_t: * hb_font_get_variation_glyph_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @unicode: The Unicode code point to query
* @variation_selector: The variation-selector code point to query
* @glyph: (out): The glyph ID retrieved
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
@ -193,6 +221,8 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo
* followed by a specified Variation Selector code point. Glyph IDs must be * followed by a specified Variation Selector code point. Glyph IDs must be
* returned in a #hb_codepoint_t output parameter. * returned in a #hb_codepoint_t output parameter.
* *
* Return value: %true if data found, %false otherwise
*
**/ **/
typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t unicode, hb_codepoint_t variation_selector,
@ -202,12 +232,22 @@ typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *
/** /**
* hb_font_get_nominal_glyphs_func_t: * hb_font_get_nominal_glyphs_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @count: number of code points to query
* @first_unicode: The first Unicode code point to query
* @unicode_stride: The stride between successive code points
* @first_glyph: (out): The first glyph ID retrieved
* @glyph_stride: The stride between successive glyph IDs
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the nominal glyph IDs for a sequence of * This method should retrieve the nominal glyph IDs for a sequence of
* Unicode code points. Glyph IDs must be returned in a #hb_codepoint_t * Unicode code points. Glyph IDs must be returned in a #hb_codepoint_t
* output parameter. * output parameter.
*
* Return value: the number of code points processed
* *
**/ **/
typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data, typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data,
@ -220,12 +260,18 @@ typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void
/** /**
* hb_font_get_glyph_advance_func_t: * hb_font_get_glyph_advance_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the advance for a specified glyph. The * This method should retrieve the advance for a specified glyph. The
* method must return an #hb_position_t. * method must return an #hb_position_t.
* *
* Return value: The advance of @glyph within @font
*
**/ **/
typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data, typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph, hb_codepoint_t glyph,
@ -257,6 +303,14 @@ typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
/** /**
* hb_font_get_glyph_advances_func_t: * hb_font_get_glyph_advances_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @count: The number of glyph IDs in the sequence queried
* @first_glyph: The first glyph ID to query
* @glyph_stride: The stride between successive glyph IDs
* @first_advance: (out): The first advance retrieved
* @advance_stride: The stride between successive advances
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
@ -295,12 +349,20 @@ typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
/** /**
* hb_font_get_glyph_origin_func_t: * hb_font_get_glyph_origin_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
* @x: (out): The X coordinate of the origin
* @y: (out): The Y coordinate of the origin
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the (X,Y) coordinates (in font units) of the * This method should retrieve the (X,Y) coordinates (in font units) of the
* origin for a glyph. Each coordinate must be returned in an #hb_position_t * origin for a glyph. Each coordinate must be returned in an #hb_position_t
* output parameter. * output parameter.
*
* Return value: %true if data found, %false otherwise
* *
**/ **/
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
@ -314,7 +376,7 @@ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *fon
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the (X,Y) coordinates (in font units) of the * This method should retrieve the (X,Y) coordinates (in font units) of the
* origin for a glyph, in horizontal-direction text segments. Each * origin for a glyph, for horizontal-direction text segments. Each
* coordinate must be returned in an #hb_position_t output parameter. * coordinate must be returned in an #hb_position_t output parameter.
* *
**/ **/
@ -326,25 +388,53 @@ typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the (X,Y) coordinates (in font units) of the * This method should retrieve the (X,Y) coordinates (in font units) of the
* origin for a glyph, in vertical-direction text segments. Each coordinate * origin for a glyph, for vertical-direction text segments. Each coordinate
* must be returned in an #hb_position_t output parameter. * must be returned in an #hb_position_t output parameter.
* *
**/ **/
typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t; typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
/**
* hb_font_get_glyph_kerning_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @first_glyph: The glyph ID of the first glyph in the glyph pair
* @second_glyph: The glyph ID of the second glyph in the glyph pair
* @user_data: User data pointer passed by the caller
*
* This method should retrieve the kerning-adjustment value for a glyph-pair in
* the specified font, for horizontal text segments.
*
**/
typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data, typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
void *user_data); void *user_data);
/**
* hb_font_get_glyph_h_kerning_func_t:
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* This method should retrieve the kerning-adjustment value for a glyph-pair in
* the specified font, for horizontal text segments.
*
**/
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t; typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
/** /**
* hb_font_get_glyph_extents_func_t: * hb_font_get_glyph_extents_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
* @extents: (out): The #hb_glyph_extents_t retrieved
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the extents for a specified glyph. Extents must be * This method should retrieve the extents for a specified glyph. Extents must be
* returned in an #hb_glyph_extents output parameter. * returned in an #hb_glyph_extents output parameter.
*
* Return value: %true if data found, %false otherwise
* *
**/ **/
typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
@ -354,6 +444,13 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo
/** /**
* hb_font_get_glyph_contour_point_func_t: * hb_font_get_glyph_contour_point_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
* @point_index: The contour-point index to query
* @x: (out): The X value retrieved for the contour point
* @y: (out): The Y value retrieved for the contour point
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
@ -361,6 +458,8 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo
* specified contour point in a glyph. Each coordinate must be returned as * specified contour point in a glyph. Each coordinate must be returned as
* an #hb_position_t output parameter. * an #hb_position_t output parameter.
* *
* Return value: %true if data found, %false otherwise
*
**/ **/
typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph, unsigned int point_index, hb_codepoint_t glyph, unsigned int point_index,
@ -370,12 +469,20 @@ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, vo
/** /**
* hb_font_get_glyph_name_func_t: * hb_font_get_glyph_name_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
* @name: (out) (array length=size): Name string retrieved for the glyph ID
* @size: Length of the glyph-name string retrieved
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the glyph name that corresponds to a * This method should retrieve the glyph name that corresponds to a
* glyph ID. The name should be returned in a string output parameter. * glyph ID. The name should be returned in a string output parameter.
* *
* Return value: %true if data found, %false otherwise
*
**/ **/
typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph, hb_codepoint_t glyph,
@ -384,12 +491,20 @@ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_
/** /**
* hb_font_get_glyph_from_name_func_t: * hb_font_get_glyph_from_name_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @name: (array length=len): The name string to query
* @len: The length of the name queried
* @glyph: (out): The glyph ID retrieved
* @user_data: User data pointer passed by the caller
* *
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
* *
* This method should retrieve the glyph ID that corresponds to a glyph-name * This method should retrieve the glyph ID that corresponds to a glyph-name
* string. * string.
* *
* Return value: %true if data found, %false otherwise
*
**/ **/
typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data, typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data,
const char *name, int len, /* -1 means nul-terminated */ const char *name, int len, /* -1 means nul-terminated */
@ -404,7 +519,7 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_font_h_extents_func_t. * Sets the implementation function for #hb_font_get_font_h_extents_func_t.
* *
@ -420,7 +535,7 @@ hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_font_v_extents_func_t. * Sets the implementation function for #hb_font_get_font_v_extents_func_t.
* *
@ -436,7 +551,7 @@ hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_nominal_glyph_func_t. * Sets the implementation function for #hb_font_get_nominal_glyph_func_t.
* *
@ -452,7 +567,7 @@ hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_nominal_glyphs_func_t. * Sets the implementation function for #hb_font_get_nominal_glyphs_func_t.
* *
@ -468,7 +583,7 @@ hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_variation_glyph_func_t. * Sets the implementation function for #hb_font_get_variation_glyph_func_t.
* *
@ -484,7 +599,7 @@ hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_h_advance_func_t. * Sets the implementation function for #hb_font_get_glyph_h_advance_func_t.
* *
@ -500,7 +615,7 @@ hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_v_advance_func_t. * Sets the implementation function for #hb_font_get_glyph_v_advance_func_t.
* *
@ -516,7 +631,7 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_h_advances_func_t. * Sets the implementation function for #hb_font_get_glyph_h_advances_func_t.
* *
@ -532,7 +647,7 @@ hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_v_advances_func_t. * Sets the implementation function for #hb_font_get_glyph_v_advances_func_t.
* *
@ -548,7 +663,7 @@ hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_h_origin_func_t. * Sets the implementation function for #hb_font_get_glyph_h_origin_func_t.
* *
@ -564,7 +679,7 @@ hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_v_origin_func_t. * Sets the implementation function for #hb_font_get_glyph_v_origin_func_t.
* *
@ -577,12 +692,12 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
/** /**
* hb_font_funcs_set_glyph_h_kerning_func: * hb_font_funcs_set_glyph_h_kerning_func:
* @ffuncs: font functions. * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: * @user_data: Data to pass to @func
* @destroy: * @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* *
* Sets the implementation function for #hb_font_get_glyph_h_kerning_func_t.
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -596,7 +711,7 @@ hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_extents_func_t. * Sets the implementation function for #hb_font_get_glyph_extents_func_t.
* *
@ -612,7 +727,7 @@ hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_contour_point_func_t. * Sets the implementation function for #hb_font_get_glyph_contour_point_func_t.
* *
@ -628,7 +743,7 @@ hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_name_func_t. * Sets the implementation function for #hb_font_get_glyph_name_func_t.
* *
@ -644,7 +759,7 @@ hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs,
* @ffuncs: A font-function structure * @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func * @user_data: Data to pass to @func
* @destroy: (optional): The function to call when @user_data is not needed anymore * @destroy: (nullable): The function to call when @user_data is not needed anymore
* *
* Sets the implementation function for #hb_font_get_glyph_from_name_func_t. * Sets the implementation function for #hb_font_get_glyph_from_name_func_t.
* *

View File

@ -84,7 +84,7 @@ struct hb_ft_font_t
bool symbol; /* Whether selected cmap is symbol cmap. */ bool symbol; /* Whether selected cmap is symbol cmap. */
bool unref; /* Whether to destroy ft_face when done. */ bool unref; /* Whether to destroy ft_face when done. */
mutable hb_atomic_int_t cached_x_scale; mutable int cached_x_scale;
mutable hb_advance_cache_t advance_cache; mutable hb_advance_cache_t advance_cache;
}; };
@ -101,7 +101,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
ft_font->cached_x_scale.set_relaxed (0); ft_font->cached_x_scale = 0;
ft_font->advance_cache.init (); ft_font->advance_cache.init ();
return ft_font; return ft_font;
@ -179,13 +179,13 @@ hb_ft_font_get_load_flags (hb_font_t *font)
} }
/** /**
* hb_ft_get_face: * hb_ft_font_get_face:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* *
* Fetches the FT_Face associated with the specified #hb_font_t * Fetches the FT_Face associated with the specified #hb_font_t
* font object. * font object.
* *
* Return value: the FT_Face found * Return value: (nullable): the FT_Face found or %NULL
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -202,11 +202,12 @@ hb_ft_font_get_face (hb_font_t *font)
/** /**
* hb_ft_font_lock_face: * hb_ft_font_lock_face:
* @font: * @font: #hb_font_t to work upon
* *
* Gets the FT_Face associated with @font, This face will be kept around until
* you call hb_ft_font_unlock_face().
* *
* * Return value: (nullable): the FT_Face associated with @font or %NULL
* Return value:
* Since: 2.6.5 * Since: 2.6.5
**/ **/
FT_Face FT_Face
@ -224,11 +225,10 @@ hb_ft_font_lock_face (hb_font_t *font)
/** /**
* hb_ft_font_unlock_face: * hb_ft_font_unlock_face:
* @font: * @font: #hb_font_t to work upon
* *
* Releases an FT_Face previously obtained with hb_ft_font_lock_face().
* *
*
* Return value:
* Since: 2.6.5 * Since: 2.6.5
**/ **/
void void
@ -335,10 +335,10 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
int load_flags = ft_font->load_flags; int load_flags = ft_font->load_flags;
int mult = font->x_scale < 0 ? -1 : +1; int mult = font->x_scale < 0 ? -1 : +1;
if (font->x_scale != ft_font->cached_x_scale.get ()) if (font->x_scale != ft_font->cached_x_scale)
{ {
ft_font->advance_cache.clear (); ft_font->advance_cache.clear ();
ft_font->cached_x_scale.set (font->x_scale); ft_font->cached_x_scale = font->x_scale;
} }
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
@ -661,7 +661,7 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
/** /**
* hb_ft_face_create: * hb_ft_face_create:
* @ft_face: (destroy destroy) (scope notified): FT_Face to work upon * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
* @destroy: (optional): A callback to call when the face object is not needed anymore * @destroy: (nullable): A callback to call when the face object is not needed anymore
* *
* Creates an #hb_face_t face object from the specified FT_Face. * Creates an #hb_face_t face object from the specified FT_Face.
* *
@ -771,13 +771,13 @@ hb_ft_face_create_cached (FT_Face ft_face)
/** /**
* hb_ft_font_create: * hb_ft_font_create:
* @ft_face: (destroy destroy) (scope notified): FT_Face to work upon * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
* @destroy: (optional): A callback to call when the font object is not needed anymore * @destroy: (nullable): A callback to call when the font object is not needed anymore
* *
* Creates an #hb_font_t font object from the specified FT_Face. * Creates an #hb_font_t font object from the specified FT_Face.
* *
* <note>Note: You must set the face size on @ft_face before calling * <note>Note: You must set the face size on @ft_face before calling
* hb_ft_font_create() on it. Otherwise, HarfBuzz will not pick up * hb_ft_font_create() on it. HarfBuzz assumes size is always set and will
* the face size.</note> * access `size` member of FT_Face unconditionally.</note>
* *
* This variant of the function does not provide any life-cycle management. * This variant of the function does not provide any life-cycle management.
* *
@ -814,7 +814,7 @@ hb_ft_font_create (FT_Face ft_face,
} }
/** /**
* hb_ft_font_has_changed: * hb_ft_font_changed:
* @font: #hb_font_t to work upon * @font: #hb_font_t to work upon
* *
* Refreshes the state of @font when the underlying FT_Face has changed. * Refreshes the state of @font when the underlying FT_Face has changed.
@ -884,8 +884,8 @@ hb_ft_font_changed (hb_font_t *font)
* Creates an #hb_font_t font object from the specified FT_Face. * Creates an #hb_font_t font object from the specified FT_Face.
* *
* <note>Note: You must set the face size on @ft_face before calling * <note>Note: You must set the face size on @ft_face before calling
* hb_ft_font_create_references() on it. Otherwise, HarfBuzz will not pick up * hb_ft_font_create_referenced() on it. HarfBuzz assumes size is always set
* the face size.</note> * and will access `size` member of FT_Face unconditionally.</note>
* *
* This is the preferred variant of the hb_ft_font_create* * This is the preferred variant of the hb_ft_font_create*
* function family, because it calls FT_Reference_Face() on @ft_face, * function family, because it calls FT_Reference_Face() on @ft_face,

View File

@ -70,6 +70,8 @@ fail:
* hb_gdi_face_create: * hb_gdi_face_create:
* @hfont: a HFONT object. * @hfont: a HFONT object.
* *
* Constructs a new face object from the specified GDI HFONT.
*
* Return value: #hb_face_t object corresponding to the given input * Return value: #hb_face_t object corresponding to the given input
* *
* Since: 2.6.0 * Since: 2.6.0

View File

@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod * Google Author(s): Behdad Esfahbod
*/ */
#ifndef HB_GOBJECT_H_IN #if !defined(HB_GOBJECT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-gobject.h> instead." #error "Include <hb-gobject.h> instead."
#endif #endif
@ -40,47 +40,22 @@ HB_BEGIN_DECLS
/* Object types */ /* Object types */
/**
* hb_gobject_blob_get_type:
*
* Since: 0.9.2
**/
HB_EXTERN GType HB_EXTERN GType
hb_gobject_blob_get_type (void); hb_gobject_blob_get_type (void);
#define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ()) #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ())
/**
* hb_gobject_buffer_get_type:
*
* Since: 0.9.2
**/
HB_EXTERN GType HB_EXTERN GType
hb_gobject_buffer_get_type (void); hb_gobject_buffer_get_type (void);
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
/**
* hb_gobject_face_get_type:
*
* Since: 0.9.2
**/
HB_EXTERN GType HB_EXTERN GType
hb_gobject_face_get_type (void); hb_gobject_face_get_type (void);
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
/**
* hb_gobject_font_get_type:
*
* Since: 0.9.2
**/
HB_EXTERN GType HB_EXTERN GType
hb_gobject_font_get_type (void); hb_gobject_font_get_type (void);
#define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ()) #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ())
/**
* hb_gobject_font_funcs_get_type:
*
* Since: 0.9.2
**/
HB_EXTERN GType HB_EXTERN GType
hb_gobject_font_funcs_get_type (void); hb_gobject_font_funcs_get_type (void);
#define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ()) #define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ())
@ -97,11 +72,6 @@ HB_EXTERN GType
hb_gobject_shape_plan_get_type (void); hb_gobject_shape_plan_get_type (void);
#define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ()) #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())
/**
* hb_gobject_unicode_funcs_get_type:
*
* Since: 0.9.2
**/
HB_EXTERN GType HB_EXTERN GType
hb_gobject_unicode_funcs_get_type (void); hb_gobject_unicode_funcs_get_type (void);
#define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ()) #define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ())

View File

@ -195,6 +195,11 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED
#ifndef HB_DISABLE_DEPRECATED #ifndef HB_DISABLE_DEPRECATED
/** /**
* hb_graphite2_font_get_gr_font: * hb_graphite2_font_get_gr_font:
* @font: An #hb_font_t
*
* Always returns %NULL. Use hb_graphite2_face_get_gr_face() instead.
*
* Return value: (nullable): Graphite2 font associated with @font.
* *
* Since: 0.9.10 * Since: 0.9.10
* Deprecated: 1.4.2 * Deprecated: 1.4.2
@ -284,7 +289,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
return true; return true;
} }
buffer->ensure (glyph_count); (void) buffer->ensure (glyph_count);
scratch = buffer->get_scratch_buffer (&scratch_size); scratch = buffer->get_scratch_buffer (&scratch_size);
while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) + while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) +
DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size) DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size)

View File

@ -922,7 +922,7 @@ HB_FUNCOBJ (hb_none);
template <typename C, typename V, template <typename C, typename V,
hb_requires (hb_is_iterable (C))> hb_requires (hb_is_iterable (C))>
inline void inline void
hb_fill (C& c, const V &v) hb_fill (C&& c, const V &v)
{ {
for (auto i = hb_iter (c); i; i++) for (auto i = hb_iter (c); i; i++)
*i = v; *i = v;

View File

@ -80,6 +80,11 @@ static inline Type& StructAfter(TObject &X)
* Size checking * Size checking
*/ */
/* Size signifying variable-sized array */
#ifndef HB_VAR_ARRAY
#define HB_VAR_ARRAY 1
#endif
/* Check _assertion in a method environment */ /* Check _assertion in a method environment */
#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
void _instance_assertion_on_line_##_line () const \ void _instance_assertion_on_line_##_line () const \

View File

@ -117,7 +117,7 @@ hb_map_destroy (hb_map_t *map)
* @map: A map * @map: A map
* @key: The user-data key to set * @key: The user-data key to set
* @data: A pointer to the user data to set * @data: A pointer to the user data to set
* @destroy: (optional): A callback to call when @data is not needed anymore * @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key * @replace: Whether to replace an existing data with the same key
* *
* Attaches a user-data key/data pair to the specified map. * Attaches a user-data key/data pair to the specified map.
@ -162,7 +162,7 @@ hb_map_get_user_data (hb_map_t *map,
* *
* Tests whether memory allocation for a set was successful. * Tests whether memory allocation for a set was successful.
* *
* Return value: %true if allocation succeeded, false otherwise * Return value: %true if allocation succeeded, %false otherwise
* *
* Since: 1.7.7 * Since: 1.7.7
**/ **/
@ -230,7 +230,7 @@ hb_map_del (hb_map_t *map,
* *
* Tests whether @key is an element of @map. * Tests whether @key is an element of @map.
* *
* Return value: %true if @key is found in @map, false otherwise * Return value: %true if @key is found in @map, %false otherwise
* *
* Since: 1.7.7 * Since: 1.7.7
**/ **/
@ -253,6 +253,9 @@ hb_map_has (const hb_map_t *map,
void void
hb_map_clear (hb_map_t *map) hb_map_clear (hb_map_t *map)
{ {
if (unlikely (hb_object_is_immutable (map)))
return;
return map->clear (); return map->clear ();
} }

View File

@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod * Google Author(s): Behdad Esfahbod
*/ */
#ifndef HB_H_IN #if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb.h> instead." #error "Include <hb.h> instead."
#endif #endif
@ -36,7 +36,11 @@
HB_BEGIN_DECLS HB_BEGIN_DECLS
/* /**
* HB_MAP_VALUE_INVALID:
*
* Unset #hb_map_t value.
*
* Since: 1.7.7 * Since: 1.7.7
*/ */
#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1) #define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1)

View File

@ -97,8 +97,6 @@ struct hb_hashmap_t
void reset () void reset ()
{ {
if (unlikely (hb_object_is_immutable (this)))
return;
successful = true; successful = true;
clear (); clear ();
} }
@ -171,8 +169,6 @@ struct hb_hashmap_t
void clear () void clear ()
{ {
if (unlikely (hb_object_is_immutable (this)))
return;
if (items) if (items)
for (auto &_ : hb_iter (items, mask + 1)) for (auto &_ : hb_iter (items, mask + 1))
_.clear (); _.clear ();
@ -181,6 +177,7 @@ struct hb_hashmap_t
} }
bool is_empty () const { return population == 0; } bool is_empty () const { return population == 0; }
explicit operator bool () const { return !is_empty (); }
unsigned int get_population () const { return population; } unsigned int get_population () const { return population; }

View File

@ -49,6 +49,10 @@ template <bool b> using hb_bool_constant = hb_integral_constant<bool, b>;
using hb_true_type = hb_bool_constant<true>; using hb_true_type = hb_bool_constant<true>;
using hb_false_type = hb_bool_constant<false>; using hb_false_type = hb_bool_constant<false>;
/* Static-assert as expression. */
template <bool cond> struct static_assert_expr;
template <> struct static_assert_expr<true> : hb_false_type {};
#define static_assert_expr(C) static_assert_expr<C>::value
/* Basic type SFINAE. */ /* Basic type SFINAE. */
@ -220,6 +224,8 @@ struct hb_reference_wrapper<T&>
}; };
/* Type traits */
template <typename T> template <typename T>
using hb_is_integral = hb_bool_constant< using hb_is_integral = hb_bool_constant<
hb_is_same (hb_decay<T>, char) || hb_is_same (hb_decay<T>, char) ||
@ -292,6 +298,15 @@ template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigne
#define hb_int_max(T) hb_int_max<T>::value #define hb_int_max(T) hb_int_max<T>::value
/* Class traits. */
#define HB_DELETE_COPY_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
#define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \
TypeName() = delete; \
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
template <typename T, typename> template <typename T, typename>
struct _hb_is_destructible : hb_false_type {}; struct _hb_is_destructible : hb_false_type {};

View File

@ -73,24 +73,6 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M) #define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
# include <sched.h>
# define HB_SCHED_YIELD() sched_yield ()
#else
# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
#endif
/* This actually is not a totally awful implementation. */
typedef volatile int hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT 0
#define hb_mutex_impl_init(M) *(M) = 0
#define hb_mutex_impl_lock(M) HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
#define hb_mutex_impl_unlock(M) __sync_lock_release (M)
#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
#elif defined(HB_NO_MT) #elif defined(HB_NO_MT)
typedef int hb_mutex_impl_t; typedef int hb_mutex_impl_t;

View File

@ -140,9 +140,7 @@ struct hb_lockable_set_t
* Reference-count. * Reference-count.
*/ */
#define HB_REFERENCE_COUNT_INERT_VALUE 0 #define HB_REFERENCE_COUNT_INIT {0}
#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
struct hb_reference_count_t struct hb_reference_count_t
{ {
@ -152,9 +150,9 @@ struct hb_reference_count_t
int get_relaxed () const { return ref_count.get_relaxed (); } int get_relaxed () const { return ref_count.get_relaxed (); }
int inc () const { return ref_count.inc (); } int inc () const { return ref_count.inc (); }
int dec () const { return ref_count.dec (); } int dec () const { return ref_count.dec (); }
void fini () { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); } void fini () { ref_count.set_relaxed (-0x0000DEAD); }
bool is_inert () const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; } bool is_inert () const { return !ref_count.get_relaxed (); }
bool is_valid () const { return ref_count.get_relaxed () > 0; } bool is_valid () const { return ref_count.get_relaxed () > 0; }
}; };
@ -197,15 +195,10 @@ struct hb_user_data_array_t
struct hb_object_header_t struct hb_object_header_t
{ {
hb_reference_count_t ref_count; hb_reference_count_t ref_count;
mutable hb_atomic_int_t writable; mutable hb_atomic_int_t writable = 0;
hb_atomic_ptr_t<hb_user_data_array_t> user_data; hb_atomic_ptr_t<hb_user_data_array_t> user_data;
}; };
#define HB_OBJECT_HEADER_STATIC \ #define HB_OBJECT_HEADER_STATIC {}
{ \
HB_REFERENCE_COUNT_INIT, \
HB_ATOMIC_INT_INIT (false), \
HB_ATOMIC_PTR_INIT (nullptr) \
}
/* /*

View File

@ -48,7 +48,7 @@ namespace OT {
*/ */
struct OpenTypeFontFile; struct OpenTypeFontFile;
struct OffsetTable; struct OpenTypeOffsetTable;
struct TTCHeader; struct TTCHeader;
@ -78,7 +78,7 @@ typedef struct TableRecord
DEFINE_SIZE_STATIC (16); DEFINE_SIZE_STATIC (16);
} OpenTypeTable; } OpenTypeTable;
typedef struct OffsetTable typedef struct OpenTypeOffsetTable
{ {
friend struct OpenTypeFontFile; friend struct OpenTypeFontFile;
@ -218,7 +218,7 @@ struct TTCHeaderVersion1
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
FixedVersion<>version; /* Version of the TTC Header (1.0), FixedVersion<>version; /* Version of the TTC Header (1.0),
* 0x00010000u */ * 0x00010000u */
LArrayOf<LOffsetTo<OffsetTable>> LArrayOf<LOffsetTo<OpenTypeOffsetTable>>
table; /* Array of offsets to the OffsetTable for each font table; /* Array of offsets to the OffsetTable for each font
* from the beginning of the file */ * from the beginning of the file */
public: public:

View File

@ -53,14 +53,19 @@ namespace OT {
*/ */
/* Integer types in big-endian order and no alignment requirement */ /* Integer types in big-endian order and no alignment requirement */
template <typename Type, unsigned int Size> template <typename Type,
unsigned int Size = sizeof (Type)>
struct IntType struct IntType
{ {
typedef Type type; typedef Type type;
typedef hb_conditional<hb_is_signed (Type), signed, unsigned> wide_type;
IntType& operator = (wide_type i) { v = i; return *this; } IntType () = default;
operator wide_type () const { return v; } explicit constexpr IntType (Type V) : v {V} {}
IntType& operator = (Type i) { v = i; return *this; }
/* For reason we define cast out operator for signed/unsigned, instead of Type, see:
* https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */
operator hb_conditional<hb_is_signed (Type), signed, unsigned> () const { return v; }
bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; }
bool operator != (const IntType &o) const { return !(*this == o); } bool operator != (const IntType &o) const { return !(*this == o); }
@ -80,14 +85,21 @@ struct IntType
return pb->cmp (*pa); return pb->cmp (*pa);
} }
template <typename Type2> template <typename Type2,
hb_enable_if (hb_is_integral (Type2) &&
sizeof (Type2) < sizeof (int) &&
sizeof (Type) < sizeof (int))>
int cmp (Type2 a) const int cmp (Type2 a) const
{ {
Type b = v; Type b = v;
if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int)) return (int) a - (int) b;
return (int) a - (int) b; }
else template <typename Type2,
return a < b ? -1 : a == b ? 0 : +1; hb_enable_if (hb_is_convertible (Type2, Type))>
int cmp (Type2 a) const
{
Type b = v;
return a < b ? -1 : a == b ? 0 : +1;
} }
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {
@ -100,12 +112,12 @@ struct IntType
DEFINE_SIZE_STATIC (Size); DEFINE_SIZE_STATIC (Size);
}; };
typedef IntType<uint8_t, 1> HBUINT8; /* 8-bit unsigned integer. */ typedef IntType<uint8_t> HBUINT8; /* 8-bit unsigned integer. */
typedef IntType<int8_t, 1> HBINT8; /* 8-bit signed integer. */ typedef IntType<int8_t> HBINT8; /* 8-bit signed integer. */
typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */ typedef IntType<uint16_t> HBUINT16; /* 16-bit unsigned integer. */
typedef IntType<int16_t, 2> HBINT16; /* 16-bit signed integer. */ typedef IntType<int16_t> HBINT16; /* 16-bit signed integer. */
typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */ typedef IntType<uint32_t> HBUINT32; /* 32-bit unsigned integer. */
typedef IntType<int32_t, 4> HBINT32; /* 32-bit signed integer. */ typedef IntType<int32_t> HBINT32; /* 32-bit signed integer. */
/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type. /* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
* Works for unsigned, but not signed, since we rely on compiler for sign-extension. */ * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */ typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
@ -163,8 +175,8 @@ struct Tag : HBUINT32
{ {
Tag& operator = (hb_tag_t i) { HBUINT32::operator= (i); return *this; } Tag& operator = (hb_tag_t i) { HBUINT32::operator= (i); return *this; }
/* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */
operator const char* () const { return reinterpret_cast<const char *> (&this->v); } operator const char* () const { return reinterpret_cast<const char *> (this); }
operator char* () { return reinterpret_cast<char *> (&this->v); } operator char* () { return reinterpret_cast<char *> (this); }
public: public:
DEFINE_SIZE_STATIC (4); DEFINE_SIZE_STATIC (4);
}; };

View File

@ -183,7 +183,7 @@ struct CFFIndex
else else
{ {
serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; })); serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; }));
for (const byte_str_t &_ : +it) for (const auto &_ : +it)
_.copy (c); _.copy (c);
} }
return_trace (true); return_trace (true);

View File

@ -426,7 +426,7 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
else else
{ {
extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ()); extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ());
extents->width = font->em_scalef_x (bounds.max.x.to_real () - bounds.min.x.to_real ()); extents->width = font->em_scalef_x (bounds.max.x.to_real ()) - extents->x_bearing;
} }
if (bounds.min.y >= bounds.max.y) if (bounds.min.y >= bounds.max.y)
{ {
@ -436,7 +436,7 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
else else
{ {
extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ()); extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ());
extents->height = font->em_scalef_y (bounds.min.y.to_real () - bounds.max.y.to_real ()); extents->height = font->em_scalef_y (bounds.min.y.to_real ()) - extents->y_bearing;
} }
return true; return true;

View File

@ -127,7 +127,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
else else
{ {
extents->x_bearing = font->em_scalef_x (param.min_x.to_real ()); extents->x_bearing = font->em_scalef_x (param.min_x.to_real ());
extents->width = font->em_scalef_x (param.max_x.to_real () - param.min_x.to_real ()); extents->width = font->em_scalef_x (param.max_x.to_real ()) - extents->x_bearing;
} }
if (param.min_y >= param.max_y) if (param.min_y >= param.max_y)
{ {
@ -137,7 +137,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
else else
{ {
extents->y_bearing = font->em_scalef_y (param.max_y.to_real ()); extents->y_bearing = font->em_scalef_y (param.max_y.to_real ());
extents->height = font->em_scalef_y (param.min_y.to_real () - param.max_y.to_real ()); extents->height = font->em_scalef_y (param.min_y.to_real ()) - extents->y_bearing;
} }
return true; return true;

View File

@ -95,7 +95,7 @@ struct CmapSubtableFormat4
HBUINT16 *endCode = c->start_embed<HBUINT16> (); HBUINT16 *endCode = c->start_embed<HBUINT16> ();
hb_codepoint_t prev_endcp = 0xFFFF; hb_codepoint_t prev_endcp = 0xFFFF;
for (const hb_item_type<Iterator> _ : +it) for (const auto& _ : +it)
{ {
if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first) if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
{ {
@ -131,7 +131,7 @@ struct CmapSubtableFormat4
HBUINT16 *startCode = c->start_embed<HBUINT16> (); HBUINT16 *startCode = c->start_embed<HBUINT16> ();
hb_codepoint_t prev_cp = 0xFFFF; hb_codepoint_t prev_cp = 0xFFFF;
for (const hb_item_type<Iterator> _ : +it) for (const auto& _ : +it)
{ {
if (prev_cp == 0xFFFF || prev_cp + 1u != _.first) if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
{ {
@ -170,7 +170,7 @@ struct CmapSubtableFormat4
if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size) if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
return nullptr; return nullptr;
for (const hb_item_type<Iterator> _ : +it) for (const auto& _ : +it)
{ {
if (_.first == startCode[i]) if (_.first == startCode[i])
{ {
@ -696,7 +696,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF; hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
hb_codepoint_t glyphID = 0; hb_codepoint_t glyphID = 0;
for (const hb_item_type<Iterator> _ : +it) for (const auto& _ : +it)
{ {
if (startCharCode == 0xFFFF) if (startCharCode == 0xFFFF)
{ {

View File

@ -455,8 +455,8 @@ struct IndexSubtableRecord
unsigned int old_cbdt_prime_length = bitmap_size_context->cbdt_prime->length; unsigned int old_cbdt_prime_length = bitmap_size_context->cbdt_prime->length;
// Set to invalid state to indicate filling glyphs is not yet started. // Set to invalid state to indicate filling glyphs is not yet started.
if (unlikely (!records->resize (records->length + 1))) if (unlikely (!c->serializer->check_success (records->resize (records->length + 1))))
return_trace (c->serializer->check_success (false)); return_trace (false);
(*records)[records->length - 1].firstGlyphIndex = 1; (*records)[records->length - 1].firstGlyphIndex = 1;
(*records)[records->length - 1].lastGlyphIndex = 0; (*records)[records->length - 1].lastGlyphIndex = 0;
@ -567,8 +567,8 @@ struct IndexSubtableArray
hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup; hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup;
build_lookup (c, bitmap_size_context, &lookup); build_lookup (c, bitmap_size_context, &lookup);
if (unlikely (lookup.in_error ())) if (unlikely (!c->serializer->propagate_error (lookup)))
return c->serializer->check_success (false); return false;
bitmap_size_context->size = 0; bitmap_size_context->size = 0;
bitmap_size_context->num_tables = 0; bitmap_size_context->num_tables = 0;

View File

@ -214,7 +214,7 @@ struct COLR
if (unlikely (!old_record)) if (unlikely (!old_record))
return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord)); return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord));
BaseGlyphRecord new_record; BaseGlyphRecord new_record = {};
new_record.glyphId = new_gid; new_record.glyphId = new_gid;
new_record.numLayers = old_record->numLayers; new_record.numLayers = old_record->numLayers;
return hb_pair_t<bool, BaseGlyphRecord> (true, new_record); return hb_pair_t<bool, BaseGlyphRecord> (true, new_record);

View File

@ -37,9 +37,6 @@
#include "hb-ot-color-sbix-table.hh" #include "hb-ot-color-sbix-table.hh"
#include "hb-ot-color-svg-table.hh" #include "hb-ot-color-svg-table.hh"
#include <stdlib.h>
#include <string.h>
/** /**
* SECTION:hb-ot-color * SECTION:hb-ot-color
@ -64,7 +61,7 @@
* *
* Tests whether a face includes a `CPAL` color-palette table. * Tests whether a face includes a `CPAL` color-palette table.
* *
* Return value: true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 2.1.0 * Since: 2.1.0
*/ */
@ -195,7 +192,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face,
* *
* Tests whether a face includes any `COLR` color layers. * Tests whether a face includes any `COLR` color layers.
* *
* Return value: true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 2.1.0 * Since: 2.1.0
*/ */
@ -242,7 +239,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
* *
* Tests whether a face includes any `SVG` glyph images. * Tests whether a face includes any `SVG` glyph images.
* *
* Return value: true if data found, false otherwise. * Return value: %true if data found, %false otherwise.
* *
* Since: 2.1.0 * Since: 2.1.0
*/ */
@ -280,7 +277,7 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
* *
* Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables). * Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables).
* *
* Return value: true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 2.1.0 * Since: 2.1.0
*/ */

View File

@ -26,7 +26,7 @@
* Google Author(s): Sascha Brawer, Behdad Esfahbod * Google Author(s): Sascha Brawer, Behdad Esfahbod
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif
@ -66,6 +66,8 @@ hb_ot_color_palette_color_get_name_id (hb_face_t *face,
* @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: Flag indicating that the color * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: Flag indicating that the color
* palette is appropriate to use when displaying the font on a dark background such as black. * palette is appropriate to use when displaying the font on a dark background such as black.
* *
* Flags that describe the properties of color palette.
*
* Since: 2.1.0 * Since: 2.1.0
*/ */
typedef enum { /*< flags >*/ typedef enum { /*< flags >*/
@ -95,6 +97,8 @@ hb_ot_color_has_layers (hb_face_t *face);
/** /**
* hb_ot_color_layer_t: * hb_ot_color_layer_t:
* @glyph: the glyph ID of the layer
* @color_index: the palette color index of the layer
* *
* Pairs of glyph and color index. * Pairs of glyph and color index.
* *

View File

@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod * Google Author(s): Behdad Esfahbod
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif
@ -41,6 +41,13 @@ HB_BEGIN_DECLS
/* https://github.com/harfbuzz/harfbuzz/issues/1734 */ /* https://github.com/harfbuzz/harfbuzz/issues/1734 */
/**
* HB_MATH_GLYPH_PART_FLAG_EXTENDER:
*
* Use #HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER instead.
*
* Deprecated: 2.5.1
*/
#define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER #define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER
@ -71,6 +78,8 @@ hb_ot_tag_from_language (hb_language_t language);
/** /**
* HB_OT_VAR_NO_AXIS_INDEX: * HB_OT_VAR_NO_AXIS_INDEX:
* *
* Do not use.
*
* Since: 1.4.2 * Since: 1.4.2
* Deprecated: 2.2.0 * Deprecated: 2.2.0
*/ */
@ -78,6 +87,13 @@ hb_ot_tag_from_language (hb_language_t language);
/** /**
* hb_ot_var_axis_t: * hb_ot_var_axis_t:
* @tag: axis tag
* @name_id: axis name identifier
* @min_value: minimum value of the axis
* @default_value: default value of the axis
* @max_value: maximum value of the axis
*
* Use #hb_ot_var_axis_info_t instead.
* *
* Since: 1.4.2 * Since: 1.4.2
* Deprecated: 2.2.0 * Deprecated: 2.2.0

View File

@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod, Roozbeh Pournader * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif

View File

@ -186,7 +186,7 @@ struct glyf
| hb_map (&SubsetGlyph::padded_size) | hb_map (&SubsetGlyph::padded_size)
; ;
if (c->serializer->in_error ()) return_trace (false); if (unlikely (c->serializer->in_error ())) return_trace (false);
return_trace (c->serializer->check_success (_add_loca_and_head (c->plan, return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
padded_offsets))); padded_offsets)));
} }
@ -944,9 +944,9 @@ struct glyf
return; return;
} }
extents->x_bearing = font->em_scalef_x (min_x); extents->x_bearing = font->em_scalef_x (min_x);
extents->width = font->em_scalef_x (max_x - min_x); extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
extents->y_bearing = font->em_scalef_y (max_y); extents->y_bearing = font->em_scalef_y (max_y);
extents->height = font->em_scalef_y (min_y - max_y); extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
} }
protected: protected:

View File

@ -43,7 +43,7 @@ namespace OT {
struct head struct head
{ {
friend struct OffsetTable; friend struct OpenTypeOffsetTable;
static constexpr hb_tag_t tableTag = HB_OT_TAG_head; static constexpr hb_tag_t tableTag = HB_OT_TAG_head;

View File

@ -1128,7 +1128,7 @@ struct Lookup
out->lookupType = lookupType; out->lookupType = lookupType;
out->lookupFlag = lookupFlag; out->lookupFlag = lookupFlag;
const hb_set_t *glyphset = c->plan->glyphset (); const hb_set_t *glyphset = c->plan->glyphset_gsub ();
unsigned int lookup_type = get_type (); unsigned int lookup_type = get_type ();
+ hb_iter (get_subtables <TSubTable> ()) + hb_iter (get_subtables <TSubTable> ())
| hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); }) | hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
@ -1251,8 +1251,9 @@ struct CoverageFormat1
{ {
/* TODO Speed up, using hb_set_next() and bsearch()? */ /* TODO Speed up, using hb_set_next() and bsearch()? */
unsigned int count = glyphArray.len; unsigned int count = glyphArray.len;
const HBGlyphID *arr = glyphArray.arrayZ;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
if (glyphs->has (glyphArray[i])) if (glyphs->has (arr[i]))
return true; return true;
return false; return false;
} }
@ -1356,18 +1357,21 @@ struct CoverageFormat2
bool intersects (const hb_set_t *glyphs) const bool intersects (const hb_set_t *glyphs) const
{ {
/* TODO Speed up, using hb_set_next() and bsearch()? */ /* TODO Speed up, using hb_set_next() and bsearch()? */
unsigned int count = rangeRecord.len; /* TODO(iter) Rewrite as dagger. */
for (unsigned int i = 0; i < count; i++) unsigned count = rangeRecord.len;
if (rangeRecord[i].intersects (glyphs)) const RangeRecord *arr = rangeRecord.arrayZ;
for (unsigned i = 0; i < count; i++)
if (arr[i].intersects (glyphs))
return true; return true;
return false; return false;
} }
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
{ {
unsigned int i; /* TODO(iter) Rewrite as dagger. */
unsigned int count = rangeRecord.len; unsigned count = rangeRecord.len;
for (i = 0; i < count; i++) { const RangeRecord *arr = rangeRecord.arrayZ;
const RangeRecord &range = rangeRecord[i]; for (unsigned i = 0; i < count; i++) {
const RangeRecord &range = arr[i];
if (range.value <= index && if (range.value <= index &&
index < (unsigned int) range.value + (range.last - range.first) && index < (unsigned int) range.value + (range.last - range.first) &&
range.intersects (glyphs)) range.intersects (glyphs))
@ -1502,7 +1506,7 @@ struct Coverage
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it = auto it =
@ -1729,7 +1733,7 @@ struct ClassDefFormat1
hb_map_t *klass_map = nullptr /*OUT*/) const hb_map_t *klass_map = nullptr /*OUT*/) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->_glyphset_gsub; const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
hb_sorted_vector_t<HBGlyphID> glyphs; hb_sorted_vector_t<HBGlyphID> glyphs;
@ -1784,7 +1788,7 @@ struct ClassDefFormat1
} }
template <typename set_t> template <typename set_t>
bool collect_class (set_t *glyphs, unsigned int klass) const bool collect_class (set_t *glyphs, unsigned klass) const
{ {
unsigned int count = classValue.len; unsigned int count = classValue.len;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
@ -1802,7 +1806,7 @@ struct ClassDefFormat1
if (classValue[iter - start]) return true; if (classValue[iter - start]) return true;
return false; return false;
} }
bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const
{ {
unsigned int count = classValue.len; unsigned int count = classValue.len;
if (klass == 0) if (klass == 0)
@ -1815,8 +1819,12 @@ struct ClassDefFormat1
if (hb_set_next (glyphs, &g)) return true; if (hb_set_next (glyphs, &g)) return true;
/* Fall through. */ /* Fall through. */
} }
/* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */
HBUINT16 k {klass};
const HBUINT16 *arr = classValue.arrayZ;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
if (classValue[i] == klass && glyphs->has (startGlyph + i)) if (arr[i] == k && glyphs->has (startGlyph + i))
return true; return true;
return false; return false;
} }
@ -1898,7 +1906,7 @@ struct ClassDefFormat2
hb_map_t *klass_map = nullptr /*OUT*/) const hb_map_t *klass_map = nullptr /*OUT*/) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->_glyphset_gsub; const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
hb_sorted_vector_t<HBGlyphID> glyphs; hb_sorted_vector_t<HBGlyphID> glyphs;
@ -1961,11 +1969,14 @@ struct ClassDefFormat2
/* TODO Speed up, using hb_set_next() and bsearch()? */ /* TODO Speed up, using hb_set_next() and bsearch()? */
unsigned int count = rangeRecord.len; unsigned int count = rangeRecord.len;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
if (rangeRecord[i].intersects (glyphs)) {
const auto& range = rangeRecord[i];
if (range.intersects (glyphs) && range.value)
return true; return true;
}
return false; return false;
} }
bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const
{ {
unsigned int count = rangeRecord.len; unsigned int count = rangeRecord.len;
if (klass == 0) if (klass == 0)
@ -1984,8 +1995,12 @@ struct ClassDefFormat2
return true; return true;
/* Fall through. */ /* Fall through. */
} }
/* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */
HBUINT16 k {klass};
const RangeRecord *arr = rangeRecord.arrayZ;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs)) if (arr[i].value == k && arr[i].intersects (glyphs))
return true; return true;
return false; return false;
} }

View File

@ -566,6 +566,26 @@ struct AnchorMatrix
return_trace (true); return_trace (true);
} }
bool subset (hb_subset_context_t *c,
unsigned cols,
const hb_map_t *klass_mapping) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
auto indexes =
+ hb_range (rows * cols)
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); })
;
out->serialize (c->serializer,
(unsigned) rows,
this,
c->plan->layout_variation_idx_map,
indexes);
return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
@ -755,7 +775,7 @@ struct SinglePosFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it = auto it =
@ -870,7 +890,7 @@ struct SinglePosFormat2
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
unsigned sub_length = valueFormat.get_len (); unsigned sub_length = valueFormat.get_len ();
@ -1129,7 +1149,7 @@ struct PairSet
if (unlikely (!c->serializer->extend_min (out))) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->len = 0; out->len = 0;
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
unsigned len1 = valueFormats[0].get_len (); unsigned len1 = valueFormats[0].get_len ();
@ -1250,7 +1270,7 @@ struct PairPosFormat1
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);
@ -1441,7 +1461,7 @@ struct PairPosFormat2
}) })
; ;
const hb_set_t &glyphset = *c->plan->_glyphset_gsub; const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it = auto it =
@ -1728,7 +1748,7 @@ struct CursivePosFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);
@ -1904,7 +1924,7 @@ struct MarkBasePosFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);
@ -2025,10 +2045,37 @@ typedef AnchorMatrix LigatureAttach; /* component-major--
* mark-minor-- * mark-minor--
* ordered by class--zero-based. */ * ordered by class--zero-based. */
typedef OffsetListOf<LigatureAttach> LigatureArray; /* Array of LigatureAttach tables ordered by LigatureCoverage Index */
/* Array of LigatureAttach struct LigatureArray : OffsetListOf<LigatureAttach>
* tables ordered by {
* LigatureCoverage Index */ template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
bool subset (hb_subset_context_t *c,
Iterator coverage,
unsigned class_count,
const hb_map_t *klass_mapping) const
{
TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
auto *out = c->serializer->start_embed (this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
for (const auto _ : + hb_zip (coverage, *this)
| hb_filter (glyphset, hb_first))
{
auto *matrix = out->serialize_append (c->serializer);
if (unlikely (!matrix)) return_trace (false);
matrix->serialize_subset (c,
_.second,
this,
class_count,
klass_mapping);
}
return_trace (this->len);
}
};
struct MarkLigPosFormat1 struct MarkLigPosFormat1
{ {
@ -2130,8 +2177,56 @@ struct MarkLigPosFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
// TODO(subset) const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
return_trace (false); const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->format = format;
hb_map_t klass_mapping;
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
if (!klass_mapping.get_population ()) return_trace (false);
out->classCount = klass_mapping.get_population ();
auto mark_iter =
+ hb_zip (this+markCoverage, this+markArray)
| hb_filter (glyphset, hb_first)
;
auto new_mark_coverage =
+ mark_iter
| hb_map_retains_sorting (hb_first)
| hb_map_retains_sorting (glyph_map)
;
if (!out->markCoverage.serialize (c->serializer, out)
.serialize (c->serializer, new_mark_coverage))
return_trace (false);
out->markArray.serialize (c->serializer, out)
.serialize (c->serializer,
&klass_mapping,
c->plan->layout_variation_idx_map,
&(this+markArray),
+ mark_iter
| hb_map (hb_second));
auto new_ligature_coverage =
+ hb_iter (this + ligatureCoverage)
| hb_filter (glyphset)
| hb_map_retains_sorting (glyph_map)
;
if (!out->ligatureCoverage.serialize (c->serializer, out)
.serialize (c->serializer, new_ligature_coverage))
return_trace (false);
out->ligatureArray.serialize_subset (c, ligatureArray, this,
hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
return_trace (true);
} }
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
@ -2164,6 +2259,7 @@ struct MarkLigPosFormat1
DEFINE_SIZE_STATIC (12); DEFINE_SIZE_STATIC (12);
}; };
struct MarkLigPos struct MarkLigPos
{ {
template <typename context_t, typename ...Ts> template <typename context_t, typename ...Ts>
@ -2288,7 +2384,7 @@ struct MarkMarkPosFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);

View File

@ -356,7 +356,7 @@ struct Sequence
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
if (!intersects (&glyphset)) return_trace (false); if (!intersects (&glyphset)) return_trace (false);
@ -447,7 +447,7 @@ struct MultipleSubstFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);
@ -582,7 +582,7 @@ struct AlternateSet
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it = auto it =
@ -682,7 +682,7 @@ struct AlternateSubstFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);
@ -840,7 +840,7 @@ struct Ligature
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false); if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
@ -1058,7 +1058,7 @@ struct LigatureSubstFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);

View File

@ -89,7 +89,7 @@ struct hb_closure_context_t :
bool is_lookup_done (unsigned int lookup_index) bool is_lookup_done (unsigned int lookup_index)
{ {
if (done_lookups->in_error ()) if (unlikely (done_lookups->in_error ()))
return true; return true;
/* Have we visited this lookup with the current set of glyphs? */ /* Have we visited this lookup with the current set of glyphs? */
@ -146,7 +146,6 @@ struct hb_closure_lookups_context_t :
if (is_lookup_visited (lookup_index)) if (is_lookup_visited (lookup_index))
return; return;
set_lookup_visited (lookup_index);
nesting_level_left--; nesting_level_left--;
recurse_func (this, lookup_index); recurse_func (this, lookup_index);
nesting_level_left++; nesting_level_left++;
@ -163,10 +162,10 @@ struct hb_closure_lookups_context_t :
bool is_lookup_visited (unsigned lookup_index) bool is_lookup_visited (unsigned lookup_index)
{ {
if (lookup_count++ > HB_MAX_LOOKUP_INDICES) if (unlikely (lookup_count++ > HB_MAX_LOOKUP_INDICES))
return true; return true;
if (visited_lookups->in_error ()) if (unlikely (visited_lookups->in_error ()))
return true; return true;
return visited_lookups->has (lookup_index); return visited_lookups->has (lookup_index);
@ -660,7 +659,7 @@ struct hb_ot_apply_context_t :
void replace_glyph (hb_codepoint_t glyph_index) const void replace_glyph (hb_codepoint_t glyph_index) const
{ {
_set_glyph_props (glyph_index); _set_glyph_props (glyph_index);
buffer->replace_glyph (glyph_index); (void) buffer->replace_glyph (glyph_index);
} }
void replace_glyph_inplace (hb_codepoint_t glyph_index) const void replace_glyph_inplace (hb_codepoint_t glyph_index) const
{ {
@ -671,13 +670,13 @@ struct hb_ot_apply_context_t :
unsigned int class_guess) const unsigned int class_guess) const
{ {
_set_glyph_props (glyph_index, class_guess, true); _set_glyph_props (glyph_index, class_guess, true);
buffer->replace_glyph (glyph_index); (void) buffer->replace_glyph (glyph_index);
} }
void output_glyph_for_component (hb_codepoint_t glyph_index, void output_glyph_for_component (hb_codepoint_t glyph_index,
unsigned int class_guess) const unsigned int class_guess) const
{ {
_set_glyph_props (glyph_index, class_guess, false, true); _set_glyph_props (glyph_index, class_guess, false, true);
buffer->output_glyph (glyph_index); (void) buffer->output_glyph (glyph_index);
} }
}; };
@ -1044,7 +1043,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
hb_min (this_comp, last_num_components); hb_min (this_comp, last_num_components);
_hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
@ -1188,7 +1187,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
/* Don't recurse to ourself at same position. /* Don't recurse to ourself at same position.
* Note that this test is too naive, it doesn't catch longer loops. */ * Note that this test is too naive, it doesn't catch longer loops. */
if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index) if (unlikely (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index))
continue; continue;
if (unlikely (!buffer->move_to (match_positions[idx]))) if (unlikely (!buffer->move_to (match_positions[idx])))
@ -1226,7 +1225,8 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
* mean that n match positions where removed, as there might * mean that n match positions where removed, as there might
* have been marks and default-ignorables in the sequence. We * have been marks and default-ignorables in the sequence. We
* should instead drop match positions between current-position * should instead drop match positions between current-position
* and current-position + n instead. * and current-position + n instead. Though, am not sure which
* one is better. Both cases have valid uses. Sigh.
* *
* It should be possible to construct tests for both of these cases. * It should be possible to construct tests for both of these cases.
*/ */
@ -1272,7 +1272,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c,
match_positions[next] += delta; match_positions[next] += delta;
} }
buffer->move_to (end); (void) buffer->move_to (end);
return_trace (true); return_trace (true);
} }
@ -1389,9 +1389,11 @@ struct Rule
lookup_context); lookup_context);
} }
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c,
ContextClosureLookupContext &lookup_context) const
{ {
if (unlikely (c->lookup_limit_exceeded ())) return; if (unlikely (c->lookup_limit_exceeded ())) return;
if (!intersects (c->glyphs, lookup_context)) return;
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
(inputZ.as_array (inputCount ? inputCount - 1 : 0)); (inputZ.as_array (inputCount ? inputCount - 1 : 0));
@ -1521,14 +1523,13 @@ struct RuleSet
; ;
} }
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c,
ContextClosureLookupContext &lookup_context) const
{ {
if (unlikely (c->lookup_limit_exceeded ())) return; if (unlikely (c->lookup_limit_exceeded ())) return;
return
+ hb_iter (rule) + hb_iter (rule)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([&] (const Rule &_) { _.closure_lookups (c); }) | hb_apply ([&] (const Rule &_) { _.closure_lookups (c, lookup_context); })
; ;
} }
@ -1647,9 +1648,16 @@ struct ContextFormat1
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c) const
{ {
+ hb_iter (ruleSet) struct ContextClosureLookupContext lookup_context = {
{intersects_glyph},
nullptr
};
+ hb_zip (this+coverage, ruleSet)
| hb_filter (*c->glyphs, hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); }) | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c, lookup_context); })
; ;
} }
@ -1700,7 +1708,7 @@ struct ContextFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);
@ -1791,10 +1799,24 @@ struct ContextFormat2
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c) const
{ {
if (!(this+coverage).intersects (c->glyphs))
return;
const ClassDef &class_def = this+classDef;
struct ContextClosureLookupContext lookup_context = {
{intersects_class},
&class_def
};
+ hb_iter (ruleSet) + hb_iter (ruleSet)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); }) | hb_enumerate
; | hb_filter ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
{ return class_def.intersects_class (c->glyphs, p.first); })
| hb_map (hb_second)
| hb_apply ([&] (const RuleSet & _)
{ _.closure_lookups (c, lookup_context); });
} }
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {} void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
@ -1860,8 +1882,8 @@ struct ContextFormat2
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
bool ret = true; bool ret = true;
int non_zero_index = 0, index = 0; int non_zero_index = 0, index = 0;
for (const hb_pair_t<unsigned, const OffsetTo<RuleSet>&> _ : + hb_enumerate (ruleSet) for (const auto& _ : + hb_enumerate (ruleSet)
| hb_filter (klass_map, hb_first)) | hb_filter (klass_map, hb_first))
{ {
auto *o = out->ruleSet.serialize_append (c->serializer); auto *o = out->ruleSet.serialize_append (c->serializer);
if (unlikely (!o)) if (unlikely (!o))
@ -1945,6 +1967,8 @@ struct ContextFormat3
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c) const
{ {
if (!intersects (c->glyphs))
return;
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount)); const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
recurse_lookups (c, lookupCount, lookupRecord); recurse_lookups (c, lookupCount, lookupRecord);
} }
@ -2010,6 +2034,7 @@ struct ContextFormat3
for (const OffsetTo<Coverage>& offset : coverages) for (const OffsetTo<Coverage>& offset : coverages)
{ {
/* TODO(subset) This looks like should not be necessary to write this way. */
auto *o = c->serializer->allocate_size<OffsetTo<Coverage>> (OffsetTo<Coverage>::static_size); auto *o = c->serializer->allocate_size<OffsetTo<Coverage>> (OffsetTo<Coverage>::static_size);
if (unlikely (!o)) return_trace (false); if (unlikely (!o)) return_trace (false);
if (!o->serialize_subset (c, offset, this)) return_trace (false); if (!o->serialize_subset (c, offset, this)) return_trace (false);
@ -2238,9 +2263,11 @@ struct ChainRule
lookup_context); lookup_context);
} }
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c,
ChainContextClosureLookupContext &lookup_context) const
{ {
if (unlikely (c->lookup_limit_exceeded ())) return; if (unlikely (c->lookup_limit_exceeded ())) return;
if (!intersects (c->glyphs, lookup_context)) return;
const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
@ -2296,11 +2323,7 @@ struct ChainRule
{ {
c->copy (len); c->copy (len);
for (const auto g : it) for (const auto g : it)
{ c->copy ((HBUINT16) g);
HBUINT16 gid;
gid = g;
c->copy (gid);
}
} }
ChainRule* copy (hb_serialize_context_t *c, ChainRule* copy (hb_serialize_context_t *c,
@ -2328,12 +2351,19 @@ struct ChainRule
| hb_map (mapping)); | hb_map (mapping));
const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead); const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead);
HBUINT16 lookupCount;
lookupCount = lookupRecord.len;
if (!c->copy (lookupCount)) return_trace (nullptr);
for (unsigned i = 0; i < (unsigned) lookupCount; i++) HBUINT16* lookupCount = c->embed (&(lookupRecord.len));
if (!lookupCount) return_trace (nullptr);
for (unsigned i = 0; i < lookupRecord.len; i++)
{
if (!lookup_map->has (lookupRecord[i].lookupListIndex))
{
(*lookupCount)--;
continue;
}
if (!c->copy (lookupRecord[i], lookup_map)) return_trace (nullptr); if (!c->copy (lookupRecord[i], lookup_map)) return_trace (nullptr);
}
return_trace (out); return_trace (out);
} }
@ -2351,7 +2381,7 @@ struct ChainRule
if (!backtrack_map) if (!backtrack_map)
{ {
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
if (!hb_all (backtrack, glyphset) || if (!hb_all (backtrack, glyphset) ||
!hb_all (input, glyphset) || !hb_all (input, glyphset) ||
!hb_all (lookahead, glyphset)) !hb_all (lookahead, glyphset))
@ -2424,14 +2454,14 @@ struct ChainRuleSet
; ;
} }
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c,
ChainContextClosureLookupContext &lookup_context) const
{ {
if (unlikely (c->lookup_limit_exceeded ())) return; if (unlikely (c->lookup_limit_exceeded ())) return;
return
+ hb_iter (rule) + hb_iter (rule)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c); }) | hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c, lookup_context); })
; ;
} }
@ -2552,9 +2582,16 @@ struct ChainContextFormat1
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c) const
{ {
+ hb_iter (ruleSet) struct ChainContextClosureLookupContext lookup_context = {
{intersects_glyph},
{nullptr, nullptr, nullptr}
};
+ hb_zip (this+coverage, ruleSet)
| hb_filter (*c->glyphs, hb_first)
| hb_map (hb_second)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); }) | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c, lookup_context); })
; ;
} }
@ -2604,7 +2641,7 @@ struct ChainContextFormat1
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset (); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_map_t &glyph_map = *c->plan->glyph_map; const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);
@ -2701,9 +2738,28 @@ struct ChainContextFormat2
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c) const
{ {
if (!(this+coverage).intersects (c->glyphs))
return;
const ClassDef &backtrack_class_def = this+backtrackClassDef;
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
struct ChainContextClosureLookupContext lookup_context = {
{intersects_class},
{&backtrack_class_def,
&input_class_def,
&lookahead_class_def}
};
+ hb_iter (ruleSet) + hb_iter (ruleSet)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); }) | hb_enumerate
| hb_filter([&] (unsigned klass)
{ return input_class_def.intersects_class (c->glyphs, klass); }, hb_first)
| hb_map (hb_second)
| hb_apply ([&] (const ChainRuleSet &_)
{ _.closure_lookups (c, lookup_context); })
; ;
} }
@ -2779,24 +2835,23 @@ struct ChainContextFormat2
out->coverage.serialize_subset (c, coverage, this); out->coverage.serialize_subset (c, coverage, this);
hb_map_t backtrack_klass_map; hb_map_t backtrack_klass_map;
out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &backtrack_klass_map);
if (unlikely (!c->serializer->check_success (!backtrack_klass_map.in_error ())))
return_trace (false);
// subset inputClassDef based on glyphs survived in Coverage subsetting
hb_map_t input_klass_map; hb_map_t input_klass_map;
out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map);
if (unlikely (!c->serializer->check_success (!input_klass_map.in_error ())))
return_trace (false);
hb_map_t lookahead_klass_map; hb_map_t lookahead_klass_map;
out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &backtrack_klass_map);
// TODO: subset inputClassDef based on glyphs survived in Coverage subsetting
out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map);
out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, &lookahead_klass_map); out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, &lookahead_klass_map);
if (unlikely (!c->serializer->check_success (!lookahead_klass_map.in_error ())))
if (unlikely (!c->serializer->propagate_error (backtrack_klass_map,
input_klass_map,
lookahead_klass_map)))
return_trace (false); return_trace (false);
unsigned non_zero_index = 0, index = 0; int non_zero_index = -1, index = 0;
bool ret = true; bool ret = true;
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
auto last_non_zero = c->serializer->snapshot ();
for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet) for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
| hb_filter (input_klass_map, hb_first) | hb_filter (input_klass_map, hb_first)
| hb_map (hb_second)) | hb_map (hb_second))
@ -2812,19 +2867,20 @@ struct ChainContextFormat2
&backtrack_klass_map, &backtrack_klass_map,
&input_klass_map, &input_klass_map,
&lookahead_klass_map)) &lookahead_klass_map))
{
last_non_zero = c->serializer->snapshot ();
non_zero_index = index; non_zero_index = index;
}
index++; index++;
} }
if (!ret) return_trace (ret); if (!ret) return_trace (ret);
//prune empty trailing ruleSets // prune empty trailing ruleSets
--index; if (index > non_zero_index) {
while (index > non_zero_index) c->serializer->revert (last_non_zero);
{ out->ruleSet.len = non_zero_index + 1;
out->ruleSet.pop ();
index--;
} }
return_trace (bool (out->ruleSet)); return_trace (bool (out->ruleSet));
@ -2908,6 +2964,9 @@ struct ChainContextFormat3
void closure_lookups (hb_closure_lookups_context_t *c) const void closure_lookups (hb_closure_lookups_context_t *c) const
{ {
if (!intersects (c->glyphs))
return;
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
@ -2986,13 +3045,16 @@ struct ChainContextFormat3
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> (); auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> ();
if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) return_trace (false); if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
return_trace (false);
+ it for (auto& offset : it) {
| hb_apply (subset_offset_array (c, *out, base)) auto *o = out->serialize_append (c->serializer);
; if (unlikely (!o) || !o->serialize_subset (c, offset, base))
return_trace (false);
}
return_trace (out->len); return_trace (true);
} }
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
@ -3113,6 +3175,24 @@ struct ExtensionFormat1
extensionLookupType != T::SubTable::Extension); extensionLookupType != T::SubTable::Extension);
} }
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (this);
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
out->format = format;
out->extensionLookupType = extensionLookupType;
const auto& src_offset =
reinterpret_cast<const LOffsetTo<typename T::SubTable> &> (extensionOffset);
auto& dest_offset =
reinterpret_cast<LOffsetTo<typename T::SubTable> &> (out->extensionOffset);
return_trace (dest_offset.serialize_subset (c, src_offset, this, get_type ()));
}
protected: protected:
HBUINT16 format; /* Format identifier. Set to 1. */ HBUINT16 format; /* Format identifier. Set to 1. */
HBUINT16 extensionLookupType; /* Lookup type of subtable referenced HBUINT16 extensionLookupType; /* Lookup type of subtable referenced
@ -3143,6 +3223,18 @@ struct Extension
} }
} }
// Specialization of dispatch for subset. dispatch() normally just
// dispatches to the sub table this points too, but for subset
// we need to run subset on this subtable too.
template <typename ...Ts>
typename hb_subset_context_t::return_t dispatch (hb_subset_context_t *c, Ts&&... ds) const
{
switch (u.format) {
case 1: return u.format1.subset (c);
default: return c->default_return_value ();
}
}
template <typename context_t, typename ...Ts> template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{ {
@ -3320,20 +3412,34 @@ struct GSUBGPOS
return_trace (true); return_trace (true);
} }
void closure_features (const hb_map_t *lookup_indexes, /* IN */ void prune_features (const hb_map_t *lookup_indices, /* IN */
hb_set_t *feature_indexes /* OUT */) const hb_set_t *feature_indices /* IN/OUT */) const
{ {
unsigned int feature_count = hb_min (get_feature_count (), (unsigned) HB_MAX_FEATURES); #ifndef HB_NO_VAR
for (unsigned i = 0; i < feature_count; i++) // This is the set of feature indices which have alternate versions defined
// if the FeatureVariation's table and the alternate version(s) intersect the
// set of lookup indices.
hb_set_t alternate_feature_indices;
if (version.to_int () >= 0x00010001u)
(this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
if (unlikely (alternate_feature_indices.in_error())) {
feature_indices->successful = false;
return;
}
#endif
for (unsigned i : feature_indices->iter())
{ {
const Feature& f = get_feature (i); const Feature& f = get_feature (i);
if ((!f.featureParams.is_null ()) || f.intersects_lookup_indexes (lookup_indexes))
feature_indexes->add (i); if (f.featureParams.is_null ()
} && !f.intersects_lookup_indexes (lookup_indices)
#ifndef HB_NO_VAR #ifndef HB_NO_VAR
if (version.to_int () >= 0x00010001u) && !alternate_feature_indices.has (i)
(this+featureVars).closure_features (lookup_indexes, feature_indexes);
#endif #endif
)
feature_indices->del (i);
}
} }
unsigned int get_size () const unsigned int get_size () const

View File

@ -76,7 +76,7 @@
* Tests whether a face includes any kerning data in the 'kern' table. * Tests whether a face includes any kerning data in the 'kern' table.
* Does NOT test for kerning lookups in the GPOS table. * Does NOT test for kerning lookups in the GPOS table.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
**/ **/
bool bool
@ -92,7 +92,7 @@ hb_ot_layout_has_kerning (hb_face_t *face)
* Tests whether a face includes any state-machine kerning in the 'kern' table. * Tests whether a face includes any state-machine kerning in the 'kern' table.
* Does NOT examine the GPOS table. * Does NOT examine the GPOS table.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
**/ **/
bool bool
@ -112,7 +112,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face)
* *
* Does NOT examine the GPOS table. * Does NOT examine the GPOS table.
* *
* Return value: %true is data found, false otherwise * Return value: %true is data found, %false otherwise
* *
**/ **/
bool bool
@ -268,7 +268,7 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
* *
* Tests whether a face has any glyph classes defined in its GDEF table. * Tests whether a face has any glyph classes defined in its GDEF table.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
**/ **/
hb_bool_t hb_bool_t
@ -322,7 +322,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
* @face: The #hb_face_t to work on * @face: The #hb_face_t to work on
* @glyph: The #hb_codepoint_t code point to query * @glyph: The #hb_codepoint_t code point to query
* @start_offset: offset of the first attachment point to retrieve * @start_offset: offset of the first attachment point to retrieve
* @point_count: (inout) (allow-none): Input = the maximum number of attachment points to return; * @point_count: (inout) (optional): Input = the maximum number of attachment points to return;
* Output = the actual number of attachment points returned (may be zero) * Output = the actual number of attachment points returned (may be zero)
* @point_array: (out) (array length=point_count): The array of attachment points found for the query * @point_array: (out) (array length=point_count): The array of attachment points found for the query
* *
@ -350,7 +350,7 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
* @direction: The #hb_direction_t text direction to use * @direction: The #hb_direction_t text direction to use
* @glyph: The #hb_codepoint_t code point to query * @glyph: The #hb_codepoint_t code point to query
* @start_offset: offset of the first caret position to retrieve * @start_offset: offset of the first caret position to retrieve
* @caret_count: (inout) (allow-none): Input = the maximum number of caret positions to return; * @caret_count: (inout) (optional): Input = the maximum number of caret positions to return;
* Output = the actual number of caret positions returned (may be zero) * Output = the actual number of caret positions returned (may be zero)
* @caret_array: (out) (array length=caret_count): The array of caret positions found for the query * @caret_array: (out) (array length=caret_count): The array of caret positions found for the query
* *
@ -410,9 +410,9 @@ get_gsubgpos_table (hb_face_t *face,
/** /**
* hb_ot_layout_table_get_script_tags: * hb_ot_layout_table_get_script_tags:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @start_offset: offset of the first script tag to retrieve * @start_offset: offset of the first script tag to retrieve
* @script_count: (inout) (allow-none): Input = the maximum number of script tags to return; * @script_count: (inout) (optional): Input = the maximum number of script tags to return;
* Output = the actual number of script tags returned (may be zero) * Output = the actual number of script tags returned (may be zero)
* @script_tags: (out) (array length=script_count): The array of #hb_tag_t script tags found for the query * @script_tags: (out) (array length=script_count): The array of #hb_tag_t script tags found for the query
* *
@ -437,14 +437,14 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face,
/** /**
* hb_ot_layout_table_find_script: * hb_ot_layout_table_find_script:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_tag: #hb_tag_t of the script tag requested * @script_tag: #hb_tag_t of the script tag requested
* @script_index: (out): The index of the requested script tag * @script_index: (out): The index of the requested script tag
* *
* Fetches the index if a given script tag in the specified face's GSUB table * Fetches the index if a given script tag in the specified face's GSUB table
* or GPOS table. * or GPOS table.
* *
* Return value: %true if the script is found, false otherwise * Return value: %true if the script is found, %false otherwise
* *
**/ **/
hb_bool_t hb_bool_t
@ -481,7 +481,7 @@ hb_ot_layout_table_find_script (hb_face_t *face,
/** /**
* hb_ot_layout_table_choose_script: * hb_ot_layout_table_choose_script:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_tags: Array of #hb_tag_t script tags * @script_tags: Array of #hb_tag_t script tags
* @script_index: (out): The index of the requested script tag * @script_index: (out): The index of the requested script tag
* @chosen_script: (out): #hb_tag_t of the script tag requested * @chosen_script: (out): #hb_tag_t of the script tag requested
@ -504,11 +504,22 @@ hb_ot_layout_table_choose_script (hb_face_t *face,
/** /**
* hb_ot_layout_table_select_script: * hb_ot_layout_table_select_script:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_count: Number of script tags in the array * @script_count: Number of script tags in the array
* @script_tags: Array of #hb_tag_t script tags * @script_tags: Array of #hb_tag_t script tags
* @script_index: (out): The index of the requested script * @script_index: (out) (optional): The index of the requested script
* @chosen_script: (out): #hb_tag_t of the requested script * @chosen_script: (out) (optional): #hb_tag_t of the requested script
*
* Selects an OpenType script for @table_tag from the @script_tags array.
*
* If the table does not have any of the requested scripts, then `DFLT`,
* `dflt`, and `latn` tags are tried in that order. If the table still does not
* have any of these scripts, @script_index and @chosen_script are set to
* #HB_OT_LAYOUT_NO_SCRIPT_INDEX.
*
* Return value:
* %true if one of the requested scripts is selected, %false if a fallback
* script is selected or if no scripts are selected.
* *
* Since: 2.0.0 * Since: 2.0.0
**/ **/
@ -566,9 +577,9 @@ hb_ot_layout_table_select_script (hb_face_t *face,
/** /**
* hb_ot_layout_table_get_feature_tags: * hb_ot_layout_table_get_feature_tags:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @start_offset: offset of the first feature tag to retrieve * @start_offset: offset of the first feature tag to retrieve
* @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return; * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
* Output = the actual number of feature tags returned (may be zero) * Output = the actual number of feature tags returned (may be zero)
* @feature_tags: (out) (array length=feature_count): Array of feature tags found in the table * @feature_tags: (out) (array length=feature_count): Array of feature tags found in the table
* *
@ -591,14 +602,14 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
/** /**
* hb_ot_layout_table_find_feature: * hb_ot_layout_table_find_feature:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @feature_tag: The #hb_tag_t og the requested feature tag * @feature_tag: The #hb_tag_t og the requested feature tag
* @feature_index: (out): The index of the requested feature * @feature_index: (out): The index of the requested feature
* *
* Fetches the index for a given feature tag in the specified face's GSUB table * Fetches the index for a given feature tag in the specified face's GSUB table
* or GPOS table. * or GPOS table.
* *
* Return value: %true if the feature is found, false otherwise * Return value: %true if the feature is found, %false otherwise
**/ **/
bool bool
hb_ot_layout_table_find_feature (hb_face_t *face, hb_ot_layout_table_find_feature (hb_face_t *face,
@ -626,10 +637,10 @@ hb_ot_layout_table_find_feature (hb_face_t *face,
/** /**
* hb_ot_layout_script_get_language_tags: * hb_ot_layout_script_get_language_tags:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag * @script_index: The index of the requested script tag
* @start_offset: offset of the first language tag to retrieve * @start_offset: offset of the first language tag to retrieve
* @language_count: (inout) (allow-none): Input = the maximum number of language tags to return; * @language_count: (inout) (optional): Input = the maximum number of language tags to return;
* Output = the actual number of language tags returned (may be zero) * Output = the actual number of language tags returned (may be zero)
* @language_tags: (out) (array length=language_count): Array of language tags found in the table * @language_tags: (out) (array length=language_count): Array of language tags found in the table
* *
@ -655,7 +666,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
/** /**
* hb_ot_layout_script_find_language: * hb_ot_layout_script_find_language:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag * @script_index: The index of the requested script tag
* @language_tag: The #hb_tag_t of the requested language * @language_tag: The #hb_tag_t of the requested language
* @language_index: The index of the requested language * @language_index: The index of the requested language
@ -663,7 +674,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
* Fetches the index of a given language tag in the specified face's GSUB table * Fetches the index of a given language tag in the specified face's GSUB table
* or GPOS table, underneath the specified script tag. * or GPOS table, underneath the specified script tag.
* *
* Return value: %true if the language tag is found, false otherwise * Return value: %true if the language tag is found, %false otherwise
* *
* Since: ?? * Since: ??
* Deprecated: ?? * Deprecated: ??
@ -688,7 +699,7 @@ hb_ot_layout_script_find_language (hb_face_t *face,
/** /**
* hb_ot_layout_script_select_language: * hb_ot_layout_script_select_language:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag * @script_index: The index of the requested script tag
* @language_count: The number of languages in the specified script * @language_count: The number of languages in the specified script
* @language_tags: The array of language tags * @language_tags: The array of language tags
@ -697,7 +708,7 @@ hb_ot_layout_script_find_language (hb_face_t *face,
* Fetches the index of a given language tag in the specified face's GSUB table * Fetches the index of a given language tag in the specified face's GSUB table
* or GPOS table, underneath the specified script index. * or GPOS table, underneath the specified script index.
* *
* Return value: %true if the language tag is found, false otherwise * Return value: %true if the language tag is found, %false otherwise
* *
* Since: 2.0.0 * Since: 2.0.0
**/ **/
@ -731,7 +742,7 @@ hb_ot_layout_script_select_language (hb_face_t *face,
/** /**
* hb_ot_layout_language_get_required_feature_index: * hb_ot_layout_language_get_required_feature_index:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag * @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag * @language_index: The index of the requested language tag
* @feature_index: (out): The index of the requested feature * @feature_index: (out): The index of the requested feature
@ -739,7 +750,7 @@ hb_ot_layout_script_select_language (hb_face_t *face,
* Fetches the index of a requested feature in the given face's GSUB or GPOS table, * Fetches the index of a requested feature in the given face's GSUB or GPOS table,
* underneath the specified script and language. * underneath the specified script and language.
* *
* Return value: %true if the feature is found, false otherwise * Return value: %true if the feature is found, %false otherwise
* *
**/ **/
hb_bool_t hb_bool_t
@ -761,7 +772,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
/** /**
* hb_ot_layout_language_get_required_feature: * hb_ot_layout_language_get_required_feature:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag * @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag * @language_index: The index of the requested language tag
* @feature_index: (out): The index of the requested feature * @feature_index: (out): The index of the requested feature
@ -770,7 +781,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
* Fetches the tag of a requested feature index in the given face's GSUB or GPOS table, * Fetches the tag of a requested feature index in the given face's GSUB or GPOS table,
* underneath the specified script and language. * underneath the specified script and language.
* *
* Return value: %true if the feature is found, false otherwise * Return value: %true if the feature is found, %false otherwise
* *
* Since: 0.9.30 * Since: 0.9.30
**/ **/
@ -796,11 +807,11 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
/** /**
* hb_ot_layout_language_get_feature_indexes: * hb_ot_layout_language_get_feature_indexes:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag * @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag * @language_index: The index of the requested language tag
* @start_offset: offset of the first feature tag to retrieve * @start_offset: offset of the first feature tag to retrieve
* @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return; * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
* Output: the actual number of feature tags returned (may be zero) * Output: the actual number of feature tags returned (may be zero)
* @feature_indexes: (out) (array length=feature_count): The array of feature indexes found for the query * @feature_indexes: (out) (array length=feature_count): The array of feature indexes found for the query
* *
@ -827,11 +838,11 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
/** /**
* hb_ot_layout_language_get_feature_tags: * hb_ot_layout_language_get_feature_tags:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag * @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag * @language_index: The index of the requested language tag
* @start_offset: offset of the first feature tag to retrieve * @start_offset: offset of the first feature tag to retrieve
* @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return; * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
* Output = the actual number of feature tags returned (may be zero) * Output = the actual number of feature tags returned (may be zero)
* @feature_tags: (out) (array length=feature_count): The array of #hb_tag_t feature tags found for the query * @feature_tags: (out) (array length=feature_count): The array of #hb_tag_t feature tags found for the query
* *
@ -868,7 +879,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
/** /**
* hb_ot_layout_language_find_feature: * hb_ot_layout_language_find_feature:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @script_index: The index of the requested script tag * @script_index: The index of the requested script tag
* @language_index: The index of the requested language tag * @language_index: The index of the requested language tag
* @feature_tag: #hb_tag_t of the feature tag requested * @feature_tag: #hb_tag_t of the feature tag requested
@ -877,7 +888,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
* Fetches the index of a given feature tag in the specified face's GSUB table * Fetches the index of a given feature tag in the specified face's GSUB table
* or GPOS table, underneath the specified script and language. * or GPOS table, underneath the specified script and language.
* *
* Return value: %true if the feature is found, false otherwise * Return value: %true if the feature is found, %false otherwise
* *
**/ **/
hb_bool_t hb_bool_t
@ -910,10 +921,10 @@ hb_ot_layout_language_find_feature (hb_face_t *face,
/** /**
* hb_ot_layout_feature_get_lookups: * hb_ot_layout_feature_get_lookups:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @feature_index: The index of the requested feature * @feature_index: The index of the requested feature
* @start_offset: offset of the first lookup to retrieve * @start_offset: offset of the first lookup to retrieve
* @lookup_count: (inout) (allow-none): Input = the maximum number of lookups to return; * @lookup_count: (inout) (optional): Input = the maximum number of lookups to return;
* Output = the actual number of lookups returned (may be zero) * Output = the actual number of lookups returned (may be zero)
* @lookup_indexes: (out) (array length=lookup_count): The array of lookup indexes found for the query * @lookup_indexes: (out) (array length=lookup_count): The array of lookup indexes found for the query
* *
@ -944,7 +955,7 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face,
/** /**
* hb_ot_layout_table_get_lookup_count: * hb_ot_layout_table_get_lookup_count:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* *
* Fetches the total number of lookups enumerated in the specified * Fetches the total number of lookups enumerated in the specified
* face's GSUB table or GPOS table. * face's GSUB table or GPOS table.
@ -1101,7 +1112,7 @@ script_collect_features (hb_collect_features_context_t *c,
/** /**
* hb_ot_layout_collect_features: * hb_ot_layout_collect_features:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @scripts: The array of scripts to collect features for * @scripts: The array of scripts to collect features for
* @languages: The array of languages to collect features for * @languages: The array of languages to collect features for
* @features: The array of features to collect * @features: The array of features to collect
@ -1152,7 +1163,7 @@ hb_ot_layout_collect_features (hb_face_t *face,
/** /**
* hb_ot_layout_collect_lookups: * hb_ot_layout_collect_lookups:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @scripts: The array of scripts to collect lookups for * @scripts: The array of scripts to collect lookups for
* @languages: The array of languages to collect lookups for * @languages: The array of languages to collect lookups for
* @features: The array of features to collect lookups for * @features: The array of features to collect lookups for
@ -1191,7 +1202,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
/** /**
* hb_ot_layout_lookup_collect_glyphs: * hb_ot_layout_lookup_collect_glyphs:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @lookup_index: The index of the feature lookup to query * @lookup_index: The index of the feature lookup to query
* @glyphs_before: (out): Array of glyphs preceding the substitution range * @glyphs_before: (out): Array of glyphs preceding the substitution range
* @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup * @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup
@ -1243,7 +1254,7 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
/** /**
* hb_ot_layout_table_find_feature_variations: * hb_ot_layout_table_find_feature_variations:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @coords: The variation coordinates to query * @coords: The variation coordinates to query
* @num_coords: The number of variation coordinates * @num_coords: The number of variation coordinates
* @variations_index: (out): The array of feature variations found for the query * @variations_index: (out): The array of feature variations found for the query
@ -1268,11 +1279,11 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face,
/** /**
* hb_ot_layout_feature_with_variations_get_lookups: * hb_ot_layout_feature_with_variations_get_lookups:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
* @feature_index: The index of the feature to query * @feature_index: The index of the feature to query
* @variations_index: The index of the feature variation to query * @variations_index: The index of the feature variation to query
* @start_offset: offset of the first lookup to retrieve * @start_offset: offset of the first lookup to retrieve
* @lookup_count: (inout) (allow-none): Input = the maximum number of lookups to return; * @lookup_count: (inout) (optional): Input = the maximum number of lookups to return;
* Output = the actual number of lookups returned (may be zero) * Output = the actual number of lookups returned (may be zero)
* @lookup_indexes: (out) (array length=lookup_count): The array of lookups found for the query * @lookup_indexes: (out) (array length=lookup_count): The array of lookups found for the query
* *
@ -1310,7 +1321,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
* *
* Tests whether the specified face includes any GSUB substitutions. * Tests whether the specified face includes any GSUB substitutions.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
**/ **/
hb_bool_t hb_bool_t
@ -1331,7 +1342,7 @@ hb_ot_layout_has_substitution (hb_face_t *face)
* Tests whether a specified lookup in the specified face would * Tests whether a specified lookup in the specified face would
* trigger a substitution on the given glyph sequence. * trigger a substitution on the given glyph sequence.
* *
* Return value: %true if a substitution would be triggered, false otherwise * Return value: %true if a substitution would be triggered, %false otherwise
* *
* Since: 0.9.7 * Since: 0.9.7
**/ **/
@ -1488,7 +1499,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
* hb_ot_layout_has_positioning: * hb_ot_layout_has_positioning:
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* *
* Return value: %true if the face has GPOS data, false otherwise * Tests whether the specified face includes any GPOS positioning.
*
* Return value: %true if the face has GPOS data, %false otherwise
* *
**/ **/
hb_bool_t hb_bool_t
@ -1561,7 +1574,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
* For more information on this distinction, see the [`size` feature documentation]( * For more information on this distinction, see the [`size` feature documentation](
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size). * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size).
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 0.9.10 * Since: 0.9.10
**/ **/
@ -1610,22 +1623,22 @@ hb_ot_layout_get_size_params (hb_face_t *face,
* @face: #hb_face_t to work upon * @face: #hb_face_t to work upon
* @table_tag: table tag to query, "GSUB" or "GPOS". * @table_tag: table tag to query, "GSUB" or "GPOS".
* @feature_index: index of feature to query. * @feature_index: index of feature to query.
* @label_id: (out) (allow-none): The name table name ID that specifies a string * @label_id: (out) (optional): The name table name ID that specifies a string
* for a user-interface label for this feature. (May be NULL.) * for a user-interface label for this feature. (May be NULL.)
* @tooltip_id: (out) (allow-none): The name table name ID that specifies a string * @tooltip_id: (out) (optional): The name table name ID that specifies a string
* that an application can use for tooltip text for this * that an application can use for tooltip text for this
* feature. (May be NULL.) * feature. (May be NULL.)
* @sample_id: (out) (allow-none): The name table name ID that specifies sample text * @sample_id: (out) (optional): The name table name ID that specifies sample text
* that illustrates the effect of this feature. (May be NULL.) * that illustrates the effect of this feature. (May be NULL.)
* @num_named_parameters: (out) (allow-none): Number of named parameters. (May be zero.) * @num_named_parameters: (out) (optional): Number of named parameters. (May be zero.)
* @first_param_id: (out) (allow-none): The first name table name ID used to specify * @first_param_id: (out) (optional): The first name table name ID used to specify
* strings for user-interface labels for the feature * strings for user-interface labels for the feature
* parameters. (Must be zero if numParameters is zero.) * parameters. (Must be zero if numParameters is zero.)
* *
* Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or * Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
* "Character Variant" ('cvXX') features. * "Character Variant" ('cvXX') features.
* *
* Return value: %true if data found, false otherwise * Return value: %true if data found, %false otherwise
* *
* Since: 2.0.0 * Since: 2.0.0
**/ **/
@ -1685,7 +1698,7 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face,
* @table_tag: table tag to query, "GSUB" or "GPOS". * @table_tag: table tag to query, "GSUB" or "GPOS".
* @feature_index: index of feature to query. * @feature_index: index of feature to query.
* @start_offset: offset of the first character to retrieve * @start_offset: offset of the first character to retrieve
* @char_count: (inout) (allow-none): Input = the maximum number of characters to return; * @char_count: (inout) (optional): Input = the maximum number of characters to return;
* Output = the actual number of characters returned (may be zero) * Output = the actual number of characters returned (may be zero)
* @characters: (out caller-allocates) (array length=char_count): A buffer pointer. * @characters: (out caller-allocates) (array length=char_count): A buffer pointer.
* The Unicode codepoints of the characters for which this feature provides * The Unicode codepoints of the characters for which this feature provides
@ -1769,7 +1782,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
if (applied) if (applied)
ret = true; ret = true;
else else
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
return ret; return ret;
} }
@ -1907,7 +1920,7 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
* @baseline_tag: a baseline tag * @baseline_tag: a baseline tag
* @direction: text direction. * @direction: text direction.
* @script_tag: script tag. * @script_tag: script tag.
* @language_tag: language tag. * @language_tag: language tag, currently unused.
* @coord: (out): baseline value if found. * @coord: (out): baseline value if found.
* *
* Fetches a baseline value from the face. * Fetches a baseline value from the face.
@ -1964,7 +1977,7 @@ struct hb_get_glyph_alternates_dispatch_t :
* @lookup_index: index of the feature lookup to query. * @lookup_index: index of the feature lookup to query.
* @glyph: a glyph id. * @glyph: a glyph id.
* @start_offset: starting offset. * @start_offset: starting offset.
* @alternate_count: (inout) (allow-none): Input = the maximum number of alternate glyphs to return; * @alternate_count: (inout) (optional): Input = the maximum number of alternate glyphs to return;
* Output = the actual number of alternate glyphs returned (may be zero). * Output = the actual number of alternate glyphs returned (may be zero).
* @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer. * @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer.
* Alternate glyphs associated with the glyph id. * Alternate glyphs associated with the glyph id.

View File

@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif
@ -38,10 +38,35 @@
HB_BEGIN_DECLS HB_BEGIN_DECLS
/**
* HB_OT_TAG_BASE:
*
* OpenType [Baseline Table](https://docs.microsoft.com/en-us/typography/opentype/spec/base).
*/
#define HB_OT_TAG_BASE HB_TAG('B','A','S','E') #define HB_OT_TAG_BASE HB_TAG('B','A','S','E')
/**
* HB_OT_TAG_GDEF:
*
* OpenType [Glyph Definition Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef).
*/
#define HB_OT_TAG_GDEF HB_TAG('G','D','E','F') #define HB_OT_TAG_GDEF HB_TAG('G','D','E','F')
/**
* HB_OT_TAG_GSUB:
*
* OpenType [Glyph Substitution Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gsub).
*/
#define HB_OT_TAG_GSUB HB_TAG('G','S','U','B') #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B')
/**
* HB_OT_TAG_GPOS:
*
* OpenType [Glyph Positioning Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos).
*/
#define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S')
/**
* HB_OT_TAG_JSTF:
*
* OpenType [Justification Table](https://docs.microsoft.com/en-us/typography/opentype/spec/jstf).
*/
#define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F')
@ -49,18 +74,34 @@ HB_BEGIN_DECLS
* Script & Language tags. * Script & Language tags.
*/ */
/**
* HB_OT_TAG_DEFAULT_SCRIPT:
*
* OpenType script tag, `DFLT`, for features that are not script-specific.
*
*/
#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T') #define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T')
/**
* HB_OT_TAG_DEFAULT_LANGUAGE:
*
* OpenType language tag, `dflt`. Not a valid language tag, but some fonts
* mistakenly use it.
*/
#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't') #define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't')
/** /**
* HB_OT_MAX_TAGS_PER_SCRIPT: * HB_OT_MAX_TAGS_PER_SCRIPT:
* *
* Maximum number of OpenType tags that can correspond to a give #hb_script_t.
*
* Since: 2.0.0 * Since: 2.0.0
**/ **/
#define HB_OT_MAX_TAGS_PER_SCRIPT 3u #define HB_OT_MAX_TAGS_PER_SCRIPT 3u
/** /**
* HB_OT_MAX_TAGS_PER_LANGUAGE: * HB_OT_MAX_TAGS_PER_LANGUAGE:
* *
* Maximum number of OpenType tags that can correspond to a give #hb_language_t.
*
* Since: 2.0.0 * Since: 2.0.0
**/ **/
#define HB_OT_MAX_TAGS_PER_LANGUAGE 3u #define HB_OT_MAX_TAGS_PER_LANGUAGE 3u
@ -144,9 +185,29 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
* GSUB/GPOS feature query and enumeration interface * GSUB/GPOS feature query and enumeration interface
*/ */
/**
* HB_OT_LAYOUT_NO_SCRIPT_INDEX:
*
* Special value for script index indicating unsupported script.
*/
#define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu #define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu
/**
* HB_OT_LAYOUT_NO_FEATURE_INDEX:
*
* Special value for feature index indicating unsupported feature.
*/
#define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu #define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu
/**
* HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX:
*
* Special value for language index indicating default or unsupported language.
*/
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu
/**
* HB_OT_LAYOUT_NO_VARIATIONS_INDEX:
*
* Special value for variations index indicating unsupported variation.
*/
#define HB_OT_LAYOUT_NO_VARIATIONS_INDEX 0xFFFFFFFFu #define HB_OT_LAYOUT_NO_VARIATIONS_INDEX 0xFFFFFFFFu
HB_EXTERN unsigned int HB_EXTERN unsigned int
@ -433,7 +494,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
* @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered. * @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered.
* In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered. * In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered.
* *
* Baseline tags from https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags * Baseline tags from [Baseline Tags](https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags) registry.
* *
* Since: 2.6.0 * Since: 2.6.0
*/ */
@ -446,6 +507,7 @@ typedef enum {
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'), HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'),
HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'), HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'),
/*< private >*/
_HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_layout_baseline_tag_t; } hb_ot_layout_baseline_tag_t;

View File

@ -315,12 +315,13 @@ _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
} }
static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info); static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info);
static inline bool static inline bool
_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
{ {
return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
!_hb_glyph_info_ligated (info); !_hb_glyph_info_substituted (info);
} }
static inline bool static inline bool
_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info) _hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)

View File

@ -56,7 +56,7 @@
* *
* Tests whether a face has a `MATH` table. * Tests whether a face has a `MATH` table.
* *
* Return value: true if the table is found, false otherwise * Return value: %true if the table is found, %false otherwise
* *
* Since: 1.3.3 * Since: 1.3.3
**/ **/
@ -142,7 +142,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
* *
* Tests whether the given glyph index is an extended shape in the face. * Tests whether the given glyph index is an extended shape in the face.
* *
* Return value: true if the glyph is an extended shape, false otherwise * Return value: %true if the glyph is an extended shape, %false otherwise
* *
* Since: 1.3.3 * Since: 1.3.3
**/ **/

View File

@ -24,7 +24,7 @@
* Igalia Author(s): Frédéric Wang * Igalia Author(s): Frédéric Wang
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif
@ -40,18 +40,89 @@ HB_BEGIN_DECLS
* MATH * MATH
*/ */
/**
* HB_OT_TAG_MATH:
*
* OpenType [Mathematical Typesetting Table](https://docs.microsoft.com/en-us/typography/opentype/spec/math).
*
* Since: 1.3.3
*/
#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') #define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
/* Use with hb_buffer_set_script() for math shaping. */ /**
* HB_OT_MATH_SCRIPT:
*
* OpenType script tag for math shaping, for use with
* Use with hb_buffer_set_script().
*
* Since: 1.3.3
*/
#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h') #define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
/* Types */ /* Types */
/** /**
* hb_ot_math_constant_t: * hb_ot_math_constant_t:
* @HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: scriptPercentScaleDown
* @HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: scriptScriptPercentScaleDown
* @HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: delimitedSubFormulaMinHeight
* @HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: displayOperatorMinHeight
* @HB_OT_MATH_CONSTANT_MATH_LEADING: mathLeading
* @HB_OT_MATH_CONSTANT_AXIS_HEIGHT: axisHeight
* @HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: accentBaseHeight
* @HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: flattenedAccentBaseHeight
* @HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: subscriptShiftDown
* @HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: subscriptTopMax
* @HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: subscriptBaselineDropMin
* @HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: superscriptShiftUp
* @HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: superscriptShiftUpCramped
* @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: superscriptBottomMin
* @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: superscriptBaselineDropMax
* @HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: subSuperscriptGapMin
* @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: superscriptBottomMaxWithSubscript
* @HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: spaceAfterScript
* @HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: upperLimitGapMin
* @HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: upperLimitBaselineRiseMin
* @HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: lowerLimitGapMin
* @HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: lowerLimitBaselineDropMin
* @HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: stackTopShiftUp
* @HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: stackTopDisplayStyleShiftUp
* @HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: stackBottomShiftDown
* @HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: stackBottomDisplayStyleShiftDown
* @HB_OT_MATH_CONSTANT_STACK_GAP_MIN: stackGapMin
* @HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: stackDisplayStyleGapMin
* @HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: stretchStackTopShiftUp
* @HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: stretchStackBottomShiftDown
* @HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: stretchStackGapAboveMin
* @HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: stretchStackGapBelowMin
* @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: fractionNumeratorShiftUp
* @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: fractionNumeratorDisplayStyleShiftUp
* @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: fractionDenominatorShiftDown
* @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: fractionDenominatorDisplayStyleShiftDown
* @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: fractionNumeratorGapMin
* @HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: fractionNumDisplayStyleGapMin
* @HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: fractionRuleThickness
* @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: fractionDenominatorGapMin
* @HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: fractionDenomDisplayStyleGapMin
* @HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: skewedFractionHorizontalGap
* @HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: skewedFractionVerticalGap
* @HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: overbarVerticalGap
* @HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: overbarRuleThickness
* @HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: overbarExtraAscender
* @HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: underbarVerticalGap
* @HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: underbarRuleThickness
* @HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: underbarExtraDescender
* @HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: radicalVerticalGap
* @HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: radicalDisplayStyleVerticalGap
* @HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: radicalRuleThickness
* @HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: radicalExtraAscender
* @HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: radicalKernBeforeDegree
* @HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: radicalKernAfterDegree
* @HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: radicalDegreeBottomRaisePercent
* *
* The 'MATH' table constants specified at * The 'MATH' table constants, refer to
* https://docs.microsoft.com/en-us/typography/opentype/spec/math * [OpenType documentation](https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathconstants-table)
* For more explanations.
* *
* Since: 1.3.3 * Since: 1.3.3
*/ */
@ -116,6 +187,10 @@ typedef enum {
/** /**
* hb_ot_math_kern_t: * hb_ot_math_kern_t:
* @HB_OT_MATH_KERN_TOP_RIGHT: The top right corner of the glyph.
* @HB_OT_MATH_KERN_TOP_LEFT: The top left corner of the glyph.
* @HB_OT_MATH_KERN_BOTTOM_RIGHT: The bottom right corner of the glyph.
* @HB_OT_MATH_KERN_BOTTOM_LEFT: The bottom left corner of the glyph.
* *
* The math kerning-table types defined for the four corners * The math kerning-table types defined for the four corners
* of a glyph. * of a glyph.
@ -145,6 +220,8 @@ typedef struct hb_ot_math_glyph_variant_t {
/** /**
* hb_ot_math_glyph_part_flags_t: * hb_ot_math_glyph_part_flags_t:
* @HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER: This is an extender glyph part that
* can be repeated to reach the desired length.
* *
* Flags for math glyph parts. * Flags for math glyph parts.
* *

View File

@ -41,9 +41,11 @@
* hb_ot_meta_get_entry_tags: * hb_ot_meta_get_entry_tags:
* @face: a face object * @face: a face object
* @start_offset: iteration's start offset * @start_offset: iteration's start offset
* @entries_count:(inout) (allow-none): buffer size as input, filled size as output * @entries_count:(inout) (optional): buffer size as input, filled size as output
* @entries: (out caller-allocates) (array length=entries_count): entries tags buffer * @entries: (out caller-allocates) (array length=entries_count): entries tags buffer
* *
* Fetches all available feature types.
*
* Return value: Number of all available feature types. * Return value: Number of all available feature types.
* *
* Since: 2.6.0 * Since: 2.6.0

View File

@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif
@ -54,6 +54,7 @@ typedef enum {
HB_OT_META_TAG_DESIGN_LANGUAGES = HB_TAG ('d','l','n','g'), HB_OT_META_TAG_DESIGN_LANGUAGES = HB_TAG ('d','l','n','g'),
HB_OT_META_TAG_SUPPORTED_LANGUAGES = HB_TAG ('s','l','n','g'), HB_OT_META_TAG_SUPPORTED_LANGUAGES = HB_TAG ('s','l','n','g'),
/*< private >*/
_HB_OT_META_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ _HB_OT_META_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_meta_tag_t; } hb_ot_meta_tag_t;

View File

@ -119,11 +119,11 @@ _get_gasp (hb_face_t *face, float *result, hb_ot_metrics_tag_t metrics_tag)
/** /**
* hb_ot_metrics_get_position: * hb_ot_metrics_get_position:
* @font: a #hb_font_t object. * @font: an #hb_font_t object.
* @metrics_tag: tag of metrics value you like to fetch. * @metrics_tag: tag of metrics value you like to fetch.
* @position: (out) (optional): result of metrics value from the font. * @position: (out) (optional): result of metrics value from the font.
* *
* It fetches metrics value corresponding to a given tag from a font. * Fetches metrics value corresponding to @metrics_tag from @font.
* *
* Returns: Whether found the requested metrics in the font. * Returns: Whether found the requested metrics in the font.
* Since: 2.6.0 * Since: 2.6.0
@ -193,10 +193,13 @@ hb_ot_metrics_get_position (hb_font_t *font,
#ifndef HB_NO_VAR #ifndef HB_NO_VAR
/** /**
* hb_ot_metrics_get_variation: * hb_ot_metrics_get_variation:
* @font: * @font: an #hb_font_t object.
* @metrics_tag: * @metrics_tag: tag of metrics value you like to fetch.
* *
* Returns: * Fetches metrics value corresponding to @metrics_tag from @font with the
* current font variation settings applied.
*
* Returns: The requested metric value.
* *
* Since: 2.6.0 * Since: 2.6.0
**/ **/
@ -208,10 +211,13 @@ hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
/** /**
* hb_ot_metrics_get_x_variation: * hb_ot_metrics_get_x_variation:
* @font: * @font: an #hb_font_t object.
* @metrics_tag: * @metrics_tag: tag of metrics value you like to fetch.
* *
* Returns: * Fetches horizontal metrics value corresponding to @metrics_tag from @font
* with the current font variation settings applied.
*
* Returns: The requested metric value.
* *
* Since: 2.6.0 * Since: 2.6.0
**/ **/
@ -223,10 +229,13 @@ hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
/** /**
* hb_ot_metrics_get_y_variation: * hb_ot_metrics_get_y_variation:
* @font: * @font: an #hb_font_t object.
* @metrics_tag: * @metrics_tag: tag of metrics value you like to fetch.
* *
* Returns: * Fetches vertical metrics value corresponding to @metrics_tag from @font with
* the current font variation settings applied.
*
* Returns: The requested metric value.
* *
* Since: 2.6.0 * Since: 2.6.0
**/ **/

View File

@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif
@ -66,7 +66,8 @@ HB_BEGIN_DECLS
* @HB_OT_METRICS_TAG_UNDERLINE_SIZE: underline size. * @HB_OT_METRICS_TAG_UNDERLINE_SIZE: underline size.
* @HB_OT_METRICS_TAG_UNDERLINE_OFFSET: underline offset. * @HB_OT_METRICS_TAG_UNDERLINE_OFFSET: underline offset.
* *
* From https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags * Metric tags corresponding to [MVAR Value
* Tags](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags)
* *
* Since: 2.6.0 * Since: 2.6.0
**/ **/
@ -100,6 +101,7 @@ typedef enum {
HB_OT_METRICS_TAG_UNDERLINE_SIZE = HB_TAG ('u','n','d','s'), HB_OT_METRICS_TAG_UNDERLINE_SIZE = HB_TAG ('u','n','d','s'),
HB_OT_METRICS_TAG_UNDERLINE_OFFSET = HB_TAG ('u','n','d','o'), HB_OT_METRICS_TAG_UNDERLINE_OFFSET = HB_TAG ('u','n','d','o'),
/*< private >*/
_HB_OT_METRICS_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ _HB_OT_METRICS_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_metrics_tag_t; } hb_ot_metrics_tag_t;

View File

@ -46,7 +46,7 @@
/** /**
* hb_ot_name_list_names: * hb_ot_name_list_names:
* @face: font face. * @face: font face.
* @num_entries: (out) (allow-none): number of returned entries. * @num_entries: (out) (optional): number of returned entries.
* *
* Enumerates all available name IDs and language combinations. Returned * Enumerates all available name IDs and language combinations. Returned
* array is owned by the @face and should not be modified. It can be * array is owned by the @face and should not be modified. It can be
@ -150,7 +150,7 @@ hb_ot_name_get_utf (hb_face_t *face,
* @face: font face. * @face: font face.
* @name_id: OpenType name identifier to fetch. * @name_id: OpenType name identifier to fetch.
* @language: language to fetch the name for. * @language: language to fetch the name for.
* @text_size: (inout) (allow-none): input size of @text buffer, and output size of * @text_size: (inout) (optional): input size of @text buffer, and output size of
* text written to buffer. * text written to buffer.
* @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
* *
@ -177,7 +177,7 @@ hb_ot_name_get_utf8 (hb_face_t *face,
* @face: font face. * @face: font face.
* @name_id: OpenType name identifier to fetch. * @name_id: OpenType name identifier to fetch.
* @language: language to fetch the name for. * @language: language to fetch the name for.
* @text_size: (inout) (allow-none): input size of @text buffer, and output size of * @text_size: (inout) (optional): input size of @text buffer, and output size of
* text written to buffer. * text written to buffer.
* @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
* *
@ -203,7 +203,7 @@ hb_ot_name_get_utf16 (hb_face_t *face,
* @face: font face. * @face: font face.
* @name_id: OpenType name identifier to fetch. * @name_id: OpenType name identifier to fetch.
* @language: language to fetch the name for. * @language: language to fetch the name for.
* @text_size: (inout) (allow-none): input size of @text buffer, and output size of * @text_size: (inout) (optional): input size of @text buffer, and output size of
* text written to buffer. * text written to buffer.
* @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
* *

View File

@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif

View File

@ -177,15 +177,14 @@ struct OS2
if (!c->plan->glyphs_requested->is_empty ()) if (!c->plan->glyphs_requested->is_empty ())
{ {
hb_map_t unicode_glyphid_map; hb_map_t unicode_glyphid_map;
OT::cmap::accelerator_t cmap; OT::cmap::accelerator_t cmap;
cmap.init (c->plan->source); cmap.init (c->plan->source);
cmap.collect_mapping (&unicodes, &unicode_glyphid_map); cmap.collect_mapping (&unicodes, &unicode_glyphid_map);
cmap.fini (); cmap.fini ();
if (c->plan->unicodes->is_empty ()) unicodes.clear (); hb_set_set (&unicodes, c->plan->unicodes);
else hb_set_set (&unicodes, c->plan->unicodes);
+ unicode_glyphid_map.iter () + unicode_glyphid_map.iter ()
| hb_filter (c->plan->glyphs_requested, hb_second) | hb_filter (c->plan->glyphs_requested, hb_second)
| hb_map (hb_first) | hb_map (hb_first)

View File

@ -87,7 +87,6 @@ struct post
if (unlikely (!post_prime)) return_trace (false); if (unlikely (!post_prime)) return_trace (false);
serialize (c->serializer); serialize (c->serializer);
if (c->serializer->in_error () || c->serializer->ran_out_of_room) return_trace (false);
return_trace (true); return_trace (true);
} }

View File

@ -142,7 +142,7 @@
OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \ OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
) \ ) \
OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
/* ASSERT_STATIC_EXPR_ZERO (len(FromGlyphs) == len(ToGlyphs)) */ /* static_assert_expr (len(FromGlyphs) == len(ToGlyphs)) */
#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \ #define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
OT_SUBLOOKUP(Name, 1, \ OT_SUBLOOKUP(Name, 1, \
@ -151,7 +151,7 @@
OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \ OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
) \ ) \
OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \ OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
/* ASSERT_STATIC_EXPR_ZERO (len(FirstGlyphs) == len(LigatureSetOffsets)) */ /* static_assert_expr (len(FirstGlyphs) == len(LigatureSetOffsets)) */
#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \ #define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
OT_UARRAY(Name, OT_LIST(LigatureSetOffsets)) OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))

View File

@ -33,7 +33,7 @@
/* buffer var allocations */ /* buffer var allocations */
#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */ #define arabic_shaping_action() complex_var_u8_auxiliary() /* arabic shaping action */
#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0 #define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0

View File

@ -119,7 +119,7 @@ data_destroy_hangul (void *data)
#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu)) #define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu))
/* buffer var allocations */ /* buffer var allocations */
#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */ #define hangul_shaping_feature() complex_var_u8_auxiliary() /* hangul jamo shaping feature */
static bool static bool
is_zero_width_char (hb_font_t *font, is_zero_width_char (hb_font_t *font,
@ -205,7 +205,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
{ {
/* Tone mark follows a valid syllable; move it in front, unless it's zero width. */ /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */
buffer->unsafe_to_break_from_outbuffer (start, buffer->idx); buffer->unsafe_to_break_from_outbuffer (start, buffer->idx);
buffer->next_glyph (); if (unlikely (!buffer->next_glyph ())) break;
if (!is_zero_width_char (font, u)) if (!is_zero_width_char (font, u))
{ {
buffer->merge_out_clusters (start, end + 1); buffer->merge_out_clusters (start, end + 1);
@ -218,23 +218,25 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
else else
{ {
/* No valid syllable as base for tone mark; try to insert dotted circle. */ /* No valid syllable as base for tone mark; try to insert dotted circle. */
if (!(buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) && if (!(buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) &&
font->has_glyph (0x25CCu)) font->has_glyph (0x25CCu))
{ {
hb_codepoint_t chars[2]; hb_codepoint_t chars[2];
if (!is_zero_width_char (font, u)) { if (!is_zero_width_char (font, u))
{
chars[0] = u; chars[0] = u;
chars[1] = 0x25CCu; chars[1] = 0x25CCu;
} else { } else
{
chars[0] = 0x25CCu; chars[0] = 0x25CCu;
chars[1] = u; chars[1] = u;
} }
buffer->replace_glyphs (1, 2, chars); (void) buffer->replace_glyphs (1, 2, chars);
} }
else else
{ {
/* No dotted circle available in the font; just leave tone mark untouched. */ /* No dotted circle available in the font; just leave tone mark untouched. */
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
} }
start = end = buffer->out_len; start = end = buffer->out_len;
@ -271,9 +273,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex; hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex;
if (font->has_glyph (s)) if (font->has_glyph (s))
{ {
buffer->replace_glyphs (t ? 3 : 2, 1, &s); (void) buffer->replace_glyphs (t ? 3 : 2, 1, &s);
if (unlikely (!buffer->successful))
return;
end = start + 1; end = start + 1;
continue; continue;
} }
@ -285,17 +285,19 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
* Set jamo features on the individual glyphs, and advance past them. * Set jamo features on the individual glyphs, and advance past them.
*/ */
buffer->cur().hangul_shaping_feature() = LJMO; buffer->cur().hangul_shaping_feature() = LJMO;
buffer->next_glyph (); (void) buffer->next_glyph ();
buffer->cur().hangul_shaping_feature() = VJMO; buffer->cur().hangul_shaping_feature() = VJMO;
buffer->next_glyph (); (void) buffer->next_glyph ();
if (t) if (t)
{ {
buffer->cur().hangul_shaping_feature() = TJMO; buffer->cur().hangul_shaping_feature() = TJMO;
buffer->next_glyph (); (void) buffer->next_glyph ();
end = start + 3; end = start + 3;
} }
else else
end = start + 2; end = start + 2;
if (unlikely (!buffer->successful))
break;
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
buffer->merge_out_clusters (start, end); buffer->merge_out_clusters (start, end);
continue; continue;
@ -321,9 +323,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t new_s = s + new_tindex; hb_codepoint_t new_s = s + new_tindex;
if (font->has_glyph (new_s)) if (font->has_glyph (new_s))
{ {
buffer->replace_glyphs (2, 1, &new_s); (void) buffer->replace_glyphs (2, 1, &new_s);
if (unlikely (!buffer->successful))
return;
end = start + 1; end = start + 1;
continue; continue;
} }
@ -347,19 +347,18 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
(!tindex || font->has_glyph (decomposed[2]))) (!tindex || font->has_glyph (decomposed[2])))
{ {
unsigned int s_len = tindex ? 3 : 2; unsigned int s_len = tindex ? 3 : 2;
buffer->replace_glyphs (1, s_len, decomposed); (void) buffer->replace_glyphs (1, s_len, decomposed);
/* If we decomposed an LV because of a non-combining T following, /* If we decomposed an LV because of a non-combining T following,
* we want to include this T in the syllable. * we want to include this T in the syllable.
*/ */
if (has_glyph && !tindex) if (has_glyph && !tindex)
{ {
buffer->next_glyph (); (void) buffer->next_glyph ();
s_len++; s_len++;
} }
if (unlikely (!buffer->successful)) if (unlikely (!buffer->successful))
return; break;
/* We decomposed S: apply jamo features to the individual glyphs /* We decomposed S: apply jamo features to the individual glyphs
* that are now in buffer->out_info. * that are now in buffer->out_info.
@ -383,17 +382,15 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
if (has_glyph) if (has_glyph)
{ {
/* We didn't decompose the S, so just advance past it. */ /* We didn't decompose the S, so just advance past it and fall through. */
end = start + 1; end = start + 1;
buffer->next_glyph ();
continue;
} }
} }
/* Didn't find a recognizable syllable, so we leave end <= start; /* Didn't find a recognizable syllable, so we leave end <= start;
* this will prevent tone-mark reordering happening. * this will prevent tone-mark reordering happening.
*/ */
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
buffer->swap_buffers (); buffer->swap_buffers ();
} }

View File

@ -31,8 +31,37 @@
#include "hb.hh" #include "hb.hh"
enum indic_syllable_type_t {
indic_consonant_syllable,
indic_vowel_syllable,
indic_standalone_cluster,
indic_symbol_cluster,
indic_broken_cluster,
indic_non_indic_cluster,
};
#line 36 "hb-ot-shape-complex-indic-machine.hh"
#line 45 "hb-ot-shape-complex-indic-machine.hh"
#define indic_syllable_machine_ex_A 10u
#define indic_syllable_machine_ex_C 1u
#define indic_syllable_machine_ex_CM 17u
#define indic_syllable_machine_ex_CS 19u
#define indic_syllable_machine_ex_DOTTEDCIRCLE 12u
#define indic_syllable_machine_ex_H 4u
#define indic_syllable_machine_ex_M 7u
#define indic_syllable_machine_ex_N 3u
#define indic_syllable_machine_ex_PLACEHOLDER 11u
#define indic_syllable_machine_ex_RS 13u
#define indic_syllable_machine_ex_Ra 16u
#define indic_syllable_machine_ex_Repha 15u
#define indic_syllable_machine_ex_SM 8u
#define indic_syllable_machine_ex_Symbol 18u
#define indic_syllable_machine_ex_V 2u
#define indic_syllable_machine_ex_ZWJ 6u
#define indic_syllable_machine_ex_ZWNJ 5u
#line 65 "hb-ot-shape-complex-indic-machine.hh"
static const unsigned char _indic_syllable_machine_trans_keys[] = { static const unsigned char _indic_syllable_machine_trans_keys[] = {
8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u,
@ -384,18 +413,18 @@ static const int indic_syllable_machine_error = -1;
static const int indic_syllable_machine_en_main = 39; static const int indic_syllable_machine_en_main = 39;
#line 36 "hb-ot-shape-complex-indic-machine.rl" #line 46 "hb-ot-shape-complex-indic-machine.rl"
#line 93 "hb-ot-shape-complex-indic-machine.rl" #line 102 "hb-ot-shape-complex-indic-machine.rl"
#define found_syllable(syllable_type) \ #define found_syllable(syllable_type) \
HB_STMT_START { \ HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \ for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \ syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END } HB_STMT_END
@ -407,7 +436,7 @@ find_syllables_indic (hb_buffer_t *buffer)
int cs; int cs;
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
#line 411 "hb-ot-shape-complex-indic-machine.hh" #line 440 "hb-ot-shape-complex-indic-machine.hh"
{ {
cs = indic_syllable_machine_start; cs = indic_syllable_machine_start;
ts = 0; ts = 0;
@ -415,7 +444,7 @@ find_syllables_indic (hb_buffer_t *buffer)
act = 0; act = 0;
} }
#line 113 "hb-ot-shape-complex-indic-machine.rl" #line 122 "hb-ot-shape-complex-indic-machine.rl"
p = 0; p = 0;
@ -423,7 +452,7 @@ find_syllables_indic (hb_buffer_t *buffer)
unsigned int syllable_serial = 1; unsigned int syllable_serial = 1;
#line 427 "hb-ot-shape-complex-indic-machine.hh" #line 456 "hb-ot-shape-complex-indic-machine.hh"
{ {
int _slen; int _slen;
int _trans; int _trans;
@ -437,7 +466,7 @@ _resume:
#line 1 "NONE" #line 1 "NONE"
{ts = p;} {ts = p;}
break; break;
#line 441 "hb-ot-shape-complex-indic-machine.hh" #line 470 "hb-ot-shape-complex-indic-machine.hh"
} }
_keys = _indic_syllable_machine_trans_keys + (cs<<1); _keys = _indic_syllable_machine_trans_keys + (cs<<1);
@ -460,64 +489,64 @@ _eof_trans:
{te = p+1;} {te = p+1;}
break; break;
case 11: case 11:
#line 89 "hb-ot-shape-complex-indic-machine.rl" #line 98 "hb-ot-shape-complex-indic-machine.rl"
{te = p+1;{ found_syllable (non_indic_cluster); }} {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
break; break;
case 13: case 13:
#line 84 "hb-ot-shape-complex-indic-machine.rl" #line 93 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }} {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
break; break;
case 14: case 14:
#line 85 "hb-ot-shape-complex-indic-machine.rl" #line 94 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (vowel_syllable); }} {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
break; break;
case 17: case 17:
#line 86 "hb-ot-shape-complex-indic-machine.rl" #line 95 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (standalone_cluster); }} {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
break; break;
case 19: case 19:
#line 87 "hb-ot-shape-complex-indic-machine.rl" #line 96 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (symbol_cluster); }} {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
break; break;
case 15: case 15:
#line 88 "hb-ot-shape-complex-indic-machine.rl" #line 97 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }} {te = p;p--;{ found_syllable (indic_broken_cluster); }}
break; break;
case 16: case 16:
#line 89 "hb-ot-shape-complex-indic-machine.rl" #line 98 "hb-ot-shape-complex-indic-machine.rl"
{te = p;p--;{ found_syllable (non_indic_cluster); }} {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
break; break;
case 1: case 1:
#line 84 "hb-ot-shape-complex-indic-machine.rl" #line 93 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (consonant_syllable); }} {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
break; break;
case 3: case 3:
#line 85 "hb-ot-shape-complex-indic-machine.rl" #line 94 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (vowel_syllable); }} {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
break; break;
case 7: case 7:
#line 86 "hb-ot-shape-complex-indic-machine.rl" #line 95 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (standalone_cluster); }} {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
break; break;
case 8: case 8:
#line 87 "hb-ot-shape-complex-indic-machine.rl" #line 96 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (symbol_cluster); }} {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
break; break;
case 4: case 4:
#line 88 "hb-ot-shape-complex-indic-machine.rl" #line 97 "hb-ot-shape-complex-indic-machine.rl"
{{p = ((te))-1;}{ found_syllable (broken_cluster); }} {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); }}
break; break;
case 6: case 6:
#line 1 "NONE" #line 1 "NONE"
{ switch( act ) { { switch( act ) {
case 1: case 1:
{{p = ((te))-1;} found_syllable (consonant_syllable); } {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
break; break;
case 5: case 5:
{{p = ((te))-1;} found_syllable (broken_cluster); } {{p = ((te))-1;} found_syllable (indic_broken_cluster); }
break; break;
case 6: case 6:
{{p = ((te))-1;} found_syllable (non_indic_cluster); } {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
break; break;
} }
} }
@ -525,22 +554,22 @@ _eof_trans:
case 18: case 18:
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}
#line 84 "hb-ot-shape-complex-indic-machine.rl" #line 93 "hb-ot-shape-complex-indic-machine.rl"
{act = 1;} {act = 1;}
break; break;
case 5: case 5:
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}
#line 88 "hb-ot-shape-complex-indic-machine.rl" #line 97 "hb-ot-shape-complex-indic-machine.rl"
{act = 5;} {act = 5;}
break; break;
case 12: case 12:
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}
#line 89 "hb-ot-shape-complex-indic-machine.rl" #line 98 "hb-ot-shape-complex-indic-machine.rl"
{act = 6;} {act = 6;}
break; break;
#line 544 "hb-ot-shape-complex-indic-machine.hh" #line 573 "hb-ot-shape-complex-indic-machine.hh"
} }
_again: _again:
@ -549,7 +578,7 @@ _again:
#line 1 "NONE" #line 1 "NONE"
{ts = 0;} {ts = 0;}
break; break;
#line 553 "hb-ot-shape-complex-indic-machine.hh" #line 582 "hb-ot-shape-complex-indic-machine.hh"
} }
if ( ++p != pe ) if ( ++p != pe )
@ -565,7 +594,7 @@ _again:
} }
#line 121 "hb-ot-shape-complex-indic-machine.rl" #line 130 "hb-ot-shape-complex-indic-machine.rl"
} }

View File

@ -82,7 +82,7 @@
#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M) #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { static const uint16_t indic_table[] = {
#define indic_offset_0x0028u 0 #define indic_offset_0x0028u 0
@ -404,7 +404,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {
}; /* Table items: 1792; occupancy: 70% */ }; /* Table items: 1792; occupancy: 70% */
INDIC_TABLE_ELEMENT_TYPE uint16_t
hb_indic_get_categories (hb_codepoint_t u) hb_indic_get_categories (hb_codepoint_t u)
{ {
switch (u >> 12) switch (u >> 12)

View File

@ -29,6 +29,7 @@
#ifndef HB_NO_OT_SHAPE #ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-complex-indic.hh" #include "hb-ot-shape-complex-indic.hh"
#include "hb-ot-shape-complex-indic-machine.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh" #include "hb-ot-shape-complex-vowel-constraints.hh"
#include "hb-ot-layout.hh" #include "hb-ot-layout.hh"
@ -337,19 +338,6 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan,
return POS_BASE_C; return POS_BASE_C;
} }
enum indic_syllable_type_t {
indic_consonant_syllable,
indic_vowel_syllable,
indic_standalone_cluster,
indic_symbol_cluster,
indic_broken_cluster,
indic_non_indic_cluster,
};
#include "hb-ot-shape-complex-indic-machine.hh"
static void static void
setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer, hb_buffer_t *buffer,
@ -764,7 +752,28 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* We could use buffer->sort() for this, if there was no special * We could use buffer->sort() for this, if there was no special
* reordering of pre-base stuff happening later... * reordering of pre-base stuff happening later...
* We don't want to merge_clusters all of that, which buffer->sort() * We don't want to merge_clusters all of that, which buffer->sort()
* would. * would. Here's a concrete example:
*
* Assume there's a pre-base consonant and explicit Halant before base,
* followed by a prebase-reordering (left) Matra:
*
* C,H,ZWNJ,B,M
*
* At this point in reordering we would have:
*
* M,C,H,ZWNJ,B
*
* whereas in final reordering we will bring the Matra closer to Base:
*
* C,H,ZWNJ,M,B
*
* That's why we don't want to merge-clusters anything before the Base
* at this point. But if something moved from after Base to before it,
* we should merge clusters from base to them. In final-reordering, we
* only move things around before base, and merge-clusters up to base.
* These two merge-clusters from the two sides of base will interlock
* to merge things correctly. See:
* https://github.com/harfbuzz/harfbuzz/issues/2272
*/ */
if (indic_plan->is_old_spec || end - start > 127) if (indic_plan->is_old_spec || end - start > 127)
buffer->merge_clusters (base, end); buffer->merge_clusters (base, end);
@ -774,17 +783,18 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
for (unsigned int i = base; i < end; i++) for (unsigned int i = base; i < end; i++)
if (info[i].syllable() != 255) if (info[i].syllable() != 255)
{ {
unsigned int min = i;
unsigned int max = i; unsigned int max = i;
unsigned int j = start + info[i].syllable(); unsigned int j = start + info[i].syllable();
while (j != i) while (j != i)
{ {
min = hb_min (min, j);
max = hb_max (max, j); max = hb_max (max, j);
unsigned int next = start + info[j].syllable(); unsigned int next = start + info[j].syllable();
info[j].syllable() = 255; /* So we don't process j later again. */ info[j].syllable() = 255; /* So we don't process j later again. */
j = next; j = next;
} }
if (i != max) buffer->merge_clusters (hb_max (base, min), max + 1);
buffer->merge_clusters (i, max + 1);
} }
} }
@ -938,69 +948,6 @@ initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
} }
} }
static inline void
insert_dotted_circles_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
/* Note: This loop is extra overhead, but should not be measurable.
* TODO Use a buffer scratch flag to remove the loop. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == indic_broken_cluster)
{
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CCu;
set_indic_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
indic_syllable_type_t syllable_type = (indic_syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == indic_broken_cluster))
{
last_syllable = syllable;
hb_glyph_info_t ginfo = dottedcircle;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().indic_category() == OT_Repha)
buffer->next_glyph ();
buffer->output_info (ginfo);
}
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
static void static void
initial_reordering_indic (const hb_ot_shape_plan_t *plan, initial_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font, hb_font_t *font,
@ -1008,11 +955,16 @@ initial_reordering_indic (const hb_ot_shape_plan_t *plan,
{ {
if (!buffer->message (font, "start reordering indic initial")) if (!buffer->message (font, "start reordering indic initial"))
return; return;
update_consonant_positions_indic (plan, font, buffer); update_consonant_positions_indic (plan, font, buffer);
insert_dotted_circles_indic (plan, font, buffer); hb_syllabic_insert_dotted_circles (font, buffer,
indic_broken_cluster,
OT_DOTTEDCIRCLE,
OT_Repha);
foreach_syllable (buffer, start, end) foreach_syllable (buffer, start, end)
initial_reordering_syllable_indic (plan, font->face, buffer, start, end); initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
(void) buffer->message (font, "end reordering indic initial"); (void) buffer->message (font, "end reordering indic initial");
} }

View File

@ -29,16 +29,14 @@
#include "hb.hh" #include "hb.hh"
#include "hb-ot-shape-complex.hh" #include "hb-ot-shape-complex-syllabic.hh"
/* buffer var allocations */ /* buffer var allocations */
#define indic_category() complex_var_u8_0() /* indic_category_t */ #define indic_category() complex_var_u8_category() /* indic_category_t */
#define indic_position() complex_var_u8_1() /* indic_position_t */ #define indic_position() complex_var_u8_auxiliary() /* indic_position_t */
#define INDIC_TABLE_ELEMENT_TYPE uint16_t
/* Cateories used in the OpenType spec: /* Cateories used in the OpenType spec:
* https://docs.microsoft.com/en-us/typography/script-development/devanagari * https://docs.microsoft.com/en-us/typography/script-development/devanagari
*/ */
@ -177,7 +175,7 @@ enum indic_matra_category_t {
#define INDIC_COMBINE_CATEGORIES(S,M) \ #define INDIC_COMBINE_CATEGORIES(S,M) \
( \ ( \
ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ static_assert_expr (S < 255 && M < 255) + \
( S | \ ( S | \
( \ ( \
( \ ( \
@ -194,7 +192,7 @@ enum indic_matra_category_t {
) \ ) \
) )
HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE HB_INTERNAL uint16_t
hb_indic_get_categories (hb_codepoint_t u); hb_indic_get_categories (hb_codepoint_t u);
@ -307,17 +305,12 @@ static const hb_codepoint_t ra_chars[] = {
0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */ 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */ 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
0x179Au, /* Khmer */
}; };
static inline bool static inline bool
is_ra (hb_codepoint_t u) is_ra (hb_codepoint_t u)
{ {
for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++) return hb_array (ra_chars).lfind (u);
if (u == ra_chars[i])
return true;
return false;
} }
static inline void static inline void
@ -325,7 +318,7 @@ set_indic_properties (hb_glyph_info_t &info)
{ {
hb_codepoint_t u = info.codepoint; hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u); unsigned int type = hb_indic_get_categories (u);
indic_category_t cat = (indic_category_t) (type & 0x7Fu); indic_category_t cat = (indic_category_t) (type & 0xFFu);
indic_position_t pos = (indic_position_t) (type >> 8); indic_position_t pos = (indic_position_t) (type >> 8);
@ -370,6 +363,7 @@ set_indic_properties (hb_glyph_info_t &info)
else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N; else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N;
else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */ else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
else if (unlikely (u == 0x0B55u)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/2849 */
else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */ else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */ else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */

View File

@ -1,211 +1,179 @@
#line 1 "hb-ot-shape-complex-khmer-machine.rl" #line 1 "hb-ot-shape-complex-khmer-machine.rl"
/* /*
* Copyright © 2011,2012 Google, Inc. * Copyright © 2011,2012 Google, Inc.
* *
* This is part of HarfBuzz, a text shaping library. * This is part of HarfBuzz, a text shaping library.
* *
* Permission is hereby granted, without written agreement and without * Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this * license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the * software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in * above copyright notice and the following two paragraphs appear in
* all copies of this software. * all copies of this software.
* *
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE. * DAMAGE.
* *
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
* *
* Google Author(s): Behdad Esfahbod * Google Author(s): Behdad Esfahbod
*/ */
#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
#include "hb.hh" #include "hb.hh"
enum khmer_syllable_type_t {
#line 36 "hb-ot-shape-complex-khmer-machine.hh" khmer_consonant_syllable,
static const unsigned char _khmer_syllable_machine_trans_keys[] = { khmer_broken_cluster,
5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, khmer_non_khmer_cluster,
5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u,
5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u,
22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u,
5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u,
0
}; };
static const char _khmer_syllable_machine_key_spans[] = {
22, 17, 22, 17, 16, 17, 22, 17, #line 41 "hb-ot-shape-complex-khmer-machine.hh"
22, 17, 17, 22, 17, 16, 17, 22, #define khmer_syllable_machine_ex_C 1u
17, 22, 17, 22, 29, 25, 25, 25, #define khmer_syllable_machine_ex_Coeng 14u
1, 18, 25, 25, 25, 16, 22, 25, #define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
25, 1, 18, 25, 25, 16, 25, 25 #define khmer_syllable_machine_ex_PLACEHOLDER 11u
#define khmer_syllable_machine_ex_Ra 16u
#define khmer_syllable_machine_ex_Robatic 20u
#define khmer_syllable_machine_ex_V 2u
#define khmer_syllable_machine_ex_VAbv 26u
#define khmer_syllable_machine_ex_VBlw 27u
#define khmer_syllable_machine_ex_VPre 28u
#define khmer_syllable_machine_ex_VPst 29u
#define khmer_syllable_machine_ex_Xgroup 21u
#define khmer_syllable_machine_ex_Ygroup 22u
#define khmer_syllable_machine_ex_ZWJ 6u
#define khmer_syllable_machine_ex_ZWNJ 5u
#line 59 "hb-ot-shape-complex-khmer-machine.hh"
static const unsigned char _khmer_syllable_machine_trans_keys[] = {
2u, 8u, 2u, 6u, 2u, 8u, 2u, 6u,
0u, 0u, 2u, 6u, 2u, 8u, 2u, 6u,
2u, 8u, 2u, 6u, 2u, 6u, 2u, 8u,
2u, 6u, 0u, 0u, 2u, 6u, 2u, 8u,
2u, 6u, 2u, 8u, 2u, 6u, 2u, 8u,
0u, 11u, 2u, 11u, 2u, 11u, 2u, 11u,
7u, 7u, 2u, 7u, 2u, 11u, 2u, 11u,
2u, 11u, 0u, 0u, 2u, 8u, 2u, 11u,
2u, 11u, 7u, 7u, 2u, 7u, 2u, 11u,
2u, 11u, 0u, 0u, 2u, 11u, 2u, 11u,
0u
};
static const signed char _khmer_syllable_machine_char_class[] = {
0, 0, 1, 1, 2, 2, 1, 1,
1, 1, 3, 3, 1, 4, 1, 0,
1, 1, 1, 5, 6, 7, 1, 1,
1, 8, 9, 10, 11, 0
}; };
static const short _khmer_syllable_machine_index_offsets[] = { static const short _khmer_syllable_machine_index_offsets[] = {
0, 23, 41, 64, 82, 99, 117, 140, 0, 7, 12, 19, 24, 25, 30, 37,
158, 181, 199, 217, 240, 258, 275, 293, 42, 49, 54, 59, 66, 71, 72, 77,
316, 334, 357, 375, 398, 428, 454, 480, 84, 89, 96, 101, 108, 120, 130, 140,
506, 508, 527, 553, 579, 605, 622, 645, 150, 151, 157, 167, 177, 187, 188, 195,
671, 697, 699, 718, 744, 770, 787, 813 205, 215, 216, 222, 232, 242, 243, 253,
0
}; };
static const char _khmer_syllable_machine_indicies[] = { static const signed char _khmer_syllable_machine_indicies[] = {
1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 3, 0, 4, 1,
0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 1, 0, 0, 0,
3, 0, 0, 0, 0, 4, 0, 1, 3, 0, 4, 5, 0, 0, 0, 4,
1, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 8, 9, 0,
0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 10, 0, 4, 9, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0, 0, 10, 11, 0, 0, 0, 12, 0,
0, 0, 0, 0, 0, 0, 0, 0, 4, 11, 0, 0, 0, 12, 14, 13,
0, 3, 0, 0, 0, 0, 4, 0, 13, 13, 15, 14, 16, 16, 16, 15,
5, 5, 0, 0, 0, 0, 0, 0, 16, 17, 18, 16, 16, 16, 17, 19,
0, 0, 0, 0, 0, 0, 0, 0, 20, 16, 16, 16, 21, 22, 16, 16,
4, 0, 6, 6, 0, 0, 0, 0, 16, 23, 16, 17, 22, 16, 16, 16,
0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 16, 16, 16, 25, 16, 17,
0, 6, 0, 7, 7, 0, 0, 0, 24, 16, 16, 16, 25, 14, 16, 16,
0, 0, 0, 0, 0, 0, 0, 0, 26, 15, 16, 17, 29, 28, 30, 2,
0, 0, 0, 8, 0, 9, 9, 0, 31, 28, 15, 19, 17, 23, 25, 21,
0, 0, 0, 0, 0, 0, 0, 0, 33, 32, 34, 2, 3, 6, 4, 10,
0, 0, 0, 0, 0, 10, 0, 0, 12, 8, 35, 32, 36, 32, 3, 6,
0, 0, 4, 0, 9, 9, 0, 0, 4, 10, 12, 8, 5, 32, 36, 32,
0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 32, 32, 32, 8, 6, 7,
0, 0, 0, 0, 10, 0, 11, 11, 32, 36, 32, 8, 6, 37, 32, 36,
0, 0, 0, 0, 0, 0, 0, 0, 32, 10, 6, 4, 32, 32, 8, 38,
0, 0, 0, 0, 0, 0, 12, 0, 32, 36, 32, 12, 6, 4, 10, 32,
0, 0, 0, 4, 0, 11, 11, 0, 8, 35, 32, 34, 32, 3, 6, 4,
0, 0, 0, 0, 0, 0, 0, 0, 10, 12, 8, 29, 14, 39, 39, 39,
0, 0, 0, 0, 0, 12, 0, 14, 15, 39, 17, 41, 40, 42, 40, 15,
14, 13, 13, 13, 13, 13, 13, 13, 19, 17, 23, 25, 21, 18, 40, 42,
13, 13, 13, 13, 13, 13, 13, 15, 40, 17, 19, 40, 40, 40, 21, 19,
13, 14, 14, 16, 16, 16, 16, 16, 20, 40, 42, 40, 21, 19, 43, 40,
16, 16, 16, 16, 16, 16, 16, 16, 42, 40, 23, 19, 17, 40, 40, 21,
16, 15, 16, 16, 16, 16, 17, 16, 44, 40, 42, 40, 25, 19, 17, 23,
18, 18, 16, 16, 16, 16, 16, 16, 40, 21, 45, 46, 40, 31, 26, 15,
16, 16, 16, 16, 16, 16, 16, 16, 19, 17, 23, 25, 21, 41, 40, 31,
17, 16, 19, 19, 16, 16, 16, 16, 40, 15, 19, 17, 23, 25, 21, 0
16, 16, 16, 16, 16, 16, 16, 16,
16, 19, 16, 20, 20, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 21, 16, 22, 22, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 23, 16, 16,
16, 16, 17, 16, 22, 22, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 23, 16, 24, 24,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 25, 16,
16, 16, 16, 17, 16, 24, 24, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 25, 16, 14,
14, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 26, 15,
16, 16, 16, 16, 17, 16, 28, 28,
27, 27, 29, 29, 27, 27, 27, 27,
2, 2, 27, 30, 27, 28, 27, 27,
27, 27, 15, 19, 27, 27, 27, 17,
23, 25, 21, 27, 32, 32, 31, 31,
31, 31, 31, 31, 31, 33, 31, 31,
31, 31, 31, 2, 3, 6, 31, 31,
31, 4, 10, 12, 8, 31, 34, 34,
31, 31, 31, 31, 31, 31, 31, 35,
31, 31, 31, 31, 31, 31, 3, 6,
31, 31, 31, 4, 10, 12, 8, 31,
5, 5, 31, 31, 31, 31, 31, 31,
31, 35, 31, 31, 31, 31, 31, 31,
4, 6, 31, 31, 31, 31, 31, 31,
8, 31, 6, 31, 7, 7, 31, 31,
31, 31, 31, 31, 31, 35, 31, 31,
31, 31, 31, 31, 8, 6, 31, 36,
36, 31, 31, 31, 31, 31, 31, 31,
35, 31, 31, 31, 31, 31, 31, 10,
6, 31, 31, 31, 4, 31, 31, 8,
31, 37, 37, 31, 31, 31, 31, 31,
31, 31, 35, 31, 31, 31, 31, 31,
31, 12, 6, 31, 31, 31, 4, 10,
31, 8, 31, 34, 34, 31, 31, 31,
31, 31, 31, 31, 33, 31, 31, 31,
31, 31, 31, 3, 6, 31, 31, 31,
4, 10, 12, 8, 31, 28, 28, 31,
31, 31, 31, 31, 31, 31, 31, 31,
31, 31, 31, 31, 28, 31, 14, 14,
38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 15, 38,
38, 38, 38, 17, 38, 40, 40, 39,
39, 39, 39, 39, 39, 39, 41, 39,
39, 39, 39, 39, 39, 15, 19, 39,
39, 39, 17, 23, 25, 21, 39, 18,
18, 39, 39, 39, 39, 39, 39, 39,
41, 39, 39, 39, 39, 39, 39, 17,
19, 39, 39, 39, 39, 39, 39, 21,
39, 19, 39, 20, 20, 39, 39, 39,
39, 39, 39, 39, 41, 39, 39, 39,
39, 39, 39, 21, 19, 39, 42, 42,
39, 39, 39, 39, 39, 39, 39, 41,
39, 39, 39, 39, 39, 39, 23, 19,
39, 39, 39, 17, 39, 39, 21, 39,
43, 43, 39, 39, 39, 39, 39, 39,
39, 41, 39, 39, 39, 39, 39, 39,
25, 19, 39, 39, 39, 17, 23, 39,
21, 39, 44, 44, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39,
39, 44, 39, 45, 45, 39, 39, 39,
39, 39, 39, 39, 30, 39, 39, 39,
39, 39, 26, 15, 19, 39, 39, 39,
17, 23, 25, 21, 39, 40, 40, 39,
39, 39, 39, 39, 39, 39, 30, 39,
39, 39, 39, 39, 39, 15, 19, 39,
39, 39, 17, 23, 25, 21, 39, 0
}; };
static const char _khmer_syllable_machine_trans_targs[] = { static const signed char _khmer_syllable_machine_index_defaults[] = {
20, 1, 28, 22, 23, 3, 24, 5, 0, 0, 0, 0, 0, 0, 0, 0,
25, 7, 26, 9, 27, 20, 10, 31, 0, 0, 13, 16, 16, 16, 16, 16,
20, 32, 12, 33, 14, 34, 16, 35, 16, 16, 16, 16, 28, 32, 32, 32,
18, 36, 39, 20, 21, 30, 37, 20, 32, 32, 32, 32, 32, 32, 39, 40,
0, 29, 2, 4, 6, 8, 20, 20, 40, 40, 40, 40, 40, 40, 40, 40,
11, 13, 15, 17, 38, 19 0
}; };
static const char _khmer_syllable_machine_trans_actions[] = { static const signed char _khmer_syllable_machine_cond_targs[] = {
1, 0, 2, 2, 2, 0, 0, 0, 20, 1, 28, 22, 23, 3, 24, 5,
2, 0, 2, 0, 2, 3, 0, 4, 25, 7, 26, 9, 27, 20, 10, 31,
5, 2, 0, 0, 0, 2, 0, 2, 20, 32, 12, 33, 14, 34, 16, 35,
0, 2, 4, 8, 2, 9, 0, 10, 18, 36, 39, 20, 20, 21, 30, 37,
0, 0, 0, 0, 0, 0, 11, 12, 20, 0, 29, 2, 4, 6, 8, 20,
0, 0, 0, 0, 4, 0 20, 11, 13, 15, 17, 38, 19, 0
}; };
static const char _khmer_syllable_machine_to_state_actions[] = { static const signed char _khmer_syllable_machine_cond_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 3, 0, 4,
0, 0, 0, 0, 6, 0, 0, 0, 5, 2, 0, 0, 0, 2, 0, 2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 8, 2, 9, 0,
0, 0, 0, 0, 0, 0, 0, 0 10, 0, 0, 0, 0, 0, 0, 11,
12, 0, 0, 0, 0, 4, 0, 0
}; };
static const char _khmer_syllable_machine_from_state_actions[] = { static const signed char _khmer_syllable_machine_to_state_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0,
0
}; };
static const unsigned char _khmer_syllable_machine_eof_trans[] = { static const signed char _khmer_syllable_machine_from_state_actions[] = {
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 14, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0,
17, 17, 17, 17, 0, 32, 32, 32, 0, 0, 0, 0, 7, 0, 0, 0,
32, 32, 32, 32, 32, 32, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0,
40, 40, 40, 40, 40, 40, 40, 40 0, 0, 0, 0, 0, 0, 0, 0,
0
};
static const signed char _khmer_syllable_machine_eof_trans[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 14, 17, 17, 17, 17, 17,
17, 17, 17, 17, 28, 33, 33, 33,
33, 33, 33, 33, 33, 33, 40, 41,
41, 41, 41, 41, 41, 41, 41, 41,
0
}; };
static const int khmer_syllable_machine_start = 20; static const int khmer_syllable_machine_start = 20;
@ -215,156 +183,271 @@ static const int khmer_syllable_machine_error = -1;
static const int khmer_syllable_machine_en_main = 20; static const int khmer_syllable_machine_en_main = 20;
#line 36 "hb-ot-shape-complex-khmer-machine.rl" #line 43 "hb-ot-shape-complex-khmer-machine.rl"
#line 80 "hb-ot-shape-complex-khmer-machine.rl" #line 86 "hb-ot-shape-complex-khmer-machine.rl"
#define found_syllable(syllable_type) \ #define found_syllable(syllable_type) \
HB_STMT_START { \ HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \ for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \ syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END } HB_STMT_END
static void static void
find_syllables_khmer (hb_buffer_t *buffer) find_syllables_khmer (hb_buffer_t *buffer)
{ {
unsigned int p, pe, eof, ts, te, act HB_UNUSED; unsigned int p, pe, eof, ts, te, act HB_UNUSED;
int cs; int cs;
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
#line 242 "hb-ot-shape-complex-khmer-machine.hh" #line 210 "hb-ot-shape-complex-khmer-machine.hh"
{ {
cs = khmer_syllable_machine_start; cs = (int)khmer_syllable_machine_start;
ts = 0; ts = 0;
te = 0; te = 0;
act = 0; act = 0;
} }
#line 100 "hb-ot-shape-complex-khmer-machine.rl" #line 106 "hb-ot-shape-complex-khmer-machine.rl"
p = 0; p = 0;
pe = eof = buffer->len; pe = eof = buffer->len;
unsigned int syllable_serial = 1; unsigned int syllable_serial = 1;
#line 258 "hb-ot-shape-complex-khmer-machine.hh" #line 226 "hb-ot-shape-complex-khmer-machine.hh"
{ {
int _slen; unsigned int _trans = 0;
int _trans; const unsigned char * _keys;
const unsigned char *_keys; const signed char * _inds;
const char *_inds; int _ic;
if ( p == pe ) _resume: {}
goto _test_eof; if ( p == pe && p != eof )
_resume: goto _out;
switch ( _khmer_syllable_machine_from_state_actions[cs] ) { switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
case 7: case 7: {
{
#line 1 "NONE" #line 1 "NONE"
{ts = p;} {ts = p;}}
break;
#line 272 "hb-ot-shape-complex-khmer-machine.hh" #line 241 "hb-ot-shape-complex-khmer-machine.hh"
}
_keys = _khmer_syllable_machine_trans_keys + (cs<<1); break;
_inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs]; }
}
_slen = _khmer_syllable_machine_key_spans[cs];
_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) && if ( p == eof ) {
( info[p].khmer_category()) <= _keys[1] ? if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
( info[p].khmer_category()) - _keys[0] : _slen ]; _trans = (unsigned int)_khmer_syllable_machine_eof_trans[cs] - 1;
}
_eof_trans: }
cs = _khmer_syllable_machine_trans_targs[_trans]; else {
_keys = ( _khmer_syllable_machine_trans_keys + ((cs<<1)));
if ( _khmer_syllable_machine_trans_actions[_trans] == 0 ) _inds = ( _khmer_syllable_machine_indicies + (_khmer_syllable_machine_index_offsets[cs]));
goto _again;
if ( (info[p].khmer_category()) <= 29 && (info[p].khmer_category()) >= 1 ) {
switch ( _khmer_syllable_machine_trans_actions[_trans] ) { _ic = (int)_khmer_syllable_machine_char_class[(int)(info[p].khmer_category()) - 1];
case 2: if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
_trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) ));
else
_trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
}
else {
_trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
}
}
cs = (int)_khmer_syllable_machine_cond_targs[_trans];
if ( _khmer_syllable_machine_cond_actions[_trans] != 0 ) {
switch ( _khmer_syllable_machine_cond_actions[_trans] ) {
case 2: {
{
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}}
break;
case 8: #line 279 "hb-ot-shape-complex-khmer-machine.hh"
#line 76 "hb-ot-shape-complex-khmer-machine.rl"
{te = p+1;{ found_syllable (non_khmer_cluster); }}
break; break;
case 10: }
#line 74 "hb-ot-shape-complex-khmer-machine.rl" case 8: {
{te = p;p--;{ found_syllable (consonant_syllable); }} {
break; #line 82 "hb-ot-shape-complex-khmer-machine.rl"
case 12: {te = p+1;{
#line 75 "hb-ot-shape-complex-khmer-machine.rl" #line 82 "hb-ot-shape-complex-khmer-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }} found_syllable (khmer_non_khmer_cluster); }
break; }}
case 11:
#line 76 "hb-ot-shape-complex-khmer-machine.rl" #line 292 "hb-ot-shape-complex-khmer-machine.hh"
{te = p;p--;{ found_syllable (non_khmer_cluster); }}
break;
case 1: break;
#line 74 "hb-ot-shape-complex-khmer-machine.rl" }
{{p = ((te))-1;}{ found_syllable (consonant_syllable); }} case 10: {
break; {
case 5: #line 80 "hb-ot-shape-complex-khmer-machine.rl"
#line 75 "hb-ot-shape-complex-khmer-machine.rl" {te = p;p = p - 1;{
{{p = ((te))-1;}{ found_syllable (broken_cluster); }} #line 80 "hb-ot-shape-complex-khmer-machine.rl"
break; found_syllable (khmer_consonant_syllable); }
case 3: }}
#line 305 "hb-ot-shape-complex-khmer-machine.hh"
break;
}
case 12: {
{
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
{te = p;p = p - 1;{
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
found_syllable (khmer_broken_cluster); }
}}
#line 318 "hb-ot-shape-complex-khmer-machine.hh"
break;
}
case 11: {
{
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
{te = p;p = p - 1;{
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
found_syllable (khmer_non_khmer_cluster); }
}}
#line 331 "hb-ot-shape-complex-khmer-machine.hh"
break;
}
case 1: {
{
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
{p = ((te))-1;
{
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
found_syllable (khmer_consonant_syllable); }
}}
#line 345 "hb-ot-shape-complex-khmer-machine.hh"
break;
}
case 5: {
{
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
{p = ((te))-1;
{
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
found_syllable (khmer_broken_cluster); }
}}
#line 359 "hb-ot-shape-complex-khmer-machine.hh"
break;
}
case 3: {
{
#line 1 "NONE" #line 1 "NONE"
{ switch( act ) { {switch( act ) {
case 2: case 2: {
{{p = ((te))-1;} found_syllable (broken_cluster); } p = ((te))-1;
break; {
case 3: #line 81 "hb-ot-shape-complex-khmer-machine.rl"
{{p = ((te))-1;} found_syllable (non_khmer_cluster); } found_syllable (khmer_broken_cluster); }
break; break;
} }
} case 3: {
break; p = ((te))-1;
case 4: {
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
found_syllable (khmer_non_khmer_cluster); }
break;
}
}}
}
#line 385 "hb-ot-shape-complex-khmer-machine.hh"
break;
}
case 4: {
{
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}}
#line 75 "hb-ot-shape-complex-khmer-machine.rl"
{act = 2;} #line 395 "hb-ot-shape-complex-khmer-machine.hh"
break;
case 9: {
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
{act = 2;}}
#line 401 "hb-ot-shape-complex-khmer-machine.hh"
break;
}
case 9: {
{
#line 1 "NONE" #line 1 "NONE"
{te = p+1;} {te = p+1;}}
#line 76 "hb-ot-shape-complex-khmer-machine.rl"
{act = 3;} #line 411 "hb-ot-shape-complex-khmer-machine.hh"
break;
#line 342 "hb-ot-shape-complex-khmer-machine.hh" {
} #line 82 "hb-ot-shape-complex-khmer-machine.rl"
{act = 3;}}
_again:
switch ( _khmer_syllable_machine_to_state_actions[cs] ) { #line 417 "hb-ot-shape-complex-khmer-machine.hh"
case 6:
break;
}
}
}
if ( p == eof ) {
if ( cs >= 20 )
goto _out;
}
else {
switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
case 6: {
{
#line 1 "NONE" #line 1 "NONE"
{ts = 0;} {ts = 0;}}
break;
#line 351 "hb-ot-shape-complex-khmer-machine.hh" #line 437 "hb-ot-shape-complex-khmer-machine.hh"
break;
}
}
p += 1;
goto _resume;
}
_out: {}
} }
if ( ++p != pe ) #line 114 "hb-ot-shape-complex-khmer-machine.rl"
goto _resume;
_test_eof: {}
if ( p == eof )
{
if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
_trans = _khmer_syllable_machine_eof_trans[cs] - 1;
goto _eof_trans;
}
}
}
#line 108 "hb-ot-shape-complex-khmer-machine.rl"
} }
#undef found_syllable #undef found_syllable

View File

@ -1,113 +0,0 @@
/*
* Copyright © 2011,2012 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
#include "hb.hh"
%%{
machine khmer_syllable_machine;
alphtype unsigned char;
write data;
}%%
%%{
# Same order as enum khmer_category_t. Not sure how to avoid duplication.
C = 1;
V = 2;
ZWNJ = 5;
ZWJ = 6;
PLACEHOLDER = 11;
DOTTEDCIRCLE = 12;
Coeng= 14;
Ra = 16;
Robatic = 20;
Xgroup = 21;
Ygroup = 22;
VAbv = 26;
VBlw = 27;
VPre = 28;
VPst = 29;
c = (C | Ra | V);
cn = c.((ZWJ|ZWNJ)?.Robatic)?;
joiner = (ZWJ | ZWNJ);
xgroup = (joiner*.Xgroup)*;
ygroup = Ygroup*;
# This grammar was experimentally extracted from what Uniscribe allows.
matra_group = VPre? xgroup VBlw? xgroup (joiner?.VAbv)? xgroup VPst?;
syllable_tail = xgroup matra_group xgroup (Coeng.c)? ygroup;
broken_cluster = (Coeng.cn)* (Coeng | syllable_tail);
consonant_syllable = (cn|PLACEHOLDER|DOTTEDCIRCLE) broken_cluster;
other = any;
main := |*
consonant_syllable => { found_syllable (consonant_syllable); };
broken_cluster => { found_syllable (broken_cluster); };
other => { found_syllable (non_khmer_cluster); };
*|;
}%%
#define found_syllable(syllable_type) \
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables_khmer (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
int cs;
hb_glyph_info_t *info = buffer->info;
%%{
write init;
getkey info[p].khmer_category();
}%%
p = 0;
pe = eof = buffer->len;
unsigned int syllable_serial = 1;
%%{
write exec;
}%%
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */

View File

@ -29,6 +29,7 @@
#ifndef HB_NO_OT_SHAPE #ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-complex-khmer.hh" #include "hb-ot-shape-complex-khmer.hh"
#include "hb-ot-shape-complex-khmer-machine.hh"
#include "hb-ot-layout.hh" #include "hb-ot-layout.hh"
@ -140,27 +141,6 @@ override_features_khmer (hb_ot_shape_planner_t *plan)
struct khmer_shape_plan_t struct khmer_shape_plan_t
{ {
bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
{
hb_codepoint_t glyph = virama_glyph;
if (unlikely (virama_glyph == (hb_codepoint_t) -1))
{
if (!font->get_nominal_glyph (0x17D2u, &glyph))
glyph = 0;
/* Technically speaking, the spec says we should apply 'locl' to virama too.
* Maybe one day... */
/* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
* during shape planning... Instead, overwrite it here. It's safe. Don't worry! */
virama_glyph = glyph;
}
*pglyph = glyph;
return glyph != 0;
}
mutable hb_codepoint_t virama_glyph;
hb_mask_t mask_array[KHMER_NUM_FEATURES]; hb_mask_t mask_array[KHMER_NUM_FEATURES];
}; };
@ -171,8 +151,6 @@ data_create_khmer (const hb_ot_shape_plan_t *plan)
if (unlikely (!khmer_plan)) if (unlikely (!khmer_plan))
return nullptr; return nullptr;
khmer_plan->virama_glyph = (hb_codepoint_t) -1;
for (unsigned int i = 0; i < ARRAY_LENGTH (khmer_plan->mask_array); i++) for (unsigned int i = 0; i < ARRAY_LENGTH (khmer_plan->mask_array); i++)
khmer_plan->mask_array[i] = (khmer_features[i].flags & F_GLOBAL) ? khmer_plan->mask_array[i] = (khmer_features[i].flags & F_GLOBAL) ?
0 : plan->map.get_1_mask (khmer_features[i].tag); 0 : plan->map.get_1_mask (khmer_features[i].tag);
@ -186,15 +164,6 @@ data_destroy_khmer (void *data)
free (data); free (data);
} }
enum khmer_syllable_type_t {
khmer_consonant_syllable,
khmer_broken_cluster,
khmer_non_khmer_cluster,
};
#include "hb-ot-shape-complex-khmer-machine.hh"
static void static void
setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer, hb_buffer_t *buffer,
@ -321,76 +290,17 @@ reorder_syllable_khmer (const hb_ot_shape_plan_t *plan,
} }
} }
static inline void
insert_dotted_circles_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
/* Note: This loop is extra overhead, but should not be measurable.
* TODO Use a buffer scratch flag to remove the loop. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == khmer_broken_cluster)
{
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CCu;
set_khmer_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == khmer_broken_cluster))
{
last_syllable = syllable;
hb_glyph_info_t ginfo = dottedcircle;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().khmer_category() == OT_Repha)
buffer->next_glyph ();
buffer->output_info (ginfo);
}
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
static void static void
reorder_khmer (const hb_ot_shape_plan_t *plan, reorder_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font, hb_font_t *font,
hb_buffer_t *buffer) hb_buffer_t *buffer)
{ {
if (buffer->message (font, "start reordering khmer")) { if (buffer->message (font, "start reordering khmer"))
insert_dotted_circles_khmer (plan, font, buffer); {
hb_syllabic_insert_dotted_circles (font, buffer,
khmer_broken_cluster,
OT_DOTTEDCIRCLE,
OT_Repha);
foreach_syllable (buffer, start, end) foreach_syllable (buffer, start, end)
reorder_syllable_khmer (plan, font->face, buffer, start, end); reorder_syllable_khmer (plan, font->face, buffer, start, end);

View File

@ -54,7 +54,7 @@ set_khmer_properties (hb_glyph_info_t &info)
{ {
hb_codepoint_t u = info.codepoint; hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u); unsigned int type = hb_indic_get_categories (u);
khmer_category_t cat = (khmer_category_t) (type & 0x7Fu); khmer_category_t cat = (khmer_category_t) (type & 0xFFu);
indic_position_t pos = (indic_position_t) (type >> 8); indic_position_t pos = (indic_position_t) (type >> 8);

View File

@ -1,69 +0,0 @@
/*
* Copyright © 2019,2020 David Corbett
*
* 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.
*/
#ifndef HB_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH
#define HB_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH
#include "hb.hh"
template <typename Iter>
struct machine_index_t :
hb_iter_with_fallback_t<machine_index_t<Iter>,
typename Iter::item_t>
{
machine_index_t (const Iter& it) : it (it) {}
machine_index_t (const machine_index_t& o) : it (o.it) {}
static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
typename Iter::item_t __item__ () const { return *it; }
typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
unsigned __len__ () const { return it.len (); }
void __next__ () { ++it; }
void __forward__ (unsigned n) { it += n; }
void __prev__ () { --it; }
void __rewind__ (unsigned n) { it -= n; }
void operator = (unsigned n)
{ unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; }
void operator = (const machine_index_t& o) { *this = (*o.it).first; }
bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; }
bool operator != (const machine_index_t& o) const { return !(*this == o); }
private:
Iter it;
};
struct
{
template <typename Iter,
hb_requires (hb_is_iterable (Iter))>
machine_index_t<hb_iter_type<Iter>>
operator () (Iter&& it) const
{ return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
}
HB_FUNCOBJ (machine_index);
#endif /* HB_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH */

View File

@ -31,8 +31,43 @@
#include "hb.hh" #include "hb.hh"
enum myanmar_syllable_type_t {
myanmar_consonant_syllable,
myanmar_punctuation_cluster,
myanmar_broken_cluster,
myanmar_non_myanmar_cluster,
};
#line 36 "hb-ot-shape-complex-myanmar-machine.hh"
#line 43 "hb-ot-shape-complex-myanmar-machine.hh"
#define myanmar_syllable_machine_ex_A 10u
#define myanmar_syllable_machine_ex_As 18u
#define myanmar_syllable_machine_ex_C 1u
#define myanmar_syllable_machine_ex_CS 19u
#define myanmar_syllable_machine_ex_D 32u
#define myanmar_syllable_machine_ex_D0 20u
#define myanmar_syllable_machine_ex_DB 3u
#define myanmar_syllable_machine_ex_GB 11u
#define myanmar_syllable_machine_ex_H 4u
#define myanmar_syllable_machine_ex_IV 2u
#define myanmar_syllable_machine_ex_MH 21u
#define myanmar_syllable_machine_ex_MR 22u
#define myanmar_syllable_machine_ex_MW 23u
#define myanmar_syllable_machine_ex_MY 24u
#define myanmar_syllable_machine_ex_P 31u
#define myanmar_syllable_machine_ex_PT 25u
#define myanmar_syllable_machine_ex_Ra 16u
#define myanmar_syllable_machine_ex_V 8u
#define myanmar_syllable_machine_ex_VAbv 26u
#define myanmar_syllable_machine_ex_VBlw 27u
#define myanmar_syllable_machine_ex_VPre 28u
#define myanmar_syllable_machine_ex_VPst 29u
#define myanmar_syllable_machine_ex_VS 30u
#define myanmar_syllable_machine_ex_ZWJ 6u
#define myanmar_syllable_machine_ex_ZWNJ 5u
#line 71 "hb-ot-shape-complex-myanmar-machine.hh"
static const unsigned char _myanmar_syllable_machine_trans_keys[] = { static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u,
@ -293,18 +328,18 @@ static const int myanmar_syllable_machine_error = -1;
static const int myanmar_syllable_machine_en_main = 0; static const int myanmar_syllable_machine_en_main = 0;
#line 36 "hb-ot-shape-complex-myanmar-machine.rl" #line 44 "hb-ot-shape-complex-myanmar-machine.rl"
#line 94 "hb-ot-shape-complex-myanmar-machine.rl" #line 101 "hb-ot-shape-complex-myanmar-machine.rl"
#define found_syllable(syllable_type) \ #define found_syllable(syllable_type) \
HB_STMT_START { \ HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \ for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
syllable_serial++; \ syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END } HB_STMT_END
@ -316,7 +351,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
int cs; int cs;
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
#line 320 "hb-ot-shape-complex-myanmar-machine.hh" #line 355 "hb-ot-shape-complex-myanmar-machine.hh"
{ {
cs = myanmar_syllable_machine_start; cs = myanmar_syllable_machine_start;
ts = 0; ts = 0;
@ -324,7 +359,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
act = 0; act = 0;
} }
#line 114 "hb-ot-shape-complex-myanmar-machine.rl" #line 121 "hb-ot-shape-complex-myanmar-machine.rl"
p = 0; p = 0;
@ -332,7 +367,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
unsigned int syllable_serial = 1; unsigned int syllable_serial = 1;
#line 336 "hb-ot-shape-complex-myanmar-machine.hh" #line 371 "hb-ot-shape-complex-myanmar-machine.hh"
{ {
int _slen; int _slen;
int _trans; int _trans;
@ -346,7 +381,7 @@ _resume:
#line 1 "NONE" #line 1 "NONE"
{ts = p;} {ts = p;}
break; break;
#line 350 "hb-ot-shape-complex-myanmar-machine.hh" #line 385 "hb-ot-shape-complex-myanmar-machine.hh"
} }
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1); _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@ -365,38 +400,38 @@ _eof_trans:
switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
case 6: case 6:
#line 86 "hb-ot-shape-complex-myanmar-machine.rl" #line 93 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (consonant_syllable); }} {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
break; break;
case 4: case 4:
#line 87 "hb-ot-shape-complex-myanmar-machine.rl" #line 94 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (non_myanmar_cluster); }} {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
break; break;
case 10: case 10:
#line 88 "hb-ot-shape-complex-myanmar-machine.rl" #line 95 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (punctuation_cluster); }} {te = p+1;{ found_syllable (myanmar_punctuation_cluster); }}
break; break;
case 8: case 8:
#line 89 "hb-ot-shape-complex-myanmar-machine.rl" #line 96 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (broken_cluster); }} {te = p+1;{ found_syllable (myanmar_broken_cluster); }}
break; break;
case 3: case 3:
#line 90 "hb-ot-shape-complex-myanmar-machine.rl" #line 97 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p+1;{ found_syllable (non_myanmar_cluster); }} {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
break; break;
case 5: case 5:
#line 86 "hb-ot-shape-complex-myanmar-machine.rl" #line 93 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (consonant_syllable); }} {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
break; break;
case 7: case 7:
#line 89 "hb-ot-shape-complex-myanmar-machine.rl" #line 96 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (broken_cluster); }} {te = p;p--;{ found_syllable (myanmar_broken_cluster); }}
break; break;
case 9: case 9:
#line 90 "hb-ot-shape-complex-myanmar-machine.rl" #line 97 "hb-ot-shape-complex-myanmar-machine.rl"
{te = p;p--;{ found_syllable (non_myanmar_cluster); }} {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
break; break;
#line 400 "hb-ot-shape-complex-myanmar-machine.hh" #line 435 "hb-ot-shape-complex-myanmar-machine.hh"
} }
_again: _again:
@ -405,7 +440,7 @@ _again:
#line 1 "NONE" #line 1 "NONE"
{ts = 0;} {ts = 0;}
break; break;
#line 409 "hb-ot-shape-complex-myanmar-machine.hh" #line 444 "hb-ot-shape-complex-myanmar-machine.hh"
} }
if ( ++p != pe ) if ( ++p != pe )
@ -421,7 +456,7 @@ _again:
} }
#line 122 "hb-ot-shape-complex-myanmar-machine.rl" #line 129 "hb-ot-shape-complex-myanmar-machine.rl"
} }

View File

@ -29,6 +29,7 @@
#ifndef HB_NO_OT_SHAPE #ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-complex-myanmar.hh" #include "hb-ot-shape-complex-myanmar.hh"
#include "hb-ot-shape-complex-myanmar-machine.hh"
/* /*
@ -97,17 +98,6 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ); map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
} }
enum myanmar_syllable_type_t {
myanmar_consonant_syllable,
myanmar_punctuation_cluster,
myanmar_broken_cluster,
myanmar_non_myanmar_cluster,
};
#include "hb-ot-shape-complex-myanmar-machine.hh"
static void static void
setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer, hb_buffer_t *buffer,
@ -265,70 +255,16 @@ reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
} }
} }
static inline void
insert_dotted_circles_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
/* Note: This loop is extra overhead, but should not be measurable.
* TODO Use a buffer scratch flag to remove the loop. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == myanmar_broken_cluster)
{
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CCu;
set_myanmar_properties (dottedcircle);
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == myanmar_broken_cluster))
{
last_syllable = syllable;
hb_glyph_info_t ginfo = dottedcircle;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
buffer->output_info (ginfo);
}
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
static void static void
reorder_myanmar (const hb_ot_shape_plan_t *plan, reorder_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font, hb_font_t *font,
hb_buffer_t *buffer) hb_buffer_t *buffer)
{ {
if (buffer->message (font, "start reordering myanmar")) { if (buffer->message (font, "start reordering myanmar"))
insert_dotted_circles_myanmar (plan, font, buffer); {
hb_syllabic_insert_dotted_circles (font, buffer,
myanmar_broken_cluster,
OT_GB);
foreach_syllable (buffer, start, end) foreach_syllable (buffer, start, end)
reorder_syllable_myanmar (plan, font->face, buffer, start, end); reorder_syllable_myanmar (plan, font->face, buffer, start, end);

View File

@ -64,7 +64,7 @@ set_myanmar_properties (hb_glyph_info_t &info)
{ {
hb_codepoint_t u = info.codepoint; hb_codepoint_t u = info.codepoint;
unsigned int type = hb_indic_get_categories (u); unsigned int type = hb_indic_get_categories (u);
unsigned int cat = type & 0x7Fu; unsigned int cat = type & 0xFFu;
indic_position_t pos = (indic_position_t) (type >> 8); indic_position_t pos = (indic_position_t) (type >> 8);
/* Myanmar /* Myanmar

View File

@ -0,0 +1,100 @@
/*
* Copyright © 2021 Behdad Esfahbod.
*
* 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.
*/
#include "hb.hh"
#ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-complex-syllabic.hh"
void
hb_syllabic_insert_dotted_circles (hb_font_t *font,
hb_buffer_t *buffer,
unsigned int broken_syllable_type,
unsigned int dottedcircle_category,
int repha_category)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
/* Note: This loop is extra overhead, but should not be measurable.
* TODO Use a buffer scratch flag to remove the loop. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == broken_syllable_type)
{
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_codepoint_t dottedcircle_glyph;
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CCu;
dottedcircle.complex_var_u8_category() = dottedcircle_category;
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
if (unlikely (last_syllable != syllable && (syllable & 0x0F) == broken_syllable_type))
{
last_syllable = syllable;
hb_glyph_info_t ginfo = dottedcircle;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
/* Insert dottedcircle after possible Repha. */
if (repha_category != -1)
{
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().complex_var_u8_category() == (unsigned) repha_category)
(void) buffer->next_glyph ();
}
(void) buffer->output_info (ginfo);
}
else
(void) buffer->next_glyph ();
}
buffer->swap_buffers ();
}
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright © 2021 Behdad Esfahbod.
*
* 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.
*/
#ifndef HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
#define HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
#include "hb.hh"
#include "hb-ot-shape-complex.hh"
HB_INTERNAL void
hb_syllabic_insert_dotted_circles (hb_font_t *font,
hb_buffer_t *buffer,
unsigned int broken_syllable_type,
unsigned int dottedcircle_category,
int repha_category = -1);
#endif /* HB_OT_SHAPE_COMPLEX_SYLLABIC_HH */

View File

@ -323,20 +323,19 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
buffer->clear_output (); buffer->clear_output ();
unsigned int count = buffer->len; unsigned int count = buffer->len;
for (buffer->idx = 0; buffer->idx < count && buffer->successful;) for (buffer->idx = 0; buffer->idx < count /* No need for: && buffer->successful */;)
{ {
hb_codepoint_t u = buffer->cur().codepoint; hb_codepoint_t u = buffer->cur().codepoint;
if (likely (!IS_SARA_AM (u))) { if (likely (!IS_SARA_AM (u)))
buffer->next_glyph (); {
if (unlikely (!buffer->next_glyph ())) break;
continue; continue;
} }
/* Is SARA AM. Decompose and reorder. */ /* Is SARA AM. Decompose and reorder. */
hb_glyph_info_t &nikhahit = buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u)); (void) buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u));
_hb_glyph_info_set_continuation (&nikhahit); _hb_glyph_info_set_continuation (&buffer->prev());
buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u)); if (unlikely (!buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u)))) break;
if (unlikely (!buffer->successful))
return;
/* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */ /* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */
unsigned int end = buffer->out_len; unsigned int end = buffer->out_len;

File diff suppressed because it is too large Load Diff

View File

@ -31,56 +31,57 @@
* UnicodeData.txt does not have a header. * UnicodeData.txt does not have a header.
*/ */
#ifndef HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
#define HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
#include "hb.hh" #include "hb.hh"
#ifndef HB_NO_OT_SHAPE #include "hb-ot-shape-complex-use-machine.hh"
#include "hb-ot-shape-complex-use.hh"
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-macros"
#define B USE_B /* BASE */ #define B USE(B) /* BASE */
#define CS USE_CS /* CONS_WITH_STACKER */ #define CS USE(CS) /* CONS_WITH_STACKER */
#define G USE_G /* HIEROGLYPH */ #define G USE(G) /* HIEROGLYPH */
#define GB USE_GB /* BASE_OTHER */ #define GB USE(GB) /* BASE_OTHER */
#define H USE_H /* HALANT */ #define H USE(H) /* HALANT */
#define HN USE_HN /* HALANT_NUM */ #define HN USE(HN) /* HALANT_NUM */
#define HVM USE_HVM /* HALANT_OR_VOWEL_MODIFIER */ #define HVM USE(HVM) /* HALANT_OR_VOWEL_MODIFIER */
#define J USE_J /* HIEROGLYPH_JOINER */ #define J USE(J) /* HIEROGLYPH_JOINER */
#define N USE_N /* BASE_NUM */ #define N USE(N) /* BASE_NUM */
#define O USE_O /* OTHER */ #define O USE(O) /* OTHER */
#define R USE_R /* REPHA */ #define R USE(R) /* REPHA */
#define S USE_S /* SYM */ #define S USE(S) /* SYM */
#define SB USE_SB /* HIEROGLYPH_SEGMENT_BEGIN */ #define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
#define SE USE_SE /* HIEROGLYPH_SEGMENT_END */ #define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
#define SUB USE_SUB /* CONS_SUB */ #define SUB USE(SUB) /* CONS_SUB */
#define Sk USE_Sk /* SAKOT */ #define Sk USE(Sk) /* SAKOT */
#define ZWNJ USE_ZWNJ /* ZWNJ */ #define ZWNJ USE(ZWNJ) /* ZWNJ */
#define CMAbv USE_CMAbv #define CMAbv USE(CMAbv)
#define CMBlw USE_CMBlw #define CMBlw USE(CMBlw)
#define FAbv USE_FAbv #define FAbv USE(FAbv)
#define FBlw USE_FBlw #define FBlw USE(FBlw)
#define FPst USE_FPst #define FPst USE(FPst)
#define FMAbv USE_FMAbv #define FMAbv USE(FMAbv)
#define FMBlw USE_FMBlw #define FMBlw USE(FMBlw)
#define FMPst USE_FMPst #define FMPst USE(FMPst)
#define MAbv USE_MAbv #define MAbv USE(MAbv)
#define MBlw USE_MBlw #define MBlw USE(MBlw)
#define MPst USE_MPst #define MPst USE(MPst)
#define MPre USE_MPre #define MPre USE(MPre)
#define SMAbv USE_SMAbv #define SMAbv USE(SMAbv)
#define SMBlw USE_SMBlw #define SMBlw USE(SMBlw)
#define VAbv USE_VAbv #define VAbv USE(VAbv)
#define VBlw USE_VBlw #define VBlw USE(VBlw)
#define VPst USE_VPst #define VPst USE(VPst)
#define VPre USE_VPre #define VPre USE(VPre)
#define VMAbv USE_VMAbv #define VMAbv USE(VMAbv)
#define VMBlw USE_VMBlw #define VMBlw USE(VMBlw)
#define VMPst USE_VMPst #define VMPst USE(VMPst)
#define VMPre USE_VMPre #define VMPre USE(VMPre)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
static const USE_TABLE_ELEMENT_TYPE use_table[] = { static const uint8_t use_table[] = {
#define use_offset_0x0028u 0 #define use_offset_0x0028u 0
@ -767,7 +768,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
/* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv, /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv,
/* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VMAbv, O, O, O, O, /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O,
/* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
#define use_offset_0x11800u 5848 #define use_offset_0x11800u 5848
@ -1066,7 +1067,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
}; /* Table items: 8824; occupancy: 79% */ }; /* Table items: 8824; occupancy: 79% */
USE_TABLE_ELEMENT_TYPE static inline uint8_t
hb_use_get_category (hb_codepoint_t u) hb_use_get_category (hb_codepoint_t u)
{ {
switch (u >> 12) switch (u >> 12)
@ -1154,7 +1155,7 @@ hb_use_get_category (hb_codepoint_t u)
default: default:
break; break;
} }
return USE_O; return USE(O);
} }
#undef B #undef B
@ -1198,5 +1199,5 @@ hb_use_get_category (hb_codepoint_t u)
#undef VMPre #undef VMPre
#endif #endif /* HB_OT_SHAPE_COMPLEX_USE_TABLE_HH */
/* == End of generated table == */ /* == End of generated table == */

View File

@ -30,14 +30,12 @@
#ifndef HB_NO_OT_SHAPE #ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-complex-use.hh" #include "hb-ot-shape-complex-use-machine.hh"
#include "hb-ot-shape-complex-use-table.hh"
#include "hb-ot-shape-complex-arabic.hh" #include "hb-ot-shape-complex-arabic.hh"
#include "hb-ot-shape-complex-arabic-joining-list.hh" #include "hb-ot-shape-complex-arabic-joining-list.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh" #include "hb-ot-shape-complex-vowel-constraints.hh"
/* buffer var allocations */
#define use_category() complex_var_u8_1()
/* /*
* Universal Shaping Engine. * Universal Shaping Engine.
@ -69,11 +67,11 @@ use_topographical_features[] =
}; };
/* Same order as use_topographical_features. */ /* Same order as use_topographical_features. */
enum joining_form_t { enum joining_form_t {
USE_ISOL, JOINING_FORM_ISOL,
USE_INIT, JOINING_FORM_INIT,
USE_MEDI, JOINING_FORM_MEDI,
USE_FINA, JOINING_FORM_FINA,
_USE_NONE _JOINING_FORM_NONE
}; };
static const hb_tag_t static const hb_tag_t
use_other_features[] = use_other_features[] =
@ -186,22 +184,6 @@ data_destroy_use (void *data)
free (data); free (data);
} }
enum use_syllable_type_t {
use_independent_cluster,
use_virama_terminated_cluster,
use_sakot_terminated_cluster,
use_standard_cluster,
use_number_joiner_terminated_cluster,
use_numeral_cluster,
use_symbol_cluster,
use_hieroglyph_cluster,
use_broken_cluster,
use_non_cluster,
};
#include "hb-ot-shape-complex-use-machine.hh"
static void static void
setup_masks_use (const hb_ot_shape_plan_t *plan, setup_masks_use (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer, hb_buffer_t *buffer,
@ -239,7 +221,7 @@ setup_rphf_mask (const hb_ot_shape_plan_t *plan,
foreach_syllable (buffer, start, end) foreach_syllable (buffer, start, end)
{ {
unsigned int limit = info[start].use_category() == USE_R ? 1 : hb_min (3u, end - start); unsigned int limit = info[start].use_category() == USE(R) ? 1 : hb_min (3u, end - start);
for (unsigned int i = start; i < start + limit; i++) for (unsigned int i = start; i < start + limit; i++)
info[i].mask |= mask; info[i].mask |= mask;
} }
@ -253,7 +235,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
if (use_plan->arabic_plan) if (use_plan->arabic_plan)
return; return;
static_assert ((USE_INIT < 4 && USE_ISOL < 4 && USE_MEDI < 4 && USE_FINA < 4), ""); static_assert ((JOINING_FORM_INIT < 4 && JOINING_FORM_ISOL < 4 && JOINING_FORM_MEDI < 4 && JOINING_FORM_FINA < 4), "");
hb_mask_t masks[4], all_masks = 0; hb_mask_t masks[4], all_masks = 0;
for (unsigned int i = 0; i < 4; i++) for (unsigned int i = 0; i < 4; i++)
{ {
@ -267,7 +249,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
hb_mask_t other_masks = ~all_masks; hb_mask_t other_masks = ~all_masks;
unsigned int last_start = 0; unsigned int last_start = 0;
joining_form_t last_form = _USE_NONE; joining_form_t last_form = _JOINING_FORM_NONE;
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end) foreach_syllable (buffer, start, end)
{ {
@ -279,7 +261,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
case use_hieroglyph_cluster: case use_hieroglyph_cluster:
case use_non_cluster: case use_non_cluster:
/* These don't join. Nothing to do. */ /* These don't join. Nothing to do. */
last_form = _USE_NONE; last_form = _JOINING_FORM_NONE;
break; break;
case use_virama_terminated_cluster: case use_virama_terminated_cluster:
@ -289,18 +271,18 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
case use_numeral_cluster: case use_numeral_cluster:
case use_broken_cluster: case use_broken_cluster:
bool join = last_form == USE_FINA || last_form == USE_ISOL; bool join = last_form == JOINING_FORM_FINA || last_form == JOINING_FORM_ISOL;
if (join) if (join)
{ {
/* Fixup previous syllable's form. */ /* Fixup previous syllable's form. */
last_form = last_form == USE_FINA ? USE_MEDI : USE_INIT; last_form = last_form == JOINING_FORM_FINA ? JOINING_FORM_MEDI : JOINING_FORM_INIT;
for (unsigned int i = last_start; i < start; i++) for (unsigned int i = last_start; i < start; i++)
info[i].mask = (info[i].mask & other_masks) | masks[last_form]; info[i].mask = (info[i].mask & other_masks) | masks[last_form];
} }
/* Form for this syllable. */ /* Form for this syllable. */
last_form = join ? USE_FINA : USE_ISOL; last_form = join ? JOINING_FORM_FINA : JOINING_FORM_ISOL;
for (unsigned int i = start; i < end; i++) for (unsigned int i = start; i < end; i++)
info[i].mask = (info[i].mask & other_masks) | masks[last_form]; info[i].mask = (info[i].mask & other_masks) | masks[last_form];
@ -336,11 +318,11 @@ record_rphf_use (const hb_ot_shape_plan_t *plan,
foreach_syllable (buffer, start, end) foreach_syllable (buffer, start, end)
{ {
/* Mark a substituted repha as USE_R. */ /* Mark a substituted repha as USE(R). */
for (unsigned int i = start; i < end && (info[i].mask & mask); i++) for (unsigned int i = start; i < end && (info[i].mask & mask); i++)
if (_hb_glyph_info_substituted (&info[i])) if (_hb_glyph_info_substituted (&info[i]))
{ {
info[i].use_category() = USE_R; info[i].use_category() = USE(R);
break; break;
} }
} }
@ -359,7 +341,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
for (unsigned int i = start; i < end; i++) for (unsigned int i = start; i < end; i++)
if (_hb_glyph_info_substituted (&info[i])) if (_hb_glyph_info_substituted (&info[i]))
{ {
info[i].use_category() = USE_VPre; info[i].use_category() = USE(VPre);
break; break;
} }
} }
@ -368,7 +350,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
static inline bool static inline bool
is_halant_use (const hb_glyph_info_t &info) is_halant_use (const hb_glyph_info_t &info)
{ {
return (info.use_category() == USE_H || info.use_category() == USE_HVM) && return (info.use_category() == USE(H) || info.use_category() == USE(HVM)) &&
!_hb_glyph_info_ligated (&info); !_hb_glyph_info_ligated (&info);
} }
@ -387,24 +369,24 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
hb_glyph_info_t *info = buffer->info; hb_glyph_info_t *info = buffer->info;
#define POST_BASE_FLAGS64 (FLAG64 (USE_FAbv) | \ #define POST_BASE_FLAGS64 (FLAG64 (USE(FAbv)) | \
FLAG64 (USE_FBlw) | \ FLAG64 (USE(FBlw)) | \
FLAG64 (USE_FPst) | \ FLAG64 (USE(FPst)) | \
FLAG64 (USE_MAbv) | \ FLAG64 (USE(MAbv)) | \
FLAG64 (USE_MBlw) | \ FLAG64 (USE(MBlw)) | \
FLAG64 (USE_MPst) | \ FLAG64 (USE(MPst)) | \
FLAG64 (USE_MPre) | \ FLAG64 (USE(MPre)) | \
FLAG64 (USE_VAbv) | \ FLAG64 (USE(VAbv)) | \
FLAG64 (USE_VBlw) | \ FLAG64 (USE(VBlw)) | \
FLAG64 (USE_VPst) | \ FLAG64 (USE(VPst)) | \
FLAG64 (USE_VPre) | \ FLAG64 (USE(VPre)) | \
FLAG64 (USE_VMAbv) | \ FLAG64 (USE(VMAbv)) | \
FLAG64 (USE_VMBlw) | \ FLAG64 (USE(VMBlw)) | \
FLAG64 (USE_VMPst) | \ FLAG64 (USE(VMPst)) | \
FLAG64 (USE_VMPre)) FLAG64 (USE(VMPre)))
/* Move things forward. */ /* Move things forward. */
if (info[start].use_category() == USE_R && end - start > 1) if (info[start].use_category() == USE(R) && end - start > 1)
{ {
/* Got a repha. Reorder it towards the end, but before the first post-base /* Got a repha. Reorder it towards the end, but before the first post-base
* glyph. */ * glyph. */
@ -441,7 +423,7 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
* shift things in between forward. */ * shift things in between forward. */
j = i + 1; j = i + 1;
} }
else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) && else if (((flag) & (FLAG (USE(VPre)) | FLAG (USE(VMPre)))) &&
/* Only move the first component of a MultipleSubst. */ /* Only move the first component of a MultipleSubst. */
0 == _hb_glyph_info_get_lig_comp (&info[i]) && 0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
j < i) j < i)
@ -454,76 +436,22 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
} }
} }
static inline void
insert_dotted_circles_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
/* Note: This loop is extra overhead, but should not be measurable.
* TODO Use a buffer scratch flag to remove the loop. */
bool has_broken_syllables = false;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == use_broken_cluster)
{
has_broken_syllables = true;
break;
}
if (likely (!has_broken_syllables))
return;
hb_glyph_info_t dottedcircle = {0};
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint))
return;
dottedcircle.use_category() = hb_use_get_category (0x25CC);
buffer->clear_output ();
buffer->idx = 0;
unsigned int last_syllable = 0;
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
use_syllable_type_t syllable_type = (use_syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == use_broken_cluster))
{
last_syllable = syllable;
hb_glyph_info_t ginfo = dottedcircle;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().use_category() == USE_R)
buffer->next_glyph ();
buffer->output_info (ginfo);
}
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
static void static void
reorder_use (const hb_ot_shape_plan_t *plan, reorder_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font, hb_font_t *font,
hb_buffer_t *buffer) hb_buffer_t *buffer)
{ {
if (buffer->message (font, "start reordering USE")) { if (buffer->message (font, "start reordering USE"))
insert_dotted_circles_use (plan, font, buffer); {
hb_syllabic_insert_dotted_circles (font, buffer,
use_broken_cluster,
USE(B),
USE(R));
foreach_syllable (buffer, start, end) foreach_syllable (buffer, start, end)
reorder_syllable_use (buffer, start, end); reorder_syllable_use (buffer, start, end);
(void) buffer->message (font, "end reordering USE"); (void) buffer->message (font, "end reordering USE");
} }
HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);

View File

@ -1,96 +0,0 @@
/*
* Copyright © 2015 Mozilla Foundation.
* Copyright © 2015 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Mozilla Author(s): Jonathan Kew
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_SHAPE_COMPLEX_USE_HH
#define HB_OT_SHAPE_COMPLEX_USE_HH
#include "hb.hh"
#include "hb-ot-shape-complex.hh"
#define USE_TABLE_ELEMENT_TYPE uint8_t
/* Cateories used in the Universal Shaping Engine spec:
* https://docs.microsoft.com/en-us/typography/script-development/use
*/
/* Note: This enum is duplicated in the -machine.rl source file.
* Not sure how to avoid duplication. */
enum use_category_t {
USE_O = 0, /* OTHER */
USE_B = 1, /* BASE */
USE_N = 4, /* BASE_NUM */
USE_GB = 5, /* BASE_OTHER */
USE_SUB = 11, /* CONS_SUB */
USE_H = 12, /* HALANT */
USE_HN = 13, /* HALANT_NUM */
USE_ZWNJ = 14, /* Zero width non-joiner */
USE_R = 18, /* REPHA */
USE_S = 19, /* SYM */
USE_CS = 43, /* CONS_WITH_STACKER */
/* https://github.com/harfbuzz/harfbuzz/issues/1102 */
USE_HVM = 44, /* HALANT_OR_VOWEL_MODIFIER */
USE_Sk = 48, /* SAKOT */
USE_G = 49, /* HIEROGLYPH */
USE_J = 50, /* HIEROGLYPH_JOINER */
USE_SB = 51, /* HIEROGLYPH_SEGMENT_BEGIN */
USE_SE = 52, /* HIEROGLYPH_SEGMENT_END */
USE_FAbv = 24, /* CONS_FINAL_ABOVE */
USE_FBlw = 25, /* CONS_FINAL_BELOW */
USE_FPst = 26, /* CONS_FINAL_POST */
USE_MAbv = 27, /* CONS_MED_ABOVE */
USE_MBlw = 28, /* CONS_MED_BELOW */
USE_MPst = 29, /* CONS_MED_POST */
USE_MPre = 30, /* CONS_MED_PRE */
USE_CMAbv = 31, /* CONS_MOD_ABOVE */
USE_CMBlw = 32, /* CONS_MOD_BELOW */
USE_VAbv = 33, /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
USE_VBlw = 34, /* VOWEL_BELOW / VOWEL_BELOW_POST */
USE_VPst = 35, /* VOWEL_POST UIPC = Right */
USE_VPre = 22, /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
USE_VMAbv = 37, /* VOWEL_MOD_ABOVE */
USE_VMBlw = 38, /* VOWEL_MOD_BELOW */
USE_VMPst = 39, /* VOWEL_MOD_POST */
USE_VMPre = 23, /* VOWEL_MOD_PRE */
USE_SMAbv = 41, /* SYM_MOD_ABOVE */
USE_SMBlw = 42, /* SYM_MOD_BELOW */
USE_FMAbv = 45, /* CONS_FINAL_MOD UIPC = Top */
USE_FMBlw = 46, /* CONS_FINAL_MOD UIPC = Bottom */
USE_FMPst = 47, /* CONS_FINAL_MOD UIPC = Not_Applicable */
};
HB_INTERNAL USE_TABLE_ELEMENT_TYPE
hb_use_get_category (hb_codepoint_t u);
#endif /* HB_OT_SHAPE_COMPLEX_USE_HH */

View File

@ -23,15 +23,15 @@
static void static void
_output_dotted_circle (hb_buffer_t *buffer) _output_dotted_circle (hb_buffer_t *buffer)
{ {
hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); (void) buffer->output_glyph (0x25CCu);
_hb_glyph_info_reset_continuation (&dottedcircle); _hb_glyph_info_reset_continuation (&buffer->prev());
} }
static void static void
_output_with_dotted_circle (hb_buffer_t *buffer) _output_with_dotted_circle (hb_buffer_t *buffer)
{ {
_output_dotted_circle (buffer); _output_dotted_circle (buffer);
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
void void
@ -51,7 +51,6 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
* *
* https://github.com/harfbuzz/harfbuzz/issues/1019 * https://github.com/harfbuzz/harfbuzz/issues/1019
*/ */
bool processed = false;
buffer->clear_output (); buffer->clear_output ();
unsigned int count = buffer->len; unsigned int count = buffer->len;
switch ((unsigned) buffer->props.script) switch ((unsigned) buffer->props.script)
@ -97,15 +96,14 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
buffer->idx + 2 < count && buffer->idx + 2 < count &&
0x0907u == buffer->cur (2).codepoint) 0x0907u == buffer->cur (2).codepoint)
{ {
buffer->next_glyph (); (void) buffer->next_glyph ();
matched = true; matched = true;
} }
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_BENGALI: case HB_SCRIPT_BENGALI:
@ -124,10 +122,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x09E2u == buffer->cur (1).codepoint; matched = 0x09E2u == buffer->cur (1).codepoint;
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_GURMUKHI: case HB_SCRIPT_GURMUKHI:
@ -161,10 +158,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
} }
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_GUJARATI: case HB_SCRIPT_GUJARATI:
@ -186,10 +182,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x0ABEu == buffer->cur (1).codepoint; matched = 0x0ABEu == buffer->cur (1).codepoint;
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_ORIYA: case HB_SCRIPT_ORIYA:
@ -205,10 +200,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x0B57u == buffer->cur (1).codepoint; matched = 0x0B57u == buffer->cur (1).codepoint;
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_TAMIL: case HB_SCRIPT_TAMIL:
@ -220,10 +214,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
{ {
matched = true; matched = true;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_TELUGU: case HB_SCRIPT_TELUGU:
@ -244,10 +237,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x0C55u == buffer->cur (1).codepoint; matched = 0x0C55u == buffer->cur (1).codepoint;
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_KANNADA: case HB_SCRIPT_KANNADA:
@ -263,10 +255,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x0CCCu == buffer->cur (1).codepoint; matched = 0x0CCCu == buffer->cur (1).codepoint;
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_MALAYALAM: case HB_SCRIPT_MALAYALAM:
@ -290,10 +281,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
} }
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_SINHALA: case HB_SCRIPT_SINHALA:
@ -326,10 +316,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
} }
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_BRAHMI: case HB_SCRIPT_BRAHMI:
@ -348,10 +337,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x11042u == buffer->cur (1).codepoint; matched = 0x11042u == buffer->cur (1).codepoint;
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_KHUDAWADI: case HB_SCRIPT_KHUDAWADI:
@ -370,10 +358,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
} }
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_TIRHUTA: case HB_SCRIPT_TIRHUTA:
@ -397,10 +384,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
} }
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_MODI: case HB_SCRIPT_MODI:
@ -418,10 +404,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
} }
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
case HB_SCRIPT_TAKRI: case HB_SCRIPT_TAKRI:
@ -442,21 +427,15 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
matched = 0x116B2u == buffer->cur (1).codepoint; matched = 0x116B2u == buffer->cur (1).codepoint;
break; break;
} }
buffer->next_glyph (); (void) buffer->next_glyph ();
if (matched) _output_with_dotted_circle (buffer); if (matched) _output_with_dotted_circle (buffer);
} }
processed = true;
break; break;
default: default:
break; break;
} }
if (processed) buffer->swap_buffers ();
{
if (buffer->idx < count)
buffer->next_glyph ();
buffer->swap_buffers ();
}
} }

View File

@ -35,8 +35,8 @@
/* buffer var allocations, used by complex shapers */ /* buffer var allocations, used by complex shapers */
#define complex_var_u8_0() var2.u8[2] #define complex_var_u8_category() var2.u8[2]
#define complex_var_u8_1() var2.u8[3] #define complex_var_u8_auxiliary() var2.u8[3]
#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32 #define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
@ -186,27 +186,8 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_ARABIC: case HB_SCRIPT_ARABIC:
/* Unicode-3.0 additions */ /* Unicode-3.0 additions */
case HB_SCRIPT_MONGOLIAN:
case HB_SCRIPT_SYRIAC: case HB_SCRIPT_SYRIAC:
/* Unicode-5.0 additions */
case HB_SCRIPT_NKO:
case HB_SCRIPT_PHAGS_PA:
/* Unicode-6.0 additions */
case HB_SCRIPT_MANDAIC:
/* Unicode-7.0 additions */
case HB_SCRIPT_MANICHAEAN:
case HB_SCRIPT_PSALTER_PAHLAVI:
/* Unicode-9.0 additions */
case HB_SCRIPT_ADLAM:
/* Unicode-11.0 additions */
case HB_SCRIPT_HANIFI_ROHINGYA:
case HB_SCRIPT_SOGDIAN:
/* For Arabic script, use the Arabic shaper even if no OT script tag was found. /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
* This is because we do fallback shaping for Arabic script (and not others). * This is because we do fallback shaping for Arabic script (and not others).
* But note that Arabic shaping is applicable only to horizontal layout; for * But note that Arabic shaping is applicable only to horizontal layout; for
@ -284,8 +265,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
return &_hb_ot_complex_shaper_myanmar; return &_hb_ot_complex_shaper_myanmar;
/* https://github.com/harfbuzz/harfbuzz/issues/1162 */ #define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
case HB_SCRIPT_MYANMAR_ZAWGYI: case HB_SCRIPT_MYANMAR_ZAWGYI:
/* https://github.com/harfbuzz/harfbuzz/issues/1162 */
return &_hb_ot_complex_shaper_myanmar_zawgyi; return &_hb_ot_complex_shaper_myanmar_zawgyi;
@ -294,7 +276,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_TIBETAN: case HB_SCRIPT_TIBETAN:
/* Unicode-3.0 additions */ /* Unicode-3.0 additions */
//case HB_SCRIPT_MONGOLIAN: case HB_SCRIPT_MONGOLIAN:
//case HB_SCRIPT_SINHALA: //case HB_SCRIPT_SINHALA:
/* Unicode-3.2 additions */ /* Unicode-3.2 additions */
@ -315,8 +297,8 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-5.0 additions */ /* Unicode-5.0 additions */
case HB_SCRIPT_BALINESE: case HB_SCRIPT_BALINESE:
//case HB_SCRIPT_NKO: case HB_SCRIPT_NKO:
//case HB_SCRIPT_PHAGS_PA: case HB_SCRIPT_PHAGS_PA:
/* Unicode-5.1 additions */ /* Unicode-5.1 additions */
case HB_SCRIPT_CHAM: case HB_SCRIPT_CHAM:
@ -337,7 +319,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-6.0 additions */ /* Unicode-6.0 additions */
case HB_SCRIPT_BATAK: case HB_SCRIPT_BATAK:
case HB_SCRIPT_BRAHMI: case HB_SCRIPT_BRAHMI:
//case HB_SCRIPT_MANDAIC: case HB_SCRIPT_MANDAIC:
/* Unicode-6.1 additions */ /* Unicode-6.1 additions */
case HB_SCRIPT_CHAKMA: case HB_SCRIPT_CHAKMA:
@ -351,10 +333,10 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_KHOJKI: case HB_SCRIPT_KHOJKI:
case HB_SCRIPT_KHUDAWADI: case HB_SCRIPT_KHUDAWADI:
case HB_SCRIPT_MAHAJANI: case HB_SCRIPT_MAHAJANI:
//case HB_SCRIPT_MANICHAEAN: case HB_SCRIPT_MANICHAEAN:
case HB_SCRIPT_MODI: case HB_SCRIPT_MODI:
case HB_SCRIPT_PAHAWH_HMONG: case HB_SCRIPT_PAHAWH_HMONG:
//case HB_SCRIPT_PSALTER_PAHLAVI: case HB_SCRIPT_PSALTER_PAHLAVI:
case HB_SCRIPT_SIDDHAM: case HB_SCRIPT_SIDDHAM:
case HB_SCRIPT_TIRHUTA: case HB_SCRIPT_TIRHUTA:
@ -363,7 +345,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_MULTANI: case HB_SCRIPT_MULTANI:
/* Unicode-9.0 additions */ /* Unicode-9.0 additions */
//case HB_SCRIPT_ADLAM: case HB_SCRIPT_ADLAM:
case HB_SCRIPT_BHAIKSUKI: case HB_SCRIPT_BHAIKSUKI:
case HB_SCRIPT_MARCHEN: case HB_SCRIPT_MARCHEN:
case HB_SCRIPT_NEWA: case HB_SCRIPT_NEWA:
@ -376,11 +358,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-11.0 additions */ /* Unicode-11.0 additions */
case HB_SCRIPT_DOGRA: case HB_SCRIPT_DOGRA:
case HB_SCRIPT_GUNJALA_GONDI: case HB_SCRIPT_GUNJALA_GONDI:
//case HB_SCRIPT_HANIFI_ROHINGYA: case HB_SCRIPT_HANIFI_ROHINGYA:
case HB_SCRIPT_MAKASAR: case HB_SCRIPT_MAKASAR:
case HB_SCRIPT_MEDEFAIDRIN: case HB_SCRIPT_MEDEFAIDRIN:
case HB_SCRIPT_OLD_SOGDIAN: case HB_SCRIPT_OLD_SOGDIAN:
//case HB_SCRIPT_SOGDIAN: case HB_SCRIPT_SOGDIAN:
/* Unicode-12.0 additions */ /* Unicode-12.0 additions */
case HB_SCRIPT_ELYMAIC: case HB_SCRIPT_ELYMAIC:

View File

@ -101,8 +101,9 @@ set_glyph (hb_glyph_info_t &info, hb_font_t *font)
static inline void static inline void
output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph) output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
{ {
/* This is very confusing indeed. */
buffer->cur().glyph_index() = glyph; buffer->cur().glyph_index() = glyph;
buffer->output_glyph (unichar); /* This is very confusing indeed. */ (void) buffer->output_glyph (unichar);
_hb_glyph_info_set_unicode_props (&buffer->prev(), buffer); _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
} }
@ -110,7 +111,7 @@ static inline void
next_char (hb_buffer_t *buffer, hb_codepoint_t glyph) next_char (hb_buffer_t *buffer, hb_codepoint_t glyph)
{ {
buffer->cur().glyph_index() = glyph; buffer->cur().glyph_index() = glyph;
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
static inline void static inline void
@ -229,30 +230,35 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
{ {
hb_codepoint_t unicode = buffer->cur().codepoint; hb_codepoint_t unicode = buffer->cur().codepoint;
buffer->replace_glyphs (2, 1, &unicode); (void) buffer->replace_glyphs (2, 1, &unicode);
} }
else else
{ {
/* Just pass on the two characters separately, let GSUB do its magic. */ /* Just pass on the two characters separately, let GSUB do its magic. */
set_glyph (buffer->cur(), font); set_glyph (buffer->cur(), font);
buffer->next_glyph (); (void) buffer->next_glyph ();
set_glyph (buffer->cur(), font); set_glyph (buffer->cur(), font);
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
/* Skip any further variation selectors. */ /* Skip any further variation selectors. */
while (buffer->idx < end && unlikely (buffer->unicode->is_variation_selector (buffer->cur().codepoint))) while (buffer->idx < end &&
buffer->successful &&
unlikely (buffer->unicode->is_variation_selector (buffer->cur().codepoint)))
{ {
set_glyph (buffer->cur(), font); set_glyph (buffer->cur(), font);
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
} else { }
else
{
set_glyph (buffer->cur(), font); set_glyph (buffer->cur(), font);
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
} }
if (likely (buffer->idx < end)) { if (likely (buffer->idx < end))
{
set_glyph (buffer->cur(), font); set_glyph (buffer->cur(), font);
buffer->next_glyph (); (void) buffer->next_glyph ();
} }
} }
@ -348,7 +354,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
sizeof (buffer->info[0]), sizeof (buffer->info[0]),
&buffer->cur().glyph_index(), &buffer->cur().glyph_index(),
sizeof (buffer->info[0])); sizeof (buffer->info[0]));
buffer->next_glyphs (done); if (unlikely (!buffer->next_glyphs (done))) break;
} }
while (buffer->idx < end && buffer->successful) while (buffer->idx < end && buffer->successful)
decompose_current_character (&c, might_short_circuit); decompose_current_character (&c, might_short_circuit);
@ -419,6 +425,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
/* Third round, recompose */ /* Third round, recompose */
if (!all_simple && if (!all_simple &&
buffer->successful &&
(mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS ||
mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT)) mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT))
{ {
@ -428,8 +435,8 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
buffer->clear_output (); buffer->clear_output ();
count = buffer->len; count = buffer->len;
unsigned int starter = 0; unsigned int starter = 0;
buffer->next_glyph (); (void) buffer->next_glyph ();
while (buffer->idx < count && buffer->successful) while (buffer->idx < count /* No need for: && buffer->successful */)
{ {
hb_codepoint_t composed, glyph; hb_codepoint_t composed, glyph;
if (/* We don't try to compose a non-mark character with it's preceding starter. if (/* We don't try to compose a non-mark character with it's preceding starter.
@ -451,9 +458,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
font->get_nominal_glyph (composed, &glyph)) font->get_nominal_glyph (composed, &glyph))
{ {
/* Composes. */ /* Composes. */
buffer->next_glyph (); /* Copy to out-buffer. */ if (unlikely (!buffer->next_glyph ())) break; /* Copy to out-buffer. */
if (unlikely (!buffer->successful))
return;
buffer->merge_out_clusters (starter, buffer->out_len); buffer->merge_out_clusters (starter, buffer->out_len);
buffer->out_len--; /* Remove the second composable. */ buffer->out_len--; /* Remove the second composable. */
/* Modify starter and carry on. */ /* Modify starter and carry on. */
@ -466,7 +471,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
} }
/* Blocked, or doesn't compose. */ /* Blocked, or doesn't compose. */
buffer->next_glyph (); if (unlikely (!buffer->next_glyph ())) break;
if (info_cc (buffer->prev()) == 0) if (info_cc (buffer->prev()) == 0)
starter = buffer->out_len - 1; starter = buffer->out_len - 1;

View File

@ -534,9 +534,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
hb_glyph_info_t info = dottedcircle; hb_glyph_info_t info = dottedcircle;
info.cluster = buffer->cur().cluster; info.cluster = buffer->cur().cluster;
info.mask = buffer->cur().mask; info.mask = buffer->cur().mask;
buffer->output_info (info); (void) buffer->output_info (info);
while (buffer->idx < buffer->len && buffer->successful)
buffer->next_glyph ();
buffer->swap_buffers (); buffer->swap_buffers ();
} }

View File

@ -24,7 +24,7 @@
* Red Hat Author(s): Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
*/ */
#ifndef HB_OT_H_IN #if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
#error "Include <hb-ot.h> instead." #error "Include <hb-ot.h> instead."
#endif #endif

View File

@ -6,8 +6,8 @@
* *
* on files with these headers: * on files with these headers:
* *
* <meta name="updated_at" content="2020-11-17 08:21 AM" /> * <meta name="updated_at" content="2021-02-12 04:08 PM" />
* File-Date: 2020-09-29 * File-Date: 2021-03-05
*/ */
#ifndef HB_OT_TAG_TABLE_HH #ifndef HB_OT_TAG_TABLE_HH
@ -169,6 +169,7 @@ static const LangTag ot_languages[] = {
{"bko", HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */ {"bko", HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */
{"bla", HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */ {"bla", HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */
{"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */ {"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */
{"blg", HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */
{"bli", HB_TAG_NONE }, /* Bolia != Baluchi */ {"bli", HB_TAG_NONE }, /* Bolia != Baluchi */
{"blk", HB_TAG('B','L','K',' ')}, /* Pao Karen */ {"blk", HB_TAG('B','L','K',' ')}, /* Pao Karen */
{"blk", HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */ {"blk", HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */
@ -358,6 +359,7 @@ static const LangTag ot_languages[] = {
{"czo", HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */ {"czo", HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */
{"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */ {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */
{"da", HB_TAG('D','A','N',' ')}, /* Danish */ {"da", HB_TAG('D','A','N',' ')}, /* Danish */
/*{"dag", HB_TAG('D','A','G',' ')},*/ /* Dagbani */
{"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */ {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */
{"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */ {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */
/*{"dar", HB_TAG('D','A','R',' ')},*/ /* Dargwa */ /*{"dar", HB_TAG('D','A','R',' ')},*/ /* Dargwa */
@ -834,6 +836,7 @@ static const LangTag ot_languages[] = {
{"lri", HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */ {"lri", HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
{"lrm", HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */ {"lrm", HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
{"lrt", HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */ {"lrt", HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */
{"lsb", HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */
{"lsm", HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */ {"lsm", HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */
{"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */ {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */
{"ltg", HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */ {"ltg", HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */
@ -990,7 +993,7 @@ static const LangTag ot_languages[] = {
/*{"nga", HB_TAG('N','G','A',' ')},*/ /* Ngbaka */ /*{"nga", HB_TAG('N','G','A',' ')},*/ /* Ngbaka */
{"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */ {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */
{"ngm", HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */ {"ngm", HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */
{"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni -> Sutu */ {"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */
{"ngr", HB_TAG_NONE }, /* Engdewu != Nagari */ {"ngr", HB_TAG_NONE }, /* Engdewu != Nagari */
{"ngu", HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */ {"ngu", HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */
{"nhc", HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */ {"nhc", HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */
@ -1520,6 +1523,8 @@ static const LangTag ot_languages[] = {
{"xmm", HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */ {"xmm", HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */
{"xmv", HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */ {"xmv", HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */
{"xmw", HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */ {"xmw", HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */
{"xnj", HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */
{"xnq", HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */
{"xnr", HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */ {"xnr", HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */
/*{"xog", HB_TAG('X','O','G',' ')},*/ /* Soga */ /*{"xog", HB_TAG('X','O','G',' ')},*/ /* Soga */
{"xpe", HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */ {"xpe", HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */
@ -2808,6 +2813,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("hnd", -1); /* Southern Hindko */ return hb_language_from_string ("hnd", -1); /* Southern Hindko */
case HB_TAG('H','Y','E',' '): /* Armenian */ case HB_TAG('H','Y','E',' '): /* Armenian */
return hb_language_from_string ("hyw", -1); /* Western Armenian */ return hb_language_from_string ("hyw", -1); /* Western Armenian */
case HB_TAG('I','B','A',' '): /* Iban */
return hb_language_from_string ("iba", -1); /* Iban */
case HB_TAG('I','J','O',' '): /* Ijo */ case HB_TAG('I','J','O',' '): /* Ijo */
return hb_language_from_string ("ijo", -1); /* Ijo [family] */ return hb_language_from_string ("ijo", -1); /* Ijo [family] */
case HB_TAG('I','N','U',' '): /* Inuktitut */ case HB_TAG('I','N','U',' '): /* Inuktitut */
@ -2892,6 +2899,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("sq", -1); /* Albanian [macrolanguage] */ return hb_language_from_string ("sq", -1); /* Albanian [macrolanguage] */
case HB_TAG('S','R','B',' '): /* Serbian */ case HB_TAG('S','R','B',' '): /* Serbian */
return hb_language_from_string ("sr", -1); /* Serbian */ return hb_language_from_string ("sr", -1); /* Serbian */
case HB_TAG('S','X','T',' '): /* Sutu */
return hb_language_from_string ("xnj", -1); /* Ngoni (Tanzania) */
case HB_TAG('S','Y','R',' '): /* Syriac */ case HB_TAG('S','Y','R',' '): /* Syriac */
return hb_language_from_string ("syr", -1); /* Syriac [macrolanguage] */ return hb_language_from_string ("syr", -1); /* Syriac [macrolanguage] */
case HB_TAG('S','Y','R','E'): /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */ case HB_TAG('S','Y','R','E'): /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */

View File

@ -164,6 +164,15 @@ hb_ot_all_tags_from_script (hb_script_t script,
*count = i; *count = i;
} }
/**
* hb_ot_tag_to_script:
* @tag: a script tag
*
* Converts a script tag to an #hb_script_t.
*
* Return value: The #hb_script_t corresponding to @tag.
*
**/
hb_script_t hb_script_t
hb_ot_tag_to_script (hb_tag_t tag) hb_ot_tag_to_script (hb_tag_t tag)
{ {
@ -351,13 +360,13 @@ parse_private_use_subtag (const char *private_use_subtag,
* hb_ot_tags_from_script_and_language: * hb_ot_tags_from_script_and_language:
* @script: an #hb_script_t to convert. * @script: an #hb_script_t to convert.
* @language: an #hb_language_t to convert. * @language: an #hb_language_t to convert.
* @script_count: (allow-none): maximum number of script tags to retrieve (IN) * @script_count: (inout) (optional): maximum number of script tags to retrieve (IN)
* and actual number of script tags retrieved (OUT) * and actual number of script tags retrieved (OUT)
* @script_tags: (out) (allow-none): array of size at least @script_count to store the * @script_tags: (out) (optional): array of size at least @script_count to store the
* script tag results * script tag results
* @language_count: (allow-none): maximum number of language tags to retrieve * @language_count: (inout) (optional): maximum number of language tags to retrieve
* (IN) and actual number of language tags retrieved (OUT) * (IN) and actual number of language tags retrieved (OUT)
* @language_tags: (out) (allow-none): array of size at least @language_count to store * @language_tags: (out) (optional): array of size at least @language_count to store
* the language tag results * the language tag results
* *
* Converts an #hb_script_t and an #hb_language_t to script and language tags. * Converts an #hb_script_t and an #hb_language_t to script and language tags.
@ -424,10 +433,12 @@ hb_ot_tags_from_script_and_language (hb_script_t script,
/** /**
* hb_ot_tag_to_language: * hb_ot_tag_to_language:
* @tag: an language tag
* *
* Converts a language tag to an #hb_language_t.
* *
* * Return value: (transfer none) (nullable):
* Return value: (transfer none): * The #hb_language_t corresponding to @tag.
* *
* Since: 0.9.2 * Since: 0.9.2
**/ **/
@ -478,9 +489,9 @@ hb_ot_tag_to_language (hb_tag_t tag)
* hb_ot_tags_to_script_and_language: * hb_ot_tags_to_script_and_language:
* @script_tag: a script tag * @script_tag: a script tag
* @language_tag: a language tag * @language_tag: a language tag
* @script: (allow-none): the #hb_script_t corresponding to @script_tag (OUT). * @script: (out) (optional): the #hb_script_t corresponding to @script_tag.
* @language: (allow-none): the #hb_language_t corresponding to @script_tag and * @language: (out) (optional): the #hb_language_t corresponding to @script_tag and
* @language_tag (OUT). * @language_tag.
* *
* Converts a script tag and a language tag to an #hb_script_t and an * Converts a script tag and a language tag to an #hb_script_t and an
* #hb_language_t. * #hb_language_t.

Some files were not shown because too many files have changed in this diff Show More